diff options
Diffstat (limited to 'clang/lib/Parse/ParseExpr.cpp')
-rw-r--r-- | clang/lib/Parse/ParseExpr.cpp | 302 |
1 files changed, 256 insertions, 46 deletions
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index b74a95a3cd4b..1442df046bb9 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -22,6 +22,7 @@ #include "clang/Parse/Parser.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ExprCXX.h" #include "clang/Basic/PrettyStackTrace.h" #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" @@ -145,7 +146,7 @@ Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) { // Silence extension warnings in the sub-expression ExtensionRAIIObject O(Diags); - LHS = ParseCastExpression(false); + LHS = ParseCastExpression(AnyCastExpr); } if (!LHS.isInvalid()) @@ -169,7 +170,7 @@ ExprResult Parser::ParseAssignmentExpression(TypeCastState isTypeCast) { if (Tok.is(tok::kw_co_yield)) return ParseCoyieldExpression(); - ExprResult LHS = ParseCastExpression(/*isUnaryExpression=*/false, + ExprResult LHS = ParseCastExpression(AnyCastExpr, /*isAddressOfOperand=*/false, isTypeCast); return ParseRHSOfBinaryExpression(LHS, prec::Assignment); @@ -202,7 +203,7 @@ Parser::ParseConstantExpressionInExprEvalContext(TypeCastState isTypeCast) { Sema::ExpressionEvaluationContext::ConstantEvaluated && "Call this function only if your ExpressionEvaluationContext is " "already ConstantEvaluated"); - ExprResult LHS(ParseCastExpression(false, false, isTypeCast)); + ExprResult LHS(ParseCastExpression(AnyCastExpr, false, isTypeCast)); ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); return Actions.ActOnConstantExpression(Res); } @@ -220,7 +221,7 @@ ExprResult Parser::ParseConstantExpression(TypeCastState isTypeCast) { ExprResult Parser::ParseCaseExpression(SourceLocation CaseLoc) { EnterExpressionEvaluationContext ConstantEvaluated( Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); - ExprResult LHS(ParseCastExpression(false, false, NotTypeCast)); + ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast)); ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); return Actions.ActOnCaseExpr(CaseLoc, Res); } @@ -234,13 +235,141 @@ ExprResult Parser::ParseCaseExpression(SourceLocation CaseLoc) { ExprResult Parser::ParseConstraintExpression() { EnterExpressionEvaluationContext ConstantEvaluated( Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); - ExprResult LHS(ParseCastExpression(/*isUnaryExpression=*/false)); + ExprResult LHS(ParseCastExpression(AnyCastExpr)); ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::LogicalOr)); - if (Res.isUsable() && !Actions.CheckConstraintExpression(Res.get())) + if (Res.isUsable() && !Actions.CheckConstraintExpression(Res.get())) { + Actions.CorrectDelayedTyposInExpr(Res); return ExprError(); + } return Res; } +/// \brief Parse a constraint-logical-and-expression. +/// +/// \verbatim +/// C++2a[temp.constr.decl]p1 +/// constraint-logical-and-expression: +/// primary-expression +/// constraint-logical-and-expression '&&' primary-expression +/// +/// \endverbatim +ExprResult +Parser::ParseConstraintLogicalAndExpression(bool IsTrailingRequiresClause) { + EnterExpressionEvaluationContext ConstantEvaluated( + Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); + bool NotPrimaryExpression = false; + auto ParsePrimary = [&] () { + ExprResult E = ParseCastExpression(PrimaryExprOnly, + /*isAddressOfOperand=*/false, + /*isTypeCast=*/NotTypeCast, + /*isVectorLiteral=*/false, + &NotPrimaryExpression); + if (E.isInvalid()) + return ExprError(); + auto RecoverFromNonPrimary = [&] (ExprResult E, bool Note) { + E = ParsePostfixExpressionSuffix(E); + // Use InclusiveOr, the precedence just after '&&' to not parse the + // next arguments to the logical and. + E = ParseRHSOfBinaryExpression(E, prec::InclusiveOr); + if (!E.isInvalid()) + Diag(E.get()->getExprLoc(), + Note + ? diag::note_unparenthesized_non_primary_expr_in_requires_clause + : diag::err_unparenthesized_non_primary_expr_in_requires_clause) + << FixItHint::CreateInsertion(E.get()->getBeginLoc(), "(") + << FixItHint::CreateInsertion( + PP.getLocForEndOfToken(E.get()->getEndLoc()), ")") + << E.get()->getSourceRange(); + return E; + }; + + if (NotPrimaryExpression || + // Check if the following tokens must be a part of a non-primary + // expression + getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator, + /*CPlusPlus11=*/true) > prec::LogicalAnd || + // Postfix operators other than '(' (which will be checked for in + // CheckConstraintExpression). + Tok.isOneOf(tok::period, tok::plusplus, tok::minusminus) || + (Tok.is(tok::l_square) && !NextToken().is(tok::l_square))) { + E = RecoverFromNonPrimary(E, /*Note=*/false); + if (E.isInvalid()) + return ExprError(); + NotPrimaryExpression = false; + } + bool PossibleNonPrimary; + bool IsConstraintExpr = + Actions.CheckConstraintExpression(E.get(), Tok, &PossibleNonPrimary, + IsTrailingRequiresClause); + if (!IsConstraintExpr || PossibleNonPrimary) { + // Atomic constraint might be an unparenthesized non-primary expression + // (such as a binary operator), in which case we might get here (e.g. in + // 'requires 0 + 1 && true' we would now be at '+', and parse and ignore + // the rest of the addition expression). Try to parse the rest of it here. + if (PossibleNonPrimary) + E = RecoverFromNonPrimary(E, /*Note=*/!IsConstraintExpr); + Actions.CorrectDelayedTyposInExpr(E); + return ExprError(); + } + return E; + }; + ExprResult LHS = ParsePrimary(); + if (LHS.isInvalid()) + return ExprError(); + while (Tok.is(tok::ampamp)) { + SourceLocation LogicalAndLoc = ConsumeToken(); + ExprResult RHS = ParsePrimary(); + if (RHS.isInvalid()) { + Actions.CorrectDelayedTyposInExpr(LHS); + return ExprError(); + } + ExprResult Op = Actions.ActOnBinOp(getCurScope(), LogicalAndLoc, + tok::ampamp, LHS.get(), RHS.get()); + if (!Op.isUsable()) { + Actions.CorrectDelayedTyposInExpr(RHS); + Actions.CorrectDelayedTyposInExpr(LHS); + return ExprError(); + } + LHS = Op; + } + return LHS; +} + +/// \brief Parse a constraint-logical-or-expression. +/// +/// \verbatim +/// C++2a[temp.constr.decl]p1 +/// constraint-logical-or-expression: +/// constraint-logical-and-expression +/// constraint-logical-or-expression '||' +/// constraint-logical-and-expression +/// +/// \endverbatim +ExprResult +Parser::ParseConstraintLogicalOrExpression(bool IsTrailingRequiresClause) { + ExprResult LHS(ParseConstraintLogicalAndExpression(IsTrailingRequiresClause)); + if (!LHS.isUsable()) + return ExprError(); + while (Tok.is(tok::pipepipe)) { + SourceLocation LogicalOrLoc = ConsumeToken(); + ExprResult RHS = + ParseConstraintLogicalAndExpression(IsTrailingRequiresClause); + if (!RHS.isUsable()) { + Actions.CorrectDelayedTyposInExpr(LHS); + return ExprError(); + } + ExprResult Op = Actions.ActOnBinOp(getCurScope(), LogicalOrLoc, + tok::pipepipe, LHS.get(), RHS.get()); + if (!Op.isUsable()) { + Actions.CorrectDelayedTyposInExpr(RHS); + Actions.CorrectDelayedTyposInExpr(LHS); + return ExprError(); + } + LHS = Op; + } + return LHS; +} + bool Parser::isNotExpressionStart() { tok::TokenKind K = Tok.getKind(); if (K == tok::l_brace || K == tok::r_brace || @@ -414,7 +543,7 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { } else if (getLangOpts().CPlusPlus && NextTokPrec <= prec::Conditional) RHS = ParseAssignmentExpression(); else - RHS = ParseCastExpression(false); + RHS = ParseCastExpression(AnyCastExpr); if (RHS.isInvalid()) { // FIXME: Errors generated by the delayed typo correction should be @@ -519,22 +648,24 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { } } -/// Parse a cast-expression, or, if \p isUnaryExpression is true, -/// parse a unary-expression. +/// Parse a cast-expression, unary-expression or primary-expression, based +/// on \p ExprType. /// /// \p isAddressOfOperand exists because an id-expression that is the /// operand of address-of gets special treatment due to member pointers. /// -ExprResult Parser::ParseCastExpression(bool isUnaryExpression, +ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, bool isAddressOfOperand, TypeCastState isTypeCast, - bool isVectorLiteral) { + bool isVectorLiteral, + bool *NotPrimaryExpression) { bool NotCastExpr; - ExprResult Res = ParseCastExpression(isUnaryExpression, + ExprResult Res = ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr, isTypeCast, - isVectorLiteral); + isVectorLiteral, + NotPrimaryExpression); if (NotCastExpr) Diag(Tok, diag::err_expected_expression); return Res; @@ -759,11 +890,12 @@ class CastExpressionIdValidator final : public CorrectionCandidateCallback { /// '__is_rvalue_expr' /// \endverbatim /// -ExprResult Parser::ParseCastExpression(bool isUnaryExpression, +ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, bool isAddressOfOperand, bool &NotCastExpr, TypeCastState isTypeCast, - bool isVectorLiteral) { + bool isVectorLiteral, + bool *NotPrimaryExpression) { ExprResult Res; tok::TokenKind SavedKind = Tok.getKind(); auto SavedType = PreferredType; @@ -782,11 +914,21 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, // ParsePostfixExpressionSuffix. switch (SavedKind) { case tok::l_paren: { - // If this expression is limited to being a unary-expression, the parent can + // If this expression is limited to being a unary-expression, the paren can // not start a cast expression. - ParenParseOption ParenExprType = - (isUnaryExpression && !getLangOpts().CPlusPlus) ? CompoundLiteral - : CastExpr; + ParenParseOption ParenExprType; + switch (ParseKind) { + case CastParseKind::UnaryExprOnly: + if (!getLangOpts().CPlusPlus) + ParenExprType = CompoundLiteral; + LLVM_FALLTHROUGH; + case CastParseKind::AnyCastExpr: + ParenExprType = ParenParseOption::CastExpr; + break; + case CastParseKind::PrimaryExprOnly: + ParenExprType = FoldExpr; + break; + } ParsedType CastTy; SourceLocation RParenLoc; Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/, @@ -861,8 +1003,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, if (TryAnnotateTypeOrScopeToken()) return ExprError(); assert(Tok.isNot(tok::kw_decltype) && Tok.isNot(tok::kw___super)); - return ParseCastExpression(isUnaryExpression, isAddressOfOperand); - + return ParseCastExpression(ParseKind, isAddressOfOperand, isTypeCast, + isVectorLiteral, NotPrimaryExpression); + case tok::identifier: { // primary-expression: identifier // unqualified-id: identifier // constant: enumeration-constant @@ -949,8 +1092,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, = RevertibleTypeTraits.find(II); if (Known != RevertibleTypeTraits.end()) { Tok.setKind(Known->second); - return ParseCastExpression(isUnaryExpression, isAddressOfOperand, - NotCastExpr, isTypeCast); + return ParseCastExpression(ParseKind, isAddressOfOperand, + NotCastExpr, isTypeCast, + isVectorLiteral, NotPrimaryExpression); } } @@ -961,7 +1105,10 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, if (TryAnnotateTypeOrScopeToken()) return ExprError(); if (!Tok.is(tok::identifier)) - return ParseCastExpression(isUnaryExpression, isAddressOfOperand); + return ParseCastExpression(ParseKind, isAddressOfOperand, + NotCastExpr, isTypeCast, + isVectorLiteral, + NotPrimaryExpression); } } @@ -1076,8 +1223,10 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, Tok.is(tok::r_paren) ? nullptr : &Replacement); if (!Res.isInvalid() && Res.isUnset()) { UnconsumeToken(Replacement); - return ParseCastExpression(isUnaryExpression, isAddressOfOperand, - NotCastExpr, isTypeCast); + return ParseCastExpression(ParseKind, isAddressOfOperand, + NotCastExpr, isTypeCast, + /*isVectorLiteral=*/false, + NotPrimaryExpression); } if (!Res.isInvalid() && Tok.is(tok::less)) checkPotentialAngleBracket(Res); @@ -1122,12 +1271,16 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw___builtin_FILE: case tok::kw___builtin_FUNCTION: case tok::kw___builtin_LINE: + if (NotPrimaryExpression) + *NotPrimaryExpression = true; return ParseBuiltinPrimaryExpression(); case tok::kw___null: return Actions.ActOnGNUNullExpr(ConsumeToken()); case tok::plusplus: // unary-expression: '++' unary-expression [C99] case tok::minusminus: { // unary-expression: '--' unary-expression [C99] + if (NotPrimaryExpression) + *NotPrimaryExpression = true; // C++ [expr.unary] has: // unary-expression: // ++ cast-expression @@ -1140,7 +1293,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, // One special case is implicitly handled here: if the preceding tokens are // an ambiguous cast expression, such as "(T())++", then we recurse to // determine whether the '++' is prefix or postfix. - Res = ParseCastExpression(!getLangOpts().CPlusPlus, + Res = ParseCastExpression(getLangOpts().CPlusPlus ? + UnaryExprOnly : AnyCastExpr, /*isAddressOfOperand*/false, NotCastExpr, NotTypeCast); if (NotCastExpr) { @@ -1156,10 +1310,12 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, return Res; } case tok::amp: { // unary-expression: '&' cast-expression + if (NotPrimaryExpression) + *NotPrimaryExpression = true; // Special treatment because of member pointers SourceLocation SavedLoc = ConsumeToken(); PreferredType.enterUnary(Actions, Tok.getLocation(), tok::amp, SavedLoc); - Res = ParseCastExpression(false, true); + Res = ParseCastExpression(AnyCastExpr, true); if (!Res.isInvalid()) Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get()); return Res; @@ -1172,17 +1328,21 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::exclaim: // unary-expression: '!' cast-expression case tok::kw___real: // unary-expression: '__real' cast-expression [GNU] case tok::kw___imag: { // unary-expression: '__imag' cast-expression [GNU] + if (NotPrimaryExpression) + *NotPrimaryExpression = true; SourceLocation SavedLoc = ConsumeToken(); PreferredType.enterUnary(Actions, Tok.getLocation(), SavedKind, SavedLoc); - Res = ParseCastExpression(false); + Res = ParseCastExpression(AnyCastExpr); if (!Res.isInvalid()) Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get()); return Res; } case tok::kw_co_await: { // unary-expression: 'co_await' cast-expression + if (NotPrimaryExpression) + *NotPrimaryExpression = true; SourceLocation CoawaitLoc = ConsumeToken(); - Res = ParseCastExpression(false); + Res = ParseCastExpression(AnyCastExpr); if (!Res.isInvalid()) Res = Actions.ActOnCoawaitExpr(getCurScope(), CoawaitLoc, Res.get()); return Res; @@ -1190,9 +1350,11 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw___extension__:{//unary-expression:'__extension__' cast-expr [GNU] // __extension__ silences extension warnings in the subexpression. + if (NotPrimaryExpression) + *NotPrimaryExpression = true; ExtensionRAIIObject O(Diags); // Use RAII to do this. SourceLocation SavedLoc = ConsumeToken(); - Res = ParseCastExpression(false); + Res = ParseCastExpression(AnyCastExpr); if (!Res.isInvalid()) Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get()); return Res; @@ -1209,8 +1371,12 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw_vec_step: // unary-expression: OpenCL 'vec_step' expression // unary-expression: '__builtin_omp_required_simd_align' '(' type-name ')' case tok::kw___builtin_omp_required_simd_align: + if (NotPrimaryExpression) + *NotPrimaryExpression = true; return ParseUnaryExprOrTypeTraitExpression(); case tok::ampamp: { // unary-expression: '&&' identifier + if (NotPrimaryExpression) + *NotPrimaryExpression = true; SourceLocation AmpAmpLoc = ConsumeToken(); if (Tok.isNot(tok::identifier)) return ExprError(Diag(Tok, diag::err_expected) << tok::identifier); @@ -1229,15 +1395,23 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw_dynamic_cast: case tok::kw_reinterpret_cast: case tok::kw_static_cast: + if (NotPrimaryExpression) + *NotPrimaryExpression = true; Res = ParseCXXCasts(); break; case tok::kw___builtin_bit_cast: + if (NotPrimaryExpression) + *NotPrimaryExpression = true; Res = ParseBuiltinBitCast(); break; case tok::kw_typeid: + if (NotPrimaryExpression) + *NotPrimaryExpression = true; Res = ParseCXXTypeid(); break; case tok::kw___uuidof: + if (NotPrimaryExpression) + *NotPrimaryExpression = true; Res = ParseCXXUuidof(); break; case tok::kw_this: @@ -1302,6 +1476,10 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, return ExprError(); } + // Everything henceforth is a postfix-expression. + if (NotPrimaryExpression) + *NotPrimaryExpression = true; + if (SavedKind == tok::kw_typename) { // postfix-expression: typename-specifier '(' expression-list[opt] ')' // typename-specifier braced-init-list @@ -1338,8 +1516,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, if (TryAnnotateTypeOrScopeToken()) return ExprError(); if (!Tok.is(tok::annot_cxxscope)) - return ParseCastExpression(isUnaryExpression, isAddressOfOperand, - NotCastExpr, isTypeCast); + return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr, + isTypeCast, isVectorLiteral, + NotPrimaryExpression); Token Next = NextToken(); if (Next.is(tok::annot_template_id)) { @@ -1352,8 +1531,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false); AnnotateTemplateIdTokenAsType(); - return ParseCastExpression(isUnaryExpression, isAddressOfOperand, - NotCastExpr, isTypeCast); + return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr, + isTypeCast, isVectorLiteral, + NotPrimaryExpression); } } @@ -1369,8 +1549,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, // translate it into a type and continue parsing as a cast // expression. AnnotateTemplateIdTokenAsType(); - return ParseCastExpression(isUnaryExpression, isAddressOfOperand, - NotCastExpr, isTypeCast); + return ParseCastExpression(ParseKind, isAddressOfOperand, + NotCastExpr, isTypeCast, isVectorLiteral, + NotPrimaryExpression); } // Fall through to treat the template-id as an id-expression. @@ -1387,15 +1568,22 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, if (TryAnnotateTypeOrScopeToken()) return ExprError(); if (!Tok.is(tok::coloncolon)) - return ParseCastExpression(isUnaryExpression, isAddressOfOperand); + return ParseCastExpression(ParseKind, isAddressOfOperand, isTypeCast, + isVectorLiteral, NotPrimaryExpression); // ::new -> [C++] new-expression // ::delete -> [C++] delete-expression SourceLocation CCLoc = ConsumeToken(); - if (Tok.is(tok::kw_new)) + if (Tok.is(tok::kw_new)) { + if (NotPrimaryExpression) + *NotPrimaryExpression = true; return ParseCXXNewExpression(true, CCLoc); - if (Tok.is(tok::kw_delete)) + } + if (Tok.is(tok::kw_delete)) { + if (NotPrimaryExpression) + *NotPrimaryExpression = true; return ParseCXXDeleteExpression(true, CCLoc); + } // This is not a type name or scope specifier, it is an invalid expression. Diag(CCLoc, diag::err_expected_expression); @@ -1403,12 +1591,18 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, } case tok::kw_new: // [C++] new-expression + if (NotPrimaryExpression) + *NotPrimaryExpression = true; return ParseCXXNewExpression(false, Tok.getLocation()); case tok::kw_delete: // [C++] delete-expression + if (NotPrimaryExpression) + *NotPrimaryExpression = true; return ParseCXXDeleteExpression(false, Tok.getLocation()); case tok::kw_noexcept: { // [C++0x] 'noexcept' '(' expression ')' + if (NotPrimaryExpression) + *NotPrimaryExpression = true; Diag(Tok, diag::warn_cxx98_compat_noexcept_expr); SourceLocation KeyLoc = ConsumeToken(); BalancedDelimiterTracker T(*this, tok::l_paren); @@ -1437,13 +1631,19 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw___array_rank: case tok::kw___array_extent: + if (NotPrimaryExpression) + *NotPrimaryExpression = true; return ParseArrayTypeTrait(); case tok::kw___is_lvalue_expr: case tok::kw___is_rvalue_expr: + if (NotPrimaryExpression) + *NotPrimaryExpression = true; return ParseExpressionTrait(); case tok::at: { + if (NotPrimaryExpression) + *NotPrimaryExpression = true; SourceLocation AtLoc = ConsumeToken(); return ParseObjCAtExpression(AtLoc); } @@ -1465,8 +1665,13 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, // expression, or we have something that doesn't appear to be a lambda. // If we're in the last case, we fall back to ParseObjCMessageExpression. Res = TryParseLambdaExpression(); - if (!Res.isInvalid() && !Res.get()) + if (!Res.isInvalid() && !Res.get()) { + // We assume Objective-C++ message expressions are not + // primary-expressions. + if (NotPrimaryExpression) + *NotPrimaryExpression = true; Res = ParseObjCMessageExpression(); + } break; } Res = ParseLambdaExpression(); @@ -1486,6 +1691,11 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, // are compiling for OpenCL, we need to return an error as this implies // that the address of the function is being taken, which is illegal in CL. + if (ParseKind == PrimaryExprOnly) + // This is strictly a primary-expression - no postfix-expr pieces should be + // parsed. + return Res; + // These can be followed by postfix-expr pieces. PreferredType = SavedType; Res = ParsePostfixExpressionSuffix(Res); @@ -1929,7 +2139,7 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, return ExprError(); } - Operand = ParseCastExpression(true/*isUnaryExpression*/); + Operand = ParseCastExpression(UnaryExprOnly); } else { // If it starts with a '(', we know that it is either a parenthesized // type-name, or it is a unary-expression that starts with a compound @@ -2474,8 +2684,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, RParenLoc = T.getCloseLocation(); PreferredType.enterTypeCast(Tok.getLocation(), Ty.get().get()); - ExprResult SubExpr = ParseCastExpression(/*isUnaryExpression=*/false); - + ExprResult SubExpr = ParseCastExpression(AnyCastExpr); + if (Ty.isInvalid() || SubExpr.isInvalid()) return ExprError(); @@ -2555,7 +2765,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, // Parse the cast-expression that follows it next. // isVectorLiteral = true will make sure we don't parse any // Postfix expression yet - Result = ParseCastExpression(/*isUnaryExpression=*/false, + Result = ParseCastExpression(/*isUnaryExpression=*/AnyCastExpr, /*isAddressOfOperand=*/false, /*isTypeCast=*/IsTypeCast, /*isVectorLiteral=*/true); @@ -2607,7 +2817,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, PreferredType.enterTypeCast(Tok.getLocation(), CastTy.get()); // Parse the cast-expression that follows it next. // TODO: For cast expression with CastTy. - Result = ParseCastExpression(/*isUnaryExpression=*/false, + Result = ParseCastExpression(/*isUnaryExpression=*/AnyCastExpr, /*isAddressOfOperand=*/false, /*isTypeCast=*/IsTypeCast); if (!Result.isInvalid()) { |