// 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 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 'Incomplete const[]'}} expected-note {{incomplete type 'Incomplete const[]' is not a literal type}} constexpr ClassTemp classtemplate = {}; constexpr ClassTemp classtemplate2[] = {}; // - it has a trivial destructor struct UserProvDtor { constexpr int f() const; // expected-error {{non-literal type 'UserProvDtor' cannot have constexpr members}} ~UserProvDtor(); // expected-note {{has a user-provided destructor}} }; struct NonTrivDtor { constexpr NonTrivDtor(); constexpr int f() const; // expected-error {{non-literal type 'NonTrivDtor' cannot have constexpr members}} virtual ~NonTrivDtor() = default; // expected-note {{has a non-trivial destructor}} expected-note {{because it is virtual}} }; struct NonTrivDtorBase { ~NonTrivDtorBase(); }; template struct DerivedFromNonTrivDtor : T { // expected-note {{'DerivedFromNonTrivDtor' is not literal because it has base class 'NonTrivDtorBase' of non-literal type}} constexpr DerivedFromNonTrivDtor(); }; constexpr int f(DerivedFromNonTrivDtor) { return 0; } // expected-error {{constexpr function's 1st parameter type 'DerivedFromNonTrivDtor' 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 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() const; // expected-error {{non-literal type 'CopyCtorOnly' cannot have constexpr members}} }; struct MoveCtorOnly { // expected-note {{no constexpr constructors other than copy or move constructors}} constexpr MoveCtorOnly(MoveCtorOnly&&); constexpr int f() const; // expected-error {{non-literal type 'MoveCtorOnly' cannot have constexpr members}} }; template struct CtorArg { constexpr CtorArg(T); }; constexpr int f(CtorArg) { return 0; } // ok constexpr int f(CtorArg) { 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 struct DerivedFromVBase : T { // expected-note {{struct with virtual base class is not a literal type}} constexpr DerivedFromVBase(); }; constexpr int f(DerivedFromVBase) {} // expected-error {{constexpr function's 1st parameter type 'DerivedFromVBase' is not a literal type}} template constexpr DerivedFromVBase::DerivedFromVBase() : T() {} constexpr int nVBase = (DerivedFromVBase(), 0); // expected-error {{constant expression}} expected-note {{cannot construct object of type 'DerivedFromVBase' 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() const { return 0; } // expected-error {{non-literal type 'NonLitBase' cannot have constexpr members}} }; struct LitMemBase : Agg { Agg agg; }; template struct MemberType { T t; // expected-note {{'MemberType' is not literal because it has data member 't' of non-literal type 'NonLiteral'}} constexpr MemberType(); }; constexpr int f(MemberType) { return 0; } constexpr int f(MemberType) { 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}} }