diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-09-04 20:30:37 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-09-04 20:30:37 +0000 |
commit | 940249d8175d8db209f3e6e4557aaa6f1d99c00f (patch) | |
tree | 756c9f3cd9ff717961b6dc1a504894be82e6373d /test/CXX | |
parent | 3c6ee3dacaccb1f818db5d8b9a6169d2d116e7aa (diff) | |
download | clang-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.cpp | 55 | ||||
-rw-r--r-- | test/CXX/dcl.dcl/dcl.spec/dcl.constinit/p2.cpp | 8 | ||||
-rw-r--r-- | test/CXX/dcl.dcl/dcl.spec/dcl.constinit/p3.cpp | 6 |
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{{}} |