Author: Timm Bäder Date: 2021-03-31T16:44:19+02:00 New Revision: 5018e15fdfda855f130cdb78acb88540046853af
URL: https://github.com/llvm/llvm-project/commit/5018e15fdfda855f130cdb78acb88540046853af DIFF: https://github.com/llvm/llvm-project/commit/5018e15fdfda855f130cdb78acb88540046853af.diff LOG: [clang][parser] Allow GNU-style attributes in explicit template... ... instantiations They are currently not being diagnosed because ProhibitAttributes() does not handle attribute lists with an invalid source range. But once it does, we need to allow GNU attributes in this place. Additionally, start optionally diagnosing empty attr lists in ProhibitCXX11Attributes(), since ProhibitAttribute() does it. Differential Revision: https://reviews.llvm.org/D97362 Added: Modified: clang/include/clang/Parse/Parser.h clang/lib/Parse/ParseDecl.cpp clang/lib/Parse/ParseDeclCXX.cpp clang/test/Parser/cxx0x-attributes.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 290b451771a68..b67e541836d59 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -2639,7 +2639,8 @@ class Parser : public CodeCompletionHandler { // which standard permits but we don't supported yet, for example, attributes // appertain to decl specifiers. void ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs, - unsigned DiagID); + unsigned DiagID, + bool DiagnoseEmptyAttrs = false); /// Skip C++11 and C2x attributes and return the end location of the /// last one. diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index a044fbc3039ce..104b1b54f5785 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -1607,7 +1607,30 @@ void Parser::DiagnoseProhibitedAttributes( } void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs, - unsigned DiagID) { + unsigned DiagID, bool DiagnoseEmptyAttrs) { + + if (DiagnoseEmptyAttrs && Attrs.empty() && Attrs.Range.isValid()) { + // An attribute list has been parsed, but it was empty. + // This is the case for [[]]. + const auto &LangOpts = getLangOpts(); + auto &SM = PP.getSourceManager(); + Token FirstLSquare; + Lexer::getRawToken(Attrs.Range.getBegin(), FirstLSquare, SM, LangOpts); + + if (FirstLSquare.is(tok::l_square)) { + llvm::Optional<Token> SecondLSquare = + Lexer::findNextToken(FirstLSquare.getLocation(), SM, LangOpts); + + if (SecondLSquare && SecondLSquare->is(tok::l_square)) { + // The attribute range starts with [[, but is empty. So this must + // be [[]], which we are supposed to diagnose because + // DiagnoseEmptyAttrs is true. + Diag(Attrs.Range.getBegin(), DiagID) << Attrs.Range; + return; + } + } + } + for (const ParsedAttr &AL : Attrs) { if (!AL.isCXX11Attribute() && !AL.isC2xAttribute()) continue; @@ -4630,7 +4653,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, // or opaque-enum-declaration anywhere. if (IsElaboratedTypeSpecifier && !getLangOpts().MicrosoftExt && !getLangOpts().ObjC) { - ProhibitAttributes(attrs); + ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed, + /*DiagnoseEmptyAttrs=*/true); if (BaseType.isUsable()) Diag(BaseRange.getBegin(), diag::ext_enum_base_in_type_specifier) << (AllowEnumSpecifier == AllowDefiningTypeSpec::Yes) << BaseRange; diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 0e9bc42bfcb8f..829ed179f54c3 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1836,7 +1836,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation && TUK == Sema::TUK_Declaration) { // This is an explicit instantiation of a class template. - ProhibitAttributes(attrs); + ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed, + /*DiagnoseEmptyAttrs=*/true); TagOrTempResult = Actions.ActOnExplicitInstantiation( getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, @@ -1932,7 +1933,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TemplateParams ? TemplateParams->size() : 0)); } else { if (TUK != Sema::TUK_Declaration && TUK != Sema::TUK_Definition) - ProhibitAttributes(attrs); + ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed, + /* DiagnoseEmptyAttrs=*/true); if (TUK == Sema::TUK_Definition && TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) { diff --git a/clang/test/Parser/cxx0x-attributes.cpp b/clang/test/Parser/cxx0x-attributes.cpp index 101e03845b8f2..c9b27c1a7b893 100644 --- a/clang/test/Parser/cxx0x-attributes.cpp +++ b/clang/test/Parser/cxx0x-attributes.cpp @@ -179,6 +179,7 @@ struct [[]] N::S s; // expected-error {{an attribute list cannot appear here}} struct [[]] Template<int> t; // expected-error {{an attribute list cannot appear here}} struct [[]] ::template Template<int> u; // expected-error {{an attribute list cannot appear here}} template struct [[]] Template<char>; // expected-error {{an attribute list cannot appear here}} +template struct __attribute__((pure)) Template<std::size_t>; // We still allow GNU-style attributes here template <> struct [[]] Template<void>; enum [[]] E1 {}; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits