diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index e9efc45fff2b0b347fd7dd724be95b57b4fd5d06..9c94feb96e996f4dbcfa8a7bce941396b09f28fe 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -561,6 +561,9 @@ def warn_cxx98_compat_noexcept_expr : Warning< def warn_cxx98_compat_nullptr : Warning< "'nullptr' is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; +def warn_cxx14_compat_attribute : Warning< + "attribute on %0 declarations are incompatible with C++ standards before " + "C++1z">, InGroup<CXXPre1zCompat>, DefaultIgnore; def warn_cxx98_compat_alignas : Warning<"'alignas' is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; def warn_cxx98_compat_attribute : Warning< diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 69347520489641bd3ee8c5df3b7c1a044bd884a3..bc162fc6978f55c270944cdf6a1c7073b59149ce 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -3812,8 +3812,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, /// enumerator /// enumerator-list ',' enumerator /// enumerator: -/// enumeration-constant -/// enumeration-constant '=' constant-expression +/// enumeration-constant attributes[opt] +/// enumeration-constant attributes[opt] '=' constant-expression /// enumeration-constant: /// identifier /// @@ -3850,8 +3850,13 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { // If attributes exist after the enumerator, parse them. ParsedAttributesWithRange attrs(AttrFactory); MaybeParseGNUAttributes(attrs); - MaybeParseCXX11Attributes(attrs); - ProhibitAttributes(attrs); + ProhibitAttributes(attrs); // GNU-style attributes are prohibited. + if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) { + if (!getLangOpts().CPlusPlus1z) + Diag(Tok.getLocation(), diag::warn_cxx14_compat_attribute) + << "enumerator"; + ParseCXX11Attributes(attrs); + } SourceLocation EqualLoc; ExprResult AssignedVal; diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 223046c90d92850d2585d0fd7b0ecae86c2f1c66..1f56c8ba3b5814e476db9135de5aba1a193ee8c4 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -73,7 +73,14 @@ Decl *Parser::ParseNamespace(unsigned Context, std::vector<IdentifierInfo*> ExtraIdent; std::vector<SourceLocation> ExtraNamespaceLoc; - Token attrTok; + ParsedAttributesWithRange attrs(AttrFactory); + SourceLocation attrLoc; + if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) { + if (!getLangOpts().CPlusPlus1z) + Diag(Tok.getLocation(), diag::warn_cxx14_compat_attribute) << "namespace"; + attrLoc = Tok.getLocation(); + ParseCXX11Attributes(attrs); + } if (Tok.is(tok::identifier)) { Ident = Tok.getIdentifierInfo(); @@ -86,9 +93,8 @@ Decl *Parser::ParseNamespace(unsigned Context, } // Read label attributes, if present. - ParsedAttributes attrs(AttrFactory); if (Tok.is(tok::kw___attribute)) { - attrTok = Tok; + attrLoc = Tok.getLocation(); ParseGNUAttributes(attrs); } @@ -99,8 +105,8 @@ Decl *Parser::ParseNamespace(unsigned Context, SkipUntil(tok::semi); return nullptr; } - if (!attrs.empty()) - Diag(attrTok, diag::err_unexpected_namespace_attributes_alias); + if (attrLoc.isValid()) + Diag(attrLoc, diag::err_unexpected_namespace_attributes_alias); if (InlineLoc.isValid()) Diag(InlineLoc, diag::err_inline_namespace_alias) << FixItHint::CreateRemoval(InlineLoc); diff --git a/test/Parser/cxx0x-attributes.cpp b/test/Parser/cxx0x-attributes.cpp index f8abc76fb2f3cb584d81868bf3ac6f95f37d9ac8..3c36a6e1dc4182a8400b46ade40d3abe12b62ac4 100644 --- a/test/Parser/cxx0x-attributes.cpp +++ b/test/Parser/cxx0x-attributes.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 -Wc++14-compat %s // Need std::initializer_list namespace std { @@ -121,6 +121,7 @@ extern "C++" [[]] { } // expected-error {{an attribute list cannot appear here}} [[]] using ns::i; // expected-error {{an attribute list cannot appear here}} [[unknown]] using namespace ns; // expected-warning {{unknown attribute 'unknown' ignored}} [[noreturn]] using namespace ns; // expected-error {{'noreturn' attribute only applies to functions}} +namespace [[]] ns2 {} // expected-warning {{attribute on namespace declarations are incompatible with C++ standards before C++1z}} using [[]] alignas(4) [[]] ns::i; // expected-error {{an attribute list cannot appear here}} using [[]] alignas(4) [[]] foobar = int; // expected-error {{an attribute list cannot appear here}} expected-error {{'alignas' attribute only applies to}} @@ -172,7 +173,7 @@ enum [[]] E2; // expected-error {{forbids forward references}} enum [[]] E1; enum [[]] E3 : int; enum [[]] { - k_123 [[]] = 123 // expected-error {{an attribute list cannot appear here}} + k_123 [[]] = 123 // expected-warning {{attribute on enumerator declarations are incompatible with C++ standards before C++1z}} }; enum [[]] E1 e; // expected-error {{an attribute list cannot appear here}} enum [[]] class E4 { }; // expected-error {{an attribute list cannot appear here}} diff --git a/test/Parser/cxx1z-attributes.cpp b/test/Parser/cxx1z-attributes.cpp new file mode 100644 index 0000000000000000000000000000000000000000..52b0a53ad8fbbe7f60788f3f7f9f9fbe8709b0a6 --- /dev/null +++ b/test/Parser/cxx1z-attributes.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z %s + +namespace [[]] foo {} +namespace [[]] {} +namespace [[]] bad = foo; // expected-error {{attributes cannot be specified on namespace alias}} + +enum test { + bing [[]], + bar [[]] = 1, + baz [[]][[]], + quux [[]][[]] = 4 +}; diff --git a/www/cxx_status.html b/www/cxx_status.html index 345226b92a071366b97c51d3b97311ea23b61e34..1ba41064589943ba6502559fa21756a1b7ad872b 100644 --- a/www/cxx_status.html +++ b/www/cxx_status.html @@ -562,6 +562,11 @@ as the draft C++1z standard evolves.</p> <td><!--<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4230.html">-->N4230<!--</a>--></td> <td class="svn" align="center">SVN</td> </tr> + <tr> + <td>Attributes for namespaces and enumerators</td> + <td><!--<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4266.html">-->N4266<!--</a>--></td> + <td class="svn" align="center">SVN</td> + </tr> </table> <h2 id="ts">Technical specifications and standing documents</h2>