summaryrefslogtreecommitdiffstats
path: root/clang/lib/Parse/ParseDecl.cpp
diff options
context:
space:
mode:
authorAaron Ballman <aaron@aaronballman.com>2014-03-31 17:32:39 +0000
committerAaron Ballman <aaron@aaronballman.com>2014-03-31 17:32:39 +0000
commitb8e203939e19618ebf73ee5c85901914e3060af1 (patch)
treef80ac9cdcfd1690f51ac4254e6616495ebb8d23b /clang/lib/Parse/ParseDecl.cpp
parent4b293ebbaa96e75ea5f819e82be284d59ce436ad (diff)
downloadbcm5719-llvm-b8e203939e19618ebf73ee5c85901914e3060af1.tar.gz
bcm5719-llvm-b8e203939e19618ebf73ee5c85901914e3060af1.zip
Introduced an attribute syntax-neutral method for parsing attribute arguments that is currently being used by GNU and C++-style attributes. This allows C++11 attributes with argument lists to be handled properly, fixing the "deprecated", "type_visibility", and capability-related attributes with arguments.
llvm-svn: 205226
Diffstat (limited to 'clang/lib/Parse/ParseDecl.cpp')
-rw-r--r--clang/lib/Parse/ParseDecl.cpp113
1 files changed, 61 insertions, 52 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 552a50218f5..540bc8ef607 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -259,6 +259,65 @@ void Parser::ParseAttributeWithTypeArg(IdentifierInfo &AttrName,
0, AttrNameLoc, 0, 0, AttributeList::AS_GNU);
}
+void Parser::ParseAttributeArgsCommon(
+ IdentifierInfo *AttrName, SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc, AttributeList::Syntax Syntax) {
+ // Ignore the left paren location for now.
+ ConsumeParen();
+
+ ArgsVector ArgExprs;
+ if (Tok.is(tok::identifier)) {
+ // If this attribute wants an 'identifier' argument, make it so.
+ bool IsIdentifierArg = attributeHasIdentifierArg(*AttrName);
+ AttributeList::Kind AttrKind =
+ AttributeList::getKind(AttrName, ScopeName, Syntax);
+
+ // If we don't know how to parse this attribute, but this is the only
+ // token in this argument, assume it's meant to be an identifier.
+ if (AttrKind == AttributeList::UnknownAttribute ||
+ AttrKind == AttributeList::IgnoredAttribute) {
+ const Token &Next = NextToken();
+ IsIdentifierArg = Next.is(tok::r_paren) || Next.is(tok::comma);
+ }
+
+ if (IsIdentifierArg)
+ ArgExprs.push_back(ParseIdentifierLoc());
+ }
+
+ if (!ArgExprs.empty() ? Tok.is(tok::comma) : Tok.isNot(tok::r_paren)) {
+ // Eat the comma.
+ if (!ArgExprs.empty())
+ ConsumeToken();
+
+ // Parse the non-empty comma-separated list of expressions.
+ do {
+ std::unique_ptr<EnterExpressionEvaluationContext> Unevaluated;
+ if (attributeParsedArgsUnevaluated(*AttrName))
+ Unevaluated.reset(
+ new EnterExpressionEvaluationContext(Actions, Sema::Unevaluated));
+
+ ExprResult ArgExpr(ParseAssignmentExpression());
+ if (ArgExpr.isInvalid()) {
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return;
+ }
+ ArgExprs.push_back(ArgExpr.release());
+ // Eat the comma, move to the next argument
+ } while (TryConsumeToken(tok::comma));
+ }
+
+ SourceLocation RParen = Tok.getLocation();
+ if (!ExpectAndConsume(tok::r_paren)) {
+ SourceLocation AttrLoc = ScopeLoc.isValid() ? ScopeLoc : AttrNameLoc;
+ Attrs.addNew(AttrName, SourceRange(AttrLoc, RParen), ScopeName, ScopeLoc,
+ ArgExprs.data(), ArgExprs.size(), Syntax);
+ }
+
+ if (EndLoc)
+ *EndLoc = RParen;
+}
+
/// Parse the arguments to a parameterized GNU attribute or
/// a C++11 attribute in "gnu" namespace.
void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
@@ -314,58 +373,8 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
}
}
- // Ignore the left paren location for now.
- ConsumeParen();
-
- ArgsVector ArgExprs;
-
- if (Tok.is(tok::identifier)) {
- // If this attribute wants an 'identifier' argument, make it so.
- bool IsIdentifierArg = attributeHasIdentifierArg(*AttrName);
-
- // If we don't know how to parse this attribute, but this is the only
- // token in this argument, assume it's meant to be an identifier.
- if (AttrKind == AttributeList::UnknownAttribute ||
- AttrKind == AttributeList::IgnoredAttribute) {
- const Token &Next = NextToken();
- IsIdentifierArg = Next.is(tok::r_paren) || Next.is(tok::comma);
- }
-
- if (IsIdentifierArg)
- ArgExprs.push_back(ParseIdentifierLoc());
- }
-
- if (!ArgExprs.empty() ? Tok.is(tok::comma) : Tok.isNot(tok::r_paren)) {
- // Eat the comma.
- if (!ArgExprs.empty())
- ConsumeToken();
-
- // Parse the non-empty comma-separated list of expressions.
- do {
- std::unique_ptr<EnterExpressionEvaluationContext> Unevaluated;
- if (attributeParsedArgsUnevaluated(*AttrName))
- Unevaluated.reset(new EnterExpressionEvaluationContext(Actions,
- Sema::Unevaluated));
-
- ExprResult ArgExpr(ParseAssignmentExpression());
- if (ArgExpr.isInvalid()) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return;
- }
- ArgExprs.push_back(ArgExpr.release());
- // Eat the comma, move to the next argument
- } while (TryConsumeToken(tok::comma));
- }
-
- SourceLocation RParen = Tok.getLocation();
- if (!ExpectAndConsume(tok::r_paren)) {
- SourceLocation AttrLoc = ScopeLoc.isValid() ? ScopeLoc : AttrNameLoc;
- Attrs.addNew(AttrName, SourceRange(AttrLoc, RParen), ScopeName, ScopeLoc,
- ArgExprs.data(), ArgExprs.size(), Syntax);
- }
-
- if (EndLoc)
- *EndLoc = RParen;
+ ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
+ ScopeLoc, Syntax);
}
/// \brief Parses a single argument for a declspec, including the
OpenPOWER on IntegriCloud