Clang Project

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