From 941af68ab8dad68ed8df65f6e0559476f137bfe2 Mon Sep 17 00:00:00 2001 From: Jerin Philip Date: Sat, 19 Aug 2023 16:43:53 +0530 Subject: [PATCH 01/15] Fix `Form` to recognize `_Alignas` in addition to `alignas` --- clang/include/clang/Basic/AttributeCommonInfo.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/AttributeCommonInfo.h b/clang/include/clang/Basic/AttributeCommonInfo.h index e57adc4bf5b99..36f4eb885cf12 100644 --- a/clang/include/clang/Basic/AttributeCommonInfo.h +++ b/clang/include/clang/Basic/AttributeCommonInfo.h @@ -94,7 +94,7 @@ class AttributeCommonInfo { IsRegularKeywordAttribute(IsRegularKeywordAttribute) {} constexpr Form(tok::TokenKind Tok) : SyntaxUsed(AS_Keyword), SpellingIndex(SpellingNotCalculated), - IsAlignas(Tok == tok::kw_alignas), + IsAlignas(Tok == tok::kw_alignas || Tok == tok::kw__Alignas), IsRegularKeywordAttribute(tok::isRegularKeywordAttribute(Tok)) {} Syntax getSyntax() const { return Syntax(SyntaxUsed); } From 8c0bfe350dfa2d4d24988eb544f5c1a9eb1aec6d Mon Sep 17 00:00:00 2001 From: Jerin Philip Date: Thu, 7 Sep 2023 18:53:57 +0530 Subject: [PATCH 02/15] Avoid mixing `isCXX11Attribute` with `isAlignAs` --- clang/include/clang/Basic/AttributeCommonInfo.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Basic/AttributeCommonInfo.h b/clang/include/clang/Basic/AttributeCommonInfo.h index 36f4eb885cf12..669227589dfac 100644 --- a/clang/include/clang/Basic/AttributeCommonInfo.h +++ b/clang/include/clang/Basic/AttributeCommonInfo.h @@ -186,14 +186,14 @@ class AttributeCommonInfo { bool isGNUScope() const; bool isClangScope() const; - bool isCXX11Attribute() const { return SyntaxUsed == AS_CXX11 || IsAlignas; } + bool isCXX11Attribute() const { return SyntaxUsed == AS_CXX11; } bool isC23Attribute() const { return SyntaxUsed == AS_C23; } /// The attribute is spelled [[]] in either C or C++ mode, including standard /// attributes spelled with a keyword, like alignas. bool isStandardAttributeSyntax() const { - return isCXX11Attribute() || isC23Attribute(); + return isCXX11Attribute() || isC23Attribute() || IsAlignas; } bool isGNUAttribute() const { return SyntaxUsed == AS_GNU; } From 8f699d5dfe62b2a1eb1f67f37ffa3d4ba1f2bfce Mon Sep 17 00:00:00 2001 From: Jerin Philip Date: Thu, 7 Sep 2023 19:15:03 +0530 Subject: [PATCH 03/15] Fix diagnostic warning post `isAlignAs` decoupling --- clang/include/clang/Basic/AttributeCommonInfo.h | 2 +- clang/lib/Parse/ParseDecl.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/Basic/AttributeCommonInfo.h b/clang/include/clang/Basic/AttributeCommonInfo.h index 669227589dfac..f1e3325d44f0e 100644 --- a/clang/include/clang/Basic/AttributeCommonInfo.h +++ b/clang/include/clang/Basic/AttributeCommonInfo.h @@ -186,8 +186,8 @@ class AttributeCommonInfo { bool isGNUScope() const; bool isClangScope() const; + bool isAlignas() const { return IsAlignas; } bool isCXX11Attribute() const { return SyntaxUsed == AS_CXX11; } - bool isC23Attribute() const { return SyntaxUsed == AS_C23; } /// The attribute is spelled [[]] in either C or C++ mode, including standard diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 4a9f2caf65471..f91141f7cd39c 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -3405,8 +3405,8 @@ void Parser::ParseDeclarationSpecifiers( else { // Reject C++11 / C23 attributes that aren't type attributes. for (const ParsedAttr &PA : attrs) { - if (!PA.isCXX11Attribute() && !PA.isC23Attribute() && - !PA.isRegularKeywordAttribute()) + if (!PA.isAlignas() && !PA.isCXX11Attribute() && + !PA.isC23Attribute() && !PA.isRegularKeywordAttribute()) continue; if (PA.getKind() == ParsedAttr::UnknownAttribute) // We will warn about the unknown attribute elsewhere (in From e7ddd755f1a873421809a05a4d5d999b7a15f62e Mon Sep 17 00:00:00 2001 From: Jerin Philip Date: Sat, 19 Aug 2023 16:44:51 +0530 Subject: [PATCH 04/15] Add attribute-ignored diagnostic warning variant --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 0ac4df8edb242..f76f872a98288 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3491,10 +3491,14 @@ def err_attribute_invalid_on_decl : Error< def warn_type_attribute_deprecated_on_decl : Warning< "applying attribute %0 to a declaration is deprecated; apply it to the type instead">, InGroup; -def warn_declspec_attribute_ignored : Warning< +def warn_declspec_attribute_ignored_place_after : Warning< "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; +def warn_declspec_attribute_ignored : Warning< + "attribute %0 before " + "\"%select{class|struct|interface|union|enum|enum class|enum struct}1\" " + "is ignored">, InGroup; 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 " From ca03b9efbd0eaec1904656ce16f2d47915a26f17 Mon Sep 17 00:00:00 2001 From: Jerin Philip Date: Wed, 16 Aug 2023 16:09:52 +0530 Subject: [PATCH 05/15] Fix diagnostic emission for C Alignas --- clang/lib/Sema/SemaDecl.cpp | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index d94366dac102a..97d74b413d3f9 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -27,6 +27,7 @@ #include "clang/AST/Randstruct.h" #include "clang/AST/StmtCXX.h" #include "clang/Basic/Builtins.h" +#include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/HLSLRuntime.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceManager.h" @@ -5339,16 +5340,23 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, TypeSpecType == DeclSpec::TST_interface || TypeSpecType == DeclSpec::TST_union || TypeSpecType == DeclSpec::TST_enum) { - for (const ParsedAttr &AL : DS.getAttributes()) - 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(), AL.isRegularKeywordAttribute() - ? diag::err_declspec_keyword_has_no_effect - : diag::warn_declspec_attribute_ignored) - << AL << GetDiagnosticTypeSpecifierID(DS); + + auto EmitAttributeDiagnostic = [this, &DS](const ParsedAttr &AL) { + if (AL.isAlignas() && !getLangOpts().CPlusPlus) { + Diag(AL.getLoc(), diag::warn_declspec_attribute_ignored) + << AL << GetDiagnosticTypeSpecifierID(DS); + + } else { + Diag(AL.getLoc(), + AL.isRegularKeywordAttribute() + ? diag::err_declspec_keyword_has_no_effect + : diag::warn_declspec_attribute_ignored_place_after) + << AL << GetDiagnosticTypeSpecifierID(DS); + } + }; + + llvm::for_each(DS.getAttributes(), EmitAttributeDiagnostic); + llvm::for_each(DeclAttrs, EmitAttributeDiagnostic); } } From 1c1d4c60ee6cf4349b6ff0aa41a11603022aa425 Mon Sep 17 00:00:00 2001 From: Jerin Philip Date: Thu, 7 Sep 2023 20:06:40 +0530 Subject: [PATCH 06/15] Fix test for C files --- clang/test/C/drs/dr4xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/C/drs/dr4xx.c b/clang/test/C/drs/dr4xx.c index b8ccceaad12c5..0e25952be26f5 100644 --- a/clang/test/C/drs/dr4xx.c +++ b/clang/test/C/drs/dr4xx.c @@ -168,7 +168,7 @@ void dr444(void) { * where the diagnostic recommends causes a different, more inscrutable error * about anonymous structures. */ - _Alignas(int) struct T { /* expected-warning {{attribute '_Alignas' is ignored, place it after "struct" to apply attribute to type declaration}} */ + _Alignas(int) struct T { /* expected-warning {{attribute '_Alignas' before "struct" is ignored}} */ int i; }; From bc968c4c16c1b309e06df457b4c546956b06e6f6 Mon Sep 17 00:00:00 2001 From: Jerin Philip Date: Mon, 16 Oct 2023 12:41:50 +0530 Subject: [PATCH 07/15] Remove accidental header inclusion --- clang/lib/Sema/SemaDecl.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 97d74b413d3f9..5ed2073eea3d6 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -27,7 +27,6 @@ #include "clang/AST/Randstruct.h" #include "clang/AST/StmtCXX.h" #include "clang/Basic/Builtins.h" -#include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/HLSLRuntime.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceManager.h" From e45c9534cae9bc94e2d3aa1dc0abb4c1ffde42d2 Mon Sep 17 00:00:00 2001 From: Jerin Philip Date: Mon, 16 Oct 2023 22:01:19 +0530 Subject: [PATCH 08/15] Simplify DiagnosticId extraction and printing --- clang/lib/Sema/SemaDecl.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 5ed2073eea3d6..9f5aebe5a0fb3 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -5341,17 +5341,18 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, TypeSpecType == DeclSpec::TST_enum) { auto EmitAttributeDiagnostic = [this, &DS](const ParsedAttr &AL) { + unsigned DiagnosticId; if (AL.isAlignas() && !getLangOpts().CPlusPlus) { - Diag(AL.getLoc(), diag::warn_declspec_attribute_ignored) - << AL << GetDiagnosticTypeSpecifierID(DS); - + // Don't use the message with placement with _Alignas. + // This is because C doesnt let you use _Alignas on type declarations. + DiagnosticId = diag::warn_declspec_attribute_ignored; + } else if (AL.isRegularKeywordAttribute()) { + DiagnosticId = diag::err_declspec_keyword_has_no_effect; } else { - Diag(AL.getLoc(), - AL.isRegularKeywordAttribute() - ? diag::err_declspec_keyword_has_no_effect - : diag::warn_declspec_attribute_ignored_place_after) - << AL << GetDiagnosticTypeSpecifierID(DS); + DiagnosticId = diag::warn_declspec_attribute_ignored_place_after; } + Diag(AL.getLoc(), DiagnosticId) + << AL << GetDiagnosticTypeSpecifierID(DS); }; llvm::for_each(DS.getAttributes(), EmitAttributeDiagnostic); From eb5523dfd4c38e14568b4a3137352a1211c7db0e Mon Sep 17 00:00:00 2001 From: Jerin Philip Date: Tue, 17 Oct 2023 00:16:52 +0530 Subject: [PATCH 09/15] Add more tests: cxx0x, c1x-alignas --- clang/test/Parser/c1x-alignas.c | 1 + clang/test/Parser/cxx0x-attributes.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/clang/test/Parser/c1x-alignas.c b/clang/test/Parser/c1x-alignas.c index 8f3d9bdb62d47..76ad9873c37e2 100644 --- a/clang/test/Parser/c1x-alignas.c +++ b/clang/test/Parser/c1x-alignas.c @@ -9,5 +9,6 @@ char c4 _Alignas(32); // expected-error {{expected ';' after top level declarato char _Alignas(_Alignof(int)) c5; +_Alignas(int) struct c6; // expected-warning {{attribute '_Alignas' before "struct" is ignored}} // CHECK-EXT: '_Alignas' is a C11 extension // CHECK-EXT: '_Alignof' is a C11 extension diff --git a/clang/test/Parser/cxx0x-attributes.cpp b/clang/test/Parser/cxx0x-attributes.cpp index 10c5bbcac1022..fad3010c98b9c 100644 --- a/clang/test/Parser/cxx0x-attributes.cpp +++ b/clang/test/Parser/cxx0x-attributes.cpp @@ -451,3 +451,5 @@ namespace P2361 { // expected-warning {{use of the 'deprecated' attribute is a C++14 extension}} [[nodiscard("\123")]] int b(); // expected-error{{invalid escape sequence '\123' in an unevaluated string literal}} } + +alignas(int) struct AlignAsAttribute {}; // expected-error {{misplaced attributes; expected attributes here}} From f8a294e095ee12762a0ac877670212ee6a6eb96c Mon Sep 17 00:00:00 2001 From: Jerin Philip Date: Tue, 17 Oct 2023 01:07:02 +0530 Subject: [PATCH 10/15] Add c2x-alignas tests --- clang/test/Parser/c2x-alignas.c | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 clang/test/Parser/c2x-alignas.c diff --git a/clang/test/Parser/c2x-alignas.c b/clang/test/Parser/c2x-alignas.c new file mode 100644 index 0000000000000..447afa28dd682 --- /dev/null +++ b/clang/test/Parser/c2x-alignas.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -std=c23 -fsyntax-only -verify %s +// RUN: not %clang_cc1 -std=c99 -pedantic -fsyntax-only %s 2>&1 | FileCheck -check-prefix=CHECK-EXT %s + +_Alignas(int) struct c1; // expected-warning {{attribute '_Alignas' before "struct" is ignored}} +alignas(int) struct c1; // expected-warning {{attribute 'alignas' before "struct" is ignored}} From 4345baaa02c5e2d27a727e8b2cf22d95b2842cd9 Mon Sep 17 00:00:00 2001 From: Jerin Philip Date: Tue, 17 Oct 2023 12:18:51 +0530 Subject: [PATCH 11/15] Incorporate Release Note --- clang/docs/ReleaseNotes.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index acce35e231e71..fe0f452c5fd95 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -145,6 +145,11 @@ Attribute Changes in Clang supports but that are never the result of default argument promotion, such as ``float``. (`#59824: `_) +- Clang now warns you that the ``_Alignas`` attribute on declaration specifiers + is ignored, changed from the former incorrect suggestion to move it past + declaration specifiers. + + Improvements to Clang's diagnostics ----------------------------------- - Clang constexpr evaluator now prints template arguments when displaying From e5fa62066c92b30ece7d8957dcba5e1c797e9f54 Mon Sep 17 00:00:00 2001 From: Jerin Philip Date: Sat, 21 Oct 2023 20:34:00 +0530 Subject: [PATCH 12/15] Save temporary work --- .../include/clang/Basic/AttributeCommonInfo.h | 43 +++++++++++++++---- clang/include/clang/Sema/DeclSpec.h | 21 ++++++--- clang/lib/Parse/ParseCXXInlineMethods.cpp | 3 +- clang/lib/Parse/ParseDecl.cpp | 4 +- clang/lib/Parse/ParseDeclCXX.cpp | 4 +- clang/lib/Sema/SemaDeclAttr.cpp | 7 +-- clang/lib/Sema/SemaStmtAttr.cpp | 8 ++-- clang/test/Sema/alignas.c | 2 + 8 files changed, 67 insertions(+), 25 deletions(-) diff --git a/clang/include/clang/Basic/AttributeCommonInfo.h b/clang/include/clang/Basic/AttributeCommonInfo.h index f1e3325d44f0e..d6bdd81b6bdcc 100644 --- a/clang/include/clang/Basic/AttributeCommonInfo.h +++ b/clang/include/clang/Basic/AttributeCommonInfo.h @@ -78,6 +78,7 @@ class AttributeCommonInfo { unsigned SpellingIndex : 4; unsigned IsAlignas : 1; unsigned IsRegularKeywordAttribute : 1; + unsigned Tok : 4; protected: static constexpr unsigned SpellingNotCalculated = 0xf; @@ -91,14 +92,17 @@ class AttributeCommonInfo { bool IsRegularKeywordAttribute) : SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingIndex), IsAlignas(IsAlignas), - IsRegularKeywordAttribute(IsRegularKeywordAttribute) {} + IsRegularKeywordAttribute(IsRegularKeywordAttribute), + Tok(tok::TokenKind::unknown) {} constexpr Form(tok::TokenKind Tok) : SyntaxUsed(AS_Keyword), SpellingIndex(SpellingNotCalculated), IsAlignas(Tok == tok::kw_alignas || Tok == tok::kw__Alignas), - IsRegularKeywordAttribute(tok::isRegularKeywordAttribute(Tok)) {} + IsRegularKeywordAttribute(tok::isRegularKeywordAttribute(Tok)), + Tok(Tok) {} Syntax getSyntax() const { return Syntax(SyntaxUsed); } unsigned getSpellingIndex() const { return SpellingIndex; } + unsigned getTok() const { return Tok; } bool isAlignas() const { return IsAlignas; } bool isRegularKeywordAttribute() const { return IsRegularKeywordAttribute; } @@ -119,12 +123,14 @@ class AttributeCommonInfo { private: constexpr Form(Syntax SyntaxUsed) : SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingNotCalculated), - IsAlignas(0), IsRegularKeywordAttribute(0) {} + IsAlignas(0), IsRegularKeywordAttribute(0), + Tok(tok::TokenKind::unknown) {} unsigned SyntaxUsed : 4; unsigned SpellingIndex : 4; unsigned IsAlignas : 1; unsigned IsRegularKeywordAttribute : 1; + unsigned Tok : 4; }; AttributeCommonInfo(const IdentifierInfo *AttrName, @@ -135,7 +141,8 @@ class AttributeCommonInfo { SyntaxUsed(FormUsed.getSyntax()), SpellingIndex(FormUsed.getSpellingIndex()), IsAlignas(FormUsed.isAlignas()), - IsRegularKeywordAttribute(FormUsed.isRegularKeywordAttribute()) { + IsRegularKeywordAttribute(FormUsed.isRegularKeywordAttribute()), + Tok(FormUsed.getTok()) { assert(SyntaxUsed >= AS_GNU && SyntaxUsed <= AS_Implicit && "Invalid syntax!"); } @@ -182,18 +189,36 @@ class AttributeCommonInfo { bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; } bool isMicrosoftAttribute() const { return SyntaxUsed == AS_Microsoft; } + bool isCXX11Attribute() const { return SyntaxUsed == AS_CXX11; } + bool isC23Attribute() const { return SyntaxUsed == AS_C23; } bool isGNUScope() const; bool isClangScope() const; bool isAlignas() const { return IsAlignas; } - bool isCXX11Attribute() const { return SyntaxUsed == AS_CXX11; } - bool isC23Attribute() const { return SyntaxUsed == AS_C23; } - /// The attribute is spelled [[]] in either C or C++ mode, including standard - /// attributes spelled with a keyword, like alignas. + /// Can be treated attribute-specifier in C++ + /// [[]] || alignas() + bool isCXX11AttributeSpecifier() const { + return SyntaxUsed == AS_CXX11 || Tok == tok::TokenKind::kw_alignas; + } + + /// Can be treated attribute-specifier in C + /// [[]] || alignas(...) || _Alignas(...) + /// + /// Note: `attribute-specifier` and `alignment-specifier` are different per + /// C23-standard, but is treated similarly by this function. + bool isCAttributeSpecifier() const { + bool isCAlignAs = (Tok == tok::TokenKind::kw_alignas || + Tok == tok::TokenKind::kw__Alignas); + return SyntaxUsed == AS_C23 || isCAlignAs; + } + + /// Can be treated attribute-specifier either of + /// * C : [[]] || alignas(...) || _Alignas(...) + /// * C++: [[]] || alignas(...) bool isStandardAttributeSyntax() const { - return isCXX11Attribute() || isC23Attribute() || IsAlignas; + return isCXX11AttributeSpecifier() || isCAttributeSpecifier(); } bool isGNUAttribute() const { return SyntaxUsed == AS_GNU; } diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index ff5e2e2e57366..1043a20f00e9a 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -37,6 +37,8 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" +#include + namespace clang { class ASTContext; class CXXRecordDecl; @@ -1970,11 +1972,20 @@ class Declarator { DeclarationAttrs(DeclarationAttrs), AsmLabel(nullptr), TrailingRequiresClause(nullptr), InventedTemplateParameterList(nullptr) { - assert(llvm::all_of(DeclarationAttrs, - [](const ParsedAttr &AL) { - return (AL.isStandardAttributeSyntax() || - AL.isRegularKeywordAttribute()); - }) && + if (!(DeclarationAttrs.empty() || + llvm::all_of(DeclarationAttrs, [](const ParsedAttr &AL) { + return (AL.isStandardAttributeSyntax() || + AL.isRegularKeywordAttribute()); + }))) { + + std::raise(SIGTRAP); + } + assert((DeclarationAttrs.empty() || + llvm::all_of(DeclarationAttrs, + [](const ParsedAttr &AL) { + return (AL.isStandardAttributeSyntax() || + AL.isRegularKeywordAttribute()); + })) && "DeclarationAttrs may only contain [[]] and keyword attributes"); } diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp index 573c90a36eeab..c415ca86a3dc9 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -767,7 +767,8 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA, Diag(Tok, diag::warn_attribute_no_decl) << LA.AttrName.getName(); } - if (OnDefinition && !Attrs.empty() && !Attrs.begin()->isCXX11Attribute() && + if (OnDefinition && !Attrs.empty() && + !Attrs.begin()->isCXX11AttributeSpecifier() && Attrs.begin()->isKnownToGCC()) Diag(Tok, diag::warn_attribute_on_function_definition) << &LA.AttrName; diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index f91141f7cd39c..80da057d86b06 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -3405,8 +3405,8 @@ void Parser::ParseDeclarationSpecifiers( else { // Reject C++11 / C23 attributes that aren't type attributes. for (const ParsedAttr &PA : attrs) { - if (!PA.isAlignas() && !PA.isCXX11Attribute() && - !PA.isC23Attribute() && !PA.isRegularKeywordAttribute()) + if (!PA.isStandardAttributeSyntax() && + !PA.isRegularKeywordAttribute()) continue; if (PA.getKind() == ParsedAttr::UnknownAttribute) // We will warn about the unknown attribute elsewhere (in diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 730b6e55246d6..deef9269482d1 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -2562,7 +2562,7 @@ bool Parser::ParseCXXMemberDeclaratorBeforeInitializer( // If we saw any GNU-style attributes that are known to GCC followed by a // virt-specifier, issue a GCC-compat warning. for (const ParsedAttr &AL : DeclaratorInfo.getAttributes()) - if (AL.isKnownToGCC() && !AL.isCXX11Attribute()) + if (AL.isKnownToGCC() && !AL.isCXX11AttributeSpecifier()) Diag(AL.getLoc(), diag::warn_gcc_attribute_location); MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(DeclaratorInfo, @@ -3057,7 +3057,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // Diagnose attributes that appear in a friend member function declarator: // friend int foo [[]] (); for (const ParsedAttr &AL : DeclaratorInfo.getAttributes()) - if (AL.isCXX11Attribute() || AL.isRegularKeywordAttribute()) { + if (AL.isCXX11AttributeSpecifier() || AL.isRegularKeywordAttribute()) { auto Loc = AL.getRange().getBegin(); (AL.isRegularKeywordAttribute() ? Diag(Loc, diag::err_keyword_not_allowed) << AL diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 59e0f3e83cfdd..4d2c013781c13 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -2342,7 +2342,7 @@ static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D, } static void handleUnusedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - bool IsCXX17Attr = AL.isCXX11Attribute() && !AL.getScopeName(); + bool IsCXX17Attr = AL.isCXX11AttributeSpecifier() && !AL.getScopeName(); // If this is spelled as the standard C++17 attribute, but not in C++17, warn // about using it as an extension. @@ -8178,7 +8178,8 @@ static void handleDeprecatedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { !S.checkStringLiteralArgumentAttr(AL, 1, Replacement)) return; - if (!S.getLangOpts().CPlusPlus14 && AL.isCXX11Attribute() && !AL.isGNUScope()) + if (!S.getLangOpts().CPlusPlus14 && AL.isCXX11AttributeSpecifier() && + !AL.isGNUScope()) S.Diag(AL.getLoc(), diag::ext_cxx14_attr) << AL; D->addAttr(::new (S.Context) DeprecatedAttr(S.Context, AL, Str, Replacement)); @@ -8723,7 +8724,7 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, // Ignore C++11 attributes on declarator chunks: they appertain to the type // instead. - if (AL.isCXX11Attribute() && !Options.IncludeCXX11Attributes) + if (AL.isCXX11AttributeSpecifier() && !Options.IncludeCXX11Attributes) return; // Unknown attributes are automatically warned on. Target-specific attributes diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index ad20bc8871f10..3096d35acb5bf 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -43,7 +43,7 @@ static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const ParsedAttr &A, // If this is spelled as the standard C++17 attribute, but not in C++17, warn // about using it as an extension. - if (!S.getLangOpts().CPlusPlus17 && A.isCXX11Attribute() && + if (!S.getLangOpts().CPlusPlus17 && A.isCXX11AttributeSpecifier() && !A.getScopeName()) S.Diag(A.getLoc(), diag::ext_cxx17_attr) << A; @@ -307,7 +307,8 @@ static Attr *handleMustTailAttr(Sema &S, Stmt *St, const ParsedAttr &A, static Attr *handleLikely(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range) { - if (!S.getLangOpts().CPlusPlus20 && A.isCXX11Attribute() && !A.getScopeName()) + if (!S.getLangOpts().CPlusPlus20 && A.isCXX11AttributeSpecifier() && + !A.getScopeName()) S.Diag(A.getLoc(), diag::ext_cxx20_attr) << A << Range; return ::new (S.Context) LikelyAttr(S.Context, A); @@ -316,7 +317,8 @@ static Attr *handleLikely(Sema &S, Stmt *St, const ParsedAttr &A, static Attr *handleUnlikely(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range) { - if (!S.getLangOpts().CPlusPlus20 && A.isCXX11Attribute() && !A.getScopeName()) + if (!S.getLangOpts().CPlusPlus20 && A.isCXX11AttributeSpecifier() && + !A.getScopeName()) S.Diag(A.getLoc(), diag::ext_cxx20_attr) << A << Range; return ::new (S.Context) UnlikelyAttr(S.Context, A); diff --git a/clang/test/Sema/alignas.c b/clang/test/Sema/alignas.c index 020eff6a141c0..5243283a9128b 100644 --- a/clang/test/Sema/alignas.c +++ b/clang/test/Sema/alignas.c @@ -17,6 +17,8 @@ void f(_Alignas(1) char c) { // expected-error {{'_Alignas' attribute cannot be _Alignas(1) register char k; // expected-error {{'_Alignas' attribute cannot be applied to a variable with 'register' storage class}} } +_Alignas(int) struct alignas_before { int content;}; // expected-warning {{attribute '_Alignas' before "struct" is ignored}} + #ifdef USING_C11_SYNTAX // expected-warning@+4{{'_Alignof' applied to an expression is a GNU extension}} // expected-warning@+4{{'_Alignof' applied to an expression is a GNU extension}} From e7671282de8ceb8d46e5383252cbf5e09f673e4c Mon Sep 17 00:00:00 2001 From: Jerin Philip Date: Sat, 21 Oct 2023 20:42:33 +0530 Subject: [PATCH 13/15] This fails fewer tests, but cruft --- clang/include/clang/Basic/AttributeCommonInfo.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/AttributeCommonInfo.h b/clang/include/clang/Basic/AttributeCommonInfo.h index d6bdd81b6bdcc..7e95010cdf758 100644 --- a/clang/include/clang/Basic/AttributeCommonInfo.h +++ b/clang/include/clang/Basic/AttributeCommonInfo.h @@ -200,7 +200,8 @@ class AttributeCommonInfo { /// Can be treated attribute-specifier in C++ /// [[]] || alignas() bool isCXX11AttributeSpecifier() const { - return SyntaxUsed == AS_CXX11 || Tok == tok::TokenKind::kw_alignas; + return SyntaxUsed == AS_CXX11 || + (IsAlignas && Tok != tok::TokenKind::kw__Alignas); } /// Can be treated attribute-specifier in C From a9636f397618bd30e8439837c2358bd5ddfda0df Mon Sep 17 00:00:00 2001 From: Jerin Philip Date: Sat, 21 Oct 2023 22:15:50 +0530 Subject: [PATCH 14/15] Make the C23 alignas a FIXME --- clang/test/Parser/c2x-alignas.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/clang/test/Parser/c2x-alignas.c b/clang/test/Parser/c2x-alignas.c index 447afa28dd682..69d6116c11eed 100644 --- a/clang/test/Parser/c2x-alignas.c +++ b/clang/test/Parser/c2x-alignas.c @@ -1,5 +1,10 @@ // RUN: %clang_cc1 -std=c23 -fsyntax-only -verify %s -// RUN: not %clang_cc1 -std=c99 -pedantic -fsyntax-only %s 2>&1 | FileCheck -check-prefix=CHECK-EXT %s _Alignas(int) struct c1; // expected-warning {{attribute '_Alignas' before "struct" is ignored}} -alignas(int) struct c1; // expected-warning {{attribute 'alignas' before "struct" is ignored}} + +// FIXME: This is meant to behave the same as _Alignas, as in C23, `alignas` is a +// keyword and `_Alignas` is an alternate spelling. +// However, `alignas` is a keyword in C++ since CXX11, and is baked into +// parsing code, will need a more holistic fix to treat it also as C23 +// `alignas`. +alignas(int) struct c2; // expected-error {{misplaced attributes; expected attributes here}} From 1fcde531080899b3f5870c41ba9da052cae519ab Mon Sep 17 00:00:00 2001 From: Jerin Philip Date: Sat, 21 Oct 2023 22:23:25 +0530 Subject: [PATCH 15/15] Oops, overdid that one, correct --- clang/lib/Sema/SemaDeclAttr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 4d2c013781c13..6b3d3f243e37f 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -8724,7 +8724,7 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, // Ignore C++11 attributes on declarator chunks: they appertain to the type // instead. - if (AL.isCXX11AttributeSpecifier() && !Options.IncludeCXX11Attributes) + if (AL.isCXX11Attribute() && !Options.IncludeCXX11Attributes) return; // Unknown attributes are automatically warned on. Target-specific attributes