rsandifo-arm updated this revision to Diff 524846.
rsandifo-arm marked an inline comment as done.
rsandifo-arm added a comment.
Update onto current main. Only change is to replace C++2b with C++23.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D148702/new/
https://reviews.llvm.org/D148702
Files:
clang/examples/Attribute/Attribute.cpp
clang/examples/CallSuperAttribute/CallSuperAttrInfo.cpp
clang/include/clang/Basic/DiagnosticCommonKinds.td
clang/include/clang/Basic/DiagnosticParseKinds.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Parse/Parser.h
clang/include/clang/Sema/DeclSpec.h
clang/lib/Parse/ParseDecl.cpp
clang/lib/Parse/ParseDeclCXX.cpp
clang/lib/Parse/ParseExprCXX.cpp
clang/lib/Parse/ParsePragma.cpp
clang/lib/Parse/ParseStmt.cpp
clang/lib/Parse/ParseTentative.cpp
clang/lib/Parse/Parser.cpp
clang/lib/Sema/ParsedAttr.cpp
clang/lib/Sema/Sema.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaDeclAttr.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/lib/Sema/SemaStmtAttr.cpp
clang/lib/Sema/SemaType.cpp
clang/test/Parser/c2x-attribute-keywords.c
clang/test/Parser/c2x-attribute-keywords.m
clang/test/Parser/cxx0x-keyword-attributes.cpp
clang/utils/TableGen/ClangAttrEmitter.cpp
Index: clang/utils/TableGen/ClangAttrEmitter.cpp
===================================================================
--- clang/utils/TableGen/ClangAttrEmitter.cpp
+++ clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -3879,7 +3879,8 @@
OS << "bool diagAppertainsToDecl(Sema &S, const ParsedAttr &AL, ";
OS << "const Decl *D) const override {\n";
OS << " S.Diag(AL.getLoc(), diag::err_attribute_invalid_on_decl)\n";
- OS << " << AL << D->getLocation();\n";
+ OS << " << AL << AL.isRegularKeywordAttribute() << "
+ "D->getLocation();\n";
OS << " return false;\n";
OS << "}\n\n";
}
@@ -3908,7 +3909,7 @@
OS << (Warn ? "warn_attribute_wrong_decl_type_str"
: "err_attribute_wrong_decl_type_str");
OS << ")\n";
- OS << " << Attr << ";
+ OS << " << Attr << Attr.isRegularKeywordAttribute() << ";
OS << CalculateDiagnostic(*SubjectObj) << ";\n";
OS << " return false;\n";
OS << " }\n";
@@ -3923,7 +3924,8 @@
OS << "bool diagAppertainsToStmt(Sema &S, const ParsedAttr &AL, ";
OS << "const Stmt *St) const override {\n";
OS << " S.Diag(AL.getLoc(), diag::err_decl_attribute_invalid_on_stmt)\n";
- OS << " << AL << St->getBeginLoc();\n";
+ OS << " << AL << AL.isRegularKeywordAttribute() << "
+ "St->getBeginLoc();\n";
OS << " return false;\n";
OS << "}\n\n";
}
@@ -3942,7 +3944,7 @@
OS << (Warn ? "warn_attribute_wrong_decl_type_str"
: "err_attribute_wrong_decl_type_str");
OS << ")\n";
- OS << " << Attr << ";
+ OS << " << Attr << Attr.isRegularKeywordAttribute() << ";
OS << CalculateDiagnostic(*SubjectObj) << ";\n";
OS << " return false;\n";
OS << " }\n";
@@ -4013,7 +4015,8 @@
for (const std::string &A : DeclAttrs) {
OS << " if (const auto *A = D->getAttr<" << A << ">()) {\n";
OS << " S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)"
- << " << AL << A;\n";
+ << " << AL << A << (AL.isRegularKeywordAttribute() ||"
+ << " A->isRegularKeywordAttribute());\n";
OS << " S.Diag(A->getLocation(), diag::note_conflicting_attribute);";
OS << " \nreturn false;\n";
OS << " }\n";
@@ -4034,7 +4037,8 @@
<< ">()) {\n";
MergeDeclOS << " S.Diag(First->getLocation(), "
<< "diag::err_attributes_are_not_compatible) << First << "
- << "Second;\n";
+ << "Second << (First->isRegularKeywordAttribute() || "
+ << "Second->isRegularKeywordAttribute());\n";
MergeDeclOS << " S.Diag(Second->getLocation(), "
<< "diag::note_conflicting_attribute);\n";
MergeDeclOS << " return false;\n";
@@ -4074,7 +4078,8 @@
MergeStmtOS << " if (Iter != C.end()) {\n";
MergeStmtOS << " S.Diag((*Iter)->getLocation(), "
<< "diag::err_attributes_are_not_compatible) << *Iter << "
- << "Second;\n";
+ << "Second << ((*Iter)->isRegularKeywordAttribute() || "
+ << "Second->isRegularKeywordAttribute());\n";
MergeStmtOS << " S.Diag(Second->getLocation(), "
<< "diag::note_conflicting_attribute);\n";
MergeStmtOS << " return false;\n";
Index: clang/test/Parser/cxx0x-keyword-attributes.cpp
===================================================================
--- /dev/null
+++ clang/test/Parser/cxx0x-keyword-attributes.cpp
@@ -0,0 +1,345 @@
+// RUN: %clang_cc1 -fcxx-exceptions -fdeclspec -fexceptions -fsyntax-only -verify -std=c++11 -Wc++14-compat -Wc++14-extensions -Wc++17-extensions -triple aarch64-none-linux-gnu %s
+
+// Need std::initializer_list
+namespace std {
+ typedef decltype(sizeof(int)) size_t;
+
+ // libc++'s implementation
+ template <class _E>
+ class initializer_list
+ {
+ const _E* __begin_;
+ size_t __size_;
+
+ initializer_list(const _E* __b, size_t __s)
+ : __begin_(__b),
+ __size_(__s)
+ {}
+
+ public:
+ typedef _E value_type;
+ typedef const _E& reference;
+ typedef const _E& const_reference;
+ typedef size_t size_type;
+
+ typedef const _E* iterator;
+ typedef const _E* const_iterator;
+
+ initializer_list() : __begin_(nullptr), __size_(0) {}
+
+ size_t size() const {return __size_;}
+ const _E* begin() const {return __begin_;}
+ const _E* end() const {return __begin_ + __size_;}
+ };
+}
+
+
+// Declaration syntax checks
+__arm_streaming int before_attr; // expected-error {{'__arm_streaming' only applies to function types}}
+int __arm_streaming between_attr; // expected-error {{'__arm_streaming' only applies to function types}}
+const __arm_streaming int between_attr_2 = 0; // expected-error {{'__arm_streaming' cannot appear here}}
+int after_attr __arm_streaming; // expected-error {{'__arm_streaming' only applies to function types}}
+int * __arm_streaming ptr_attr; // expected-error {{'__arm_streaming' only applies to function types}}
+int & __arm_streaming ref_attr = after_attr; // expected-error {{'__arm_streaming' only applies to function types}}
+int && __arm_streaming rref_attr = 0; // expected-error {{'__arm_streaming' only applies to function types}}
+int array_attr [1] __arm_streaming; // expected-error {{'__arm_streaming' only applies to function types}}
+void fn_attr () __arm_streaming;
+void noexcept_fn_attr () noexcept __arm_streaming;
+struct MemberFnOrder {
+ virtual void f() const volatile && noexcept __arm_streaming final = 0;
+};
+struct __arm_streaming struct_attr; // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+class __arm_streaming class_attr {}; // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+union __arm_streaming union_attr; // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+enum __arm_streaming E { }; // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+namespace test_misplacement {
+__arm_streaming struct struct_attr2; // expected-error {{misplaced '__arm_streaming'}}
+__arm_streaming class class_attr2; // expected-error {{misplaced '__arm_streaming'}}
+__arm_streaming union union_attr2; // expected-error {{misplaced '__arm_streaming'}}
+__arm_streaming enum E2 { }; // expected-error {{misplaced '__arm_streaming'}}
+}
+
+// Checks attributes placed at wrong syntactic locations of class specifiers.
+class __arm_streaming __arm_streaming // expected-error 2 {{'__arm_streaming' cannot be applied to a declaration}}
+ attr_after_class_name_decl __arm_streaming __arm_streaming; // expected-error {{'__arm_streaming' cannot appear here}} \
+ expected-error 2 {{'__arm_streaming' cannot be applied to a declaration}}
+
+class __arm_streaming __arm_streaming // expected-error 2 {{'__arm_streaming' cannot be applied to a declaration}}
+ attr_after_class_name_definition __arm_streaming __arm_streaming __arm_streaming{}; // expected-error {{'__arm_streaming' cannot appear here}} \
+ expected-error 3 {{'__arm_streaming' cannot be applied to a declaration}}
+
+class __arm_streaming c {}; // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+class c __arm_streaming __arm_streaming x; // expected-error 2 {{'__arm_streaming' only applies to function types}}
+class c __arm_streaming __arm_streaming y __arm_streaming __arm_streaming; // expected-error 4 {{'__arm_streaming' only applies to function types}}
+class c final [(int){0}];
+
+class base {};
+class __arm_streaming __arm_streaming final_class // expected-error 2 {{'__arm_streaming' cannot be applied to a declaration}}
+ __arm_streaming alignas(float) final // expected-error {{'__arm_streaming' cannot appear here}} \
+ expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+ __arm_streaming alignas(float) __arm_streaming alignas(float): base{}; // expected-error {{'__arm_streaming' cannot appear here}}
+
+class __arm_streaming __arm_streaming final_class_another // expected-error 2 {{'__arm_streaming' cannot be applied to a declaration}}
+ __arm_streaming __arm_streaming alignas(16) final // expected-error {{'__arm_streaming' cannot appear here}} \
+ expected-error 2 {{'__arm_streaming' cannot be applied to a declaration}}
+ __arm_streaming __arm_streaming alignas(16) __arm_streaming{}; // expected-error {{'__arm_streaming' cannot appear here}}
+
+class after_class_close {} __arm_streaming; // expected-error {{'__arm_streaming' cannot appear here, place it after "class" to apply it to the type declaration}}
+
+class C {};
+
+__arm_streaming struct with_init_declarators {} init_declarator; // expected-error {{'__arm_streaming' only applies to function types}}
+__arm_streaming struct no_init_declarators; // expected-error {{misplaced '__arm_streaming'}}
+template<typename> __arm_streaming struct no_init_declarators_template; // expected-error {{'__arm_streaming' cannot appear here}}
+void fn_with_structs() {
+ __arm_streaming struct with_init_declarators {} init_declarator; // expected-error {{'__arm_streaming' only applies to function types}}
+ __arm_streaming struct no_init_declarators; // expected-error {{'__arm_streaming' cannot appear here}}
+}
+__arm_streaming; // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+struct ctordtor {
+ __arm_streaming ctordtor __arm_streaming () __arm_streaming; // expected-error 2 {{'__arm_streaming' cannot be applied to a declaration}}
+ ctordtor (C) __arm_streaming;
+ __arm_streaming ~ctordtor __arm_streaming () __arm_streaming; // expected-error 2 {{'__arm_streaming' cannot be applied to a declaration}}
+};
+__arm_streaming ctordtor::ctordtor __arm_streaming () __arm_streaming {} // expected-error 2 {{'__arm_streaming' cannot be applied to a declaration}}
+__arm_streaming ctordtor::ctordtor (C) __arm_streaming try {} catch (...) {} // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+__arm_streaming ctordtor::~ctordtor __arm_streaming () __arm_streaming {} // expected-error 2 {{'__arm_streaming' cannot be applied to a declaration}}
+extern "C++" __arm_streaming int extern_attr; // expected-error {{'__arm_streaming' only applies to function types}}
+template <typename T> __arm_streaming void template_attr (); // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+__arm_streaming __arm_streaming int __arm_streaming __arm_streaming multi_attr __arm_streaming __arm_streaming; // expected-error 6 {{'__arm_streaming' only applies to function types}}
+
+int (paren_attr) __arm_streaming; // expected-error {{'__arm_streaming' cannot appear here}}
+unsigned __arm_streaming int attr_in_decl_spec; // expected-error {{'__arm_streaming' cannot appear here}}
+unsigned __arm_streaming int __arm_streaming const double_decl_spec = 0; // expected-error 2 {{'__arm_streaming' cannot appear here}}
+class foo {
+ void const_after_attr () __arm_streaming const; // expected-error {{expected ';'}}
+};
+extern "C++" __arm_streaming { } // expected-error {{'__arm_streaming' cannot appear here}}
+__arm_streaming extern "C++" { } // expected-error {{'__arm_streaming' cannot appear here}}
+__arm_streaming template <typename T> void before_template_attr (); // expected-error {{'__arm_streaming' cannot appear here}}
+__arm_streaming namespace ns { int i; } // expected-error {{'__arm_streaming' cannot appear here}}
+__arm_streaming static_assert(true, ""); //expected-error {{'__arm_streaming' cannot appear here}}
+__arm_streaming asm(""); // expected-error {{'__arm_streaming' cannot appear here}}
+
+__arm_streaming using ns::i; // expected-warning {{ISO C++}} \
+ expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+__arm_streaming using namespace ns; // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+namespace __arm_streaming ns2 {} // expected-warning {{attributes on a namespace declaration are a C++17 extension}} \
+ expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+
+using __arm_streaming alignas(4)__arm_streaming ns::i; // expected-warning 2 {{ISO C++}} \
+ expected-error {{'__arm_streaming' cannot appear here}} \
+ expected-error {{'alignas' attribute only applies to variables, data members and tag types}} \
+ expected-warning {{ISO C++}} \
+ expected-error 2 {{'__arm_streaming' cannot be applied to a declaration}}
+using __arm_streaming alignas(4) __arm_streaming foobar = int; // expected-error {{'__arm_streaming' cannot appear here}} \
+ expected-error {{'alignas' attribute only applies to}} \
+ expected-error 2 {{'__arm_streaming' only applies to function types}}
+
+__arm_streaming using T = int; // expected-error {{'__arm_streaming' cannot appear here}}
+using T __arm_streaming = int; // expected-error {{'__arm_streaming' only applies to function types}}
+template<typename T> using U __arm_streaming = T; // expected-error {{'__arm_streaming' only applies to function types}}
+using ns::i __arm_streaming; // expected-warning {{ISO C++}} \
+ expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+using ns::i __arm_streaming, ns::i __arm_streaming; // expected-warning 2 {{ISO C++}} \
+ expected-warning {{use of multiple declarators in a single using declaration is a C++17 extension}} \
+ expected-error 2 {{'__arm_streaming' cannot be applied to a declaration}}
+struct using_in_struct_base {
+ typedef int i, j, k, l;
+};
+struct using_in_struct : using_in_struct_base {
+ __arm_streaming using using_in_struct_base::i; // expected-warning {{ISO C++}} \
+ expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+ using using_in_struct_base::j __arm_streaming; // expected-warning {{ISO C++}} \
+ expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+ __arm_streaming using using_in_struct_base::k __arm_streaming, using_in_struct_base::l __arm_streaming; // expected-warning 3 {{ISO C++}} \
+ expected-warning {{use of multiple declarators in a single using declaration is a C++17 extension}} \
+ expected-error 4 {{'__arm_streaming' cannot be applied to a declaration}}
+};
+using __arm_streaming ns::i; // expected-warning {{ISO C++}} \
+ expected-error {{'__arm_streaming' cannot appear here}} \
+ expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+using T __arm_streaming = int; // expected-error {{'__arm_streaming' only applies to function types}}
+
+auto trailing() -> __arm_streaming const int; // expected-error {{'__arm_streaming' cannot appear here}}
+auto trailing() -> const __arm_streaming int; // expected-error {{'__arm_streaming' cannot appear here}}
+auto trailing() -> const int __arm_streaming; // expected-error {{'__arm_streaming' only applies to function types}}
+auto trailing_2() -> struct struct_attr __arm_streaming; // expected-error {{'__arm_streaming' only applies to function types}}
+
+namespace N {
+ struct S {};
+};
+template<typename> struct Template {};
+
+// FIXME: Improve this diagnostic
+struct __arm_streaming N::S s; // expected-error {{'__arm_streaming' cannot appear here}}
+struct __arm_streaming Template<int> t; // expected-error {{'__arm_streaming' cannot appear here}}
+struct __arm_streaming ::template Template<int> u; // expected-error {{'__arm_streaming' cannot appear here}}
+template struct __arm_streaming Template<char>; // expected-error {{'__arm_streaming' cannot appear here}}
+template struct __attribute__((pure)) Template<std::size_t>; // We still allow GNU-style attributes here
+template <> struct __arm_streaming Template<void>; // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+
+enum __arm_streaming E1 {}; // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+enum __arm_streaming E2; // expected-error {{forbids forward references}} \
+ expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+enum __arm_streaming E1; // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+enum __arm_streaming E3 : int; // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+enum __arm_streaming { // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+ k_123 __arm_streaming = 123 // expected-warning {{attributes on an enumerator declaration are a C++17 extension}} \
+ expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+};
+enum __arm_streaming E1 e; // expected-error {{'__arm_streaming' cannot appear here}}
+enum __arm_streaming class E4 { }; // expected-error {{'__arm_streaming' cannot appear here}}
+enum struct __arm_streaming E5; // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+enum E6 {} __arm_streaming; // expected-error {{'__arm_streaming' cannot appear here, place it after "enum" to apply it to the type declaration}}
+
+struct S {
+ friend int f __arm_streaming (); // expected-error {{'__arm_streaming' cannot appear here}} \
+ expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+ friend int f2 __arm_streaming () {} // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+ __arm_streaming friend int g(); // expected-error {{'__arm_streaming' cannot appear here}}
+ __arm_streaming friend int h() { // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+ }
+ __arm_streaming friend int f3(), f4(), f5(); // expected-error {{'__arm_streaming' cannot appear here}}
+ friend int f6 __arm_streaming (), f7 __arm_streaming (), f8 __arm_streaming (); // expected-error3 {{'__arm_streaming' cannot appear here}} \
+ expected-error 3 {{'__arm_streaming' cannot be applied to a declaration}}
+ friend class __arm_streaming C; // expected-error {{'__arm_streaming' cannot appear here}}
+ __arm_streaming friend class D; // expected-error {{'__arm_streaming' cannot appear here}}
+ __arm_streaming friend int; // expected-error {{'__arm_streaming' cannot appear here}}
+};
+template<typename T> void tmpl (T) {}
+template __arm_streaming void tmpl(char); // expected-error {{'__arm_streaming' cannot appear here}}
+template void __arm_streaming tmpl(short); // expected-error {{'__arm_streaming' only applies to function types}}
+
+// Statement tests
+void foo () {
+ __arm_streaming ; // expected-error {{'__arm_streaming' cannot be applied to a statement}}
+ __arm_streaming { } // expected-error {{'__arm_streaming' cannot be applied to a statement}}
+ __arm_streaming if (0) { } // expected-error {{'__arm_streaming' cannot be applied to a statement}}
+ __arm_streaming for (;;); // expected-error {{'__arm_streaming' cannot be applied to a statement}}
+ __arm_streaming do { // expected-error {{'__arm_streaming' cannot be applied to a statement}}
+ __arm_streaming continue; // expected-error {{'__arm_streaming' cannot be applied to a statement}}
+ } while (0);
+ __arm_streaming while (0); // expected-error {{'__arm_streaming' cannot be applied to a statement}}
+
+ __arm_streaming switch (i) { // expected-error {{'__arm_streaming' cannot be applied to a statement}}
+ __arm_streaming case 0: // expected-error {{'__arm_streaming' cannot be applied to a statement}}
+ __arm_streaming default: // expected-error {{'__arm_streaming' cannot be applied to a statement}}
+ __arm_streaming break; // expected-error {{'__arm_streaming' cannot be applied to a statement}}
+ }
+
+ __arm_streaming goto there; // expected-error {{'__arm_streaming' cannot be applied to a statement}}
+ __arm_streaming there: // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+
+ __arm_streaming try { // expected-error {{'__arm_streaming' cannot be applied to a statement}}
+ } __arm_streaming catch (...) { // expected-error {{'__arm_streaming' cannot appear here}}
+ }
+
+ void bar __arm_streaming (__arm_streaming int i, __arm_streaming int j); // expected-error 2 {{'__arm_streaming' only applies to function types}} \
+ expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+ using FuncType = void (__arm_streaming int); // expected-error {{'__arm_streaming' only applies to function types}}
+ void baz(__arm_streaming...); // expected-error {{expected parameter declarator}}
+
+ __arm_streaming return; // expected-error {{'__arm_streaming' cannot be applied to a statement}}
+}
+
+// Expression tests
+void bar () {
+ new int[42]__arm_streaming[5]__arm_streaming{}; // expected-error {{'__arm_streaming' only applies to function types}}
+}
+
+// Condition tests
+void baz () {
+ if (__arm_streaming bool b = true) { // expected-error {{'__arm_streaming' only applies to function types}}
+ switch (__arm_streaming int n { 42 }) { // expected-error {{'__arm_streaming' only applies to function types}}
+ default:
+ for (__arm_streaming int n = 0; __arm_streaming char b = n < 5; ++b) { // expected-error 2 {{'__arm_streaming' only applies to function types}}
+ }
+ }
+ }
+ int x;
+ // An attribute can be applied to an expression-statement, such as the first
+ // statement in a for. But it can't be applied to a condition which is an
+ // expression.
+ for (__arm_streaming x = 0; ; ) {} // expected-error {{'__arm_streaming' cannot appear here}}
+ for (; __arm_streaming x < 5; ) {} // expected-error {{'__arm_streaming' cannot appear here}}
+ while (__arm_streaming bool k { false }) { // expected-error {{'__arm_streaming' only applies to function types}}
+ }
+ while (__arm_streaming true) { // expected-error {{'__arm_streaming' cannot appear here}}
+ }
+ do {
+ } while (__arm_streaming false); // expected-error {{'__arm_streaming' cannot appear here}}
+
+ for (__arm_streaming int n : { 1, 2, 3 }) { // expected-error {{'__arm_streaming' only applies to function types}}
+ }
+}
+
+enum class __attribute__((visibility("hidden"))) SecretKeepers {
+ one, /* rest are deprecated */ two, three
+};
+enum class __arm_streaming EvenMoreSecrets {}; // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+
+// Forbid attributes on decl specifiers.
+unsigned __arm_streaming static int __arm_streaming v1; // expected-error {{'__arm_streaming' only applies to function types}} \
+ expected-error {{'__arm_streaming' cannot appear here}}
+typedef __arm_streaming unsigned long __arm_streaming v2; // expected-error {{'__arm_streaming' only applies to function types}} \
+ expected-error {{'__arm_streaming' cannot appear here}}
+int __arm_streaming foo(int __arm_streaming x); // expected-error 2 {{'__arm_streaming' only applies to function types}}
+
+__arm_streaming; // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+
+class A {
+ A(__arm_streaming int a); // expected-error {{'__arm_streaming' only applies to function types}}
+};
+A::A(__arm_streaming int a) {} // expected-error {{'__arm_streaming' only applies to function types}}
+
+template<typename T> struct TemplateStruct {};
+class FriendClassesWithAttributes {
+ // We allow GNU-style attributes here
+ template <class _Tp, class _Alloc> friend class __attribute__((__type_visibility__("default"))) vector;
+ template <class _Tp, class _Alloc> friend class __declspec(code_seg("foo,whatever")) vector2;
+ // But not C++11 ones
+ template <class _Tp, class _Alloc> friend class __arm_streaming vector3; // expected-error {{'__arm_streaming' cannot appear here}}
+
+ // Also allowed
+ friend struct __attribute__((__type_visibility__("default"))) TemplateStruct<FriendClassesWithAttributes>;
+ friend struct __declspec(code_seg("foo,whatever")) TemplateStruct<FriendClassesWithAttributes>;
+ friend struct __arm_streaming TemplateStruct<FriendClassesWithAttributes>; // expected-error {{'__arm_streaming' cannot appear here}}
+};
+
+// Check ordering: C++11 attributes must appear before GNU attributes.
+class Ordering {
+ void f1(
+ int (__arm_streaming __attribute__(()) int n) // expected-error {{'__arm_streaming' only applies to function types}}
+ ) {
+ }
+
+ void f2(
+ int (*)(__arm_streaming __attribute__(()) int n) // expected-error {{'__arm_streaming' only applies to function types}}
+ ) {
+ }
+
+ void f3(
+ int (__attribute__(()) __arm_streaming int n) // expected-error {{'__arm_streaming' cannot appear here}}
+ ) {
+ }
+
+ void f4(
+ int (*)(__attribute__(()) __arm_streaming int n) // expected-error {{'__arm_streaming' cannot appear here}}
+ ) {
+ }
+};
+
+namespace base_specs {
+struct A {};
+struct B : __arm_streaming A {}; // expected-error {{'__arm_streaming' cannot be applied to a base specifier}}
+struct C : __arm_streaming virtual A {}; // expected-error {{'__arm_streaming' cannot be applied to a base specifier}}
+struct D : __arm_streaming public virtual A {}; // expected-error {{'__arm_streaming' cannot be applied to a base specifier}}
+struct E : public __arm_streaming virtual A {}; // expected-error {{'__arm_streaming' cannot appear here}} \
+ expected-error {{'__arm_streaming' cannot be applied to a base specifier}}
+struct F : virtual __arm_streaming public A {}; // expected-error {{'__arm_streaming' cannot appear here}} \
+ expected-error {{'__arm_streaming' cannot be applied to a base specifier}}
+}
+
+namespace __arm_streaming ns_attr {}; // expected-error {{'__arm_streaming' cannot be applied to a declaration}} \
+ expected-warning {{attributes on a namespace declaration are a C++17 extension}}
Index: clang/test/Parser/c2x-attribute-keywords.m
===================================================================
--- /dev/null
+++ clang/test/Parser/c2x-attribute-keywords.m
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -fsyntax-only -triple aarch64-none-linux-gnu -target-feature +sme -verify %s
+
+enum __arm_streaming E1 : int; // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+
+@interface Base
+@end
+
+@interface S : Base
+- (void) bar;
+@end
+
+@interface T : Base
+- (S *) foo;
+@end
+
+
+void f(T *t) {
+ __arm_streaming[[t foo] bar]; // expected-error {{'__arm_streaming' cannot be applied to a statement}}
+}
Index: clang/test/Parser/c2x-attribute-keywords.c
===================================================================
--- /dev/null
+++ clang/test/Parser/c2x-attribute-keywords.c
@@ -0,0 +1,119 @@
+// RUN: %clang_cc1 -fsyntax-only -triple aarch64-none-linux-gnu -target-feature +sme -verify=expected,notc2x -Wno-strict-prototypes %s
+// RUN: %clang_cc1 -fsyntax-only -triple aarch64-none-linux-gnu -target-feature +sme -verify=expected,c2x %s
+
+enum __arm_streaming E { // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+ One __arm_streaming, // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+ Two,
+ Three __arm_streaming // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+};
+
+enum __arm_streaming { Four }; // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+__arm_streaming enum E2 { Five }; // expected-error {{misplaced '__arm_streaming'}}
+
+// FIXME: this diagnostic can be improved.
+enum { __arm_streaming Six }; // expected-error {{expected identifier}}
+
+// FIXME: this diagnostic can be improved.
+enum E3 __arm_streaming { Seven }; // expected-error {{expected identifier or '('}}
+
+struct __arm_streaming S1 { // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+ int i __arm_streaming; // expected-error {{'__arm_streaming' only applies to function types}}
+ int __arm_streaming j; // expected-error {{'__arm_streaming' only applies to function types}}
+ int k[10] __arm_streaming; // expected-error {{'__arm_streaming' only applies to function types}}
+ int l __arm_streaming[10]; // expected-error {{'__arm_streaming' only applies to function types}}
+ __arm_streaming int m, n; // expected-error {{'__arm_streaming' only applies to function types}}
+ int o __arm_streaming : 12; // expected-error {{'__arm_streaming' only applies to function types}}
+ int __arm_streaming : 0; // expected-error {{'__arm_streaming' only applies to function types}}
+ int p, __arm_streaming : 0; // expected-error {{'__arm_streaming' cannot appear here}}
+ int q, __arm_streaming r; // expected-error {{'__arm_streaming' cannot appear here}}
+ __arm_streaming int; // expected-error {{'__arm_streaming' cannot appear here}} \
+ // expected-warning {{declaration does not declare anything}}
+};
+
+__arm_streaming struct S2 { int a; }; // expected-error {{misplaced '__arm_streaming'}}
+struct S3 __arm_streaming { int a; }; // expected-error {{'__arm_streaming' cannot appear here}} \
+ expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+
+union __arm_streaming U { // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+ double d __arm_streaming; // expected-error {{'__arm_streaming' only applies to function types; type here is 'double'}}
+ __arm_streaming int i; // expected-error {{'__arm_streaming' only applies to function types; type here is 'int'}}
+};
+
+__arm_streaming union U2 { double d; }; // expected-error {{misplaced '__arm_streaming'}}
+union U3 __arm_streaming { double d; }; // expected-error {{'__arm_streaming' cannot appear here}} \
+ expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+
+struct __arm_streaming IncompleteStruct; // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+union __arm_streaming IncompleteUnion; // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+enum __arm_streaming IncompleteEnum; // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+
+__arm_streaming void f1(void); // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+void __arm_streaming f2(void); // expected-error {{'__arm_streaming' only applies to function types}}
+void f3 __arm_streaming (void); // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+void f4(void) __arm_streaming;
+
+void f5(int i __arm_streaming, __arm_streaming int j, int __arm_streaming k); // expected-error 3 {{'__arm_streaming' only applies to function types}}
+
+void f6(a, b) __arm_streaming int a; int b; { // expected-error {{'__arm_streaming' cannot appear here}} \
+ c2x-warning {{deprecated}}
+}
+
+// FIXME: technically, an attribute list cannot appear here, but we currently
+// parse it as part of the return type of the function, which is reasonable
+// behavior given that we *don't* want to parse it as part of the K&R parameter
+// declarations. It is disallowed to avoid a parsing ambiguity we already
+// handle well.
+int (*f7(a, b))(int, int) __arm_streaming int a; int b; { // c2x-warning {{deprecated}}
+ return 0;
+}
+
+__arm_streaming int a, b; // expected-error {{'__arm_streaming' only applies to function types}}
+int c __arm_streaming, d __arm_streaming; // expected-error 2 {{'__arm_streaming' only applies to function types}}
+
+void f8(void) __arm_streaming {
+ __arm_streaming int i, j; // expected-error {{'__arm_streaming' only applies to function types}}
+ int k, l __arm_streaming; // expected-error {{'__arm_streaming' only applies to function types}}
+}
+
+__arm_streaming void f9(void) { // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+ int i[10] __arm_streaming; // expected-error {{'__arm_streaming' only applies to function types}}
+ int (*fp1)(void)__arm_streaming;
+ int (*fp2 __arm_streaming)(void); // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+
+ int * __arm_streaming *ipp; // expected-error {{'__arm_streaming' only applies to function types}}
+}
+
+void f10(int j[static 10] __arm_streaming, int k[*] __arm_streaming); // expected-error 2 {{'__arm_streaming' only applies to function types}}
+
+void f11(void) {
+ __arm_streaming {} // expected-error {{'__arm_streaming' cannot be applied to a statement}}
+ __arm_streaming if (1) {} // expected-error {{'__arm_streaming' cannot be applied to a statement}}
+
+ __arm_streaming switch (1) { // expected-error {{'__arm_streaming' cannot be applied to a statement}}
+ __arm_streaming case 1: __arm_streaming break; // expected-error 2 {{'__arm_streaming' cannot be applied to a statement}}
+ __arm_streaming default: break; // expected-error {{'__arm_streaming' cannot be applied to a statement}}
+ }
+
+ goto foo;
+ __arm_streaming foo: (void)1; // expected-error {{'__arm_streaming' cannot be applied to a declaration}}
+
+ __arm_streaming for (;;); // expected-error {{'__arm_streaming' cannot be applied to a statement}}
+ __arm_streaming while (1); // expected-error {{'__arm_streaming' cannot be applied to a statement}}
+ __arm_streaming do __arm_streaming { } while(1); // expected-error 2 {{'__arm_streaming' cannot be applied to a statement}}
+
+ __arm_streaming (void)1; // expected-error {{'__arm_streaming' cannot be applied to a statement}}
+
+ __arm_streaming; // expected-error {{'__arm_streaming' cannot be applied to a statement}}
+
+ (void)sizeof(int [4]__arm_streaming); // expected-error {{'__arm_streaming' only applies to function types}}
+ (void)sizeof(struct __arm_streaming S3 { int a __arm_streaming; }); // expected-error {{'__arm_streaming' cannot be applied to a declaration}} \
+ // expected-error {{'__arm_streaming' only applies to function types; type here is 'int'}}
+
+ __arm_streaming return; // expected-error {{'__arm_streaming' cannot be applied to a statement}}
+
+ __arm_streaming asm (""); // expected-error {{'__arm_streaming' cannot appear here}}
+}
+
+struct __arm_streaming S4 *s; // expected-error {{'__arm_streaming' cannot appear here}}
+struct S5 {};
+int c = sizeof(struct __arm_streaming S5); // expected-error {{'__arm_streaming' cannot appear here}}
Index: clang/lib/Sema/SemaType.cpp
===================================================================
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -103,8 +103,10 @@
}
}
- S.Diag(loc, diag::warn_type_attribute_wrong_type) << name << WhichType
- << type;
+ S.Diag(loc, attr.isRegularKeywordAttribute()
+ ? diag::err_type_attribute_wrong_type
+ : diag::warn_type_attribute_wrong_type)
+ << name << WhichType << type;
}
// objc_gc applies to Objective-C pointers or, otherwise, to the
@@ -685,7 +687,7 @@
for (ParsedAttr &attr : AttrsCopy) {
// Do not distribute [[]] attributes. They have strict rules for what
// they appertain to.
- if (attr.isStandardAttributeSyntax())
+ if (attr.isStandardAttributeSyntax() || attr.isRegularKeywordAttribute())
continue;
switch (attr.getKind()) {
@@ -7334,12 +7336,12 @@
if (Attrs[attr::Ptr32] && Attrs[attr::Ptr64]) {
S.Diag(PAttr.getLoc(), diag::err_attributes_are_not_compatible)
<< "'__ptr32'"
- << "'__ptr64'";
+ << "'__ptr64'" << 0;
return true;
} else if (Attrs[attr::SPtr] && Attrs[attr::UPtr]) {
S.Diag(PAttr.getLoc(), diag::err_attributes_are_not_compatible)
<< "'__sptr'"
- << "'__uptr'";
+ << "'__uptr'" << 0;
return true;
}
@@ -7862,8 +7864,7 @@
CallingConv CC = fn->getCallConv();
if (CC == CC_X86FastCall) {
S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
- << FunctionType::getNameForCallConv(CC)
- << "regparm";
+ << FunctionType::getNameForCallConv(CC) << "regparm" << 0;
attr.setInvalid();
return true;
}
@@ -7942,8 +7943,8 @@
// and the CCs don't match.
if (S.getCallingConvAttributedType(type)) {
S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
- << FunctionType::getNameForCallConv(CC)
- << FunctionType::getNameForCallConv(CCOld);
+ << FunctionType::getNameForCallConv(CC)
+ << FunctionType::getNameForCallConv(CCOld) << 0;
attr.setInvalid();
return true;
}
@@ -7975,7 +7976,7 @@
// Also diagnose fastcall with regparm.
if (CC == CC_X86FastCall && fn->getHasRegParm()) {
S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
- << "regparm" << FunctionType::getNameForCallConv(CC_X86FastCall);
+ << "regparm" << FunctionType::getNameForCallConv(CC_X86FastCall) << 0;
attr.setInvalid();
return true;
}
@@ -8491,12 +8492,13 @@
if (attr.isInvalid())
continue;
- if (attr.isStandardAttributeSyntax()) {
+ if (attr.isStandardAttributeSyntax() || attr.isRegularKeywordAttribute()) {
// [[gnu::...]] attributes are treated as declaration attributes, so may
// not appertain to a DeclaratorChunk. If we handle them as type
// attributes, accept them in that position and diagnose the GCC
// incompatibility.
if (attr.isGNUScope()) {
+ assert(attr.isStandardAttributeSyntax());
bool IsTypeAttr = attr.isTypeAttr();
if (TAL == TAL_DeclChunk) {
state.getSema().Diag(attr.getLoc(),
@@ -8524,9 +8526,11 @@
switch (attr.getKind()) {
default:
// A [[]] attribute on a declarator chunk must appertain to a type.
- if (attr.isStandardAttributeSyntax() && TAL == TAL_DeclChunk) {
+ if ((attr.isStandardAttributeSyntax() ||
+ attr.isRegularKeywordAttribute()) &&
+ TAL == TAL_DeclChunk) {
state.getSema().Diag(attr.getLoc(), diag::err_attribute_not_type_attr)
- << attr;
+ << attr << attr.isRegularKeywordAttribute();
attr.setUsedAsTypeAttr();
}
break;
@@ -8707,7 +8711,8 @@
// Attributes with standard syntax have strict rules for what they
// appertain to and hence should not use the "distribution" logic below.
- if (attr.isStandardAttributeSyntax()) {
+ if (attr.isStandardAttributeSyntax() ||
+ attr.isRegularKeywordAttribute()) {
if (!handleFunctionTypeAttr(state, attr, type)) {
diagnoseBadTypeAttribute(state.getSema(), attr, type);
attr.setInvalid();
Index: clang/lib/Sema/SemaStmtAttr.cpp
===================================================================
--- clang/lib/Sema/SemaStmtAttr.cpp
+++ clang/lib/Sema/SemaStmtAttr.cpp
@@ -490,7 +490,9 @@
!(A.existsInTarget(S.Context.getTargetInfo()) ||
(S.Context.getLangOpts().SYCLIsDevice && Aux &&
A.existsInTarget(*Aux)))) {
- S.Diag(A.getLoc(), A.isDeclspecAttribute()
+ S.Diag(A.getLoc(), A.isRegularKeywordAttribute()
+ ? (unsigned)diag::err_keyword_not_supported_on_target
+ : A.isDeclspecAttribute()
? (unsigned)diag::warn_unhandled_ms_attribute_ignored
: (unsigned)diag::warn_unknown_attribute_ignored)
<< A << A.getRange();
@@ -526,7 +528,7 @@
// declaration attribute is not written on a statement, but this code is
// needed for attributes in Attr.td that do not list any subjects.
S.Diag(A.getRange().getBegin(), diag::err_decl_attribute_invalid_on_stmt)
- << A << St->getBeginLoc();
+ << A << A.isRegularKeywordAttribute() << St->getBeginLoc();
return nullptr;
}
}
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -2710,10 +2710,12 @@
for (const ParsedAttr &AL : Attributes) {
if (AL.isInvalid() || AL.getKind() == ParsedAttr::IgnoredAttribute)
continue;
- Diag(AL.getLoc(), AL.getKind() == ParsedAttr::UnknownAttribute
- ? (unsigned)diag::warn_unknown_attribute_ignored
- : (unsigned)diag::err_base_specifier_attribute)
- << AL << AL.getRange();
+ if (AL.getKind() == ParsedAttr::UnknownAttribute)
+ Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored)
+ << AL << AL.getRange();
+ else
+ Diag(AL.getLoc(), diag::err_base_specifier_attribute)
+ << AL << AL.isRegularKeywordAttribute() << AL.getRange();
}
TypeSourceInfo *TInfo = nullptr;
Index: clang/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -273,7 +273,9 @@
template <typename AttrTy>
static bool checkAttrMutualExclusion(Sema &S, Decl *D, const ParsedAttr &AL) {
if (const auto *A = D->getAttr<AttrTy>()) {
- S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) << AL << A;
+ S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
+ << AL << A
+ << (AL.isRegularKeywordAttribute() || A->isRegularKeywordAttribute());
S.Diag(A->getLocation(), diag::note_conflicting_attribute);
return true;
}
@@ -283,8 +285,9 @@
template <typename AttrTy>
static bool checkAttrMutualExclusion(Sema &S, Decl *D, const Attr &AL) {
if (const auto *A = D->getAttr<AttrTy>()) {
- S.Diag(AL.getLocation(), diag::err_attributes_are_not_compatible) << &AL
- << A;
+ S.Diag(AL.getLocation(), diag::err_attributes_are_not_compatible)
+ << &AL << A
+ << (AL.isRegularKeywordAttribute() || A->isRegularKeywordAttribute());
S.Diag(A->getLocation(), diag::note_conflicting_attribute);
return true;
}
@@ -1878,8 +1881,11 @@
// Cannot have two ownership attributes of different kinds for the same
// index.
if (I->getOwnKind() != K && llvm::is_contained(I->args(), Idx)) {
- S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) << AL << I;
- return;
+ S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
+ << AL << I
+ << (AL.isRegularKeywordAttribute() ||
+ I->isRegularKeywordAttribute());
+ return;
} else if (K == OwnershipAttr::Returns &&
I->getOwnKind() == OwnershipAttr::Returns) {
// A returns attribute conflicts with any other returns attribute using
@@ -2164,7 +2170,7 @@
// nonstatic) when in Microsoft compatibility mode.
if (S.getLangOpts().MSVCCompat && isa<CXXMethodDecl>(D)) {
S.Diag(AL.getLoc(), diag::err_attribute_wrong_decl_type_str)
- << AL << "non-member functions";
+ << AL << 0 << "non-member functions";
return;
}
}
@@ -2177,7 +2183,7 @@
if (!isa<ObjCMethodDecl>(D)) {
S.Diag(Attrs.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attrs << ExpectedFunctionOrMethod;
+ << Attrs << 0 << ExpectedFunctionOrMethod;
return;
}
@@ -2218,7 +2224,9 @@
bool Sema::CheckAttrTarget(const ParsedAttr &AL) {
// Check whether the attribute is valid on the current target.
if (!AL.existsInTarget(Context.getTargetInfo())) {
- Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored)
+ Diag(AL.getLoc(), AL.isRegularKeywordAttribute()
+ ? diag::err_keyword_not_supported_on_target
+ : diag::warn_unknown_attribute_ignored)
<< AL << AL.getRange();
AL.setInvalid();
return true;
@@ -2238,7 +2246,7 @@
S.Diag(AL.getLoc(), AL.isStandardAttributeSyntax()
? diag::err_attribute_wrong_decl_type
: diag::warn_attribute_wrong_decl_type)
- << AL << ExpectedFunctionMethodOrBlock;
+ << AL << 0 << ExpectedFunctionMethodOrBlock;
return;
}
}
@@ -2888,12 +2896,10 @@
}
// 'type_visibility' can only go on a type or namespace.
- if (isTypeVisibility &&
- !(isa<TagDecl>(D) ||
- isa<ObjCInterfaceDecl>(D) ||
- isa<NamespaceDecl>(D))) {
+ if (isTypeVisibility && !(isa<TagDecl>(D) || isa<ObjCInterfaceDecl>(D) ||
+ isa<NamespaceDecl>(D))) {
S.Diag(AL.getRange().getBegin(), diag::err_attribute_wrong_decl_type)
- << AL << ExpectedTypeOrNamespace;
+ << AL << 0 << ExpectedTypeOrNamespace;
return;
}
@@ -3112,12 +3118,12 @@
}
} else {
S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
- << AL << ExpectedFunctionMethodOrBlock;
+ << AL << 0 << ExpectedFunctionMethodOrBlock;
return;
}
} else {
S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
- << AL << ExpectedFunctionMethodOrBlock;
+ << AL << 0 << ExpectedFunctionMethodOrBlock;
return;
}
D->addAttr(::new (S.Context) SentinelAttr(S.Context, AL, sentinel, nullPos));
@@ -3142,7 +3148,7 @@
// as a function pointer.
if (isa<VarDecl>(D))
S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type_str)
- << AL << "functions, classes, or enumerations";
+ << AL << 0 << "functions, classes, or enumerations";
// If this is spelled as the standard C++17 attribute, but not in C++17,
// warn about using it as an extension. If there are attribute arguments,
@@ -3188,7 +3194,7 @@
// Nothing to warn about here.
} else
S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
- << AL << ExpectedVariableOrFunction;
+ << AL << 0 << ExpectedVariableOrFunction;
return;
}
@@ -3884,7 +3890,7 @@
(EA->isWarning() && NewAttr == "warning");
if (!Match) {
Diag(EA->getLocation(), diag::err_attributes_are_not_compatible)
- << CI << EA;
+ << CI << EA << 0;
Diag(CI.getLoc(), diag::note_conflicting_attribute);
return nullptr;
}
@@ -4201,8 +4207,8 @@
RD = dyn_cast<RecordDecl>(D);
if (!RD || !RD->isUnion()) {
- S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) << AL
- << ExpectedUnion;
+ S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << AL << 0 << ExpectedUnion;
return;
}
@@ -4393,9 +4399,10 @@
if (ED->getLangOpts().CPlusPlus)
DiagKind = 4;
} else if (!isa<TagDecl>(D)) {
- Diag(AttrLoc, diag::err_attribute_wrong_decl_type) << &TmpAttr
- << (TmpAttr.isC11() ? ExpectedVariableOrField
- : ExpectedVariableFieldOrTag);
+ Diag(AttrLoc, diag::err_attribute_wrong_decl_type)
+ << &TmpAttr << 0
+ << (TmpAttr.isC11() ? ExpectedVariableOrField
+ : ExpectedVariableFieldOrTag);
return;
}
if (DiagKind != -1) {
@@ -4818,8 +4825,9 @@
// ImplicitParm or VarTemplateSpecialization).
if (VD->getKind() != Decl::Var) {
Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
- << AL << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass
- : ExpectedVariableOrFunction);
+ << AL << 0
+ << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass
+ : ExpectedVariableOrFunction);
return nullptr;
}
// Attribute does not apply to non-static local variables.
@@ -4838,8 +4846,9 @@
// ImplicitParm or VarTemplateSpecialization).
if (VD->getKind() != Decl::Var) {
Diag(AL.getLocation(), diag::warn_attribute_wrong_decl_type)
- << &AL << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass
- : ExpectedVariableOrFunction);
+ << &AL << 0
+ << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass
+ : ExpectedVariableOrFunction);
return nullptr;
}
// Attribute does not apply to non-static local variables.
@@ -4870,7 +4879,7 @@
if (const auto *PrevSNA = D->getAttr<SwiftNameAttr>()) {
if (PrevSNA->getName() != Name && !PrevSNA->isImplicit()) {
Diag(PrevSNA->getLocation(), diag::err_attributes_are_not_compatible)
- << PrevSNA << &SNA;
+ << PrevSNA << &SNA << 0;
Diag(SNA.getLoc(), diag::note_conflicting_attribute);
}
@@ -5035,7 +5044,7 @@
if (!isa<ObjCMethodDecl>(D)) {
S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
- << AL << ExpectedFunctionOrMethod;
+ << AL << AL.isRegularKeywordAttribute() << ExpectedFunctionOrMethod;
return;
}
@@ -5166,7 +5175,7 @@
: nullptr;
if (ExistingDerefType != ParmType.getTypePtrOrNull()) {
S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
- << AL << OAttr;
+ << AL << OAttr << 0;
S.Diag(OAttr->getLocation(), diag::note_conflicting_attribute);
}
return;
@@ -5183,7 +5192,7 @@
: nullptr;
if (ExistingDerefType != ParmType.getTypePtrOrNull()) {
S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
- << AL << PAttr;
+ << AL << PAttr << 0;
S.Diag(PAttr->getLocation(), diag::note_conflicting_attribute);
}
return;
@@ -5418,7 +5427,7 @@
if (auto existingAttr = D->getAttr<ParameterABIAttr>()) {
if (existingAttr->getABI() != abi) {
Diag(CI.getLoc(), diag::err_attributes_are_not_compatible)
- << getParameterABISpelling(abi) << existingAttr;
+ << getParameterABISpelling(abi) << existingAttr << 0;
Diag(existingAttr->getLocation(), diag::note_conflicting_attribute);
return;
}
@@ -5610,7 +5619,7 @@
if (!isa<VarDecl>(D)) {
S.Diag(AL.getLoc(), diag::err_attribute_wrong_decl_type)
- << AL << ExpectedVariable;
+ << AL << 0 << ExpectedVariable;
return;
}
@@ -5907,7 +5916,7 @@
break;
}
S.Diag(D->getBeginLoc(), diag::warn_attribute_wrong_decl_type)
- << AL.getRange() << AL << ExpectedDeclKind;
+ << AL.getRange() << AL << 0 << ExpectedDeclKind;
return;
}
@@ -6179,10 +6188,11 @@
}
static void handleObjCOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (hasDeclarator(D)) return;
+ if (hasDeclarator(D))
+ return;
S.Diag(D->getBeginLoc(), diag::err_attribute_wrong_decl_type)
- << AL.getRange() << AL << ExpectedVariable;
+ << AL.getRange() << AL << 0 << ExpectedVariable;
}
static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D,
@@ -6675,8 +6685,8 @@
Params = F->parameters();
if (!F->hasWrittenPrototype()) {
- Diag(Loc, diag::warn_attribute_wrong_decl_type) << AL
- << ExpectedFunctionWithProtoType;
+ Diag(Loc, diag::warn_attribute_wrong_decl_type)
+ << AL << 0 << ExpectedFunctionWithProtoType;
return false;
}
}
@@ -6796,7 +6806,7 @@
if (!isa<TypedefNameDecl>(D)) {
S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type_str)
- << AL << "typedefs";
+ << AL << 0 << "typedefs";
return;
}
@@ -7271,7 +7281,7 @@
// a function with no parameters and void return type.
if (!isFunctionOrMethod(D)) {
S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
- << "'interrupt'" << ExpectedFunctionOrMethod;
+ << "'interrupt'" << 0 << ExpectedFunctionOrMethod;
return;
}
@@ -7344,7 +7354,7 @@
if (!isFunctionOrMethod(D)) {
S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
- << "'interrupt'" << ExpectedFunctionOrMethod;
+ << "'interrupt'" << 0 << ExpectedFunctionOrMethod;
return;
}
@@ -7419,7 +7429,7 @@
CXXMethodDecl::isStaticOverloadedOperator(
cast<NamedDecl>(D)->getDeclName().getCXXOverloadedOperator())) {
S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
- << AL << ExpectedFunctionWithProtoType;
+ << AL << 0 << ExpectedFunctionWithProtoType;
return;
}
// Interrupt handler must have void return type.
@@ -7475,7 +7485,7 @@
static void handleAVRInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!isFunctionOrMethod(D)) {
S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
- << "'interrupt'" << ExpectedFunction;
+ << "'interrupt'" << 0 << ExpectedFunction;
return;
}
@@ -7488,7 +7498,7 @@
static void handleAVRSignalAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!isFunctionOrMethod(D)) {
S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
- << "'signal'" << ExpectedFunction;
+ << "'signal'" << 0 << ExpectedFunction;
return;
}
@@ -7541,10 +7551,11 @@
return ::new (Context) BTFDeclTagAttr(Context, AL, AL.getBTFDeclTag());
}
-static void handleWebAssemblyExportNameAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+static void handleWebAssemblyExportNameAttr(Sema &S, Decl *D,
+ const ParsedAttr &AL) {
if (!isFunctionOrMethod(D)) {
S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
- << "'export_name'" << ExpectedFunction;
+ << "'export_name'" << 0 << ExpectedFunction;
return;
}
@@ -7668,7 +7679,7 @@
if (D->getFunctionType() == nullptr) {
S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
- << "'interrupt'" << ExpectedFunction;
+ << "'interrupt'" << 0 << ExpectedFunction;
return;
}
@@ -7863,7 +7874,7 @@
// Attribute can only be applied to function types.
if (!isa<FunctionDecl>(D)) {
S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
- << AL << ExpectedFunction;
+ << AL << 0 << ExpectedFunction;
return;
}
@@ -8142,7 +8153,7 @@
.Case("no_sanitize_memory", "memory");
if (isGlobalVar(D) && SanitizerName != "address")
S.Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
- << AL << ExpectedFunction;
+ << AL << 0 << ExpectedFunction;
// FIXME: Rather than create a NoSanitizeSpecificAttr, this creates a
// NoSanitizeAttr object; but we need to calculate the correct spelling list
@@ -8603,7 +8614,9 @@
if (AL.getKind() == ParsedAttr::UnknownAttribute ||
!AL.existsInTarget(S.Context.getTargetInfo())) {
S.Diag(AL.getLoc(),
- AL.isDeclspecAttribute()
+ AL.isRegularKeywordAttribute()
+ ? (unsigned)diag::err_keyword_not_supported_on_target
+ : AL.isDeclspecAttribute()
? (unsigned)diag::warn_unhandled_ms_attribute_ignored
: (unsigned)diag::warn_unknown_attribute_ignored)
<< AL << AL.getRange();
@@ -8632,7 +8645,7 @@
if (AL.isTypeAttr()) {
if (Options.IgnoreTypeAttributes)
break;
- if (!AL.isStandardAttributeSyntax()) {
+ if (!AL.isStandardAttributeSyntax() && !AL.isRegularKeywordAttribute()) {
// Non-[[]] type attributes are handled in processTypeAttrs(); silently
// move on.
break;
@@ -8697,7 +8710,7 @@
// needed for type attributes as well as statement attributes in Attr.td
// that do not list any subjects.
S.Diag(AL.getLoc(), diag::err_attribute_invalid_on_decl)
- << AL << D->getLocation();
+ << AL << AL.isRegularKeywordAttribute() << D->getLocation();
break;
case ParsedAttr::AT_Interrupt:
handleInterruptAttr(S, D, AL);
@@ -9408,19 +9421,19 @@
} else if (!D->hasAttr<CUDAGlobalAttr>()) {
if (const auto *A = D->getAttr<AMDGPUFlatWorkGroupSizeAttr>()) {
Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
- << A << ExpectedKernelFunction;
+ << A << 0 << ExpectedKernelFunction;
D->setInvalidDecl();
} else if (const auto *A = D->getAttr<AMDGPUWavesPerEUAttr>()) {
Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
- << A << ExpectedKernelFunction;
+ << A << 0 << ExpectedKernelFunction;
D->setInvalidDecl();
} else if (const auto *A = D->getAttr<AMDGPUNumSGPRAttr>()) {
Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
- << A << ExpectedKernelFunction;
+ << A << 0 << ExpectedKernelFunction;
D->setInvalidDecl();
} else if (const auto *A = D->getAttr<AMDGPUNumVGPRAttr>()) {
Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
- << A << ExpectedKernelFunction;
+ << A << 0 << ExpectedKernelFunction;
D->setInvalidDecl();
}
}
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -5315,10 +5315,14 @@
TypeSpecType == DeclSpec::TST_union ||
TypeSpecType == DeclSpec::TST_enum) {
for (const ParsedAttr &AL : DS.getAttributes())
- Diag(AL.getLoc(), diag::warn_declspec_attribute_ignored)
+ Diag(AL.getLoc(), AL.isRegularKeywordAttribute()
+ ? diag::err_declspec_keyword_has_no_effect
+ : diag::warn_declspec_attribute_ignored)
<< AL << GetDiagnosticTypeSpecifierID(DS);
for (const ParsedAttr &AL : DeclAttrs)
- Diag(AL.getLoc(), diag::warn_declspec_attribute_ignored)
+ Diag(AL.getLoc(), AL.isRegularKeywordAttribute()
+ ? diag::err_declspec_keyword_has_no_effect
+ : diag::warn_declspec_attribute_ignored)
<< AL << GetDiagnosticTypeSpecifierID(DS);
}
}
Index: clang/lib/Sema/Sema.cpp
===================================================================
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -1184,7 +1184,7 @@
!(isa<FunctionDecl>(PrevDecl) || isa<VarDecl>(PrevDecl)))
for (const auto &WI : WeakIDs.second)
Diag(WI.getLocation(), diag::warn_attribute_wrong_decl_type)
- << "'weak'" << ExpectedVariableOrFunction;
+ << "'weak'" << 0 << ExpectedVariableOrFunction;
else
for (const auto &WI : WeakIDs.second)
Diag(WI.getLocation(), diag::warn_weak_identifier_undeclared)
Index: clang/lib/Sema/ParsedAttr.cpp
===================================================================
--- clang/lib/Sema/ParsedAttr.cpp
+++ clang/lib/Sema/ParsedAttr.cpp
@@ -203,6 +203,11 @@
}
bool ParsedAttr::slidesFromDeclToDeclSpecLegacyBehavior() const {
+ if (isRegularKeywordAttribute())
+ // The appurtenance rules are applied strictly for all regular keyword
+ // atributes.
+ return false;
+
assert(isStandardAttributeSyntax());
// We have historically allowed some type attributes with standard attribute
Index: clang/lib/Parse/Parser.cpp
===================================================================
--- clang/lib/Parse/Parser.cpp
+++ clang/lib/Parse/Parser.cpp
@@ -2461,6 +2461,7 @@
ParsedAttributes Attrs(AttrFactory);
MaybeParseCXX11Attributes(Attrs);
ProhibitCXX11Attributes(Attrs, diag::err_attribute_not_module_attr,
+ diag::err_keyword_not_module_attr,
/*DiagnoseEmptyAttrs=*/false,
/*WarnOnUnknownAttrs=*/true);
@@ -2530,6 +2531,7 @@
MaybeParseCXX11Attributes(Attrs);
// We don't support any module import attributes yet.
ProhibitCXX11Attributes(Attrs, diag::err_attribute_not_import_attr,
+ diag::err_keyword_not_import_attr,
/*DiagnoseEmptyAttrs=*/false,
/*WarnOnUnknownAttrs=*/true);
Index: clang/lib/Parse/ParseTentative.cpp
===================================================================
--- clang/lib/Parse/ParseTentative.cpp
+++ clang/lib/Parse/ParseTentative.cpp
@@ -723,6 +723,9 @@
if (Tok.is(tok::kw_alignas))
return CAK_AttributeSpecifier;
+ if (Tok.isRegularKeywordAttribute())
+ return CAK_AttributeSpecifier;
+
if (Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square))
return CAK_NotAttributeSpecifier;
@@ -862,7 +865,8 @@
bool Parser::TrySkipAttributes() {
while (Tok.isOneOf(tok::l_square, tok::kw___attribute, tok::kw___declspec,
- tok::kw_alignas)) {
+ tok::kw_alignas) ||
+ Tok.isRegularKeywordAttribute()) {
if (Tok.is(tok::l_square)) {
ConsumeBracket();
if (Tok.isNot(tok::l_square))
@@ -873,6 +877,8 @@
// Note that explicitly checking for `[[` and `]]` allows to fail as
// expected in the case of the Objective-C message send syntax.
ConsumeBracket();
+ } else if (Tok.isRegularKeywordAttribute()) {
+ ConsumeToken();
} else {
ConsumeToken();
if (Tok.isNot(tok::l_paren))
Index: clang/lib/Parse/ParseStmt.cpp
===================================================================
--- clang/lib/Parse/ParseStmt.cpp
+++ clang/lib/Parse/ParseStmt.cpp
@@ -335,7 +335,12 @@
case tok::kw_asm: {
for (const ParsedAttr &AL : CXX11Attrs)
- Diag(AL.getRange().getBegin(), diag::warn_attribute_ignored) << AL;
+ // Could be relaxed if asm-related regular keyword attributes are
+ // added later.
+ (AL.isRegularKeywordAttribute()
+ ? Diag(AL.getRange().getBegin(), diag::err_keyword_not_allowed)
+ : Diag(AL.getRange().getBegin(), diag::warn_attribute_ignored))
+ << AL;
// Prevent these from being interpreted as statement attributes later on.
CXX11Attrs.clear();
ProhibitAttributes(GNUAttrs);
Index: clang/lib/Parse/ParsePragma.cpp
===================================================================
--- clang/lib/Parse/ParsePragma.cpp
+++ clang/lib/Parse/ParsePragma.cpp
@@ -1819,7 +1819,8 @@
ConsumeToken();
};
- if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) {
+ if ((Tok.is(tok::l_square) && NextToken().is(tok::l_square)) ||
+ Tok.isRegularKeywordAttribute()) {
// Parse the CXX11 style attribute.
ParseCXX11AttributeSpecifier(Attrs);
} else if (Tok.is(tok::kw___attribute)) {
Index: clang/lib/Parse/ParseExprCXX.cpp
===================================================================
--- clang/lib/Parse/ParseExprCXX.cpp
+++ clang/lib/Parse/ParseExprCXX.cpp
@@ -1364,7 +1364,8 @@
if (isCXX11AttributeSpecifier()) {
Diag(Tok, getLangOpts().CPlusPlus23
? diag::warn_cxx20_compat_decl_attrs_on_lambda
- : diag::ext_decl_attrs_on_lambda);
+ : diag::ext_decl_attrs_on_lambda)
+ << Tok.getIdentifierInfo() << Tok.isRegularKeywordAttribute();
MaybeParseCXX11Attributes(D);
}
@@ -1499,6 +1500,7 @@
tok::kw___private, tok::kw___global, tok::kw___local,
tok::kw___constant, tok::kw___generic, tok::kw_groupshared,
tok::kw_requires, tok::kw_noexcept) ||
+ Tok.isRegularKeywordAttribute() ||
(Tok.is(tok::l_square) && NextToken().is(tok::l_square));
if (HasSpecifiers && !HasParentheses && !getLangOpts().CPlusPlus23) {
Index: clang/lib/Parse/ParseDeclCXX.cpp
===================================================================
--- clang/lib/Parse/ParseDeclCXX.cpp
+++ clang/lib/Parse/ParseDeclCXX.cpp
@@ -635,6 +635,7 @@
Tok.is(tok::identifier) &&
(NextToken().is(tok::semi) || NextToken().is(tok::comma) ||
NextToken().is(tok::ellipsis) || NextToken().is(tok::l_square) ||
+ NextToken().isRegularKeywordAttribute() ||
NextToken().is(tok::kw___attribute)) &&
D.SS.isNotEmpty() && LastII == Tok.getIdentifierInfo() &&
!D.SS.getScopeRep()->getAsNamespace() &&
@@ -767,11 +768,15 @@
// If we had any misplaced attributes from earlier, this is where they
// should have been written.
if (MisplacedAttrs.Range.isValid()) {
- Diag(MisplacedAttrs.Range.getBegin(), diag::err_attributes_not_allowed)
+ auto *FirstAttr =
+ MisplacedAttrs.empty() ? nullptr : &MisplacedAttrs.front();
+ auto &Range = MisplacedAttrs.Range;
+ (FirstAttr && FirstAttr->isRegularKeywordAttribute()
+ ? Diag(Range.getBegin(), diag::err_keyword_not_allowed) << FirstAttr
+ : Diag(Range.getBegin(), diag::err_attributes_not_allowed))
<< FixItHint::CreateInsertionFromRange(
- Tok.getLocation(),
- CharSourceRange::getTokenRange(MisplacedAttrs.Range))
- << FixItHint::CreateRemoval(MisplacedAttrs.Range);
+ Tok.getLocation(), CharSourceRange::getTokenRange(Range))
+ << FixItHint::CreateRemoval(Range);
Attrs.takeAllFrom(MisplacedAttrs);
}
@@ -1384,6 +1389,8 @@
// This switch enumerates the valid "follow" set for type-specifiers.
switch (Tok.getKind()) {
default:
+ if (Tok.isRegularKeywordAttribute())
+ return true;
break;
case tok::semi: // struct foo {...} ;
case tok::star: // struct foo {...} * P;
@@ -1841,6 +1848,7 @@
} else if (isClassCompatibleKeyword() &&
(NextToken().is(tok::l_square) ||
NextToken().is(tok::kw_alignas) ||
+ NextToken().isRegularKeywordAttribute() ||
isCXX11VirtSpecifier(NextToken()) != VirtSpecifiers::VS_None)) {
// We can't tell if this is a definition or reference
// until we skipped the 'final' and C++11 attribute specifiers.
@@ -1862,6 +1870,8 @@
ConsumeParen();
if (!SkipUntil(tok::r_paren, StopAtSemi))
break;
+ } else if (Tok.isRegularKeywordAttribute()) {
+ ConsumeToken();
} else {
break;
}
@@ -1898,7 +1908,11 @@
// them to the right place.
SourceRange AttrRange = Attributes.Range;
if (AttrRange.isValid()) {
- Diag(AttrRange.getBegin(), diag::err_attributes_not_allowed)
+ auto *FirstAttr = Attributes.empty() ? nullptr : &Attributes.front();
+ auto Loc = AttrRange.getBegin();
+ (FirstAttr && FirstAttr->isRegularKeywordAttribute()
+ ? Diag(Loc, diag::err_keyword_not_allowed) << FirstAttr
+ : Diag(Loc, diag::err_attributes_not_allowed))
<< AttrRange
<< FixItHint::CreateInsertionFromRange(
AttrFixitLoc, CharSourceRange(AttrRange, true))
@@ -1946,6 +1960,7 @@
TUK == Sema::TUK_Declaration) {
// This is an explicit instantiation of a class template.
ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed,
+ diag::err_keyword_not_allowed,
/*DiagnoseEmptyAttrs=*/true);
TagOrTempResult = Actions.ActOnExplicitInstantiation(
@@ -1962,6 +1977,7 @@
(TUK == Sema::TUK_Friend &&
TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate)) {
ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed,
+ diag::err_keyword_not_allowed,
/*DiagnoseEmptyAttrs=*/true);
TypeResult = Actions.ActOnTagTemplateIdType(
TUK, TagType, StartLoc, SS, TemplateId->TemplateKWLoc,
@@ -2031,6 +2047,7 @@
} else if (TUK == Sema::TUK_Friend &&
TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) {
ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed,
+ diag::err_keyword_not_allowed,
/*DiagnoseEmptyAttrs=*/true);
TagOrTempResult = Actions.ActOnTemplatedFriendTag(
@@ -2041,6 +2058,7 @@
} else {
if (TUK != Sema::TUK_Declaration && TUK != Sema::TUK_Definition)
ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed,
+ diag::err_keyword_not_allowed,
/* DiagnoseEmptyAttrs=*/true);
if (TUK == Sema::TUK_Definition &&
@@ -3017,12 +3035,14 @@
//
// Diagnose attributes that appear in a friend member function declarator:
// friend int foo [[]] ();
- SmallVector<SourceRange, 4> Ranges;
- DeclaratorInfo.getCXX11AttributeRanges(Ranges);
- for (SmallVectorImpl<SourceRange>::iterator I = Ranges.begin(),
- E = Ranges.end();
- I != E; ++I)
- Diag((*I).getBegin(), diag::err_attributes_not_allowed) << *I;
+ for (const ParsedAttr &AL : DeclaratorInfo.getAttributes())
+ if (AL.isCXX11Attribute() || AL.isRegularKeywordAttribute()) {
+ auto Loc = AL.getRange().getBegin();
+ (AL.isRegularKeywordAttribute()
+ ? Diag(Loc, diag::err_keyword_not_allowed) << AL
+ : Diag(Loc, diag::err_attributes_not_allowed))
+ << AL.getRange();
+ }
ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo,
TemplateParams);
@@ -4470,6 +4490,14 @@
return;
}
+ if (Tok.isRegularKeywordAttribute()) {
+ SourceLocation Loc = Tok.getLocation();
+ IdentifierInfo *AttrName = Tok.getIdentifierInfo();
+ Attrs.addNew(AttrName, Loc, nullptr, Loc, nullptr, 0, Tok.getKind());
+ ConsumeToken();
+ return;
+ }
+
assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square) &&
"Not a double square bracket attribute list");
@@ -4589,26 +4617,30 @@
/// attribute-specifier-seq:
/// attribute-specifier-seq[opt] attribute-specifier
void Parser::ParseCXX11Attributes(ParsedAttributes &Attrs) {
- assert(standardAttributesAllowed());
+ assert(standardAttributesAllowed() || Tok.isRegularKeywordAttribute());
SourceLocation StartLoc = Tok.getLocation();
SourceLocation EndLoc = StartLoc;
do {
ParseCXX11AttributeSpecifier(Attrs, &EndLoc);
- } while (isCXX11AttributeSpecifier());
+ } while (isAllowedCXX11AttributeSpecifier());
Attrs.Range = SourceRange(StartLoc, EndLoc);
}
void Parser::DiagnoseAndSkipCXX11Attributes() {
+ auto Keyword =
+ Tok.isRegularKeywordAttribute() ? Tok.getIdentifierInfo() : nullptr;
// Start and end location of an attribute or an attribute list.
SourceLocation StartLoc = Tok.getLocation();
SourceLocation EndLoc = SkipCXX11Attributes();
if (EndLoc.isValid()) {
SourceRange Range(StartLoc, EndLoc);
- Diag(StartLoc, diag::err_attributes_not_allowed) << Range;
+ (Keyword ? Diag(StartLoc, diag::err_keyword_not_allowed) << Keyword
+ : Diag(StartLoc, diag::err_attributes_not_allowed))
+ << Range;
}
}
@@ -4624,6 +4656,9 @@
T.consumeOpen();
T.skipToEnd();
EndLoc = T.getCloseLocation();
+ } else if (Tok.isRegularKeywordAttribute()) {
+ EndLoc = Tok.getLocation();
+ ConsumeToken();
} else {
assert(Tok.is(tok::kw_alignas) && "not an attribute specifier");
ConsumeToken();
Index: clang/lib/Parse/ParseDecl.cpp
===================================================================
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -1693,30 +1693,43 @@
void Parser::DiagnoseMisplacedCXX11Attribute(ParsedAttributes &Attrs,
SourceLocation CorrectLocation) {
assert((Tok.is(tok::l_square) && NextToken().is(tok::l_square)) ||
- Tok.is(tok::kw_alignas));
+ Tok.is(tok::kw_alignas) || Tok.isRegularKeywordAttribute());
// Consume the attributes.
+ auto Keyword =
+ Tok.isRegularKeywordAttribute() ? Tok.getIdentifierInfo() : nullptr;
SourceLocation Loc = Tok.getLocation();
ParseCXX11Attributes(Attrs);
CharSourceRange AttrRange(SourceRange(Loc, Attrs.Range.getEnd()), true);
// FIXME: use err_attributes_misplaced
- Diag(Loc, diag::err_attributes_not_allowed)
- << FixItHint::CreateInsertionFromRange(CorrectLocation, AttrRange)
- << FixItHint::CreateRemoval(AttrRange);
+ (Keyword ? Diag(Loc, diag::err_keyword_not_allowed) << Keyword
+ : Diag(Loc, diag::err_attributes_not_allowed))
+ << FixItHint::CreateInsertionFromRange(CorrectLocation, AttrRange)
+ << FixItHint::CreateRemoval(AttrRange);
}
void Parser::DiagnoseProhibitedAttributes(
- const SourceRange &Range, const SourceLocation CorrectLocation) {
+ const ParsedAttributesView &Attrs, const SourceLocation CorrectLocation) {
+ auto *FirstAttr = Attrs.empty() ? nullptr : &Attrs.front();
if (CorrectLocation.isValid()) {
- CharSourceRange AttrRange(Range, true);
- Diag(CorrectLocation, diag::err_attributes_misplaced)
+ CharSourceRange AttrRange(Attrs.Range, true);
+ (FirstAttr && FirstAttr->isRegularKeywordAttribute()
+ ? Diag(CorrectLocation, diag::err_keyword_misplaced) << FirstAttr
+ : Diag(CorrectLocation, diag::err_attributes_misplaced))
<< FixItHint::CreateInsertionFromRange(CorrectLocation, AttrRange)
<< FixItHint::CreateRemoval(AttrRange);
- } else
- Diag(Range.getBegin(), diag::err_attributes_not_allowed) << Range;
+ } else {
+ const SourceRange &Range = Attrs.Range;
+ (FirstAttr && FirstAttr->isRegularKeywordAttribute()
+ ? Diag(Range.getBegin(), diag::err_keyword_not_allowed) << FirstAttr
+ : Diag(Range.getBegin(), diag::err_attributes_not_allowed))
+ << Range;
+ }
}
-void Parser::ProhibitCXX11Attributes(ParsedAttributes &Attrs, unsigned DiagID,
+void Parser::ProhibitCXX11Attributes(ParsedAttributes &Attrs,
+ unsigned AttrDiagID,
+ unsigned KeywordDiagID,
bool DiagnoseEmptyAttrs,
bool WarnOnUnknownAttrs) {
@@ -1736,13 +1749,18 @@
// The attribute range starts with [[, but is empty. So this must
// be [[]], which we are supposed to diagnose because
// DiagnoseEmptyAttrs is true.
- Diag(Attrs.Range.getBegin(), DiagID) << Attrs.Range;
+ Diag(Attrs.Range.getBegin(), AttrDiagID) << Attrs.Range;
return;
}
}
}
for (const ParsedAttr &AL : Attrs) {
+ if (AL.isRegularKeywordAttribute()) {
+ Diag(AL.getLoc(), KeywordDiagID) << AL;
+ AL.setInvalid();
+ continue;
+ }
if (!AL.isCXX11Attribute() && !AL.isC2xAttribute())
continue;
if (AL.getKind() == ParsedAttr::UnknownAttribute) {
@@ -1750,7 +1768,7 @@
Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored)
<< AL << AL.getRange();
} else {
- Diag(AL.getLoc(), DiagID) << AL;
+ Diag(AL.getLoc(), AttrDiagID) << AL;
AL.setInvalid();
}
}
@@ -1758,8 +1776,10 @@
void Parser::DiagnoseCXX11AttributeExtension(ParsedAttributes &Attrs) {
for (const ParsedAttr &PA : Attrs) {
- if (PA.isCXX11Attribute() || PA.isC2xAttribute())
- Diag(PA.getLoc(), diag::ext_cxx11_attr_placement) << PA << PA.getRange();
+ if (PA.isCXX11Attribute() || PA.isC2xAttribute() ||
+ PA.isRegularKeywordAttribute())
+ Diag(PA.getLoc(), diag::ext_cxx11_attr_placement)
+ << PA << PA.isRegularKeywordAttribute() << PA.getRange();
}
}
@@ -1991,11 +2011,11 @@
return getLangOpts().CPlusPlus11 && isCXX11VirtSpecifier(NextToken());
default:
- return false;
+ return Tok.isRegularKeywordAttribute();
}
default:
- return false;
+ return Tok.isRegularKeywordAttribute();
}
}
@@ -3287,13 +3307,17 @@
switch (Tok.getKind()) {
default:
+ if (Tok.isRegularKeywordAttribute())
+ goto Attribute;
+
DoneWithDeclSpec:
if (!AttrsLastTime)
ProhibitAttributes(attrs);
else {
// Reject C++11 / C2x attributes that aren't type attributes.
for (const ParsedAttr &PA : attrs) {
- if (!PA.isCXX11Attribute() && !PA.isC2xAttribute())
+ if (!PA.isCXX11Attribute() && !PA.isC2xAttribute() &&
+ !PA.isRegularKeywordAttribute())
continue;
if (PA.getKind() == ParsedAttr::UnknownAttribute)
// We will warn about the unknown attribute elsewhere (in
@@ -3312,7 +3336,8 @@
if (PA.isTypeAttr() && PA.getKind() != ParsedAttr::AT_LifetimeBound &&
PA.getKind() != ParsedAttr::AT_AnyX86NoCfCheck)
continue;
- Diag(PA.getLoc(), diag::err_attribute_not_type_attr) << PA;
+ Diag(PA.getLoc(), diag::err_attribute_not_type_attr)
+ << PA << PA.isRegularKeywordAttribute();
PA.setInvalid();
}
@@ -3326,9 +3351,10 @@
case tok::l_square:
case tok::kw_alignas:
- if (!standardAttributesAllowed() || !isCXX11AttributeSpecifier())
+ if (!isAllowedCXX11AttributeSpecifier())
goto DoneWithDeclSpec;
+ Attribute:
ProhibitAttributes(attrs);
// FIXME: It would be good to recover by accepting the attributes,
// but attempting to do that now would cause serious
@@ -5004,6 +5030,7 @@
if (IsElaboratedTypeSpecifier && !getLangOpts().MicrosoftExt &&
!getLangOpts().ObjC) {
ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed,
+ diag::err_keyword_not_allowed,
/*DiagnoseEmptyAttrs=*/true);
if (BaseType.isUsable())
Diag(BaseRange.getBegin(), diag::ext_enum_base_in_type_specifier)
@@ -5149,7 +5176,7 @@
// If attributes exist after the enumerator, parse them.
ParsedAttributes attrs(AttrFactory);
MaybeParseGNUAttributes(attrs);
- if (standardAttributesAllowed() && isCXX11AttributeSpecifier()) {
+ if (isAllowedCXX11AttributeSpecifier()) {
if (getLangOpts().CPlusPlus)
Diag(Tok.getLocation(), getLangOpts().CPlusPlus17
? diag::warn_cxx14_compat_ns_enum_attribute
@@ -5874,8 +5901,8 @@
DeclSpec &DS, unsigned AttrReqs, bool AtomicAllowed,
bool IdentifierRequired,
std::optional<llvm::function_ref<void()>> CodeCompletionHandler) {
- if (standardAttributesAllowed() && (AttrReqs & AR_CXX11AttributesParsed) &&
- isCXX11AttributeSpecifier()) {
+ if ((AttrReqs & AR_CXX11AttributesParsed) &&
+ isAllowedCXX11AttributeSpecifier()) {
ParsedAttributes Attrs(AttrFactory);
ParseCXX11Attributes(Attrs);
DS.takeAttributesFrom(Attrs);
@@ -6649,6 +6676,10 @@
PrototypeScope.Exit();
} else if (Tok.is(tok::l_square)) {
ParseBracketDeclarator(D);
+ } else if (Tok.isRegularKeywordAttribute()) {
+ // For consistency with attribute parsing.
+ Diag(Tok, diag::err_keyword_not_allowed) << Tok.getIdentifierInfo();
+ ConsumeToken();
} else if (Tok.is(tok::kw_requires) && D.hasGroupingParens()) {
// This declarator is declaring a function, but the requires clause is
// in the wrong place:
@@ -7053,7 +7084,7 @@
TrailingReturnTypeLoc = Range.getBegin();
EndLoc = Range.getEnd();
}
- } else if (standardAttributesAllowed()) {
+ } else {
MaybeParseCXX11Attributes(FnAttrs);
}
}
Index: clang/include/clang/Sema/DeclSpec.h
===================================================================
--- clang/include/clang/Sema/DeclSpec.h
+++ clang/include/clang/Sema/DeclSpec.h
@@ -1972,9 +1972,10 @@
InventedTemplateParameterList(nullptr) {
assert(llvm::all_of(DeclarationAttrs,
[](const ParsedAttr &AL) {
- return AL.isStandardAttributeSyntax();
+ return (AL.isStandardAttributeSyntax() ||
+ AL.isRegularKeywordAttribute());
}) &&
- "DeclarationAttrs may only contain [[]] attributes");
+ "DeclarationAttrs may only contain [[]] and keyword attributes");
}
~Declarator() {
@@ -2619,14 +2620,6 @@
return false;
}
- /// Return a source range list of C++11 attributes associated
- /// with the declarator.
- void getCXX11AttributeRanges(SmallVectorImpl<SourceRange> &Ranges) {
- for (const ParsedAttr &AL : Attrs)
- if (AL.isCXX11Attribute())
- Ranges.push_back(AL.getRange());
- }
-
void setAsmLabel(Expr *E) { AsmLabel = E; }
Expr *getAsmLabel() const { return AsmLabel; }
Index: clang/include/clang/Parse/Parser.h
===================================================================
--- clang/include/clang/Parse/Parser.h
+++ clang/include/clang/Parse/Parser.h
@@ -2691,6 +2691,18 @@
return LO.DoubleSquareBracketAttributes;
}
+ /// Return true if the next token should be treated as a [[]] attribute,
+ /// or as a keyword that behaves like one. The former is only true if
+ /// [[]] attributes are enabled, whereas the latter is true whenever
+ /// such a keyword appears. The arguments are as for
+ /// isCXX11AttributeSpecifier.
+ bool isAllowedCXX11AttributeSpecifier(bool Disambiguate = false,
+ bool OuterMightBeMessageSend = false) {
+ return (Tok.isRegularKeywordAttribute() ||
+ (standardAttributesAllowed() &&
+ isCXX11AttributeSpecifier(Disambiguate, OuterMightBeMessageSend)));
+ }
+
// Check for the start of an attribute-specifier-seq in a context where an
// attribute is not allowed.
bool CheckProhibitedCXX11Attribute() {
@@ -2703,11 +2715,13 @@
bool DiagnoseProhibitedCXX11Attribute();
void CheckMisplacedCXX11Attribute(ParsedAttributes &Attrs,
SourceLocation CorrectLocation) {
- if (!standardAttributesAllowed())
- return;
- if ((Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square)) &&
- Tok.isNot(tok::kw_alignas))
- return;
+ if (!Tok.isRegularKeywordAttribute()) {
+ if (!standardAttributesAllowed())
+ return;
+ if ((Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square)) &&
+ Tok.isNot(tok::kw_alignas))
+ return;
+ }
DiagnoseMisplacedCXX11Attribute(Attrs, CorrectLocation);
}
void DiagnoseMisplacedCXX11Attribute(ParsedAttributes &Attrs,
@@ -2721,7 +2735,7 @@
SourceLocation FixItLoc = SourceLocation()) {
if (Attrs.Range.isInvalid())
return;
- DiagnoseProhibitedAttributes(Attrs.Range, FixItLoc);
+ DiagnoseProhibitedAttributes(Attrs, FixItLoc);
Attrs.clear();
}
@@ -2729,10 +2743,10 @@
SourceLocation FixItLoc = SourceLocation()) {
if (Attrs.Range.isInvalid())
return;
- DiagnoseProhibitedAttributes(Attrs.Range, FixItLoc);
+ DiagnoseProhibitedAttributes(Attrs, FixItLoc);
Attrs.clearListOnly();
}
- void DiagnoseProhibitedAttributes(const SourceRange &Range,
+ void DiagnoseProhibitedAttributes(const ParsedAttributesView &Attrs,
SourceLocation FixItLoc);
// Forbid C++11 and C2x attributes that appear on certain syntactic locations
@@ -2741,7 +2755,8 @@
// For the most cases we don't want to warn on unknown type attributes, but
// left them to later diagnoses. However, for a few cases like module
// declarations and module import declarations, we should do it.
- void ProhibitCXX11Attributes(ParsedAttributes &Attrs, unsigned DiagID,
+ void ProhibitCXX11Attributes(ParsedAttributes &Attrs, unsigned AttrDiagID,
+ unsigned KeywordDiagId,
bool DiagnoseEmptyAttrs = false,
bool WarnOnUnknownAttrs = false);
@@ -2795,7 +2810,7 @@
bool MaybeParseAttributes(unsigned WhichAttrKinds, ParsedAttributes &Attrs,
LateParsedAttrList *LateAttrs = nullptr) {
if (Tok.isOneOf(tok::kw___attribute, tok::kw___declspec) ||
- (standardAttributesAllowed() && isCXX11AttributeSpecifier())) {
+ isAllowedCXX11AttributeSpecifier()) {
ParseAttributes(WhichAttrKinds, Attrs, LateAttrs);
return true;
}
@@ -2847,7 +2862,7 @@
}
}
void MaybeParseCXX11Attributes(Declarator &D) {
- if (standardAttributesAllowed() && isCXX11AttributeSpecifier()) {
+ if (isAllowedCXX11AttributeSpecifier()) {
ParsedAttributes Attrs(AttrFactory);
ParseCXX11Attributes(Attrs);
D.takeAttributes(Attrs);
@@ -2856,8 +2871,7 @@
bool MaybeParseCXX11Attributes(ParsedAttributes &Attrs,
bool OuterMightBeMessageSend = false) {
- if (standardAttributesAllowed() &&
- isCXX11AttributeSpecifier(false, OuterMightBeMessageSend)) {
+ if (isAllowedCXX11AttributeSpecifier(false, OuterMightBeMessageSend)) {
ParseCXX11Attributes(Attrs);
return true;
}
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3022,7 +3022,7 @@
def err_nsobject_attribute : Error<
"'NSObject' attribute is for pointer types only">;
def err_attributes_are_not_compatible : Error<
- "%0 and %1 attributes are not compatible">;
+ "%0 and %1%select{ attributes|}2 are not compatible">;
def err_attribute_invalid_argument : Error<
"%select{a reference type|an array type|a non-vector or "
"non-vectorizable scalar type}0 is an invalid argument to attribute %1">;
@@ -3430,9 +3430,9 @@
def note_attribute_has_no_effect_on_compile_time_if_here : Note<
"annotating the 'if %select{constexpr|consteval}0' statement here">;
def err_decl_attribute_invalid_on_stmt : Error<
- "%0 attribute cannot be applied to a statement">;
+ "%0%select{ attribute|}1 cannot be applied to a statement">;
def err_attribute_invalid_on_decl : Error<
- "%0 attribute cannot be applied to a declaration">;
+ "%0%select{ attribute|}1 cannot be applied to a declaration">;
def warn_type_attribute_deprecated_on_decl : Warning<
"applying attribute %0 to a declaration is deprecated; apply it to the type instead">,
InGroup<DeprecatedAttributes>;
@@ -3440,6 +3440,10 @@
"attribute %0 is ignored, place it after "
"\"%select{class|struct|interface|union|enum|enum class|enum struct}1\" to apply attribute to "
"type declaration">, InGroup<IgnoredAttributes>;
+def err_declspec_keyword_has_no_effect : Error<
+ "%0 cannot appear here, place it after "
+ "\"%select{class|struct|interface|union|enum}1\" to apply it to the "
+ "type declaration">;
def warn_attribute_precede_definition : Warning<
"attribute declaration must precede definition">,
InGroup<IgnoredAttributes>;
@@ -3538,11 +3542,11 @@
def err_alias_not_supported_on_darwin : Error <
"aliases are not supported on darwin">;
def warn_attribute_wrong_decl_type_str : Warning<
- "%0 attribute only applies to %1">, InGroup<IgnoredAttributes>;
+ "%0%select{ attribute|}1 only applies to %2">, InGroup<IgnoredAttributes>;
def err_attribute_wrong_decl_type_str : Error<
warn_attribute_wrong_decl_type_str.Summary>;
def warn_attribute_wrong_decl_type : Warning<
- "%0 attribute only applies to %select{"
+ "%0%select{ attribute|}1 only applies to %select{"
"functions"
"|unions"
"|variables and functions"
@@ -3555,13 +3559,15 @@
"|types and namespaces"
"|variables, functions and classes"
"|kernel functions"
- "|non-K&R-style functions}1">,
+ "|non-K&R-style functions}2">,
InGroup<IgnoredAttributes>;
def err_attribute_wrong_decl_type : Error<warn_attribute_wrong_decl_type.Summary>;
def warn_type_attribute_wrong_type : Warning<
"'%0' only applies to %select{function|pointer|"
"Objective-C object or block pointer}1 types; type here is %2">,
InGroup<IgnoredAttributes>;
+def err_type_attribute_wrong_type : Error<
+ warn_type_attribute_wrong_type.Summary>;
def warn_incomplete_encoded_type : Warning<
"encoding of %0 type is incomplete because %1 component has unknown encoding">,
InGroup<DiagGroup<"encode-type">>;
@@ -3612,7 +3618,7 @@
def warn_attribute_not_on_decl : Warning<
"%0 attribute ignored when parsing type">, InGroup<IgnoredAttributes>;
def err_base_specifier_attribute : Error<
- "%0 attribute cannot be applied to a base specifier">;
+ "%0%select{ attribute|}1 cannot be applied to a base specifier">;
def warn_declspec_allocator_nonpointer : Warning<
"ignoring __declspec(allocator) because the function return type %0 is not "
"a pointer or reference type">, InGroup<IgnoredAttributes>;
Index: clang/include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticParseKinds.td
+++ clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -733,10 +733,12 @@
def err_using_attribute_ns_conflict : Error<
"attribute with scope specifier cannot follow default scope specifier">;
def err_attributes_not_allowed : Error<"an attribute list cannot appear here">;
+def err_keyword_not_allowed : Error<"%0 cannot appear here">;
def ext_cxx11_attr_placement : ExtWarn<
- "ISO C++ does not allow an attribute list to appear here">,
+ "ISO C++ does not allow %select{an attribute list|%0}1 to appear here">,
InGroup<DiagGroup<"cxx-attribute-extension">>;
def err_attributes_misplaced : Error<"misplaced attributes; expected attributes here">;
+def err_keyword_misplaced : Error<"misplaced %0; expected %0 here">;
def err_l_square_l_square_not_attribute : Error<
"C++11 only allows consecutive left square brackets when "
"introducing an attribute">;
@@ -1014,14 +1016,15 @@
def err_capture_default_first : Error<
"capture default must be first">;
def ext_decl_attrs_on_lambda : ExtWarn<
- "an attribute specifier sequence in this position is a C++23 extension">,
- InGroup<CXX23>;
+ "%select{an attribute specifier sequence|%0}1 in this position "
+ "is a C++23 extension">, InGroup<CXX23>;
def ext_lambda_missing_parens : ExtWarn<
"lambda without a parameter clause is a C++23 extension">,
InGroup<CXX23>;
def warn_cxx20_compat_decl_attrs_on_lambda : Warning<
- "an attribute specifier sequence in this position is incompatible with C++ "
- "standards before C++23">, InGroup<CXXPre23Compat>, DefaultIgnore;
+ "%select{an attribute specifier sequence|%1}0 in this position "
+ "is incompatible with C++ standards before C++23">,
+ InGroup<CXXPre23Compat>, DefaultIgnore;
// C++17 lambda expressions
def err_expected_star_this_capture : Error<
@@ -1582,8 +1585,12 @@
"expected a module name after '%select{module|import}0'">;
def err_attribute_not_module_attr : Error<
"%0 attribute cannot be applied to a module">;
+def err_keyword_not_module_attr : Error<
+ "%0 cannot be applied to a module">;
def err_attribute_not_import_attr : Error<
"%0 attribute cannot be applied to a module import">;
+def err_keyword_not_import_attr : Error<
+ "%0 cannot be applied to a module import">;
def err_module_expected_semi : Error<
"expected ';' after module name">;
def err_global_module_introducer_not_at_start : Error<
Index: clang/include/clang/Basic/DiagnosticCommonKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticCommonKinds.td
+++ clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -121,7 +121,7 @@
def note_decl_hiding_tag_type : Note<
"%1 %0 is hidden by a non-type declaration of %0 here">;
def err_attribute_not_type_attr : Error<
- "%0 attribute cannot be applied to types">;
+ "%0%select{ attribute|}1 cannot be applied to types">;
def err_enum_template : Error<"enumeration cannot be a template">;
def warn_cxx20_compat_consteval : Warning<
@@ -175,6 +175,8 @@
"unknown attribute %0 ignored">, InGroup<UnknownAttributes>;
def warn_attribute_ignored : Warning<"%0 attribute ignored">,
InGroup<IgnoredAttributes>;
+def err_keyword_not_supported_on_target : Error<
+ "%0 is not supported on this target">;
def err_use_of_tag_name_without_tag : Error<
"must use '%1' tag to refer to type %0%select{| in this scope}2">;
Index: clang/examples/CallSuperAttribute/CallSuperAttrInfo.cpp
===================================================================
--- clang/examples/CallSuperAttribute/CallSuperAttrInfo.cpp
+++ clang/examples/CallSuperAttribute/CallSuperAttrInfo.cpp
@@ -169,7 +169,7 @@
const auto *TheMethod = dyn_cast_or_null<CXXMethodDecl>(D);
if (!TheMethod || !TheMethod->isVirtual()) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
- << Attr << "virtual functions";
+ << Attr << 0 << "virtual functions";
return false;
}
MarkedMethods.insert(TheMethod);
Index: clang/examples/Attribute/Attribute.cpp
===================================================================
--- clang/examples/Attribute/Attribute.cpp
+++ clang/examples/Attribute/Attribute.cpp
@@ -43,7 +43,7 @@
// This attribute appertains to functions only.
if (!isa<FunctionDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
- << Attr << "functions";
+ << Attr << 0 << "functions";
return false;
}
return true;
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits