aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Parse/ParseDecl.cpp
diff options
context:
space:
mode:
authorAaron Ballman <aaron@aaronballman.com>2021-01-27 15:27:53 -0500
committerAaron Ballman <aaron@aaronballman.com>2021-01-27 15:30:15 -0500
commit9f2c7effd7f386e95aff3358500bc30974d35b0d (patch)
tree73c2c747ab70825d018ef09affba78be7cefb1a2 /clang/lib/Parse/ParseDecl.cpp
parent8e6713436462daa43d84f8450d07a54f7657c31b (diff)
downloadllvm-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.cpp35
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: