[cfe-commits] r72279 - /cfe/trunk/lib/Parse/ParseExprCXX.cpp
Argiris Kirtzidis
akyrtzi at gmail.com
Fri May 22 14:09:48 PDT 2009
Author: akirtzidis
Date: Fri May 22 16:09:47 2009
New Revision: 72279
URL: http://llvm.org/viewvc/llvm-project?rev=72279&view=rev
Log:
The disambiguation process for ambiguous paren expressions is not "side effects free", e.g:
(T(*)(int[x+y]));
is an (invalid) paren expression, but "x+y" will be parsed as part of the (rejected) type-id,
so unnecessary Action calls are made for an unused (and possibly leaked) "x+y".
Use a different scheme, similar to parsing inline methods. The parenthesized tokens are cached,
the context that follows is determined (possibly by parsing a cast-expression),
and then we re-introduce the cached tokens into the token stream and parse them appropriately.
Modified:
cfe/trunk/lib/Parse/ParseExprCXX.cpp
Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=72279&r1=72278&r2=72279&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Fri May 22 16:09:47 2009
@@ -1067,68 +1067,82 @@
//
// The good news is that the parser can disambiguate this part without
// making any unnecessary Action calls.
-
- // Start tentantive parsing.
- TentativeParsingAction PA(*this);
-
- // Parse the type-id but don't create a type with ActOnTypeName yet.
- DeclSpec DS;
- ParseSpecifierQualifierList(DS);
-
- // Parse the abstract-declarator, if present.
- Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
- ParseDeclarator(DeclaratorInfo);
-
- if (!Tok.is(tok::r_paren)) {
- PA.Commit();
+ //
+ // It uses a scheme similar to parsing inline methods. The parenthesized
+ // tokens are cached, the context that follows is determined (possibly by
+ // parsing a cast-expression), and then we re-introduce the cached tokens
+ // into the token stream and parse them appropriately.
+
+ ParenParseOption ParseAs;
+ CachedTokens Toks;
+
+ // Store the tokens of the parentheses. We will parse them after we determine
+ // the context that follows them.
+ if (!ConsumeAndStoreUntil(tok::r_paren, tok::unknown, Toks, tok::semi)) {
+ // We didn't find the ')' we expected.
MatchRHSPunctuation(tok::r_paren, LParenLoc);
return ExprError();
}
- RParenLoc = ConsumeParen();
-
if (Tok.is(tok::l_brace)) {
- // Compound literal. Ok, we can commit the parsed tokens and continue
- // normal parsing.
- ExprType = CompoundLiteral;
- PA.Commit();
- TypeResult Ty = true;
- if (!DeclaratorInfo.isInvalidType())
- Ty = Actions.ActOnTypeName(CurScope, DeclaratorInfo);
- return ParseCompoundLiteralExpression(Ty.get(), LParenLoc, RParenLoc);
+ ParseAs = CompoundLiteral;
+ } else {
+ bool NotCastExpr;
+ // Try parsing the cast-expression that may follow.
+ // If it is not a cast-expression, NotCastExpr will be true and no token
+ // will be consumed.
+ Result = ParseCastExpression(false/*isUnaryExpression*/,
+ false/*isAddressofOperand*/,
+ NotCastExpr);
+
+ // If we parsed a cast-expression, it's really a type-id, otherwise it's
+ // an expression.
+ ParseAs = NotCastExpr ? SimpleExpr : CastExpr;
}
- // We parsed '(' type-name ')' and the thing after it wasn't a '{'.
+ // The current token should go after the cached tokens.
+ Toks.push_back(Tok);
+ // Re-enter the stored parenthesized tokens into the token stream, so we may
+ // parse them now.
+ PP.EnterTokenStream(Toks.data(), Toks.size(),
+ true/*DisableMacroExpansion*/, false/*OwnsTokens*/);
+ // Drop the current token and bring the first cached one. It's the same token
+ // as when we entered this function.
+ ConsumeAnyToken();
+
+ if (ParseAs >= CompoundLiteral) {
+ TypeResult Ty = ParseTypeName();
+
+ // Match the ')'.
+ if (Tok.is(tok::r_paren))
+ RParenLoc = ConsumeParen();
+ else
+ MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+ if (ParseAs == CompoundLiteral) {
+ ExprType = CompoundLiteral;
+ return ParseCompoundLiteralExpression(Ty.get(), LParenLoc, RParenLoc);
+ }
+
+ // We parsed '(' type-id ')' and the thing after it wasn't a '{'.
+ assert(ParseAs == CastExpr);
- if (DeclaratorInfo.isInvalidType()) {
- PA.Commit();
- return ExprError();
- }
+ if (Ty.isInvalid())
+ return ExprError();
- bool NotCastExpr;
- // Parse the cast-expression that follows it next.
- Result = ParseCastExpression(false/*isUnaryExpression*/,
- false/*isAddressofOperand*/,
- NotCastExpr);
-
- if (NotCastExpr == false) {
- // We parsed a cast-expression. That means it's really a type-id, so commit
- // the parsed tokens and continue normal parsing.
- PA.Commit();
- TypeResult Ty = Actions.ActOnTypeName(CurScope, DeclaratorInfo);
CastTy = Ty.get();
+
+ // Result is what ParseCastExpression returned earlier.
if (!Result.isInvalid())
Result = Actions.ActOnCastExpr(LParenLoc, CastTy, RParenLoc,move(Result));
return move(Result);
}
+
+ // Not a compound literal, and not followed by a cast-expression.
+ assert(ParseAs == SimpleExpr);
- // If we get here, the things after the parens are not the start of
- // a cast-expression. This means we must actually parse the tokens inside
- // the parens as an expression.
- PA.Revert();
-
- Result = ParseExpression();
ExprType = SimpleExpr;
+ Result = ParseExpression();
if (!Result.isInvalid() && Tok.is(tok::r_paren))
Result = Actions.ActOnParenExpr(LParenLoc, Tok.getLocation(), move(Result));
@@ -1137,7 +1151,7 @@
SkipUntil(tok::r_paren);
return ExprError();
}
-
+
if (Tok.is(tok::r_paren))
RParenLoc = ConsumeParen();
else
More information about the cfe-commits
mailing list