Author: Aleksandr Platonov Date: 2022-03-15T22:30:22+03:00 New Revision: 8bd00557e3f43b46a96cf0e357d5e65624c85a2b
URL: https://github.com/llvm/llvm-project/commit/8bd00557e3f43b46a96cf0e357d5e65624c85a2b DIFF: https://github.com/llvm/llvm-project/commit/8bd00557e3f43b46a96cf0e357d5e65624c85a2b.diff LOG: [clang][parser] Allow GNU attributes before namespace identifier GCC supports: - `namespace <gnu attributes> identifier` - `namespace identifier <gnu attributes>` But clang supports only `namespace identifier <gnu attributes>` and diagnostics for `namespace <gnu attributes> identifier` case looks unclear: Code: ``` namespace __attribute__((visibility("hidden"))) A { } ``` Diags: ``` test.cpp:1:49: error: expected identifier or '{' namespace __attribute__((visibility("hidden"))) A ^ test.cpp:1:49: error: C++ requires a type specifier for all declarations test.cpp:3:2: error: expected ';' after top level declarator } ``` This patch adds support for `namespace <gnu attributes> identifier` and also forbids gnu attributes for nested namespaces (this already done for C++ attributes). Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D121245 Added: clang/test/Parser/namespace-attributes.cpp Modified: clang/docs/ReleaseNotes.rst clang/lib/Parse/ParseDeclCXX.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 2422c8f2cba7a..ed79b647ed794 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -94,6 +94,11 @@ Attribute Changes in Clang locations a declaration attribute may appear. This fixes `Issue 53805 <https://github.com/llvm/llvm-project/issues/53805>`_. +- Improved namespace attributes handling: + - Handle GNU attributes before a namespace identifier and subsequent + attributes of diff erent kinds. + - Emit error on GNU attributes for a nested namespace definition. + Windows Support --------------- diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 4ac3baba0d689..77fc504ebe462 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -74,15 +74,27 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, SourceLocation FirstNestedInlineLoc; ParsedAttributesWithRange attrs(AttrFactory); - SourceLocation attrLoc; - if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) { - Diag(Tok.getLocation(), getLangOpts().CPlusPlus17 - ? diag::warn_cxx14_compat_ns_enum_attribute - : diag::ext_ns_enum_attribute) - << 0 /*namespace*/; - attrLoc = Tok.getLocation(); - ParseCXX11Attributes(attrs); - } + + auto ReadAttributes = [&] { + bool MoreToParse; + do { + MoreToParse = false; + if (Tok.is(tok::kw___attribute)) { + ParseGNUAttributes(attrs); + MoreToParse = true; + } + if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) { + 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(); if (Tok.is(tok::identifier)) { Ident = Tok.getIdentifierInfo(); @@ -108,16 +120,14 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, } } + ReadAttributes(); + + SourceLocation attrLoc = attrs.Range.getBegin(); + // A nested namespace definition cannot have attributes. if (!ExtraNSs.empty() && attrLoc.isValid()) Diag(attrLoc, diag::err_unexpected_nested_namespace_attribute); - // Read label attributes, if present. - if (Tok.is(tok::kw___attribute)) { - attrLoc = Tok.getLocation(); - ParseGNUAttributes(attrs); - } - if (Tok.is(tok::equal)) { if (!Ident) { Diag(Tok, diag::err_expected) << tok::identifier; diff --git a/clang/test/Parser/namespace-attributes.cpp b/clang/test/Parser/namespace-attributes.cpp new file mode 100644 index 0000000000000..9f925b742dfeb --- /dev/null +++ b/clang/test/Parser/namespace-attributes.cpp @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -std=c++17 -verify %s + +namespace __attribute__(()) A +{ +} + +namespace A __attribute__(()) +{ +} + +namespace __attribute__(()) [[]] A +{ +} + +namespace [[]] __attribute__(()) A +{ +} + +namespace A __attribute__(()) [[]] +{ +} + +namespace A [[]] __attribute__(()) +{ +} + +namespace [[]] A __attribute__(()) +{ +} + +namespace __attribute__(()) A [[]] +{ +} + +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}} +{ +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits