https://github.com/a-tarasyuk updated https://github.com/llvm/llvm-project/pull/121614
>From b8f6ffc0a98a0d3ac55fba4e6ee680f1edea4571 Mon Sep 17 00:00:00 2001 From: Oleksandr T <oleksandr.taras...@outlook.com> Date: Sat, 4 Jan 2025 02:24:26 +0200 Subject: [PATCH 1/4] [Clang] disallow attributes after namespace identifier --- clang/docs/ReleaseNotes.rst | 2 ++ clang/include/clang/Basic/DiagnosticParseKinds.td | 2 ++ clang/lib/Parse/ParseDeclCXX.cpp | 9 ++++++--- clang/test/Parser/namespace-attributes.cpp | 10 +++++----- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index e0aef1af2135cd..43a95fd022c070 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -553,6 +553,8 @@ Attribute Changes in Clang - Clang now permits the usage of the placement new operator in ``[[msvc::constexpr]]`` context outside of the std namespace. (#GH74924) +- Clang now disallows the use of attributes after the namespace name. (#GH121407) + Improvements to Clang's diagnostics ----------------------------------- diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 86fcae209c40db..9d76376cd6b015 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -283,6 +283,8 @@ def err_unexpected_qualified_namespace_alias : Error< "namespace alias must be a single identifier">; def err_unexpected_nested_namespace_attribute : Error< "attributes cannot be specified on a nested namespace definition">; +def err_attribute_after_namespace : Error< + "standard attributes cannot appear after the namespace name">; def err_inline_namespace_alias : Error<"namespace alias cannot be inline">; def err_namespace_nonnamespace_scope : Error< "namespaces can only be defined in global or namespace scope">; diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index f30603feb65c5d..ec87163ffb7cee 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -81,7 +81,7 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, ParsedAttributes attrs(AttrFactory); - auto ReadAttributes = [&] { + auto ReadAttributes = [&](bool TrailingAttrs) { bool MoreToParse; do { MoreToParse = false; @@ -90,6 +90,9 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, MoreToParse = true; } if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) { + if (TrailingAttrs) + Diag(Tok.getLocation(), diag::err_attribute_after_namespace); + Diag(Tok.getLocation(), getLangOpts().CPlusPlus17 ? diag::warn_cxx14_compat_ns_enum_attribute : diag::ext_ns_enum_attribute) @@ -100,7 +103,7 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, } while (MoreToParse); }; - ReadAttributes(); + ReadAttributes(/*TrailingAttrs*/ false); if (Tok.is(tok::identifier)) { Ident = Tok.getIdentifierInfo(); @@ -126,7 +129,7 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, } } - ReadAttributes(); + ReadAttributes(/*TrailingAttrs*/ true); SourceLocation attrLoc = attrs.Range.getBegin(); diff --git a/clang/test/Parser/namespace-attributes.cpp b/clang/test/Parser/namespace-attributes.cpp index 9f925b742dfebd..8a873c55c5d633 100644 --- a/clang/test/Parser/namespace-attributes.cpp +++ b/clang/test/Parser/namespace-attributes.cpp @@ -16,11 +16,11 @@ namespace [[]] __attribute__(()) A { } -namespace A __attribute__(()) [[]] +namespace A __attribute__(()) [[]] // expected-error {{standard attributes cannot appear after the namespace name}} { } -namespace A [[]] __attribute__(()) +namespace A [[]] __attribute__(()) // expected-error {{standard attributes cannot appear after the namespace name}} { } @@ -28,14 +28,14 @@ namespace [[]] A __attribute__(()) { } -namespace __attribute__(()) A [[]] +namespace __attribute__(()) A [[]] // expected-error {{standard attributes cannot appear after the namespace name}} { } -namespace A::B __attribute__(()) // expected-error{{attributes cannot be specified on a nested namespace definition}} +namespace A::B __attribute__(()) // expected-error {{attributes cannot be specified on a nested namespace definition}} { } -namespace __attribute__(()) A::B // expected-error{{attributes cannot be specified on a nested namespace definition}} +namespace __attribute__(()) A::B // expected-error {{attributes cannot be specified on a nested namespace definition}} { } >From b8bf77687644c035683ae64a0a2a8e788ad74a83 Mon Sep 17 00:00:00 2001 From: Oleksandr T <oleksandr.taras...@outlook.com> Date: Sun, 5 Jan 2025 12:07:40 +0200 Subject: [PATCH 2/4] change param name from TrailingAttrs to CheckProhibitedCXX11Attribute --- clang/lib/Parse/ParseDeclCXX.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index ec87163ffb7cee..7b810bb66138d3 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -81,7 +81,7 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, ParsedAttributes attrs(AttrFactory); - auto ReadAttributes = [&](bool TrailingAttrs) { + auto ReadAttributes = [&](bool CheckProhibitedCXX11Attribute) { bool MoreToParse; do { MoreToParse = false; @@ -90,7 +90,7 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, MoreToParse = true; } if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) { - if (TrailingAttrs) + if (CheckProhibitedCXX11Attribute) Diag(Tok.getLocation(), diag::err_attribute_after_namespace); Diag(Tok.getLocation(), getLangOpts().CPlusPlus17 @@ -103,7 +103,7 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, } while (MoreToParse); }; - ReadAttributes(/*TrailingAttrs*/ false); + ReadAttributes(/*CheckProhibitedCXX11Attribute*/ false); if (Tok.is(tok::identifier)) { Ident = Tok.getIdentifierInfo(); @@ -129,7 +129,7 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, } } - ReadAttributes(/*TrailingAttrs*/ true); + ReadAttributes(/*CheckProhibitedCXX11Attribute*/ true); SourceLocation attrLoc = attrs.Range.getBegin(); >From c752a8af98f688557673e5b7b975cc6f2a669740 Mon Sep 17 00:00:00 2001 From: Oleksandr T <oleksandr.taras...@outlook.com> Date: Mon, 6 Jan 2025 00:20:04 +0200 Subject: [PATCH 3/4] refactor attributes handling to use existing helpers --- .../clang/Basic/DiagnosticParseKinds.td | 2 -- clang/lib/Parse/ParseDeclCXX.cpp | 36 +++++++------------ clang/test/Parser/namespace-attributes.cpp | 21 +++-------- 3 files changed, 17 insertions(+), 42 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 9d76376cd6b015..86fcae209c40db 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -283,8 +283,6 @@ def err_unexpected_qualified_namespace_alias : Error< "namespace alias must be a single identifier">; def err_unexpected_nested_namespace_attribute : Error< "attributes cannot be specified on a nested namespace definition">; -def err_attribute_after_namespace : Error< - "standard attributes cannot appear after the namespace name">; def err_inline_namespace_alias : Error<"namespace alias cannot be inline">; def err_namespace_nonnamespace_scope : Error< "namespaces can only be defined in global or namespace scope">; diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 7b810bb66138d3..7d4146d5c833fd 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -81,29 +81,15 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, ParsedAttributes attrs(AttrFactory); - auto ReadAttributes = [&](bool CheckProhibitedCXX11Attribute) { - bool MoreToParse; - do { - MoreToParse = false; - if (Tok.is(tok::kw___attribute)) { - ParseGNUAttributes(attrs); - MoreToParse = true; - } - if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) { - if (CheckProhibitedCXX11Attribute) - Diag(Tok.getLocation(), diag::err_attribute_after_namespace); - - Diag(Tok.getLocation(), getLangOpts().CPlusPlus17 - ? diag::warn_cxx14_compat_ns_enum_attribute - : diag::ext_ns_enum_attribute) - << 0 /*namespace*/; - ParseCXX11Attributes(attrs); - MoreToParse = true; - } - } while (MoreToParse); - }; - - ReadAttributes(/*CheckProhibitedCXX11Attribute*/ false); + MaybeParseGNUAttributes(attrs); + if (isAllowedCXX11AttributeSpecifier()) { + if (getLangOpts().CPlusPlus11) + Diag(Tok.getLocation(), getLangOpts().CPlusPlus17 + ? diag::warn_cxx14_compat_ns_enum_attribute + : diag::ext_ns_enum_attribute) + << 0 /*namespace*/; + ParseCXX11Attributes(attrs); + } if (Tok.is(tok::identifier)) { Ident = Tok.getIdentifierInfo(); @@ -129,7 +115,9 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, } } - ReadAttributes(/*CheckProhibitedCXX11Attribute*/ true); + MaybeParseGNUAttributes(attrs); + if (Tok.is(tok::l_square)) + CheckProhibitedCXX11Attribute(); SourceLocation attrLoc = attrs.Range.getBegin(); diff --git a/clang/test/Parser/namespace-attributes.cpp b/clang/test/Parser/namespace-attributes.cpp index 8a873c55c5d633..b199db2ed38810 100644 --- a/clang/test/Parser/namespace-attributes.cpp +++ b/clang/test/Parser/namespace-attributes.cpp @@ -4,31 +4,20 @@ namespace __attribute__(()) A { } -namespace A __attribute__(()) +namespace A __attribute__(()) [[]] // expected-error {{an attribute list cannot appear here}} { } -namespace __attribute__(()) [[]] A -{ -} - -namespace [[]] __attribute__(()) A -{ -} - -namespace A __attribute__(()) [[]] // expected-error {{standard attributes cannot appear after the namespace name}} -{ -} - -namespace A [[]] __attribute__(()) // expected-error {{standard attributes cannot appear after the namespace name}} -{ +namespace A [[]] __attribute__(()) // expected-error {{an attribute list cannot appear here}} \ + // expected-error {{expected '{'}} +{ // expected-error {{expected unqualified-id}} } namespace [[]] A __attribute__(()) { } -namespace __attribute__(()) A [[]] // expected-error {{standard attributes cannot appear after the namespace name}} +namespace __attribute__(()) A [[]] // expected-error {{an attribute list cannot appear here}} { } >From f5780f08194f157dd84723c00043e9894015c4c0 Mon Sep 17 00:00:00 2001 From: Oleksandr T <oleksandr.taras...@outlook.com> Date: Mon, 6 Jan 2025 00:46:56 +0200 Subject: [PATCH 4/4] handle GNU/CXX11 attributes before namespace name --- clang/lib/Parse/ParseDeclCXX.cpp | 21 +++++++++++---------- clang/test/Parser/namespace-attributes.cpp | 13 ++++++++++--- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 7d4146d5c833fd..fddb8a5729ee8c 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -81,14 +81,15 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, ParsedAttributes attrs(AttrFactory); - MaybeParseGNUAttributes(attrs); - if (isAllowedCXX11AttributeSpecifier()) { - if (getLangOpts().CPlusPlus11) - Diag(Tok.getLocation(), getLangOpts().CPlusPlus17 - ? diag::warn_cxx14_compat_ns_enum_attribute - : diag::ext_ns_enum_attribute) - << 0 /*namespace*/; - ParseCXX11Attributes(attrs); + while (MaybeParseGNUAttributes(attrs) || isAllowedCXX11AttributeSpecifier()) { + if (isAllowedCXX11AttributeSpecifier()) { + if (getLangOpts().CPlusPlus11) + Diag(Tok.getLocation(), getLangOpts().CPlusPlus17 + ? diag::warn_cxx14_compat_ns_enum_attribute + : diag::ext_ns_enum_attribute) + << 0 /*namespace*/; + ParseCXX11Attributes(attrs); + } } if (Tok.is(tok::identifier)) { @@ -115,9 +116,9 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, } } + DiagnoseAndSkipCXX11Attributes(); MaybeParseGNUAttributes(attrs); - if (Tok.is(tok::l_square)) - CheckProhibitedCXX11Attribute(); + DiagnoseAndSkipCXX11Attributes(); SourceLocation attrLoc = attrs.Range.getBegin(); diff --git a/clang/test/Parser/namespace-attributes.cpp b/clang/test/Parser/namespace-attributes.cpp index b199db2ed38810..11bf8711cfad5d 100644 --- a/clang/test/Parser/namespace-attributes.cpp +++ b/clang/test/Parser/namespace-attributes.cpp @@ -8,15 +8,22 @@ namespace A __attribute__(()) [[]] // expected-error {{an attribute list cannot { } -namespace A [[]] __attribute__(()) // expected-error {{an attribute list cannot appear here}} \ - // expected-error {{expected '{'}} -{ // expected-error {{expected unqualified-id}} +namespace A [[]] __attribute__(()) // expected-error {{an attribute list cannot appear here}} +{ } namespace [[]] A __attribute__(()) { } +namespace [[]] __attribute__(()) A +{ +} + +namespace __attribute__(()) [[]] A +{ +} + namespace __attribute__(()) A [[]] // expected-error {{an attribute list cannot appear here}} { } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits