From: Timm Bäder Date: Wed, 3 Mar 2021 09:45:07 +0000 (+0100) Subject: [clang][parser] Allow GNU-style attributes in explicit template... X-Git-Tag: llvmorg-14-init~10801 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5018e15fdfda855f130cdb78acb88540046853af;p=platform%2Fupstream%2Fllvm.git [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 --- diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 290b451..b67e541 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -2639,7 +2639,8 @@ private: // 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 a044fbc..104b1b5 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 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 0e9bc42b..829ed17 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 101e03845..c9b27c1 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 t; // expected-error {{an attribute list cannot appear here}} struct [[]] ::template Template u; // expected-error {{an attribute list cannot appear here}} template struct [[]] Template; // expected-error {{an attribute list cannot appear here}} +template struct __attribute__((pure)) Template; // We still allow GNU-style attributes here template <> struct [[]] Template; enum [[]] E1 {};