Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
-----------------------------------

Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/DiagnosticParseKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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">;
Expand Down
9 changes: 6 additions & 3 deletions clang/lib/Parse/ParseDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,

ParsedAttributes attrs(AttrFactory);

auto ReadAttributes = [&] {
auto ReadAttributes = [&](bool TrailingAttrs) {
bool MoreToParse;
do {
MoreToParse = false;
Expand All @@ -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)
Expand All @@ -100,7 +103,7 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,
} while (MoreToParse);
};

ReadAttributes();
ReadAttributes(/*TrailingAttrs*/ false);

if (Tok.is(tok::identifier)) {
Ident = Tok.getIdentifierInfo();
Expand All @@ -126,7 +129,7 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,
}
}

ReadAttributes();
ReadAttributes(/*TrailingAttrs*/ true);

SourceLocation attrLoc = attrs.Range.getBegin();

Expand Down
10 changes: 5 additions & 5 deletions clang/test/Parser/namespace-attributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,26 @@ 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}}
{
}

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}}
{
}
Loading