diff options
Diffstat (limited to 'lib/Parse/ParseExpr.cpp')
| -rw-r--r-- | lib/Parse/ParseExpr.cpp | 104 | 
1 files changed, 81 insertions, 23 deletions
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index d0d97de84c10..95a28a8d5a14 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -347,7 +347,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 +384,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 +454,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 +466,24 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback {      if (isa<TypeDecl>(ND))        return WantTypeSpecifiers; -    return AllowNonTypes && -           CorrectionCandidateCallback::ValidateCandidate(candidate); + +    if (!AllowNonTypes || !CorrectionCandidateCallback::ValidateCandidate(candidate)) +      return false; + +    if (!(NextToken.is(tok::equal) || NextToken.is(tok::arrow) || +          NextToken.is(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;  };  } @@ -908,14 +929,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.is(tok::periodstar) || Tok.is(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, @@ -1441,10 +1468,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 +1484,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 +1553,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 +1569,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 +1595,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 '++' @@ -2088,6 +2131,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 +2310,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 +2413,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 +2460,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 +2554,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();  | 
