summaryrefslogtreecommitdiff
path: root/test/CXX
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2019-09-04 20:30:37 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2019-09-04 20:30:37 +0000
commit940249d8175d8db209f3e6e4557aaa6f1d99c00f (patch)
tree756c9f3cd9ff717961b6dc1a504894be82e6373d /test/CXX
parent3c6ee3dacaccb1f818db5d8b9a6169d2d116e7aa (diff)
downloadclang-940249d8175d8db209f3e6e4557aaa6f1d99c00f.tar.gz
[c++20] P1143R2: Add support for the C++20 'constinit' keyword.
This is mostly the same as the [[clang::require_constant_initialization]] attribute, but has a couple of additional syntactic and semantic restrictions. In passing, I added a warning for the attribute form being added after we have already seen the initialization of the variable (but before we see the definition); that case previously slipped between the cracks and the attribute was silently ignored. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@370972 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CXX')
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.constinit/p1.cpp55
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.constinit/p2.cpp8
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.constinit/p3.cpp6
3 files changed, 69 insertions, 0 deletions
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constinit/p1.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constinit/p1.cpp
new file mode 100644
index 0000000000..170c8c7be0
--- /dev/null
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constinit/p1.cpp
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 -std=c++2a -verify %s
+
+constinit int a;
+constinit thread_local int b;
+constinit static int c;
+
+void f() {
+ constinit static int a;
+ constinit thread_local int b;
+ constinit int c; // expected-error {{local variable cannot be declared 'constinit'}}
+}
+
+namespace missing {
+ int a; // expected-note {{add the 'constinit' specifier}}
+ extern constinit int a; // expected-error {{added after initialization}}
+
+ // We allow inheriting 'constinit' from a forward declaration as an extension.
+ extern constinit int b; // expected-note {{here}}
+ int b; // expected-warning {{'constinit' specifier missing}}
+}
+
+struct S {
+ static constinit int a; // expected-note {{here}}
+ static constinit constexpr int b; // expected-error {{cannot combine with previous}} expected-note {{here}}
+ static constinit const int c = 1;
+ static constinit const int d = 1;
+};
+int S::a; // expected-warning {{'constinit' specifier missing}}
+int S::b; // expected-warning {{'constinit' specifier missing}}
+const int S::c;
+inline const int S::d;
+
+struct T {
+ static int a;
+ static constexpr int b = 1; // expected-note {{add the 'constinit' specifier}}
+ static const int c = 1; // expected-note {{add the 'constinit' specifier}}
+ static const int d = 1; // expected-note {{add the 'constinit' specifier}}
+};
+constinit int T::a;
+constinit const int T::b; // expected-error {{'constinit' specifier added after initialization}}
+constinit const int T::c; // expected-error {{'constinit' specifier added after initialization}}
+constinit inline const int T::d; // expected-error {{'constinit' specifier added after initialization}}
+
+constinit void g() {} // expected-error {{constinit can only be used in variable declarations}}
+
+// (These used to trigger crashes.)
+void h();
+constinit void h(); // expected-error {{constinit can only be used in variable declarations}}
+constexpr void i(); // expected-note {{here}}
+constinit void i(); // expected-error {{non-constexpr declaration of 'i' follows constexpr declaration}}
+// expected-error@-1 {{constinit can only be used in variable declarations}}
+
+typedef constinit int type; // expected-error {{typedef cannot be constinit}}
+using type = constinit int; // expected-error {{type name does not allow constinit specifier}}
+auto q() -> int constinit; // expected-error {{type name does not allow constinit specifier}}
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constinit/p2.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constinit/p2.cpp
new file mode 100644
index 0000000000..22ac7a191b
--- /dev/null
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constinit/p2.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -std=c++2a -verify %s
+
+int f(); // expected-note 2{{declared here}}
+
+constinit int a;
+constinit int b = f(); // expected-error {{does not have a constant initializer}} expected-note {{required by}} expected-note {{non-constexpr function 'f'}}
+extern constinit int c; // expected-note {{here}} expected-note {{required by}}
+int c = f(); // expected-warning {{missing}} expected-error {{does not have a constant initializer}} expected-note {{non-constexpr function 'f'}}
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constinit/p3.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constinit/p3.cpp
new file mode 100644
index 0000000000..0baea03e4b
--- /dev/null
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constinit/p3.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -std=c++2a -verify %s
+
+const char *g() { return "dynamic initialization"; } // expected-note {{declared here}}
+constexpr const char *f(bool b) { return b ? "constant initialization" : g(); } // expected-note {{non-constexpr function 'g'}}
+constinit const char *c = f(true);
+constinit const char *d = f(false); // expected-error {{does not have a constant initializer}} expected-note 2{{}}