1 | // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s |
2 | // RUN: %clang_cc1 -fsyntax-only -verify -std=c++1y %s -DCXX1Y |
3 | |
4 | struct NonLiteral { NonLiteral(); }; |
5 | |
6 | // A type is a literal type if it is: |
7 | |
8 | // [C++1y] - void |
9 | constexpr void f() {} |
10 | #ifndef CXX1Y |
11 | // expected-error@-2 {{'void' is not a literal type}} |
12 | #endif |
13 | |
14 | // - a scalar type |
15 | constexpr int f1(double) { return 0; } |
16 | |
17 | // - a reference type |
18 | struct S { S(); }; |
19 | constexpr int f2(S &) { return 0; } |
20 | |
21 | struct BeingDefined; |
22 | extern BeingDefined beingdefined; |
23 | struct BeingDefined { |
24 | static constexpr BeingDefined& t = beingdefined; |
25 | }; |
26 | |
27 | // - a class type that has all of the following properties: |
28 | |
29 | // (implied) - it is complete |
30 | |
31 | struct Incomplete; // expected-note 2{{forward declaration of 'Incomplete'}} |
32 | template<class T> struct ClassTemp {}; |
33 | |
34 | 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}} |
35 | 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}} |
36 | constexpr ClassTemp<int> classtemplate = {}; |
37 | constexpr ClassTemp<int> classtemplate2[] = {}; |
38 | |
39 | // - it has a trivial destructor |
40 | struct UserProvDtor { |
41 | ~UserProvDtor(); // expected-note {{has a user-provided destructor}} |
42 | }; |
43 | constexpr int f(UserProvDtor) { return 0; } // expected-error {{'UserProvDtor' is not a literal type}} |
44 | struct NonTrivDtor { |
45 | constexpr NonTrivDtor(); |
46 | virtual ~NonTrivDtor() = default; // expected-note {{has a non-trivial destructor}} expected-note {{because it is virtual}} |
47 | }; |
48 | constexpr int f(NonTrivDtor) { return 0; } // expected-error {{'NonTrivDtor' is not a literal type}} |
49 | struct NonTrivDtorBase { |
50 | ~NonTrivDtorBase(); |
51 | }; |
52 | template<typename T> |
53 | struct DerivedFromNonTrivDtor : T { // expected-note {{'DerivedFromNonTrivDtor<NonTrivDtorBase>' is not literal because it has base class 'NonTrivDtorBase' of non-literal type}} |
54 | constexpr DerivedFromNonTrivDtor(); |
55 | }; |
56 | constexpr int f(DerivedFromNonTrivDtor<NonTrivDtorBase>) { return 0; } // expected-error {{constexpr function's 1st parameter type 'DerivedFromNonTrivDtor<NonTrivDtorBase>' is not a literal type}} |
57 | struct TrivDtor { |
58 | constexpr TrivDtor(); |
59 | }; |
60 | constexpr int f(TrivDtor) { return 0; } |
61 | struct TrivDefaultedDtor { |
62 | constexpr TrivDefaultedDtor(); |
63 | ~TrivDefaultedDtor() = default; |
64 | }; |
65 | constexpr int f(TrivDefaultedDtor) { return 0; } |
66 | |
67 | // - it is an aggregate type or has at least one constexpr constructor or |
68 | // constexpr constructor template that is not a copy or move constructor |
69 | struct Agg { |
70 | int a; |
71 | char *b; |
72 | }; |
73 | constexpr int f3(Agg a) { return a.a; } |
74 | struct CtorTemplate { |
75 | template<typename T> constexpr CtorTemplate(T); |
76 | }; |
77 | 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}} |
78 | constexpr CopyCtorOnly(CopyCtorOnly&); |
79 | }; |
80 | constexpr int f(CopyCtorOnly) { return 0; } // expected-error {{'CopyCtorOnly' is not a literal type}} |
81 | struct MoveCtorOnly { // expected-note {{no constexpr constructors other than copy or move constructors}} |
82 | constexpr MoveCtorOnly(MoveCtorOnly&&); |
83 | }; |
84 | constexpr int f(MoveCtorOnly) { return 0; } // expected-error {{'MoveCtorOnly' is not a literal type}} |
85 | template<typename T> |
86 | struct CtorArg { |
87 | constexpr CtorArg(T); |
88 | }; |
89 | constexpr int f(CtorArg<int>) { return 0; } // ok |
90 | constexpr int f(CtorArg<NonLiteral>) { return 0; } // ok, ctor is still constexpr |
91 | // We have a special-case diagnostic for classes with virtual base classes. |
92 | struct VBase {}; |
93 | struct HasVBase : virtual VBase {}; // expected-note 2{{virtual base class declared here}} |
94 | struct Derived : HasVBase { |
95 | constexpr Derived() {} // expected-error {{constexpr constructor not allowed in struct with virtual base class}} |
96 | }; |
97 | template<typename T> struct DerivedFromVBase : T { // expected-note {{struct with virtual base class is not a literal type}} |
98 | constexpr DerivedFromVBase(); |
99 | }; |
100 | constexpr int f(DerivedFromVBase<HasVBase>) {} // expected-error {{constexpr function's 1st parameter type 'DerivedFromVBase<HasVBase>' is not a literal type}} |
101 | template<typename T> constexpr DerivedFromVBase<T>::DerivedFromVBase() : T() {} |
102 | 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}} |
103 | |
104 | // - it has all non-static data members and base classes of literal types |
105 | struct NonLitMember { |
106 | S s; // expected-note {{has data member 's' of non-literal type 'S'}} |
107 | }; |
108 | constexpr int f(NonLitMember) {} // expected-error {{1st parameter type 'NonLitMember' is not a literal type}} |
109 | struct NonLitBase : |
110 | S { // expected-note {{base class 'S' of non-literal type}} |
111 | constexpr NonLitBase(); |
112 | }; |
113 | constexpr int f(NonLitBase) { return 0; } // expected-error {{'NonLitBase' is not a literal type}} |
114 | struct LitMemBase : Agg { |
115 | Agg agg; |
116 | }; |
117 | template<typename T> |
118 | struct MemberType { |
119 | T t; // expected-note {{'MemberType<NonLiteral>' is not literal because it has data member 't' of non-literal type 'NonLiteral'}} |
120 | constexpr MemberType(); |
121 | }; |
122 | constexpr int f(MemberType<int>) { return 0; } |
123 | constexpr int f(MemberType<NonLiteral>) { return 0; } // expected-error {{not a literal type}} |
124 | |
125 | // - an array of literal type [C++1y] other than an array of runtime bound |
126 | struct ArrGood { |
127 | Agg agg[24]; |
128 | double d[12]; |
129 | TrivDtor td[3]; |
130 | TrivDefaultedDtor tdd[3]; |
131 | }; |
132 | constexpr int f(ArrGood) { return 0; } |
133 | |
134 | struct ArrBad { |
135 | S s[3]; // expected-note {{data member 's' of non-literal type 'S [3]'}} |
136 | }; |
137 | constexpr int f(ArrBad) { return 0; } // expected-error {{1st parameter type 'ArrBad' is not a literal type}} |
138 | |
139 | constexpr int arb(int n) { |
140 | int a[n]; // expected-error {{variable of non-literal type 'int [n]' cannot be defined in a constexpr function}} |
141 | } |
142 | constexpr long Overflow[ // expected-error {{constexpr variable cannot have non-literal type 'long const[(1 << 30) << 2]'}} |
143 | (1 << 30) << 2]{}; // expected-warning {{requires 34 bits to represent}} |
144 | |
145 | namespace inherited_ctor { |
146 | struct A { constexpr A(int); }; |
147 | struct B : A { |
148 | B(); |
149 | using A::A; |
150 | }; |
151 | constexpr int f(B) { return 0; } // ok |
152 | |
153 | struct C { constexpr C(int); }; |
154 | struct D : C { // expected-note {{because}} |
155 | D(int); |
156 | using C::C; |
157 | }; |
158 | constexpr int f(D) { return 0; } // expected-error {{not a literal type}} |
159 | |
160 | // This one is a bit odd: F inherits E's default constructor, which is |
161 | // constexpr. Because F has a constructor of its own, it doesn't declare a |
162 | // default constructor hiding E's one. |
163 | struct E {}; |
164 | struct F : E { |
165 | F(int); |
166 | using E::E; |
167 | }; |
168 | constexpr int f(F) { return 0; } |
169 | |
170 | // FIXME: Is this really the right behavior? We presumably should be checking |
171 | // whether the inherited constructor would be a copy or move constructor for |
172 | // the derived class, not for the base class. |
173 | struct G { constexpr G(const G&); }; |
174 | struct H : G { // expected-note {{because}} |
175 | using G::G; |
176 | }; |
177 | constexpr int f(H) { return 0; } // expected-error {{not a literal type}} |
178 | |
179 | struct J; |
180 | struct I { constexpr I(const J&); }; |
181 | struct J : I { |
182 | using I::I; |
183 | }; |
184 | constexpr int f(J) { return 0; } |
185 | } |
186 | |