• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // RUN: %clang_cc1 -verify -std=c++11 -fcxx-exceptions -Werror=c++1y-extensions %s
2 // RUN: %clang_cc1 -verify -std=c++1y -fcxx-exceptions -DCXX1Y %s
3 
4 namespace N {
5   typedef char C;
6 }
7 
8 namespace M {
9   typedef double D;
10 }
11 
12 struct NonLiteral { // expected-note 2{{no constexpr constructors}}
NonLiteralNonLiteral13   NonLiteral() {}
NonLiteralNonLiteral14   NonLiteral(int) {}
15 };
16 struct Literal {
LiteralLiteral17   constexpr Literal() {}
18   explicit Literal(int); // expected-note 2 {{here}}
operator intLiteral19   operator int() const { return 0; }
20 };
21 
22 // In the definition of a constexpr constructor, each of the parameter types
23 // shall be a literal type.
24 struct S {
SS25   constexpr S(int, N::C) {}
SS26   constexpr S(int, NonLiteral, N::C) {} // expected-error {{constexpr constructor's 2nd parameter type 'NonLiteral' is not a literal type}}
SS27   constexpr S(int, NonLiteral = 42) {} // expected-error {{constexpr constructor's 2nd parameter type 'NonLiteral' is not a literal type}}
28 
29   // In addition, either its function-body shall be = delete or = default
30   constexpr S() = default;
31   constexpr S(Literal) = delete;
32 };
33 
34 // or it shall satisfy the following constraints:
35 
36 // - the class shall not have any virtual base classes;
37 struct T : virtual S { // expected-note {{here}}
TT38   constexpr T() {} // expected-error {{constexpr constructor not allowed in struct with virtual base class}}
39 };
40 namespace IndirectVBase {
41   struct A {};
42   struct B : virtual A {}; // expected-note {{here}}
43   class C : public B {
44   public:
C()45     constexpr C() {} // expected-error {{constexpr constructor not allowed in class with virtual base class}}
46   };
47 }
48 
49 // - its function-body shall not be a function-try-block;
50 struct U {
UU51   constexpr U()
52     try // expected-error {{function try block not allowed in constexpr constructor}}
53     : u() {
54   } catch (...) {
55     throw;
56   }
57   int u;
58 };
59 
60 // - the compound-statememt of its function-body shall contain only
61 struct V {
VV62   constexpr V() {
63     //  - null statements,
64     ;
65 
66     //  - static_assert-declarations,
67     static_assert(true, "the impossible happened!");
68 
69     //  - typedef declarations and alias-declarations that do not define classes
70     //    or enumerations,
71     typedef int I;
72     typedef struct S T;
73     using J = int;
74     using K = int[sizeof(I) + sizeof(J)];
75     // Note, the standard requires we reject this.
76     struct U;
77 
78     //  - using-declarations,
79     using N::C;
80 
81     //  - and using-directives;
82     using namespace N;
83   }
84 
VV85   constexpr V(int(&)[1]) {
86     for (int n = 0; n < 10; ++n)
87       /**/;
88 #ifndef CXX1Y
89     // expected-error@-3 {{statement not allowed in constexpr constructor}}
90 #endif
91   }
VV92   constexpr V(int(&)[2]) {
93     constexpr int a = 0;
94 #ifndef CXX1Y
95     // expected-error@-2 {{variable declaration in a constexpr constructor is a C++14 extension}}
96 #endif
97   }
VV98   constexpr V(int(&)[3]) {
99     constexpr int ForwardDecl(int);
100 #ifndef CXX1Y
101     // expected-error@-2 {{use of this statement in a constexpr constructor is a C++14 extension}}
102 #endif
103   }
VV104   constexpr V(int(&)[4]) {
105     typedef struct { } S1;
106 #ifndef CXX1Y
107     // expected-error@-2 {{type definition in a constexpr constructor is a C++14 extension}}
108 #endif
109   }
VV110   constexpr V(int(&)[5]) {
111     using S2 = struct { };
112 #ifndef CXX1Y
113     // expected-error@-2 {{type definition in a constexpr constructor is a C++14 extension}}
114 #endif
115   }
VV116   constexpr V(int(&)[6]) {
117     struct S3 { };
118 #ifndef CXX1Y
119     // expected-error@-2 {{type definition in a constexpr constructor is a C++14 extension}}
120 #endif
121   }
VV122   constexpr V(int(&)[7]) {
123     return;
124 #ifndef CXX1Y
125     // expected-error@-2 {{use of this statement in a constexpr constructor is a C++14 extension}}
126 #endif
127   }
128 };
129 
130 // - every non-static data member and base class sub-object shall be initialized
131 struct W {
132   int n; // expected-note {{member not initialized by constructor}}
WW133   constexpr W() {} // expected-error {{constexpr constructor must initialize all members}}
134 };
135 struct AnonMembers {
136   int a; // expected-note {{member not initialized by constructor}}
137   union { // expected-note 2{{member not initialized by constructor}}
138     char b;
139     struct {
140       double c;
141       long d; // expected-note {{member not initialized by constructor}}
142     };
143     union {
144       char e;
145       void *f;
146     };
147   };
148   struct { // expected-note {{member not initialized by constructor}}
149     long long g;
150     struct {
151       int h; // expected-note {{member not initialized by constructor}}
152       double i; // expected-note {{member not initialized by constructor}}
153     };
154     union { // expected-note 2{{member not initialized by constructor}}
155       char *j;
156       AnonMembers *k;
157     };
158   };
159 
AnonMembersAnonMembers160   constexpr AnonMembers(int(&)[1]) : a(), b(), g(), h(), i(), j() {} // ok
161   // missing d, i, j/k union
AnonMembersAnonMembers162   constexpr AnonMembers(int(&)[2]) : a(), c(), g(), h() {} // expected-error {{constexpr constructor must initialize all members}}
AnonMembersAnonMembers163   constexpr AnonMembers(int(&)[3]) : a(), e(), g(), h(), i(), k() {} // ok
164   // missing h, j/k union
AnonMembersAnonMembers165   constexpr AnonMembers(int(&)[4]) : a(), c(), d(), g(), i() {} // expected-error {{constexpr constructor must initialize all members}}
166   // missing b/c/d/e/f union
AnonMembersAnonMembers167   constexpr AnonMembers(int(&)[5]) : a(), g(), h(), i(), k() {} // expected-error {{constexpr constructor must initialize all members}}
168   // missing a, b/c/d/e/f union, g/h/i/j/k struct
AnonMembersAnonMembers169   constexpr AnonMembers(int(&)[6]) {} // expected-error {{constexpr constructor must initialize all members}}
170 };
171 
172 union Empty {
Empty()173   constexpr Empty() {} // ok
174 } constexpr empty1;
175 
176 struct EmptyVariant {
177   union {};
178   struct {};
EmptyVariantEmptyVariant179   constexpr EmptyVariant() {} // ok
180 } constexpr empty2;
181 
182 template<typename T> using Int = int;
183 template<typename T>
184 struct TemplateInit {
185   T a;
186   int b; // desired-note {{not initialized}}
187   Int<T> c; // desired-note {{not initialized}}
188   struct {
189     T d;
190     int e; // desired-note {{not initialized}}
191     Int<T> f; // desired-note {{not initialized}}
192   };
193   struct {
194     Literal l;
195     Literal m;
196     Literal n[3];
197   };
198   union { // desired-note {{not initialized}}
199     T g;
200     T h;
201   };
202   // FIXME: This is ill-formed (no diagnostic required). We should diagnose it.
TemplateInitTemplateInit203   constexpr TemplateInit() {} // desired-error {{must initialize all members}}
204 };
205 template<typename T> struct TemplateInit2 {
206   Literal l;
TemplateInit2TemplateInit2207   constexpr TemplateInit2() {} // ok
208 };
209 
210 template<typename T> struct weak_ptr {
weak_ptrweak_ptr211   constexpr weak_ptr() : p(0) {}
212   T *p;
213 };
214 template<typename T> struct enable_shared_from_this {
215   weak_ptr<T> weak_this;
enable_shared_from_thisenable_shared_from_this216   constexpr enable_shared_from_this() {} // ok
217 };
218 constexpr int f(enable_shared_from_this<int>);
219 
220 // - every constructor involved in initializing non-static data members and base
221 //   class sub-objects shall be a constexpr constructor.
222 struct ConstexprBaseMemberCtors : Literal {
223   Literal l;
224 
ConstexprBaseMemberCtorsConstexprBaseMemberCtors225   constexpr ConstexprBaseMemberCtors() : Literal(), l() {} // ok
ConstexprBaseMemberCtorsConstexprBaseMemberCtors226   constexpr ConstexprBaseMemberCtors(char) : // expected-error {{constexpr constructor never produces a constant expression}}
227     Literal(0), // expected-note {{non-constexpr constructor}}
228     l() {}
ConstexprBaseMemberCtorsConstexprBaseMemberCtors229   constexpr ConstexprBaseMemberCtors(double) : Literal(), // expected-error {{constexpr constructor never produces a constant expression}}
230     l(0) // expected-note {{non-constexpr constructor}}
231   {}
232 };
233 
234 // - every assignment-expression that is an initializer-clause appearing
235 //   directly or indirectly within a brace-or-equal-initializer for a non-static
236 //   data member that is not named by a mem-initializer-id shall be a constant
237 //   expression; and
238 //
239 // Note, we deliberately do not implement this bullet, so that we can allow the
240 // following example. (See N3308).
241 struct X {
242   int a = 0;
243   int b = 2 * a + 1; // ok, not a constant expression.
244 
XX245   constexpr X() {}
XX246   constexpr X(int c) : a(c) {} // ok, b initialized by 2 * c + 1
247 };
248 
249 union XU1 { int a; constexpr XU1() = default; }; // expected-error{{not constexpr}}
250 union XU2 { int a = 1; constexpr XU2() = default; };
251 
252 struct XU3 {
253   union {
254     int a;
255   };
256   constexpr XU3() = default; // expected-error{{not constexpr}}
257 };
258 struct XU4 {
259   union {
260     int a = 1;
261   };
262   constexpr XU4() = default;
263 };
264 
265 static_assert(XU2().a == 1, "");
266 static_assert(XU4().a == 1, "");
267 
268 //  - every implicit conversion used in converting a constructor argument to the
269 //    corresponding parameter type and converting a full-expression to the
270 //    corresponding member type shall be one of those allowed in a constant
271 //    expression.
272 //
273 // We implement the proposed resolution of DR1364 and ignore this bullet.
274 // However, we implement the intent of this wording as part of the p5 check that
275 // the function must be able to produce a constant expression.
276 int kGlobal; // expected-note {{here}}
277 struct Z {
ZZ278   constexpr Z(int a) : n(a) {}
ZZ279   constexpr Z() : n(kGlobal) {} // expected-error {{constexpr constructor never produces a constant expression}} expected-note {{read of non-const}}
280   int n;
281 };
282 
283 
284 namespace StdExample {
285   struct Length {
LengthStdExample::Length286     explicit constexpr Length(int i = 0) : val(i) { }
287   private:
288       int val;
289   };
290 }
291 
292 namespace CtorLookup {
293   // Ensure that we look up which constructor will actually be used.
294   struct A {
ACtorLookup::A295     constexpr A(const A&) {}
ACtorLookup::A296     A(A&) {}
297     constexpr A(int = 0);
298   };
299 
300   struct B : A {
301     B() = default;
302     constexpr B(const B&);
303     constexpr B(B&);
304   };
305   constexpr B::B(const B&) = default;
306   constexpr B::B(B&) = default; // expected-error {{not constexpr}}
307 
308   struct C {
309     A a;
310     C() = default;
311     constexpr C(const C&);
312     constexpr C(C&);
313   };
314   constexpr C::C(const C&) = default;
315   constexpr C::C(C&) = default; // expected-error {{not constexpr}}
316 }
317 
318 namespace PR14503 {
319   template<typename> struct V {
320     union {
321       int n;
322       struct {
323         int x,
324             y;
325       };
326     };
VPR14503::V327     constexpr V() : x(0) {}
328   };
329 
330   // The constructor is still 'constexpr' here, but the result is not intended
331   // to be a constant expression. The standard is not clear on how this should
332   // work.
333   constexpr V<int> v; // expected-error {{constant expression}} expected-note {{subobject of type 'int' is not initialized}}
334 
335   constexpr int k = V<int>().x; // FIXME: ok?
336 }
337