blob: d41b394bb60f2ff1fdb6442db15c818c5c5c990b [file] [log] [blame]
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1y %s -DCXX1Y
struct NonLiteral { NonLiteral(); };
// A type is a literal type if it is:
// [C++1y] - void
constexpr void f() {}
#ifndef CXX1Y
// expected-error@-2 {{'void' is not a literal type}}
#endif
// - a scalar type
constexpr int f1(double) { return 0; }
// - a reference type
struct S { S(); };
constexpr int f2(S &) { return 0; }
struct BeingDefined;
extern BeingDefined beingdefined;
struct BeingDefined {
static constexpr BeingDefined& t = beingdefined;
};
// - a class type that has all of the following properties:
// (implied) - it is complete
struct Incomplete; // expected-note 2{{forward declaration of 'Incomplete'}}
template<class T> struct ClassTemp {};
constexpr Incomplete incomplete = {}; // expected-error {{constexpr variable cannot have non-literal type 'const Incomplete'}} expected-note {{incomplete type 'const Incomplete' is not a literal type}}
constexpr Incomplete incomplete2[] = {}; // expected-error {{constexpr variable cannot have non-literal type 'const Incomplete[]'}} expected-note {{incomplete type 'const Incomplete[]' is not a literal type}}
constexpr ClassTemp<int> classtemplate = {};
constexpr ClassTemp<int> classtemplate2[] = {};
// - it has a trivial destructor
struct UserProvDtor {
~UserProvDtor(); // expected-note {{has a user-provided destructor}}
};
constexpr int f(UserProvDtor) { return 0; } // expected-error {{'UserProvDtor' is not a literal type}}
struct NonTrivDtor {
constexpr NonTrivDtor();
virtual ~NonTrivDtor() = default; // expected-note {{has a non-trivial destructor}} expected-note {{because it is virtual}}
};
constexpr int f(NonTrivDtor) { return 0; } // expected-error {{'NonTrivDtor' is not a literal type}}
struct NonTrivDtorBase {
~NonTrivDtorBase();
};
template<typename T>
struct DerivedFromNonTrivDtor : T { // expected-note {{'DerivedFromNonTrivDtor<NonTrivDtorBase>' is not literal because it has base class 'NonTrivDtorBase' of non-literal type}}
constexpr DerivedFromNonTrivDtor();
};
constexpr int f(DerivedFromNonTrivDtor<NonTrivDtorBase>) { return 0; } // expected-error {{constexpr function's 1st parameter type 'DerivedFromNonTrivDtor<NonTrivDtorBase>' is not a literal type}}
struct TrivDtor {
constexpr TrivDtor();
};
constexpr int f(TrivDtor) { return 0; }
struct TrivDefaultedDtor {
constexpr TrivDefaultedDtor();
~TrivDefaultedDtor() = default;
};
constexpr int f(TrivDefaultedDtor) { return 0; }
// - it is an aggregate type or has at least one constexpr constructor or
// constexpr constructor template that is not a copy or move constructor
struct Agg {
int a;
char *b;
};
constexpr int f3(Agg a) { return a.a; }
struct CtorTemplate {
template<typename T> constexpr CtorTemplate(T);
};
struct CopyCtorOnly { // expected-note {{'CopyCtorOnly' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
constexpr CopyCtorOnly(CopyCtorOnly&);
};
constexpr int f(CopyCtorOnly) { return 0; } // expected-error {{'CopyCtorOnly' is not a literal type}}
struct MoveCtorOnly { // expected-note {{no constexpr constructors other than copy or move constructors}}
constexpr MoveCtorOnly(MoveCtorOnly&&);
};
constexpr int f(MoveCtorOnly) { return 0; } // expected-error {{'MoveCtorOnly' is not a literal type}}
template<typename T>
struct CtorArg {
constexpr CtorArg(T);
};
constexpr int f(CtorArg<int>) { return 0; } // ok
constexpr int f(CtorArg<NonLiteral>) { return 0; } // ok, ctor is still constexpr
// We have a special-case diagnostic for classes with virtual base classes.
struct VBase {};
struct HasVBase : virtual VBase {}; // expected-note 2{{virtual base class declared here}}
struct Derived : HasVBase {
constexpr Derived() {} // expected-error {{constexpr constructor not allowed in struct with virtual base class}}
};
template<typename T> struct DerivedFromVBase : T { // expected-note {{struct with virtual base class is not a literal type}}
constexpr DerivedFromVBase();
};
constexpr int f(DerivedFromVBase<HasVBase>) {} // expected-error {{constexpr function's 1st parameter type 'DerivedFromVBase<HasVBase>' is not a literal type}}
template<typename T> constexpr DerivedFromVBase<T>::DerivedFromVBase() : T() {}
constexpr int nVBase = (DerivedFromVBase<HasVBase>(), 0); // expected-error {{constant expression}} expected-note {{cannot construct object of type 'DerivedFromVBase<HasVBase>' with virtual base class in a constant expression}}
// - it has all non-static data members and base classes of literal types
struct NonLitMember {
S s; // expected-note {{has data member 's' of non-literal type 'S'}}
};
constexpr int f(NonLitMember) {} // expected-error {{1st parameter type 'NonLitMember' is not a literal type}}
struct NonLitBase :
S { // expected-note {{base class 'S' of non-literal type}}
constexpr NonLitBase();
};
constexpr int f(NonLitBase) { return 0; } // expected-error {{'NonLitBase' is not a literal type}}
struct LitMemBase : Agg {
Agg agg;
};
template<typename T>
struct MemberType {
T t; // expected-note {{'MemberType<NonLiteral>' is not literal because it has data member 't' of non-literal type 'NonLiteral'}}
constexpr MemberType();
};
constexpr int f(MemberType<int>) { return 0; }
constexpr int f(MemberType<NonLiteral>) { return 0; } // expected-error {{not a literal type}}
// - an array of literal type [C++1y] other than an array of runtime bound
struct ArrGood {
Agg agg[24];
double d[12];
TrivDtor td[3];
TrivDefaultedDtor tdd[3];
};
constexpr int f(ArrGood) { return 0; }
struct ArrBad {
S s[3]; // expected-note {{data member 's' of non-literal type 'S[3]'}}
};
constexpr int f(ArrBad) { return 0; } // expected-error {{1st parameter type 'ArrBad' is not a literal type}}
constexpr int arb(int n) {
int a[n]; // expected-error {{variable of non-literal type 'int[n]' cannot be defined in a constexpr function}}
}
// expected-warning@+1 {{variable length array folded to constant array as an extension}}
constexpr long Overflow[(1 << 30) << 2]{}; // expected-warning {{requires 34 bits to represent}}
namespace inherited_ctor {
struct A { constexpr A(int); };
struct B : A {
B();
using A::A;
};
constexpr int f(B) { return 0; } // ok
struct C { constexpr C(int); };
struct D : C { // expected-note {{because}}
D(int);
using C::C;
};
constexpr int f(D) { return 0; } // expected-error {{not a literal type}}
// This one is a bit odd: F inherits E's default constructor, which is
// constexpr. Because F has a constructor of its own, it doesn't declare a
// default constructor hiding E's one.
struct E {};
struct F : E {
F(int);
using E::E;
};
constexpr int f(F) { return 0; }
// FIXME: Is this really the right behavior? We presumably should be checking
// whether the inherited constructor would be a copy or move constructor for
// the derived class, not for the base class.
struct G { constexpr G(const G&); };
struct H : G { // expected-note {{because}}
using G::G;
};
constexpr int f(H) { return 0; } // expected-error {{not a literal type}}
struct J;
struct I { constexpr I(const J&); };
struct J : I {
using I::I;
};
constexpr int f(J) { return 0; }
}