• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // RUN: %clang_cc1 -verify -std=c++11 -fcxx-exceptions %s
2 
3 namespace N {
4   typedef char C;
5 }
6 
7 namespace M {
8   typedef double D;
9 }
10 
11 struct NonLiteral { // expected-note 2{{no constexpr constructors}}
NonLiteralNonLiteral12   NonLiteral() {}
NonLiteralNonLiteral13   NonLiteral(int) {}
14 };
15 struct Literal {
LiteralLiteral16   constexpr Literal() {}
17   explicit Literal(int); // expected-note 2 {{here}}
operator intLiteral18   operator int() const { return 0; }
19 };
20 
21 // In the definition of a constexpr constructor, each of the parameter types
22 // shall be a literal type.
23 struct S {
SS24   constexpr S(int, N::C) {}
SS25   constexpr S(int, NonLiteral, N::C) {} // expected-error {{constexpr constructor's 2nd parameter type 'NonLiteral' is not a literal type}}
SS26   constexpr S(int, NonLiteral = 42) {} // expected-error {{constexpr constructor's 2nd parameter type 'NonLiteral' is not a literal type}}
27 
28   // In addition, either its function-body shall be = delete or = default
29   constexpr S() = default;
30   constexpr S(Literal) = delete;
31 };
32 
33 // or it shall satisfy the following constraints:
34 
35 // - the class shall not have any virtual base classes;
36 struct T : virtual S { // expected-note {{here}}
TT37   constexpr T() {} // expected-error {{constexpr constructor not allowed in struct with virtual base class}}
38 };
39 namespace IndirectVBase {
40   struct A {};
41   struct B : virtual A {}; // expected-note {{here}}
42   class C : public B {
43   public:
C()44     constexpr C() {} // expected-error {{constexpr constructor not allowed in class with virtual base class}}
45   };
46 }
47 
48 // - its function-body shall not be a function-try-block;
49 struct U {
UU50   constexpr U()
51     try // expected-error {{function try block not allowed in constexpr constructor}}
52     : u() {
53   } catch (...) {
54     throw;
55   }
56   int u;
57 };
58 
59 // - the compound-statememt of its function-body shall contain only
60 struct V {
VV61   constexpr V() {
62     //  - null statements,
63     ;
64 
65     //  - static_assert-declarations,
66     static_assert(true, "the impossible happened!");
67 
68     //  - typedef declarations and alias-declarations that do not define classes
69     //    or enumerations,
70     typedef int I;
71     typedef struct S T;
72     using J = int;
73     using K = int[sizeof(I) + sizeof(J)];
74     // Note, the standard requires we reject this.
75     struct U;
76 
77     //  - using-declarations,
78     using N::C;
79 
80     //  - and using-directives;
81     using namespace N;
82   }
83 
VV84   constexpr V(int(&)[1]) {
85     for (int n = 0; n < 10; ++n) // expected-error {{statement not allowed in constexpr constructor}}
86       /**/;
87   }
VV88   constexpr V(int(&)[2]) {
89     constexpr int a = 0; // expected-error {{variables cannot be declared in a constexpr constructor}}
90   }
VV91   constexpr V(int(&)[3]) {
92     constexpr int ForwardDecl(int); // expected-error {{statement not allowed in constexpr constructor}}
93   }
VV94   constexpr V(int(&)[4]) {
95     typedef struct { } S1; // expected-error {{types cannot be defined in a constexpr constructor}}
96   }
VV97   constexpr V(int(&)[5]) {
98     using S2 = struct { }; // expected-error {{types cannot be defined in a constexpr constructor}}
99   }
VV100   constexpr V(int(&)[6]) {
101     struct S3 { }; // expected-error {{types cannot be defined in a constexpr constructor}}
102   }
VV103   constexpr V(int(&)[7]) {
104     return; // expected-error {{statement not allowed in constexpr constructor}}
105   }
106 };
107 
108 // - every non-static data member and base class sub-object shall be initialized
109 struct W {
110   int n; // expected-note {{member not initialized by constructor}}
WW111   constexpr W() {} // expected-error {{constexpr constructor must initialize all members}}
112 };
113 struct AnonMembers {
114   int a; // expected-note {{member not initialized by constructor}}
115   union { // expected-note 2{{member not initialized by constructor}}
116     char b;
117     struct {
118       double c;
119       long d; // expected-note {{member not initialized by constructor}}
120     };
121     union {
122       char e;
123       void *f;
124     };
125   };
126   struct { // expected-note {{member not initialized by constructor}}
127     long long g;
128     struct {
129       int h; // expected-note {{member not initialized by constructor}}
130       double i; // expected-note {{member not initialized by constructor}}
131     };
132     union { // expected-note 2{{member not initialized by constructor}}
133       char *j;
134       AnonMembers *k;
135     };
136   };
137 
AnonMembersAnonMembers138   constexpr AnonMembers(int(&)[1]) : a(), b(), g(), h(), i(), j() {} // ok
139   // missing d, i, j/k union
AnonMembersAnonMembers140   constexpr AnonMembers(int(&)[2]) : a(), c(), g(), h() {} // expected-error {{constexpr constructor must initialize all members}}
AnonMembersAnonMembers141   constexpr AnonMembers(int(&)[3]) : a(), e(), g(), h(), i(), k() {} // ok
142   // missing h, j/k union
AnonMembersAnonMembers143   constexpr AnonMembers(int(&)[4]) : a(), c(), d(), g(), i() {} // expected-error {{constexpr constructor must initialize all members}}
144   // missing b/c/d/e/f union
AnonMembersAnonMembers145   constexpr AnonMembers(int(&)[5]) : a(), g(), h(), i(), k() {} // expected-error {{constexpr constructor must initialize all members}}
146   // missing a, b/c/d/e/f union, g/h/i/j/k struct
AnonMembersAnonMembers147   constexpr AnonMembers(int(&)[6]) {} // expected-error {{constexpr constructor must initialize all members}}
148 };
149 
150 union Empty {
Empty()151   constexpr Empty() {} // ok
152 } constexpr empty1;
153 
154 struct EmptyVariant {
155   union {};
156   struct {};
EmptyVariantEmptyVariant157   constexpr EmptyVariant() {} // ok
158 } constexpr empty2;
159 
160 template<typename T> using Int = int;
161 template<typename T>
162 struct TemplateInit {
163   T a;
164   int b; // desired-note {{not initialized}}
165   Int<T> c; // desired-note {{not initialized}}
166   struct {
167     T d;
168     int e; // desired-note {{not initialized}}
169     Int<T> f; // desired-note {{not initialized}}
170   };
171   struct {
172     Literal l;
173     Literal m;
174     Literal n[3];
175   };
176   union { // desired-note {{not initialized}}
177     T g;
178     T h;
179   };
180   // FIXME: This is ill-formed (no diagnostic required). We should diagnose it.
TemplateInitTemplateInit181   constexpr TemplateInit() {} // desired-error {{must initialize all members}}
182 };
183 template<typename T> struct TemplateInit2 {
184   Literal l;
TemplateInit2TemplateInit2185   constexpr TemplateInit2() {} // ok
186 };
187 
188 template<typename T> struct weak_ptr {
weak_ptrweak_ptr189   constexpr weak_ptr() : p(0) {}
190   T *p;
191 };
192 template<typename T> struct enable_shared_from_this {
193   weak_ptr<T> weak_this;
enable_shared_from_thisenable_shared_from_this194   constexpr enable_shared_from_this() {} // ok
195 };
196 constexpr int f(enable_shared_from_this<int>);
197 
198 // - every constructor involved in initializing non-static data members and base
199 //   class sub-objects shall be a constexpr constructor.
200 struct ConstexprBaseMemberCtors : Literal {
201   Literal l;
202 
ConstexprBaseMemberCtorsConstexprBaseMemberCtors203   constexpr ConstexprBaseMemberCtors() : Literal(), l() {} // ok
ConstexprBaseMemberCtorsConstexprBaseMemberCtors204   constexpr ConstexprBaseMemberCtors(char) : // expected-error {{constexpr constructor never produces a constant expression}}
205     Literal(0), // expected-note {{non-constexpr constructor}}
206     l() {}
ConstexprBaseMemberCtorsConstexprBaseMemberCtors207   constexpr ConstexprBaseMemberCtors(double) : Literal(), // expected-error {{constexpr constructor never produces a constant expression}}
208     l(0) // expected-note {{non-constexpr constructor}}
209   {}
210 };
211 
212 // - every assignment-expression that is an initializer-caluse appearing
213 //   directly or indirectly within a brace-or-equal-initializer for a non-static
214 //   data member that is not named by a mem-initializer-id shall be a constant
215 //   expression; and
216 //
217 // Note, we deliberately do not implement this bullet, so that we can allow the
218 // following example. (See N3308).
219 struct X {
220   int a = 0;
221   int b = 2 * a + 1; // ok, not a constant expression.
222 
XX223   constexpr X() {}
XX224   constexpr X(int c) : a(c) {} // ok, b initialized by 2 * c + 1
225 };
226 
227 //  - every implicit conversion used in converting a constructor argument to the
228 //    corresponding parameter type and converting a full-expression to the
229 //    corresponding member type shall be one of those allowed in a constant
230 //    expression.
231 //
232 // We implement the proposed resolution of DR1364 and ignore this bullet.
233 // However, we implement the intent of this wording as part of the p5 check that
234 // the function must be able to produce a constant expression.
235 int kGlobal; // expected-note {{here}}
236 struct Z {
ZZ237   constexpr Z(int a) : n(a) {}
ZZ238   constexpr Z() : n(kGlobal) {} // expected-error {{constexpr constructor never produces a constant expression}} expected-note {{read of non-const}}
239   int n;
240 };
241 
242 
243 namespace StdExample {
244   struct Length {
LengthStdExample::Length245     explicit constexpr Length(int i = 0) : val(i) { }
246   private:
247       int val;
248   };
249 }
250