diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -74,15 +74,27 @@ 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 @@ } } + 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 --- /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}} +{ +}