diff options
Diffstat (limited to 'clang/lib/Parse/ParseExpr.cpp')
-rw-r--r-- | clang/lib/Parse/ParseExpr.cpp | 412 |
1 files changed, 339 insertions, 73 deletions
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 1442df046bb93..81e87582c6ade 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -234,7 +234,7 @@ ExprResult Parser::ParseCaseExpression(SourceLocation CaseLoc) { /// \endverbatim ExprResult Parser::ParseConstraintExpression() { EnterExpressionEvaluationContext ConstantEvaluated( - Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); + Actions, Sema::ExpressionEvaluationContext::Unevaluated); ExprResult LHS(ParseCastExpression(AnyCastExpr)); ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::LogicalOr)); if (Res.isUsable() && !Actions.CheckConstraintExpression(Res.get())) { @@ -256,7 +256,7 @@ ExprResult Parser::ParseConstraintExpression() { ExprResult Parser::ParseConstraintLogicalAndExpression(bool IsTrailingRequiresClause) { EnterExpressionEvaluationContext ConstantEvaluated( - Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); + Actions, Sema::ExpressionEvaluationContext::Unevaluated); bool NotPrimaryExpression = false; auto ParsePrimary = [&] () { ExprResult E = ParseCastExpression(PrimaryExprOnly, @@ -625,13 +625,31 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { SourceRange(Actions.getExprRange(LHS.get()).getBegin(), Actions.getExprRange(RHS.get()).getEnd())); - LHS = Actions.ActOnBinOp(getCurScope(), OpToken.getLocation(), - OpToken.getKind(), LHS.get(), RHS.get()); + ExprResult BinOp = + Actions.ActOnBinOp(getCurScope(), OpToken.getLocation(), + OpToken.getKind(), LHS.get(), RHS.get()); + if (BinOp.isInvalid()) + BinOp = Actions.CreateRecoveryExpr(LHS.get()->getBeginLoc(), + RHS.get()->getEndLoc(), + {LHS.get(), RHS.get()}); + LHS = BinOp; } else { - LHS = Actions.ActOnConditionalOp(OpToken.getLocation(), ColonLoc, - LHS.get(), TernaryMiddle.get(), - RHS.get()); + ExprResult CondOp = Actions.ActOnConditionalOp( + OpToken.getLocation(), ColonLoc, LHS.get(), TernaryMiddle.get(), + RHS.get()); + if (CondOp.isInvalid()) { + std::vector<clang::Expr *> Args; + // TernaryMiddle can be null for the GNU conditional expr extension. + if (TernaryMiddle.get()) + Args = {LHS.get(), TernaryMiddle.get(), RHS.get()}; + else + Args = {LHS.get(), RHS.get()}; + CondOp = Actions.CreateRecoveryExpr(LHS.get()->getBeginLoc(), + RHS.get()->getEndLoc(), Args); + } + + LHS = CondOp; } // In this case, ActOnBinOp or ActOnConditionalOp performed the // CorrectDelayedTyposInExpr check. @@ -756,6 +774,7 @@ class CastExpressionIdValidator final : public CorrectionCandidateCallback { /// [C++11] user-defined-literal /// '(' expression ')' /// [C11] generic-selection +/// [C++2a] requires-expression /// '__func__' [C99 6.4.2.2] /// [GNU] '__FUNCTION__' /// [MS] '__FUNCDNAME__' @@ -901,6 +920,11 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, auto SavedType = PreferredType; NotCastExpr = false; + // Are postfix-expression suffix operators permitted after this + // cast-expression? If not, and we find some, we'll parse them anyway and + // diagnose them. + bool AllowSuffix = true; + // This handles all of cast-expression, unary-expression, postfix-expression, // and primary-expression. We handle them together like this for efficiency // and to simplify handling of an expression starting with a '(' token: which @@ -910,8 +934,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, // If the parsed tokens consist of a primary-expression, the cases below // break out of the switch; at the end we call ParsePostfixExpressionSuffix // to handle the postfix expression suffixes. Cases that cannot be followed - // by postfix exprs should return without invoking - // ParsePostfixExpressionSuffix. + // by postfix exprs should set AllowSuffix to false. switch (SavedKind) { case tok::l_paren: { // If this expression is limited to being a unary-expression, the paren can @@ -934,8 +957,11 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/, isTypeCast == IsTypeCast, CastTy, RParenLoc); + // FIXME: What should we do if a vector literal is followed by a + // postfix-expression suffix? Usually postfix operators are permitted on + // literals. if (isVectorLiteral) - return Res; + return Res; switch (ParenExprType) { case SimpleExpr: break; // Nothing else to do. @@ -973,14 +999,31 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, case tok::kw___objc_yes: case tok::kw___objc_no: - return ParseObjCBoolLiteral(); + Res = ParseObjCBoolLiteral(); + break; case tok::kw_nullptr: Diag(Tok, diag::warn_cxx98_compat_nullptr); - return Actions.ActOnCXXNullPtrLiteral(ConsumeToken()); + Res = Actions.ActOnCXXNullPtrLiteral(ConsumeToken()); + break; + case tok::annot_uneval_primary_expr: case tok::annot_primary_expr: Res = getExprAnnotation(Tok); + if (SavedKind == tok::annot_uneval_primary_expr) { + if (Expr *E = Res.get()) { + if (!E->isTypeDependent() && !E->containsErrors()) { + // TransformToPotentiallyEvaluated expects that it will still be in a + // (temporary) unevaluated context and then looks through that context + // to build it in the surrounding context. So we need to push an + // unevaluated context to balance things out. + EnterExpressionEvaluationContext Unevaluated( + Actions, Sema::ExpressionEvaluationContext::Unevaluated, + Sema::ReuseLambdaContextDecl); + Res = Actions.TransformToPotentiallyEvaluated(Res.get()); + } + } + } ConsumeAnnotationToken(); if (!Res.isInvalid() && Tok.is(tok::less)) checkPotentialAngleBracket(Res); @@ -1005,7 +1048,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, assert(Tok.isNot(tok::kw_decltype) && Tok.isNot(tok::kw___super)); return ParseCastExpression(ParseKind, isAddressOfOperand, isTypeCast, isVectorLiteral, NotPrimaryExpression); - + case tok::identifier: { // primary-expression: identifier // unqualified-id: identifier // constant: enumeration-constant @@ -1261,7 +1304,8 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, Res = ParseGenericSelectionExpression(); break; case tok::kw___builtin_available: - return ParseAvailabilityCheckExpr(Tok.getLocation()); + Res = ParseAvailabilityCheckExpr(Tok.getLocation()); + break; case tok::kw___builtin_va_arg: case tok::kw___builtin_offsetof: case tok::kw___builtin_choose_expr: @@ -1273,9 +1317,11 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, case tok::kw___builtin_LINE: if (NotPrimaryExpression) *NotPrimaryExpression = true; + // This parses the complete suffix; we can return early. return ParseBuiltinPrimaryExpression(); case tok::kw___null: - return Actions.ActOnGNUNullExpr(ConsumeToken()); + Res = Actions.ActOnGNUNullExpr(ConsumeToken()); + break; case tok::plusplus: // unary-expression: '++' unary-expression [C99] case tok::minusminus: { // unary-expression: '--' unary-expression [C99] @@ -1304,9 +1350,14 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, UnconsumeToken(SavedTok); return ExprError(); } - if (!Res.isInvalid()) + if (!Res.isInvalid()) { + Expr *Arg = Res.get(); Res = Actions.ActOnUnaryOp(getCurScope(), SavedTok.getLocation(), - SavedKind, Res.get()); + SavedKind, Arg); + if (Res.isInvalid()) + Res = Actions.CreateRecoveryExpr(SavedTok.getLocation(), + Arg->getEndLoc(), Arg); + } return Res; } case tok::amp: { // unary-expression: '&' cast-expression @@ -1316,8 +1367,13 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, SourceLocation SavedLoc = ConsumeToken(); PreferredType.enterUnary(Actions, Tok.getLocation(), tok::amp, SavedLoc); Res = ParseCastExpression(AnyCastExpr, true); - if (!Res.isInvalid()) - Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get()); + if (!Res.isInvalid()) { + Expr *Arg = Res.get(); + Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Arg); + if (Res.isInvalid()) + Res = Actions.CreateRecoveryExpr(Tok.getLocation(), Arg->getEndLoc(), + Arg); + } return Res; } @@ -1333,8 +1389,12 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, SourceLocation SavedLoc = ConsumeToken(); PreferredType.enterUnary(Actions, Tok.getLocation(), SavedKind, SavedLoc); Res = ParseCastExpression(AnyCastExpr); - if (!Res.isInvalid()) - Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get()); + if (!Res.isInvalid()) { + Expr *Arg = Res.get(); + Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Arg); + if (Res.isInvalid()) + Res = Actions.CreateRecoveryExpr(SavedLoc, Arg->getEndLoc(), Arg); + } return Res; } @@ -1373,7 +1433,9 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, case tok::kw___builtin_omp_required_simd_align: if (NotPrimaryExpression) *NotPrimaryExpression = true; - return ParseUnaryExprOrTypeTraitExpression(); + AllowSuffix = false; + Res = ParseUnaryExprOrTypeTraitExpression(); + break; case tok::ampamp: { // unary-expression: '&&' identifier if (NotPrimaryExpression) *NotPrimaryExpression = true; @@ -1389,12 +1451,14 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, Tok.getLocation()); Res = Actions.ActOnAddrLabel(AmpAmpLoc, Tok.getLocation(), LD); ConsumeToken(); - return Res; + AllowSuffix = false; + break; } case tok::kw_const_cast: case tok::kw_dynamic_cast: case tok::kw_reinterpret_cast: case tok::kw_static_cast: + case tok::kw_addrspace_cast: if (NotPrimaryExpression) *NotPrimaryExpression = true; Res = ParseCXXCasts(); @@ -1417,10 +1481,12 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, case tok::kw_this: Res = ParseCXXThis(); break; - + case tok::kw___builtin_unique_stable_name: + Res = ParseUniqueStableNameExpression(); + break; case tok::annot_typename: if (isStartOfObjCClassMessageMissingOpenBracket()) { - ParsedType Type = getTypeAnnotation(Tok); + TypeResult Type = getTypeAnnotation(Tok); // Fake up a Declarator to use with ActOnTypeName. DeclSpec DS(AttrFactory); @@ -1457,11 +1523,13 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, case tok::kw_long: case tok::kw___int64: case tok::kw___int128: + case tok::kw__ExtInt: case tok::kw_signed: case tok::kw_unsigned: case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw___bf16: case tok::kw__Float16: case tok::kw___float128: case tok::kw_void: @@ -1528,9 +1596,10 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, // type, translate it into a type and continue parsing as a // cast expression. CXXScopeSpec SS; - ParseOptionalCXXScopeSpecifier(SS, nullptr, + ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, + /*ObjectHadErrors=*/false, /*EnteringContext=*/false); - AnnotateTemplateIdTokenAsType(); + AnnotateTemplateIdTokenAsType(SS); return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr, isTypeCast, isVectorLiteral, NotPrimaryExpression); @@ -1548,7 +1617,8 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, // We have a template-id that we know refers to a type, // translate it into a type and continue parsing as a cast // expression. - AnnotateTemplateIdTokenAsType(); + CXXScopeSpec SS; + AnnotateTemplateIdTokenAsType(SS); return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr, isTypeCast, isVectorLiteral, NotPrimaryExpression); @@ -1577,12 +1647,16 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, if (Tok.is(tok::kw_new)) { if (NotPrimaryExpression) *NotPrimaryExpression = true; - return ParseCXXNewExpression(true, CCLoc); + Res = ParseCXXNewExpression(true, CCLoc); + AllowSuffix = false; + break; } if (Tok.is(tok::kw_delete)) { if (NotPrimaryExpression) *NotPrimaryExpression = true; - return ParseCXXDeleteExpression(true, CCLoc); + Res = ParseCXXDeleteExpression(true, CCLoc); + AllowSuffix = false; + break; } // This is not a type name or scope specifier, it is an invalid expression. @@ -1593,12 +1667,21 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, case tok::kw_new: // [C++] new-expression if (NotPrimaryExpression) *NotPrimaryExpression = true; - return ParseCXXNewExpression(false, Tok.getLocation()); + Res = ParseCXXNewExpression(false, Tok.getLocation()); + AllowSuffix = false; + break; case tok::kw_delete: // [C++] delete-expression if (NotPrimaryExpression) *NotPrimaryExpression = true; - return ParseCXXDeleteExpression(false, Tok.getLocation()); + Res = ParseCXXDeleteExpression(false, Tok.getLocation()); + AllowSuffix = false; + break; + + case tok::kw_requires: // [C++2a] requires-expression + Res = ParseRequiresExpression(); + AllowSuffix = false; + break; case tok::kw_noexcept: { // [C++0x] 'noexcept' '(' expression ')' if (NotPrimaryExpression) @@ -1614,32 +1697,36 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, // which is an unevaluated operand, can throw an exception. EnterExpressionEvaluationContext Unevaluated( Actions, Sema::ExpressionEvaluationContext::Unevaluated); - ExprResult Result = ParseExpression(); + Res = ParseExpression(); T.consumeClose(); - if (!Result.isInvalid()) - Result = Actions.ActOnNoexceptExpr(KeyLoc, T.getOpenLocation(), - Result.get(), T.getCloseLocation()); - return Result; + if (!Res.isInvalid()) + Res = Actions.ActOnNoexceptExpr(KeyLoc, T.getOpenLocation(), Res.get(), + T.getCloseLocation()); + AllowSuffix = false; + break; } #define TYPE_TRAIT(N,Spelling,K) \ case tok::kw_##Spelling: #include "clang/Basic/TokenKinds.def" - return ParseTypeTrait(); + Res = ParseTypeTrait(); + break; case tok::kw___array_rank: case tok::kw___array_extent: if (NotPrimaryExpression) *NotPrimaryExpression = true; - return ParseArrayTypeTrait(); + Res = ParseArrayTypeTrait(); + break; case tok::kw___is_lvalue_expr: case tok::kw___is_rvalue_expr: if (NotPrimaryExpression) *NotPrimaryExpression = true; - return ParseExpressionTrait(); + Res = ParseExpressionTrait(); + break; case tok::at: { if (NotPrimaryExpression) @@ -1696,6 +1783,41 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, // parsed. return Res; + if (!AllowSuffix) { + // FIXME: Don't parse a primary-expression suffix if we encountered a parse + // error already. + if (Res.isInvalid()) + return Res; + + switch (Tok.getKind()) { + case tok::l_square: + case tok::l_paren: + case tok::plusplus: + case tok::minusminus: + // "expected ';'" or similar is probably the right diagnostic here. Let + // the caller decide what to do. + if (Tok.isAtStartOfLine()) + return Res; + + LLVM_FALLTHROUGH; + case tok::period: + case tok::arrow: + break; + + default: + return Res; + } + + // This was a unary-expression for which a postfix-expression suffix is + // not permitted by the grammar (eg, a sizeof expression or + // new-expression or similar). Diagnose but parse the suffix anyway. + Diag(Tok.getLocation(), diag::err_postfix_after_unary_requires_parens) + << Tok.getKind() << Res.get()->getSourceRange() + << FixItHint::CreateInsertion(Res.get()->getBeginLoc(), "(") + << FixItHint::CreateInsertion(PP.getLocForEndOfToken(PrevTokLocation), + ")"); + } + // These can be followed by postfix-expr pieces. PreferredType = SavedType; Res = ParsePostfixExpressionSuffix(Res); @@ -1787,8 +1909,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { BalancedDelimiterTracker T(*this, tok::l_square); T.consumeOpen(); Loc = T.getOpenLocation(); - ExprResult Idx, Length; - SourceLocation ColonLoc; + ExprResult Idx, Length, Stride; + SourceLocation ColonLocFirst, ColonLocSecond; PreferredType.enterSubscript(Actions, Tok.getLocation(), LHS.get()); if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); @@ -1802,10 +1924,22 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { } if (Tok.is(tok::colon)) { // Consume ':' - ColonLoc = ConsumeToken(); - if (Tok.isNot(tok::r_square)) + ColonLocFirst = ConsumeToken(); + if (Tok.isNot(tok::r_square) && + (getLangOpts().OpenMP < 50 || + ((Tok.isNot(tok::colon) && getLangOpts().OpenMP >= 50)))) Length = ParseExpression(); } + if (getLangOpts().OpenMP >= 50 && + (OMPClauseKind == llvm::omp::Clause::OMPC_to || + OMPClauseKind == llvm::omp::Clause::OMPC_from) && + Tok.is(tok::colon)) { + // Consume ':' + ColonLocSecond = ConsumeToken(); + if (Tok.isNot(tok::r_square)) { + Stride = ParseExpression(); + } + } } else Idx = ParseExpression(); @@ -1815,10 +1949,11 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { Idx = Actions.CorrectDelayedTyposInExpr(Idx); Length = Actions.CorrectDelayedTyposInExpr(Length); if (!LHS.isInvalid() && !Idx.isInvalid() && !Length.isInvalid() && - Tok.is(tok::r_square)) { - if (ColonLoc.isValid()) { - LHS = Actions.ActOnOMPArraySectionExpr(LHS.get(), Loc, Idx.get(), - ColonLoc, Length.get(), RLoc); + !Stride.isInvalid() && Tok.is(tok::r_square)) { + if (ColonLocFirst.isValid() || ColonLocSecond.isValid()) { + LHS = Actions.ActOnOMPArraySectionExpr( + LHS.get(), Loc, Idx.get(), ColonLocFirst, ColonLocSecond, + Length.get(), Stride.get(), RLoc); } else { LHS = Actions.ActOnArraySubscriptExpr(getCurScope(), LHS.get(), Loc, Idx.get(), RLoc); @@ -1935,12 +2070,18 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { PT.consumeClose(); LHS = ExprError(); } else { - assert((ArgExprs.size() == 0 || - ArgExprs.size()-1 == CommaLocs.size())&& - "Unexpected number of commas!"); - LHS = Actions.ActOnCallExpr(getCurScope(), LHS.get(), Loc, - ArgExprs, Tok.getLocation(), + assert( + (ArgExprs.size() == 0 || ArgExprs.size() - 1 == CommaLocs.size()) && + "Unexpected number of commas!"); + Expr *Fn = LHS.get(); + SourceLocation RParLoc = Tok.getLocation(); + LHS = Actions.ActOnCallExpr(getCurScope(), Fn, Loc, ArgExprs, RParLoc, ExecConfig); + if (LHS.isInvalid()) { + ArgExprs.insert(ArgExprs.begin(), Fn); + LHS = + Actions.CreateRecoveryExpr(Fn->getBeginLoc(), RParLoc, ArgExprs); + } PT.consumeClose(); } @@ -1972,15 +2113,22 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { return ParsePostfixExpressionSuffix(Base); } - LHS = Actions.ActOnStartCXXMemberReference(getCurScope(), Base, - OpLoc, OpKind, ObjectType, + LHS = Actions.ActOnStartCXXMemberReference(getCurScope(), Base, OpLoc, + OpKind, ObjectType, MayBePseudoDestructor); - if (LHS.isInvalid()) + if (LHS.isInvalid()) { + // Clang will try to perform expression based completion as a + // fallback, which is confusing in case of member references. So we + // stop here without any completions. + if (Tok.is(tok::code_completion)) { + cutOffParsing(); + return ExprError(); + } break; - - ParseOptionalCXXScopeSpecifier(SS, ObjectType, - /*EnteringContext=*/false, - &MayBePseudoDestructor); + } + ParseOptionalCXXScopeSpecifier( + SS, ObjectType, LHS.get() && LHS.get()->containsErrors(), + /*EnteringContext=*/false, &MayBePseudoDestructor); if (SS.isNotEmpty()) ObjectType = nullptr; } @@ -2040,14 +2188,13 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { IdentifierInfo *Id = Tok.getIdentifierInfo(); SourceLocation Loc = ConsumeToken(); Name.setIdentifier(Id, Loc); - } else if (ParseUnqualifiedId(SS, - /*EnteringContext=*/false, - /*AllowDestructorName=*/true, - /*AllowConstructorName=*/ - getLangOpts().MicrosoftExt && - SS.isNotEmpty(), - /*AllowDeductionGuide=*/false, - ObjectType, &TemplateKWLoc, Name)) { + } else if (ParseUnqualifiedId( + SS, ObjectType, LHS.get() && LHS.get()->containsErrors(), + /*EnteringContext=*/false, + /*AllowDestructorName=*/true, + /*AllowConstructorName=*/ + getLangOpts().MicrosoftExt && SS.isNotEmpty(), + /*AllowDeductionGuide=*/false, &TemplateKWLoc, Name)) { (void)Actions.CorrectDelayedTyposInExpr(LHS); LHS = ExprError(); } @@ -2057,15 +2204,25 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { OpKind, SS, TemplateKWLoc, Name, CurParsedObjCImpl ? CurParsedObjCImpl->Dcl : nullptr); - if (!LHS.isInvalid() && Tok.is(tok::less)) - checkPotentialAngleBracket(LHS); + if (!LHS.isInvalid()) { + if (Tok.is(tok::less)) + checkPotentialAngleBracket(LHS); + } else if (OrigLHS && Name.isValid()) { + // Preserve the LHS if the RHS is an invalid member. + LHS = Actions.CreateRecoveryExpr(OrigLHS->getBeginLoc(), + Name.getEndLoc(), {OrigLHS}); + } break; } case tok::plusplus: // postfix-expression: postfix-expression '++' case tok::minusminus: // postfix-expression: postfix-expression '--' if (!LHS.isInvalid()) { + Expr *Arg = LHS.get(); LHS = Actions.ActOnPostfixUnaryOp(getCurScope(), Tok.getLocation(), - Tok.getKind(), LHS.get()); + Tok.getKind(), Arg); + if (LHS.isInvalid()) + LHS = Actions.CreateRecoveryExpr(Arg->getBeginLoc(), + Tok.getLocation(), Arg); } ConsumeToken(); break; @@ -2175,6 +2332,43 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, } +ExprResult Parser::ParseUniqueStableNameExpression() { + assert(Tok.is(tok::kw___builtin_unique_stable_name) && + "Not __bulitin_unique_stable_name"); + + SourceLocation OpLoc = ConsumeToken(); + BalancedDelimiterTracker T(*this, tok::l_paren); + + // typeid expressions are always parenthesized. + if (T.expectAndConsume(diag::err_expected_lparen_after, + "__builtin_unique_stable_name")) + return ExprError(); + + if (isTypeIdInParens()) { + TypeResult Ty = ParseTypeName(); + T.consumeClose(); + + if (Ty.isInvalid()) + return ExprError(); + + return Actions.ActOnUniqueStableNameExpr(OpLoc, T.getOpenLocation(), + T.getCloseLocation(), Ty.get()); + } + + EnterExpressionEvaluationContext Unevaluated( + Actions, Sema::ExpressionEvaluationContext::Unevaluated); + ExprResult Result = ParseExpression(); + + if (Result.isInvalid()) { + SkipUntil(tok::r_paren, StopAtSemi); + return Result; + } + + T.consumeClose(); + return Actions.ActOnUniqueStableNameExpr(OpLoc, T.getOpenLocation(), + T.getCloseLocation(), Result.get()); +} + /// Parse a sizeof or alignof expression. /// /// \verbatim @@ -2556,6 +2750,33 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { return ParsePostfixExpressionSuffix(Res.get()); } +bool Parser::tryParseOpenMPArrayShapingCastPart() { + assert(Tok.is(tok::l_square) && "Expected open bracket"); + bool ErrorFound = true; + TentativeParsingAction TPA(*this); + do { + if (Tok.isNot(tok::l_square)) + break; + // Consume '[' + ConsumeBracket(); + // Skip inner expression. + while (!SkipUntil(tok::r_square, tok::annot_pragma_openmp_end, + StopAtSemi | StopBeforeMatch)) + ; + if (Tok.isNot(tok::r_square)) + break; + // Consume ']' + ConsumeBracket(); + // Found ')' - done. + if (Tok.is(tok::r_paren)) { + ErrorFound = false; + break; + } + } while (Tok.isNot(tok::annot_pragma_openmp_end)); + TPA.Revert(); + return !ErrorFound; +} + /// ParseParenExpression - This parses the unit that starts with a '(' token, /// based on what is allowed by ExprType. The actual thing parsed is returned /// in ExprType. If stopIfCastExpr is true, it will only return the parsed type, @@ -2580,6 +2801,8 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { /// '(' '...' fold-operator cast-expression ')' /// '(' cast-expression fold-operator '...' /// fold-operator cast-expression ')' +/// [OPENMP] Array shaping operation +/// '(' '[' expression ']' { '[' expression ']' } cast-expression /// \endverbatim ExprResult Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, @@ -2650,7 +2873,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, // If the substmt parsed correctly, build the AST node. if (!Stmt.isInvalid()) { - Result = Actions.ActOnStmtExpr(OpenLoc, Stmt.get(), Tok.getLocation()); + Result = Actions.ActOnStmtExpr(getCurScope(), OpenLoc, Stmt.get(), + Tok.getLocation()); } else { Actions.ActOnStmtExprError(); } @@ -2685,7 +2909,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, PreferredType.enterTypeCast(Tok.getLocation(), Ty.get().get()); ExprResult SubExpr = ParseCastExpression(AnyCastExpr); - + if (Ty.isInvalid() || SubExpr.isInvalid()) return ExprError(); @@ -2855,6 +3079,38 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, Result = Actions.ActOnParenListExpr(OpenLoc, Tok.getLocation(), ArgExprs); } + } else if (getLangOpts().OpenMP >= 50 && OpenMPDirectiveParsing && + ExprType == CastExpr && Tok.is(tok::l_square) && + tryParseOpenMPArrayShapingCastPart()) { + bool ErrorFound = false; + SmallVector<Expr *, 4> OMPDimensions; + SmallVector<SourceRange, 4> OMPBracketsRanges; + do { + BalancedDelimiterTracker TS(*this, tok::l_square); + TS.consumeOpen(); + ExprResult NumElements = + Actions.CorrectDelayedTyposInExpr(ParseExpression()); + if (!NumElements.isUsable()) { + ErrorFound = true; + while (!SkipUntil(tok::r_square, tok::r_paren, + StopAtSemi | StopBeforeMatch)) + ; + } + TS.consumeClose(); + OMPDimensions.push_back(NumElements.get()); + OMPBracketsRanges.push_back(TS.getRange()); + } while (Tok.isNot(tok::r_paren)); + // Match the ')'. + T.consumeClose(); + RParenLoc = T.getCloseLocation(); + Result = Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); + if (ErrorFound) { + Result = ExprError(); + } else if (!Result.isInvalid()) { + Result = Actions.ActOnOMPArrayShapingExpr( + Result.get(), OpenLoc, RParenLoc, OMPDimensions, OMPBracketsRanges); + } + return Result; } else { InMessageExpressionRAIIObject InMessage(*this, false); @@ -3123,6 +3379,16 @@ bool Parser::ParseExpressionList(SmallVectorImpl<Expr *> &Exprs, if (Tok.is(tok::ellipsis)) Expr = Actions.ActOnPackExpansion(Expr.get(), ConsumeToken()); + else if (Tok.is(tok::code_completion)) { + // There's nothing to suggest in here as we parsed a full expression. + // Instead fail and propogate the error since caller might have something + // the suggest, e.g. signature help in function call. Note that this is + // performed before pushing the \p Expr, so that signature help can report + // current argument correctly. + SawError = true; + cutOffParsing(); + break; + } if (Expr.isInvalid()) { SkipUntil(tok::comma, tok::r_paren, StopBeforeMatch); SawError = true; |