[clang] 8bd0055 - [clang][parser] Allow GNU attributes before namespace identifier
Aleksandr Platonov via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 15 12:31:45 PDT 2022
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}}
+{
+}
More information about the cfe-commits
mailing list