Handle correctly a very ugly part of the C++ syntax. We cannot disambiguate between a parenthesized type-id and
a paren expression without considering the context past the parentheses.
Behold:
(T())x; - type-id
(T())*x; - type-id
(T())/x; - expression
(T()); - expression
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72260 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 12ba001..5c06386 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -400,6 +400,23 @@
/// id-expression that is the operand of address-of gets special treatment
/// due to member pointers.
///
+Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
+ bool isAddressOfOperand) {
+ bool NotCastExpr;
+ OwningExprResult Res = ParseCastExpression(isUnaryExpression,
+ isAddressOfOperand,
+ NotCastExpr);
+ if (NotCastExpr)
+ Diag(Tok, diag::err_expected_expression);
+ return move(Res);
+}
+
+/// ParseCastExpression - Parse a cast-expression, or, if isUnaryExpression is
+/// true, parse a unary-expression. isAddressOfOperand exists because an
+/// id-expression that is the operand of address-of gets special treatment
+/// due to member pointers. NotCastExpr is set to true if the token is not the
+/// start of a cast-expression, and no diagnostic is emitted in this case.
+///
/// cast-expression: [C99 6.5.4]
/// unary-expression
/// '(' type-name ')' cast-expression
@@ -506,9 +523,11 @@
/// '__is_base_of' [TODO]
///
Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
- bool isAddressOfOperand) {
+ bool isAddressOfOperand,
+ bool &NotCastExpr) {
OwningExprResult Res(Actions);
tok::TokenKind SavedKind = Tok.getKind();
+ NotCastExpr = false;
// This handles all of cast-expression, unary-expression, postfix-expression,
// and primary-expression. We handle them together like this for efficiency
@@ -797,7 +816,7 @@
return ParsePostfixExpressionSuffix(ParseObjCMessageExpression());
// FALL THROUGH.
default:
- Diag(Tok, diag::err_expected_expression);
+ NotCastExpr = true;
return ExprError();
}
@@ -1216,6 +1235,7 @@
GreaterThanIsOperatorScope G(GreaterThanIsOperator, true);
SourceLocation OpenLoc = ConsumeParen();
OwningExprResult Result(Actions, true);
+ bool isAmbiguousTypeId;
CastTy = 0;
if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) {
@@ -1227,9 +1247,20 @@
if (!Stmt.isInvalid() && Tok.is(tok::r_paren))
Result = Actions.ActOnStmtExpr(OpenLoc, move(Stmt), Tok.getLocation());
- } else if (ExprType >= CompoundLiteral && isTypeIdInParens()) {
+ } else if (ExprType >= CompoundLiteral &&
+ isTypeIdInParens(isAmbiguousTypeId)) {
// Otherwise, this is a compound literal expression or cast expression.
+
+ // In C++, if the type-id is ambiguous we disambiguate based on context.
+ // If stopIfCastExpr is true the context is a typeof/sizeof/alignof
+ // in which case we should treat it as type-id.
+ // if stopIfCastExpr is false, we need to determine the context past the
+ // parens, so we defer to ParseCXXAmbiguousParenExpression for that.
+ if (isAmbiguousTypeId && !stopIfCastExpr)
+ return ParseCXXAmbiguousParenExpression(ExprType, CastTy,
+ OpenLoc, RParenLoc);
+
TypeResult Ty = ParseTypeName();
// Match the ')'.