1 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s 2 3 struct NonLiteral { NonLiteral(); }; 4 5 // A type is a literal type if it is: 6 7 // - a scalar type 8 constexpr int f1(double); 9 10 // - a reference type 11 struct S { S(); }; 12 constexpr int f2(S &); 13 14 // - a class type that has all of the following properties: 15 16 // - it has a trivial destructor 17 struct UserProvDtor { 18 constexpr UserProvDtor(); // expected-error {{non-literal type 'UserProvDtor' cannot have constexpr members}} 19 ~UserProvDtor(); // expected-note {{has a user-provided destructor}} 20 }; 21 struct NonTrivDtor { 22 constexpr NonTrivDtor(); // expected-error {{non-literal type 'NonTrivDtor' cannot have constexpr members}} 23 virtual ~NonTrivDtor() = default; // expected-note {{has a non-trivial destructor}} 24 }; 25 struct NonTrivDtorBase { 26 ~NonTrivDtorBase(); 27 }; 28 template<typename T> 29 struct DerivedFromNonTrivDtor : T { // expected-note {{'DerivedFromNonTrivDtor<NonTrivDtorBase>' is not literal because it has base class 'NonTrivDtorBase' of non-literal type}} 30 constexpr DerivedFromNonTrivDtor(); 31 }; 32 constexpr int f(DerivedFromNonTrivDtor<NonTrivDtorBase>); // expected-error {{constexpr function's 1st parameter type 'DerivedFromNonTrivDtor<NonTrivDtorBase>' is not a literal type}} 33 struct TrivDtor { 34 constexpr TrivDtor(); 35 }; 36 // FIXME: when building DefinitionData we look at 'isUserProvided' before it's set up! 37 #if 0 38 struct TrivDefaultedDtor { 39 constexpr TrivDefaultedDtor(); 40 ~TrivDefaultedDtor() = default; 41 }; 42 #endif 43 44 // - it is an aggregate type or has at least one constexpr constructor or 45 // constexpr constructor template that is not a copy or move constructor 46 struct Agg { 47 int a; 48 char *b; 49 }; 50 constexpr int f3(Agg a) { return a.a; } 51 struct CtorTemplate { 52 template<typename T> constexpr CtorTemplate(T); 53 }; 54 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}} 55 constexpr CopyCtorOnly(CopyCtorOnly&); // expected-error {{non-literal type 'CopyCtorOnly' cannot have constexpr members}} 56 }; 57 struct MoveCtorOnly { // expected-note {{no constexpr constructors other than copy or move constructors}} 58 constexpr MoveCtorOnly(MoveCtorOnly&&); // expected-error {{non-literal type 'MoveCtorOnly' cannot have constexpr members}} 59 }; 60 template<typename T> 61 struct CtorArg { // expected-note {{no constexpr constructors other than copy or move constructors}} 62 constexpr CtorArg(T); // expected-note {{constructor template instantiation is not constexpr because 1st parameter type 'NonLiteral' is not a literal type}} 63 }; 64 constexpr int f(CtorArg<int>); 65 constexpr int f(CtorArg<NonLiteral>); // expected-error {{not a literal type}} 66 // We have a special-case diagnostic for classes with virtual base classes. 67 struct VBase {}; 68 struct HasVBase : virtual VBase {}; // expected-note 2{{virtual base class declared here}} 69 struct Derived : HasVBase { 70 constexpr Derived(); // expected-error {{constexpr constructor not allowed in struct with virtual base class}} 71 }; 72 template<typename T> struct DerivedFromVBase : T { // expected-note {{struct with virtual base class is not a literal type}} 73 constexpr DerivedFromVBase(); 74 }; 75 constexpr int f(DerivedFromVBase<HasVBase>); // expected-error {{constexpr function's 1st parameter type 'DerivedFromVBase<HasVBase>' is not a literal type}} 76 77 // - it has all non-static data members and base classes of literal types 78 struct NonLitMember { 79 S s; // expected-note {{has data member 's' of non-literal type 'S'}} 80 }; 81 constexpr int f(NonLitMember); // expected-error {{1st parameter type 'NonLitMember' is not a literal type}} 82 struct NonLitBase : 83 S { // expected-note {{base class 'S' of non-literal type}} 84 constexpr NonLitBase(); // expected-error {{non-literal type 'NonLitBase' cannot have constexpr members}} 85 }; 86 struct LitMemBase : Agg { 87 Agg agg; 88 }; 89 template<typename T> 90 struct MemberType { 91 T t; // expected-note {{'MemberType<NonLiteral>' is not literal because it has data member 't' of non-literal type 'NonLiteral'}} 92 constexpr MemberType(); 93 }; 94 constexpr int f(MemberType<int>); 95 constexpr int f(MemberType<NonLiteral>); // expected-error {{not a literal type}} 96 97 // - an array of literal type 98 struct ArrGood { 99 Agg agg[24]; 100 double d[12]; 101 TrivDtor td[3]; 102 }; 103 constexpr int f(ArrGood); 104 105 struct ArrBad { 106 S s[3]; // expected-note {{data member 's' of non-literal type 'S [3]'}} 107 }; 108 constexpr int f(ArrBad); // expected-error {{1st parameter type 'ArrBad' is not a literal type}} 109 110 111 // As a non-conforming tweak to the standard, we do not allow a literal type to 112 // have any mutable data members. 113 namespace MutableMembers { 114 struct MM { 115 mutable int n; // expected-note {{'MM' is not literal because it has a mutable data member}} 116 }; 117 constexpr int f(MM); // expected-error {{not a literal type}} 118 119 // Here's one reason why allowing this would be a disaster... 120 template<int n> struct Id { int k = n; }; 121 int f() { 122 // FIXME: correctly check whether the initializer is a constant expression. 123 constexpr MM m = { 0 }; // desired-error {{must be a constant expression}} 124 ++m.n; 125 return Id<m.n>().k; // expected-error {{not an integral constant expression}} 126 } 127 } 128