diff options
Diffstat (limited to 'lib/Parse/ParseExpr.cpp')
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 37 |
1 files changed, 34 insertions, 3 deletions
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 12ba001f0e..5c063868bb 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -400,6 +400,23 @@ Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, unsigned MinPrec) { /// 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 @@ Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, unsigned MinPrec) { /// '__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 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression, return ParsePostfixExpressionSuffix(ParseObjCMessageExpression()); // FALL THROUGH. default: - Diag(Tok, diag::err_expected_expression); + NotCastExpr = true; return ExprError(); } @@ -1216,6 +1235,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, 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 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, 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 ')'. |