aboutsummaryrefslogtreecommitdiff
path: root/test/CXX/special/class.inhctor/p2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/CXX/special/class.inhctor/p2.cpp')
-rw-r--r--test/CXX/special/class.inhctor/p2.cpp87
1 files changed, 87 insertions, 0 deletions
diff --git a/test/CXX/special/class.inhctor/p2.cpp b/test/CXX/special/class.inhctor/p2.cpp
new file mode 100644
index 000000000000..e4267385ced8
--- /dev/null
+++ b/test/CXX/special/class.inhctor/p2.cpp
@@ -0,0 +1,87 @@
+// RUN: %clang_cc1 -std=c++11 -verify %s
+
+template<int> struct X {};
+
+// Constructor characteristics are:
+// - the template parameter list [FIXME]
+// - the parameter-type-list
+// - absence or presence of explicit
+// - absence or presence of constexpr
+struct A {
+ A(X<0>) {} // expected-note 2{{here}}
+ constexpr A(X<1>) {}
+ explicit A(X<2>) {} // expected-note 3{{here}}
+ explicit constexpr A(X<3>) {} // expected-note 2{{here}}
+};
+
+A a0 { X<0>{} };
+A a0i = { X<0>{} };
+constexpr A a0c { X<0>{} }; // expected-error {{must be initialized by a constant expression}} expected-note {{non-constexpr}}
+constexpr A a0ic = { X<0>{} }; // expected-error {{must be initialized by a constant expression}} expected-note {{non-constexpr}}
+
+A a1 { X<1>{} };
+A a1i = { X<1>{} };
+constexpr A a1c { X<1>{} };
+constexpr A a1ic = { X<1>{} };
+
+A a2 { X<2>{} };
+A a2i = { X<2>{} }; // expected-error {{constructor is explicit}}
+constexpr A a2c { X<2>{} }; // expected-error {{must be initialized by a constant expression}} expected-note {{non-constexpr}}
+constexpr A a2ic = { X<2>{} }; // expected-error {{constructor is explicit}}
+
+A a3 { X<3>{} };
+A a3i = { X<3>{} }; // expected-error {{constructor is explicit}}
+constexpr A a3c { X<3>{} };
+constexpr A a3ic = { X<3>{} }; // expected-error {{constructor is explicit}}
+
+
+struct B : A {
+ using A::A; // expected-note 7{{here}}
+};
+
+B b0 { X<0>{} };
+B b0i = { X<0>{} };
+constexpr B b0c { X<0>{} }; // expected-error {{must be initialized by a constant expression}} expected-note {{non-constexpr}}
+constexpr B b0ic = { X<0>{} }; // expected-error {{must be initialized by a constant expression}} expected-note {{non-constexpr}}
+
+B b1 { X<1>{} };
+B b1i = { X<1>{} };
+constexpr B b1c { X<1>{} };
+constexpr B b1ic = { X<1>{} };
+
+B b2 { X<2>{} };
+B b2i = { X<2>{} }; // expected-error {{constructor is explicit}}
+constexpr B b2c { X<2>{} }; // expected-error {{must be initialized by a constant expression}} expected-note {{non-constexpr}}
+constexpr B b2ic = { X<2>{} }; // expected-error {{constructor is explicit}}
+
+B b3 { X<3>{} };
+B b3i = { X<3>{} }; // expected-error {{constructor is explicit}}
+constexpr B b3c { X<3>{} };
+constexpr B b3ic = { X<3>{} }; // expected-error {{constructor is explicit}}
+
+
+// 'constexpr' is OK even if the constructor doesn't obey the constraints.
+struct NonLiteral { NonLiteral(); };
+struct NonConstexpr { NonConstexpr(); constexpr NonConstexpr(int); }; // expected-note {{here}}
+struct Constexpr { constexpr Constexpr(int) {} };
+
+struct BothNonLiteral : NonLiteral, Constexpr { using Constexpr::Constexpr; }; // expected-note {{base class 'NonLiteral' of non-literal type}}
+constexpr BothNonLiteral bothNL{42}; // expected-error {{constexpr variable cannot have non-literal type 'const BothNonLiteral'}}
+
+struct BothNonConstexpr : NonConstexpr, Constexpr { using Constexpr::Constexpr; }; // expected-note {{non-constexpr constructor 'NonConstexpr}}
+constexpr BothNonConstexpr bothNC{42}; // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'BothNonConstexpr(42)'}}
+
+
+struct ConstexprEval {
+ constexpr ConstexprEval(int a, const char *p) : k(p[a]) {}
+ char k;
+};
+struct ConstexprEval2 {
+ char k2 = 'x';
+};
+struct ConstexprEval3 : ConstexprEval, ConstexprEval2 {
+ using ConstexprEval::ConstexprEval;
+};
+constexpr ConstexprEval3 ce{4, "foobar"};
+static_assert(ce.k == 'a', "");
+static_assert(ce.k2 == 'x', "");