p10.cpp revision 8ef7b203332b0c8d65876a1f5e6d1db4e6f40e4b
1// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s 2 3struct NonLiteral { NonLiteral(); }; 4 5// A type is a literal type if it is: 6 7// - a scalar type 8constexpr int f1(double); 9 10// - a reference type 11struct S { S(); }; 12constexpr int f2(S &); 13 14// - a class type that has all of the following properties: 15 16// - it has a trivial destructor 17struct 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 22struct NonTrivDtor { 23 constexpr NonTrivDtor(); // expected-error {{non-literal type 'NonTrivDtor' cannot have constexpr members}} 24 virtual ~NonTrivDtor() = default; // expected-note {{has a non-trivial destructor}} 25}; 26struct NonTrivDtorBase { 27 ~NonTrivDtorBase(); 28}; 29template<typename T> 30struct DerivedFromNonTrivDtor : T { // expected-note {{'DerivedFromNonTrivDtor<NonTrivDtorBase>' is not literal because it has base class 'NonTrivDtorBase' of non-literal type}} 31 constexpr DerivedFromNonTrivDtor(); 32}; 33constexpr int f(DerivedFromNonTrivDtor<NonTrivDtorBase>); // expected-error {{constexpr function's 1st parameter type 'DerivedFromNonTrivDtor<NonTrivDtorBase>' is not a literal type}} 34struct TrivDtor { 35 constexpr TrivDtor(); 36}; 37constexpr int f(TrivDtor); 38struct TrivDefaultedDtor { 39 constexpr TrivDefaultedDtor(); 40 ~TrivDefaultedDtor() = default; 41}; 42constexpr int f(TrivDefaultedDtor); 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 46struct Agg { 47 int a; 48 char *b; 49}; 50constexpr int f3(Agg a) { return a.a; } 51struct CtorTemplate { 52 template<typename T> constexpr CtorTemplate(T); 53}; 54struct 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}; 57struct 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}; 60template<typename T> 61struct 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}; 64constexpr int f(CtorArg<int>); 65constexpr int f(CtorArg<NonLiteral>); // expected-error {{not a literal type}} 66// We have a special-case diagnostic for classes with virtual base classes. 67struct VBase {}; 68struct HasVBase : virtual VBase {}; // expected-note 2{{virtual base class declared here}} 69struct Derived : HasVBase { 70 constexpr Derived(); // expected-error {{constexpr constructor not allowed in struct with virtual base class}} 71}; 72template<typename T> struct DerivedFromVBase : T { // expected-note {{struct with virtual base class is not a literal type}} 73 constexpr DerivedFromVBase(); 74}; 75constexpr 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 78struct NonLitMember { 79 S s; // expected-note {{has data member 's' of non-literal type 'S'}} 80}; 81constexpr int f(NonLitMember); // expected-error {{1st parameter type 'NonLitMember' is not a literal type}} 82struct 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}; 86struct LitMemBase : Agg { 87 Agg agg; 88}; 89template<typename T> 90struct 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}; 94constexpr int f(MemberType<int>); 95constexpr int f(MemberType<NonLiteral>); // expected-error {{not a literal type}} 96 97// - an array of literal type 98struct ArrGood { 99 Agg agg[24]; 100 double d[12]; 101 TrivDtor td[3]; 102 TrivDefaultedDtor tdd[3]; 103}; 104constexpr int f(ArrGood); 105 106struct ArrBad { 107 S s[3]; // expected-note {{data member 's' of non-literal type 'S [3]'}} 108}; 109constexpr int f(ArrBad); // expected-error {{1st parameter type 'ArrBad' is not a literal type}} 110 111 112// As a non-conforming tweak to the standard, we do not allow a literal type to 113// have any mutable data members. 114namespace MutableMembers { 115 struct MM { 116 mutable int n; // expected-note {{'MM' is not literal because it has a mutable data member}} 117 }; 118 constexpr int f(MM); // expected-error {{not a literal type}} 119 120 // Here's one reason why allowing this would be a disaster... 121 template<int n> struct Id { int k = n; }; 122 int f() { 123 constexpr MM m = { 0 }; // expected-error {{must be initialized by a constant expression}} expected-note {{non-literal type 'const MutableMembers::MM' cannot be used in a constant expression}} expected-note {{here}} 124 ++m.n; 125 return Id<m.n>().k; // expected-error {{not a constant expression}} expected-note {{initializer of 'm' is not a constant expression}} 126 } 127} 128