diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp | 169 |
1 files changed, 121 insertions, 48 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp index d0d97de..b866798 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp @@ -205,6 +205,24 @@ ExprResult Parser::ParseConstantExpression(TypeCastState isTypeCast) { return Actions.ActOnConstantExpression(Res); } +/// \brief Parse a constraint-expression. +/// +/// \verbatim +/// constraint-expression: [Concepts TS temp.constr.decl p1] +/// logical-or-expression +/// \endverbatim +ExprResult Parser::ParseConstraintExpression() { + // FIXME: this may erroneously consume a function-body as the braced + // initializer list of a compound literal + // + // FIXME: this may erroneously consume a parenthesized rvalue reference + // declarator as a parenthesized address-of-label expression + ExprResult LHS(ParseCastExpression(/*isUnaryExpression=*/false)); + ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::LogicalOr)); + + return Res; +} + bool Parser::isNotExpressionStart() { tok::TokenKind K = Tok.getKind(); if (K == tok::l_brace || K == tok::r_brace || @@ -347,7 +365,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { RHS = ParseCastExpression(false); if (RHS.isInvalid()) { + // FIXME: Errors generated by the delayed typo correction should be + // printed before errors from parsing the RHS, not after. Actions.CorrectDelayedTyposInExpr(LHS); + if (TernaryMiddle.isUsable()) + TernaryMiddle = Actions.CorrectDelayedTyposInExpr(TernaryMiddle); LHS = ExprError(); } @@ -380,7 +402,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { RHSIsInitList = false; if (RHS.isInvalid()) { + // FIXME: Errors generated by the delayed typo correction should be + // printed before errors from ParseRHSOfBinaryExpression, not after. Actions.CorrectDelayedTyposInExpr(LHS); + if (TernaryMiddle.isUsable()) + TernaryMiddle = Actions.CorrectDelayedTyposInExpr(TernaryMiddle); LHS = ExprError(); } @@ -446,8 +472,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, namespace { class CastExpressionIdValidator : public CorrectionCandidateCallback { public: - CastExpressionIdValidator(bool AllowTypes, bool AllowNonTypes) - : AllowNonTypes(AllowNonTypes) { + CastExpressionIdValidator(Token Next, bool AllowTypes, bool AllowNonTypes) + : NextToken(Next), AllowNonTypes(AllowNonTypes) { WantTypeSpecifiers = WantFunctionLikeCasts = AllowTypes; } @@ -458,11 +484,23 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback { if (isa<TypeDecl>(ND)) return WantTypeSpecifiers; - return AllowNonTypes && - CorrectionCandidateCallback::ValidateCandidate(candidate); + + if (!AllowNonTypes || !CorrectionCandidateCallback::ValidateCandidate(candidate)) + return false; + + if (!NextToken.isOneOf(tok::equal, tok::arrow, tok::period)) + return true; + + for (auto *C : candidate) { + NamedDecl *ND = C->getUnderlyingDecl(); + if (isa<ValueDecl>(ND) && !isa<FunctionDecl>(ND)) + return true; + } + return false; } private: + Token NextToken; bool AllowNonTypes; }; } @@ -808,11 +846,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, } } - if (Next.is(tok::coloncolon) || - (!ColonIsSacred && Next.is(tok::colon)) || - Next.is(tok::less) || - Next.is(tok::l_paren) || - Next.is(tok::l_brace)) { + if ((!ColonIsSacred && Next.is(tok::colon)) || + Next.isOneOf(tok::coloncolon, tok::less, tok::l_paren, + tok::l_brace)) { // If TryAnnotateTypeOrScopeToken annotates the token, tail recurse. if (TryAnnotateTypeOrScopeToken()) return ExprError(); @@ -908,14 +944,20 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, SourceLocation TemplateKWLoc; Token Replacement; auto Validator = llvm::make_unique<CastExpressionIdValidator>( - isTypeCast != NotTypeCast, isTypeCast != IsTypeCast); + Tok, isTypeCast != NotTypeCast, isTypeCast != IsTypeCast); Validator->IsAddressOfOperand = isAddressOfOperand; - Validator->WantRemainingKeywords = Tok.isNot(tok::r_paren); + if (Tok.isOneOf(tok::periodstar, tok::arrowstar)) { + Validator->WantExpressionKeywords = false; + Validator->WantRemainingKeywords = false; + } else { + Validator->WantRemainingKeywords = Tok.isNot(tok::r_paren); + } Name.setIdentifier(&II, ILoc); Res = Actions.ActOnIdExpression( getCurScope(), ScopeSpec, TemplateKWLoc, Name, Tok.is(tok::l_paren), isAddressOfOperand, std::move(Validator), - /*IsInlineAsmIdentifier=*/false, &Replacement); + /*IsInlineAsmIdentifier=*/false, + Tok.is(tok::r_paren) ? nullptr : &Replacement); if (!Res.isInvalid() && !Res.get()) { UnconsumeToken(Replacement); return ParseCastExpression(isUnaryExpression, isAddressOfOperand, @@ -1018,6 +1060,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw_sizeof: // unary-expression: 'sizeof' unary-expression // unary-expression: 'sizeof' '(' type-name ')' 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: return ParseUnaryExprOrTypeTraitExpression(); case tok::ampamp: { // unary-expression: '&&' identifier SourceLocation AmpAmpLoc = ConsumeToken(); @@ -1441,10 +1485,14 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { if (OpKind == tok::l_paren || !LHS.isInvalid()) { if (Tok.isNot(tok::r_paren)) { - if (ParseExpressionList(ArgExprs, CommaLocs, &Sema::CodeCompleteCall, - LHS.get())) { + if (ParseExpressionList(ArgExprs, CommaLocs, [&] { + Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs); + })) { (void)Actions.CorrectDelayedTyposInExpr(LHS); LHS = ExprError(); + } else if (LHS.isInvalid()) { + for (auto &E : ArgExprs) + Actions.CorrectDelayedTyposInExpr(E); } } } @@ -1453,7 +1501,19 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { if (LHS.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); } else if (Tok.isNot(tok::r_paren)) { - PT.consumeClose(); + bool HadDelayedTypo = false; + if (Actions.CorrectDelayedTyposInExpr(LHS).get() != LHS.get()) + HadDelayedTypo = true; + for (auto &E : ArgExprs) + if (Actions.CorrectDelayedTyposInExpr(E).get() != E) + HadDelayedTypo = true; + // If there were delayed typos in the LHS or ArgExprs, call SkipUntil + // instead of PT.consumeClose() to avoid emitting extra diagnostics for + // the unmatched l_paren. + if (HadDelayedTypo) + SkipUntil(tok::r_paren, StopAtSemi); + else + PT.consumeClose(); LHS = ExprError(); } else { assert((ArgExprs.size() == 0 || @@ -1510,14 +1570,14 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { cutOffParsing(); return ExprError(); } - + if (MayBePseudoDestructor && !LHS.isInvalid()) { LHS = ParseCXXPseudoDestructor(LHS.get(), OpLoc, OpKind, SS, ObjectType); break; } - // Either the action has told is that this cannot be a + // Either the action has told us that this cannot be a // pseudo-destructor expression (based on the type of base // expression), or we didn't see a '~' in the right place. We // can still parse a destructor name here, but in that case it @@ -1526,7 +1586,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { // FIXME: Add support for explicit call of template constructor. SourceLocation TemplateKWLoc; UnqualifiedId Name; - if (getLangOpts().ObjC2 && OpKind == tok::period && Tok.is(tok::kw_class)) { + if (getLangOpts().ObjC2 && OpKind == tok::period && + Tok.is(tok::kw_class)) { // Objective-C++: // After a '.' in a member access expression, treat the keyword // 'class' as if it were an identifier. @@ -1551,8 +1612,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.get(), OpLoc, OpKind, SS, TemplateKWLoc, Name, CurParsedObjCImpl ? CurParsedObjCImpl->Dcl - : nullptr, - Tok.is(tok::l_paren)); + : nullptr); break; } case tok::plusplus: // postfix-expression: postfix-expression '++' @@ -1596,10 +1656,10 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, ParsedType &CastTy, SourceRange &CastRange) { - assert((OpTok.is(tok::kw_typeof) || OpTok.is(tok::kw_sizeof) || - OpTok.is(tok::kw___alignof) || OpTok.is(tok::kw_alignof) || - OpTok.is(tok::kw__Alignof) || OpTok.is(tok::kw_vec_step)) && - "Not a typeof/sizeof/alignof/vec_step expression!"); + assert(OpTok.isOneOf(tok::kw_typeof, tok::kw_sizeof, tok::kw___alignof, + tok::kw_alignof, tok::kw__Alignof, tok::kw_vec_step, + tok::kw___builtin_omp_required_simd_align) && + "Not a typeof/sizeof/alignof/vec_step expression!"); ExprResult Operand; @@ -1607,8 +1667,8 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, if (Tok.isNot(tok::l_paren)) { // If construct allows a form without parenthesis, user may forget to put // pathenthesis around type name. - if (OpTok.is(tok::kw_sizeof) || OpTok.is(tok::kw___alignof) || - OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw__Alignof)) { + if (OpTok.isOneOf(tok::kw_sizeof, tok::kw___alignof, tok::kw_alignof, + tok::kw__Alignof)) { if (isTypeIdUnambiguously()) { DeclSpec DS(AttrFactory); ParseSpecifierQualifierList(DS); @@ -1682,9 +1742,9 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, /// [C++11] 'alignof' '(' type-id ')' /// \endverbatim ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { - assert((Tok.is(tok::kw_sizeof) || Tok.is(tok::kw___alignof) || - Tok.is(tok::kw_alignof) || Tok.is(tok::kw__Alignof) || - Tok.is(tok::kw_vec_step)) && + assert(Tok.isOneOf(tok::kw_sizeof, tok::kw___alignof, tok::kw_alignof, + tok::kw__Alignof, tok::kw_vec_step, + tok::kw___builtin_omp_required_simd_align) && "Not a sizeof/alignof/vec_step expression!"); Token OpTok = Tok; ConsumeToken(); @@ -1735,7 +1795,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { RParenLoc); } - if (OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw__Alignof)) + if (OpTok.isOneOf(tok::kw_alignof, tok::kw__Alignof)) Diag(OpTok, diag::warn_cxx98_compat_alignof); EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated, @@ -1750,11 +1810,12 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { CastRange); UnaryExprOrTypeTrait ExprKind = UETT_SizeOf; - if (OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw___alignof) || - OpTok.is(tok::kw__Alignof)) + if (OpTok.isOneOf(tok::kw_alignof, tok::kw___alignof, tok::kw__Alignof)) ExprKind = UETT_AlignOf; else if (OpTok.is(tok::kw_vec_step)) ExprKind = UETT_VecStep; + else if (OpTok.is(tok::kw___builtin_omp_required_simd_align)) + ExprKind = UETT_OpenMPRequiredSimdAlign; if (isCastExpr) return Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(), @@ -1763,7 +1824,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { CastTy.getAsOpaquePtr(), CastRange); - if (OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw__Alignof)) + if (OpTok.isOneOf(tok::kw_alignof, tok::kw__Alignof)) Diag(OpTok, diag::ext_alignof_expr) << OpTok.getIdentifierInfo(); // If we get here, the operand to the sizeof/alignof was an expresion. @@ -2064,10 +2125,10 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, // Diagnose use of bridge casts in non-arc mode. bool BridgeCast = (getLangOpts().ObjC2 && - (Tok.is(tok::kw___bridge) || - Tok.is(tok::kw___bridge_transfer) || - Tok.is(tok::kw___bridge_retained) || - Tok.is(tok::kw___bridge_retain))); + Tok.isOneOf(tok::kw___bridge, + tok::kw___bridge_transfer, + tok::kw___bridge_retained, + tok::kw___bridge_retain)); if (BridgeCast && !getLangOpts().ObjCAutoRefCount) { if (!TryConsumeToken(tok::kw___bridge)) { StringRef BridgeCastName = Tok.getName(); @@ -2088,6 +2149,17 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, if (!getCurScope()->getFnParent() && !getCurScope()->getBlockParent()) { Result = ExprError(Diag(OpenLoc, diag::err_stmtexpr_file_scope)); } else { + // Find the nearest non-record decl context. Variables declared in a + // statement expression behave as if they were declared in the enclosing + // function, block, or other code construct. + DeclContext *CodeDC = Actions.CurContext; + while (CodeDC->isRecord() || isa<EnumDecl>(CodeDC)) { + CodeDC = CodeDC->getParent(); + assert(CodeDC && !CodeDC->isFileContext() && + "statement expr not in code context"); + } + Sema::ContextRAII SavedContext(Actions, CodeDC, /*NewThisContext=*/false); + Actions.ActOnStartStmtExpr(); StmtResult Stmt(ParseCompoundStatement(true)); @@ -2256,6 +2328,11 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, InMessageExpressionRAIIObject InMessage(*this, false); Result = ParseExpression(MaybeTypeCast); + if (!getLangOpts().CPlusPlus && MaybeTypeCast && Result.isUsable()) { + // Correct typos in non-C++ code earlier so that implicit-cast-like + // expressions are parsed correctly. + Result = Actions.CorrectDelayedTyposInExpr(Result); + } ExprType = SimpleExpr; if (isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis)) @@ -2354,7 +2431,8 @@ ExprResult Parser::ParseGenericSelectionExpression() { // C11 6.5.1.1p3 "The controlling expression of a generic selection is // not evaluated." EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated); - ControllingExpr = ParseAssignmentExpression(); + ControllingExpr = + Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); if (ControllingExpr.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); @@ -2400,7 +2478,8 @@ ExprResult Parser::ParseGenericSelectionExpression() { // FIXME: These expressions should be parsed in a potentially potentially // evaluated context. - ExprResult ER(ParseAssignmentExpression()); + ExprResult ER( + Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression())); if (ER.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); @@ -2493,17 +2572,14 @@ ExprResult Parser::ParseFoldExpression(ExprResult LHS, /// [C++0x] assignment-expression /// [C++0x] braced-init-list /// \endverbatim -bool Parser::ParseExpressionList(SmallVectorImpl<Expr*> &Exprs, +bool Parser::ParseExpressionList(SmallVectorImpl<Expr *> &Exprs, SmallVectorImpl<SourceLocation> &CommaLocs, - void (Sema::*Completer)(Scope *S, - Expr *Data, - ArrayRef<Expr *> Args), - Expr *Data) { + std::function<void()> Completer) { bool SawError = false; while (1) { if (Tok.is(tok::code_completion)) { if (Completer) - (Actions.*Completer)(getCurScope(), Data, Exprs); + Completer(); else Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression); cutOffParsing(); @@ -2588,9 +2664,6 @@ void Parser::ParseBlockId(SourceLocation CaretLoc) { Declarator DeclaratorInfo(DS, Declarator::BlockLiteralContext); ParseDeclarator(DeclaratorInfo); - // We do this for: ^ __attribute__((noreturn)) {, as DS has the attributes. - DeclaratorInfo.takeAttributes(DS.getAttributes(), SourceLocation()); - MaybeParseGNUAttributes(DeclaratorInfo); // Inform sema that we are starting a block. |