diff options
author | Aaron Ballman <aaron@aaronballman.com> | 2021-01-27 15:27:53 -0500 |
---|---|---|
committer | Aaron Ballman <aaron@aaronballman.com> | 2021-01-27 15:30:15 -0500 |
commit | 9f2c7effd7f386e95aff3358500bc30974d35b0d (patch) | |
tree | 73c2c747ab70825d018ef09affba78be7cefb1a2 /clang/lib/Parse/ParseDecl.cpp | |
parent | 8e6713436462daa43d84f8450d07a54f7657c31b (diff) | |
download | llvm-9f2c7effd7f386e95aff3358500bc30974d35b0d.zip llvm-9f2c7effd7f386e95aff3358500bc30974d35b0d.tar.gz llvm-9f2c7effd7f386e95aff3358500bc30974d35b0d.tar.bz2 |
Parse different attribute syntaxes in arbitrary order
In Clang today, we parse the different attribute syntaxes
(__attribute__, __declspec, and [[]]) in a fairly rigid order. This
leads to confusion for users when they guess the order incorrectly,
and leads to bug reports like PR24559 or necessitates changes like
D94788.
This patch adds a helper function to allow us to more easily parse
attributes in arbitrary order, and then updates all of the places
where we would parse two or more different syntaxes in a rigid order to
use the helper method. The patch does not attempt to handle Microsoft
attributes ([]) because those are ambiguous with other code constructs
and we don't have any attributes that use the syntax.
Diffstat (limited to 'clang/lib/Parse/ParseDecl.cpp')
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 35 |
1 files changed, 23 insertions, 12 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 57116413..6a0ba51 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -103,6 +103,24 @@ static bool FindLocsWithCommonFileID(Preprocessor &PP, SourceLocation StartLoc, return AttrStartIsInMacro && AttrEndIsInMacro; } +void Parser::ParseAttributes(unsigned WhichAttrKinds, + ParsedAttributesWithRange &Attrs, + SourceLocation *End, + LateParsedAttrList *LateAttrs) { + bool MoreToParse; + do { + // Assume there's nothing left to parse, but if any attributes are in fact + // parsed, loop to ensure all specified attribute combinations are parsed. + MoreToParse = false; + if (WhichAttrKinds & PAKM_CXX11) + MoreToParse |= MaybeParseCXX11Attributes(Attrs, End); + if (WhichAttrKinds & PAKM_GNU) + MoreToParse |= MaybeParseGNUAttributes(Attrs, End, LateAttrs); + if (WhichAttrKinds & PAKM_Declspec) + MoreToParse |= MaybeParseMicrosoftDeclSpecs(Attrs, End); + } while (MoreToParse); +} + /// ParseGNUAttributes - Parse a non-empty attributes list. /// /// [GNU] attributes: @@ -3485,14 +3503,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, continue; } - // GNU attributes support. + // Attributes support. case tok::kw___attribute: - ParseGNUAttributes(DS.getAttributes(), nullptr, LateAttrs); - continue; - - // Microsoft declspec support. case tok::kw___declspec: - ParseMicrosoftDeclSpecs(DS.getAttributes()); + ParseAttributes(PAKM_GNU | PAKM_Declspec, DS.getAttributes(), nullptr, + LateAttrs); continue; // Microsoft single token adornments. @@ -4354,9 +4369,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, // If attributes exist after tag, parse them. ParsedAttributesWithRange attrs(AttrFactory); - MaybeParseGNUAttributes(attrs); - MaybeParseCXX11Attributes(attrs); - MaybeParseMicrosoftDeclSpecs(attrs); + MaybeParseAttributes(PAKM_GNU | PAKM_Declspec | PAKM_CXX11, attrs); SourceLocation ScopedEnumKWLoc; bool IsScopedUsingClassTag = false; @@ -4373,9 +4386,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, ProhibitAttributes(attrs); // They are allowed afterwards, though. - MaybeParseGNUAttributes(attrs); - MaybeParseCXX11Attributes(attrs); - MaybeParseMicrosoftDeclSpecs(attrs); + MaybeParseAttributes(PAKM_GNU | PAKM_Declspec | PAKM_CXX11, attrs); } // C++11 [temp.explicit]p12: |