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 | a6e8b685e13492abfb2e58dc49007deda165a00d (patch) | |
| tree | 279bbf503976a5c882db2f0699a858d10e66a5e9 /clang/test | |
| parent | eca01b031d44da54239d9956ba0acc7cf2f7798b (diff) | |
| download | bcm5719-llvm-a6e8b685e13492abfb2e58dc49007deda165a00d.tar.gz bcm5719-llvm-a6e8b685e13492abfb2e58dc49007deda165a00d.zip | |
[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.
llvm-svn: 370972
Diffstat (limited to 'clang/test')
| -rw-r--r-- | clang/test/CXX/dcl.dcl/dcl.spec/dcl.constinit/p1.cpp | 55 | ||||
| -rw-r--r-- | clang/test/CXX/dcl.dcl/dcl.spec/dcl.constinit/p2.cpp | 8 | ||||
| -rw-r--r-- | clang/test/CXX/dcl.dcl/dcl.spec/dcl.constinit/p3.cpp | 6 | ||||
| -rw-r--r-- | clang/test/FixIt/fixit-c++2a.cpp | 38 | ||||
| -rw-r--r-- | clang/test/Lexer/cxx-features.cpp | 4 | ||||
| -rw-r--r-- | clang/test/Lexer/cxx2a_keyword_as_cxx17.cpp | 2 | ||||
| -rw-r--r-- | clang/test/Misc/pragma-attribute-cxx.cpp | 4 | ||||
| -rw-r--r-- | clang/test/Misc/pragma-attribute-supported-attributes-list.test | 2 | ||||
| -rw-r--r-- | clang/test/Parser/cxx0x-decl.cpp | 19 | ||||
| -rw-r--r-- | clang/test/SemaCXX/attr-require-constant-initialization.cpp | 11 |
10 files changed, 140 insertions, 9 deletions
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constinit/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constinit/p1.cpp new file mode 100644 index 00000000000..170c8c7be0c --- /dev/null +++ b/clang/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/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constinit/p2.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constinit/p2.cpp new file mode 100644 index 00000000000..22ac7a191bd --- /dev/null +++ b/clang/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/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constinit/p3.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constinit/p3.cpp new file mode 100644 index 00000000000..0baea03e4b5 --- /dev/null +++ b/clang/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{{}} diff --git a/clang/test/FixIt/fixit-c++2a.cpp b/clang/test/FixIt/fixit-c++2a.cpp index c97bb7ae610..6fe05dabf07 100644 --- a/clang/test/FixIt/fixit-c++2a.cpp +++ b/clang/test/FixIt/fixit-c++2a.cpp @@ -1,7 +1,8 @@ -// RUN: %clang_cc1 -verify -std=c++2a %s +// RUN: %clang_cc1 -verify -std=c++2a -pedantic-errors %s // RUN: cp %s %t // RUN: not %clang_cc1 -x c++ -std=c++2a -fixit %t -// RUN: %clang_cc1 -Wall -pedantic -x c++ -std=c++2a %t +// RUN: %clang_cc1 -Wall -pedantic-errors -x c++ -std=c++2a %t +// RUN: cat %t | FileCheck %s /* This is a test of the various code modification hints that only apply in C++2a. */ @@ -13,3 +14,36 @@ template<typename ...T> void init_capture_pack(T ...a) { [&...a]{}; // expected-error {{must appear after the name}} [...&a]{}; // expected-error {{must appear after the name}} } + +namespace constinit_mismatch { + extern thread_local constinit int a; // expected-note {{declared constinit here}} + thread_local int a = 123; // expected-error {{'constinit' specifier missing on initializing declaration of 'a'}} + // CHECK: {{^}} constinit thread_local int a = 123; + + int b = 123; // expected-note {{add the 'constinit' specifier}} + extern constinit int b; // expected-error {{'constinit' specifier added after initialization of variable}} + // CHECK: {{^}} extern int b; + + template<typename> struct X { + template<int> static constinit int n; // expected-note {{constinit}} + }; + template<typename T> template<int N> + int X<T>::n = 123; // expected-error {{missing}} + // CHECK: {{^}} constinit int X<T>::n = 123; + +#define ABSL_CONST_INIT [[clang::require_constant_initialization]] + extern constinit int c; // expected-note {{constinit}} + int c; // expected-error {{missing}} + // CHECK: {{^}} ABSL_CONST_INIT int c; + +#define MY_CONST_INIT constinit + extern constinit int d; // expected-note {{constinit}} + int d; // expected-error {{missing}} + // CHECK: {{^}} MY_CONST_INIT int d; +#undef MY_CONST_INIT + + extern constinit int e; // expected-note {{constinit}} + int e; // expected-error {{missing}} + // CHECK: {{^}} ABSL_CONST_INIT int e; +#undef ABSL_CONST_INIT +} diff --git a/clang/test/Lexer/cxx-features.cpp b/clang/test/Lexer/cxx-features.cpp index a8ef6291f4c..cda6f888cbc 100644 --- a/clang/test/Lexer/cxx-features.cpp +++ b/clang/test/Lexer/cxx-features.cpp @@ -34,6 +34,10 @@ #error "wrong value for __cpp_char8_t" #endif +#if check(constinit, 0, 0, 0, 0, 201907) +#error "wrong value for __cpp_constinit" +#endif + #if check(impl_destroying_delete, 201806, 201806, 201806, 201806, 201806) #error "wrong value for __cpp_impl_destroying_delete" #endif diff --git a/clang/test/Lexer/cxx2a_keyword_as_cxx17.cpp b/clang/test/Lexer/cxx2a_keyword_as_cxx17.cpp index d2ed7d33803..a2e86931e9c 100644 --- a/clang/test/Lexer/cxx2a_keyword_as_cxx17.cpp +++ b/clang/test/Lexer/cxx2a_keyword_as_cxx17.cpp @@ -11,3 +11,5 @@ int co_yield = 0; // expected-warning {{'co_yield' is a keyword in C++2a}} int char8_t = 0; // expected-warning {{'char8_t' is a keyword in C++2a}} int concept = 0; // expected-warning {{'concept' is a keyword in C++2a}} int requires = 0; // expected-warning {{'requires' is a keyword in C++2a}} +int consteval = 0; // expected-warning {{'consteval' is a keyword in C++2a}} +int constinit = 0; // expected-warning {{'constinit' is a keyword in C++2a}} diff --git a/clang/test/Misc/pragma-attribute-cxx.cpp b/clang/test/Misc/pragma-attribute-cxx.cpp index a8a3bdebc65..38b025e4769 100644 --- a/clang/test/Misc/pragma-attribute-cxx.cpp +++ b/clang/test/Misc/pragma-attribute-cxx.cpp @@ -87,14 +87,14 @@ void testLambdaMethod() { int testCI1 = 1; // CHECK-LABEL: VarDecl{{.*}} testCI1 // CHECK-NEXT: IntegerLiteral -// CHECK-NEXT: RequireConstantInitAttr +// CHECK-NEXT: ConstInitAttr #pragma clang attribute pop int testNoCI = 0; // CHECK-LABEL: VarDecl{{.*}} testNoCI // CHECK-NEXT: IntegerLiteral -// CHECK-NOT: RequireConstantInitAttr +// CHECK-NOT: ConstInitAttr // Check support for CXX11 style attributes #pragma clang attribute push ([[noreturn]], apply_to = function) diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 83b8b9f0b9f..311ba1a857b 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -38,6 +38,7 @@ // CHECK-NEXT: CarriesDependency (SubjectMatchRule_variable_is_parameter, SubjectMatchRule_objc_method, SubjectMatchRule_function) // CHECK-NEXT: Cold (SubjectMatchRule_function) // CHECK-NEXT: Common (SubjectMatchRule_variable) +// CHECK-NEXT: ConstInit (SubjectMatchRule_variable_is_global) // CHECK-NEXT: Constructor (SubjectMatchRule_function) // CHECK-NEXT: Consumable (SubjectMatchRule_record) // CHECK-NEXT: ConsumableAutoCast (SubjectMatchRule_record) @@ -124,7 +125,6 @@ // CHECK-NEXT: Pointer (SubjectMatchRule_record_not_is_union) // CHECK-NEXT: RenderScriptKernel (SubjectMatchRule_function) // CHECK-NEXT: ReqdWorkGroupSize (SubjectMatchRule_function) -// CHECK-NEXT: RequireConstantInit (SubjectMatchRule_variable_is_global) // CHECK-NEXT: Restrict (SubjectMatchRule_function) // CHECK-NEXT: ReturnTypestate (SubjectMatchRule_function, SubjectMatchRule_variable_is_parameter) // CHECK-NEXT: ReturnsNonNull (SubjectMatchRule_objc_method, SubjectMatchRule_function) diff --git a/clang/test/Parser/cxx0x-decl.cpp b/clang/test/Parser/cxx0x-decl.cpp index 7bd82e8220b..2f219ac87fb 100644 --- a/clang/test/Parser/cxx0x-decl.cpp +++ b/clang/test/Parser/cxx0x-decl.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -verify -fsyntax-only -std=c++11 -pedantic-errors -triple x86_64-linux-gnu %s +// RUN: %clang_cc1 -verify -fsyntax-only -std=c++2a -pedantic-errors -triple x86_64-linux-gnu %s // Make sure we know these are legitimate commas and not typos for ';'. namespace Commas { @@ -108,14 +108,25 @@ namespace UsingDeclAttrs { } namespace DuplicateSpecifier { - constexpr constexpr int f(); // expected-warning {{duplicate 'constexpr' declaration specifier}} - constexpr int constexpr a = 0; // expected-warning {{duplicate 'constexpr' declaration specifier}} + constexpr constexpr int f(); // expected-error {{duplicate 'constexpr' declaration specifier}} + constexpr int constexpr a = 0; // expected-error {{duplicate 'constexpr' declaration specifier}} struct A { friend constexpr int constexpr friend f(); // expected-warning {{duplicate 'friend' declaration specifier}} \ - // expected-warning {{duplicate 'constexpr' declaration specifier}} + // expected-error {{duplicate 'constexpr' declaration specifier}} friend struct A friend; // expected-warning {{duplicate 'friend'}} expected-error {{'friend' must appear first}} }; + + constinit constexpr int n1 = 0; // expected-error {{cannot combine with previous 'constinit'}} + constexpr constinit int n2 = 0; // expected-error {{cannot combine with previous 'constexpr'}} + constinit constinit int n3 = 0; // expected-error {{duplicate 'constinit' declaration specifier}} + + consteval constexpr int f1(); // expected-error {{cannot combine with previous 'consteval'}} + constexpr consteval int f2(); // expected-error {{cannot combine with previous 'constexpr'}} + consteval consteval int f3(); // expected-error {{duplicate 'consteval' declaration specifier}} + + constinit consteval int wat = 0; // expected-error {{cannot combine with previous 'constinit'}} + consteval constinit int huh(); // expected-error {{cannot combine with previous 'consteval'}} } namespace ColonColonDecltype { diff --git a/clang/test/SemaCXX/attr-require-constant-initialization.cpp b/clang/test/SemaCXX/attr-require-constant-initialization.cpp index 2dd72ea6dba..12bae81fd2a 100644 --- a/clang/test/SemaCXX/attr-require-constant-initialization.cpp +++ b/clang/test/SemaCXX/attr-require-constant-initialization.cpp @@ -300,6 +300,17 @@ ATTR TestCtor<NotC> t(42); // expected-error {{variable does not have a constant ATTR const char *foo[] = {"abc", "def"}; ATTR PODType bar[] = {{}, {123, 456}}; + +namespace AttrAddedTooLate { + struct A { + static const int n = 0; // expected-note {{here}} + }; + ATTR const int A::n; // expected-warning {{added after initialization}} + + int m = 0; // expected-note {{here}} + extern ATTR int m; // expected-warning {{added after initialization}} +} + #elif defined(TEST_TWO) // Test for duplicate warnings struct NotC { constexpr NotC(void *) {} |

