Skip to content

Commit 8bd0055

Browse files
committed
[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
1 parent d1873d3 commit 8bd0055

File tree

3 files changed

+71
-15
lines changed

3 files changed

+71
-15
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@ Attribute Changes in Clang
9494
locations a declaration attribute may appear.
9595
This fixes `Issue 53805 <https://github.com/llvm/llvm-project/issues/53805>`_.
9696

97+
- Improved namespace attributes handling:
98+
- Handle GNU attributes before a namespace identifier and subsequent
99+
attributes of different kinds.
100+
- Emit error on GNU attributes for a nested namespace definition.
101+
97102
Windows Support
98103
---------------
99104

clang/lib/Parse/ParseDeclCXX.cpp

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,27 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,
7474
SourceLocation FirstNestedInlineLoc;
7575

7676
ParsedAttributesWithRange attrs(AttrFactory);
77-
SourceLocation attrLoc;
78-
if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) {
79-
Diag(Tok.getLocation(), getLangOpts().CPlusPlus17
80-
? diag::warn_cxx14_compat_ns_enum_attribute
81-
: diag::ext_ns_enum_attribute)
82-
<< 0 /*namespace*/;
83-
attrLoc = Tok.getLocation();
84-
ParseCXX11Attributes(attrs);
85-
}
77+
78+
auto ReadAttributes = [&] {
79+
bool MoreToParse;
80+
do {
81+
MoreToParse = false;
82+
if (Tok.is(tok::kw___attribute)) {
83+
ParseGNUAttributes(attrs);
84+
MoreToParse = true;
85+
}
86+
if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) {
87+
Diag(Tok.getLocation(), getLangOpts().CPlusPlus17
88+
? diag::warn_cxx14_compat_ns_enum_attribute
89+
: diag::ext_ns_enum_attribute)
90+
<< 0 /*namespace*/;
91+
ParseCXX11Attributes(attrs);
92+
MoreToParse = true;
93+
}
94+
} while (MoreToParse);
95+
};
96+
97+
ReadAttributes();
8698

8799
if (Tok.is(tok::identifier)) {
88100
Ident = Tok.getIdentifierInfo();
@@ -108,16 +120,14 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,
108120
}
109121
}
110122

123+
ReadAttributes();
124+
125+
SourceLocation attrLoc = attrs.Range.getBegin();
126+
111127
// A nested namespace definition cannot have attributes.
112128
if (!ExtraNSs.empty() && attrLoc.isValid())
113129
Diag(attrLoc, diag::err_unexpected_nested_namespace_attribute);
114130

115-
// Read label attributes, if present.
116-
if (Tok.is(tok::kw___attribute)) {
117-
attrLoc = Tok.getLocation();
118-
ParseGNUAttributes(attrs);
119-
}
120-
121131
if (Tok.is(tok::equal)) {
122132
if (!Ident) {
123133
Diag(Tok, diag::err_expected) << tok::identifier;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// RUN: %clang_cc1 -std=c++17 -verify %s
2+
3+
namespace __attribute__(()) A
4+
{
5+
}
6+
7+
namespace A __attribute__(())
8+
{
9+
}
10+
11+
namespace __attribute__(()) [[]] A
12+
{
13+
}
14+
15+
namespace [[]] __attribute__(()) A
16+
{
17+
}
18+
19+
namespace A __attribute__(()) [[]]
20+
{
21+
}
22+
23+
namespace A [[]] __attribute__(())
24+
{
25+
}
26+
27+
namespace [[]] A __attribute__(())
28+
{
29+
}
30+
31+
namespace __attribute__(()) A [[]]
32+
{
33+
}
34+
35+
namespace A::B __attribute__(()) // expected-error{{attributes cannot be specified on a nested namespace definition}}
36+
{
37+
}
38+
39+
namespace __attribute__(()) A::B // expected-error{{attributes cannot be specified on a nested namespace definition}}
40+
{
41+
}

0 commit comments

Comments
 (0)