367 lines · cpp
1// RUN: %clang_cc1 -verify -std=c++11 -fcxx-exceptions -Werror=c++14-extensions -Werror=c++20-extensions %s2// RUN: %clang_cc1 -verify -std=c++14 -fcxx-exceptions -DCXX14 -Werror=c++20-extensions %s3// RUN: %clang_cc1 -verify -std=c++20 -fcxx-exceptions -DCXX14 -DCXX2A %s4 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 types24// 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 = default31 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 try54#ifndef CXX2A55 // expected-error@-2 {{function try block in constexpr constructor is a C++20 extension}}56#endif57 : u() {58#ifndef CXX1459 // expected-error@-2 {{use of this statement in a constexpr constructor is a C++14 extension}}60#endif61 } catch (...) {62 throw;63 }64 int u;65};66 67// - the compound-statememt of its function-body shall contain only68struct 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 classes77 // 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 CXX1496 // expected-error@-3 {{statement not allowed in constexpr constructor}}97#endif98 }99 constexpr V(int(&)[2]) {100 constexpr int a = 0;101#ifndef CXX14102 // expected-error@-2 {{variable declaration in a constexpr constructor is a C++14 extension}}103#endif104 }105 constexpr V(int(&)[3]) {106 constexpr int ForwardDecl(int);107#ifndef CXX14108 // expected-error@-2 {{use of this statement in a constexpr constructor is a C++14 extension}}109#endif110 }111 constexpr V(int(&)[4]) {112 typedef struct { } S1;113#ifndef CXX14114 // expected-error@-2 {{type definition in a constexpr constructor is a C++14 extension}}115#endif116 }117 constexpr V(int(&)[5]) {118 using S2 = struct { };119#ifndef CXX14120 // expected-error@-2 {{type definition in a constexpr constructor is a C++14 extension}}121#endif122 }123 constexpr V(int(&)[6]) {124 struct S3 { };125#ifndef CXX14126 // expected-error@-2 {{type definition in a constexpr constructor is a C++14 extension}}127#endif128 }129 constexpr V(int(&)[7]) {130 return;131#ifndef CXX14132 // expected-error@-2 {{use of this statement in a constexpr constructor is a C++14 extension}}133#endif134 }135};136 137// - every non-static data member and base class sub-object shall be initialized138struct W {139 int n;140 constexpr W() {}141#ifndef CXX2A142 // expected-error@-2 {{constexpr constructor that does not initialize all members}}143 // expected-note@-4 {{member not initialized by constructor}}144#endif145};146struct AnonMembers {147 int a; // expected-note 0-1{{member not initialized by constructor}}148 union { // expected-note 0-2{{member not initialized by constructor}}149 char b;150 struct {151 double c;152 long d; // expected-note 0-1{{member not initialized by constructor}}153 };154 union {155 char e;156 void *f;157 };158 };159 struct { // expected-note 0-1{{member not initialized by constructor}}160 long long g;161 struct {162 int h; // expected-note 0-1{{member not initialized by constructor}}163 double i; // expected-note 0-1{{member not initialized by constructor}}164 };165 union { // expected-note 0-2{{member not initialized by constructor}}166 char *j;167 AnonMembers *k;168 };169 };170 171 constexpr AnonMembers(int(&)[1]) : a(), b(), g(), h(), i(), j() {} // ok172 // missing d, i, j/k union173 constexpr AnonMembers(int(&)[2]) : a(), c(), g(), h() {}174#ifndef CXX2A175 // expected-error@-2 {{constexpr constructor that does not initialize all members}}176#endif177 constexpr AnonMembers(int(&)[3]) : a(), e(), g(), h(), i(), k() {} // ok178 // missing h, j/k union179 constexpr AnonMembers(int(&)[4]) : a(), c(), d(), g(), i() {}180#ifndef CXX2A181 // expected-error@-2 {{constexpr constructor that does not initialize all members}}182#endif183 // missing b/c/d/e/f union184 constexpr AnonMembers(int(&)[5]) : a(), g(), h(), i(), k() {}185#ifndef CXX2A186 // expected-error@-2 {{constexpr constructor that does not initialize all members}}187#endif188 // missing a, b/c/d/e/f union, g/h/i/j/k struct189 constexpr AnonMembers(int(&)[6]) {}190#ifndef CXX2A191 // expected-error@-2 {{constexpr constructor that does not initialize all members}}192#endif193};194 195union Empty {196 constexpr Empty() {} // ok197} constexpr empty1;198 199struct EmptyVariant {200 union {}; // expected-warning {{does not declare anything}}201 struct {}; // expected-warning {{does not declare anything}}202 constexpr EmptyVariant() {} // ok203} constexpr empty2;204 205template<typename T> using Int = int;206template<typename T>207struct TemplateInit {208 T a;209 int b; // desired-note {{not initialized}}210 Int<T> c; // desired-note {{not initialized}}211 struct {212 T d;213 int e; // desired-note {{not initialized}}214 Int<T> f; // desired-note {{not initialized}}215 };216 struct {217 Literal l;218 Literal m;219 Literal n[3];220 };221 union { // desired-note {{not initialized}}222 T g;223 T h;224 };225 // FIXME: This is ill-formed (no diagnostic required). We should diagnose it.226 constexpr TemplateInit() {} // desired-error {{must initialize all members}}227};228template<typename T> struct TemplateInit2 {229 Literal l;230 constexpr TemplateInit2() {} // ok231};232 233template<typename T> struct weak_ptr {234 constexpr weak_ptr() : p(0) {}235 T *p;236};237template<typename T> struct enable_shared_from_this {238 weak_ptr<T> weak_this;239 constexpr enable_shared_from_this() {} // ok240};241constexpr int f(enable_shared_from_this<int>);242 243// - every constructor involved in initializing non-static data members and base244// class sub-objects shall be a constexpr constructor.245// This will no longer be the case once we support P2448R2246struct ConstexprBaseMemberCtors : Literal {247 Literal l;248 249 constexpr ConstexprBaseMemberCtors() : Literal(), l() {} // ok250 constexpr ConstexprBaseMemberCtors(char) : // expected-error {{constexpr constructor never produces a constant expression}}251 Literal(0), // expected-note {{non-constexpr constructor}}252 l() {}253 constexpr ConstexprBaseMemberCtors(double) : Literal(), // expected-error {{constexpr constructor never produces a constant expression}}254 l(0) // expected-note {{non-constexpr constructor}}255 {}256};257 258// - every assignment-expression that is an initializer-clause appearing259// directly or indirectly within a brace-or-equal-initializer for a non-static260// data member that is not named by a mem-initializer-id shall be a constant261// expression; and262//263// Note, we deliberately do not implement this bullet, so that we can allow the264// following example. (See N3308).265struct X {266 int a = 0;267 int b = 2 * a + 1; // ok, not a constant expression.268 269 constexpr X() {}270 constexpr X(int c) : a(c) {} // ok, b initialized by 2 * c + 1271};272 273union XU1 { int a; constexpr XU1() = default; };274#ifndef CXX2A275// expected-error@-2{{cannot be marked constexpr}}276#endif277union XU2 { int a = 1; constexpr XU2() = default; };278 279struct XU3 {280 union {281 int a;282 };283 constexpr XU3() = default;284#ifndef CXX2A285 // expected-error@-2{{cannot be marked constexpr}}286#endif287};288struct XU4 {289 union {290 int a = 1;291 };292 constexpr XU4() = default;293};294 295static_assert(XU2().a == 1, "");296static_assert(XU4().a == 1, "");297 298// - every implicit conversion used in converting a constructor argument to the299// corresponding parameter type and converting a full-expression to the300// corresponding member type shall be one of those allowed in a constant301// expression.302//303// We implement the proposed resolution of DR1364 and ignore this bullet.304// However, we implement the intent of this wording as part of the p5 check that305// the function must be able to produce a constant expression.306int kGlobal; // expected-note {{here}}307struct Z {308 constexpr Z(int a) : n(a) {}309 constexpr Z() : n(kGlobal) {} // expected-error {{constexpr constructor never produces a constant expression}} expected-note {{read of non-const}}310 int n;311};312 313 314namespace StdExample {315 struct Length {316 explicit constexpr Length(int i = 0) : val(i) { }317 private:318 int val;319 };320}321 322namespace CtorLookup {323 // Ensure that we look up which constructor will actually be used.324 struct A {325 constexpr A(const A&) {}326 A(A&) {}327 constexpr A(int = 0);328 };329 330 struct B : A {331 B() = default;332 constexpr B(const B&);333 constexpr B(B&);334 };335 constexpr B::B(const B&) = default;336 constexpr B::B(B&) = default; // expected-error {{cannot be marked constexpr}}337 338 struct C {339 A a;340 C() = default;341 constexpr C(const C&);342 constexpr C(C&);343 };344 constexpr C::C(const C&) = default;345 constexpr C::C(C&) = default; // expected-error {{cannot be marked constexpr}}346}347 348namespace PR14503 {349 template<typename> struct V {350 union {351 int n;352 struct {353 int x,354 y; // expected-note {{subobject declared here}}355 };356 };357 constexpr V() : x(0) {}358 };359 360 // The constructor is still 'constexpr' here, but the result is not intended361 // to be a constant expression. The standard is not clear on how this should362 // work.363 constexpr V<int> v; // expected-error {{constant expression}} expected-note {{subobject 'y' is not initialized}}364 365 constexpr int k = V<int>().x; // FIXME: ok?366}367