r222464 - Wire up delayed typo correction to DiagnoseEmptyLookup and set up

Peter Smith peter.smith at arm.com
Tue Dec 2 08:16:52 PST 2014


Hello,

I believe that this commit is causing some error messages that were
previously emitted to be suppressed. 

The following testcase:
// C++03 14.1:14 A template parameter shall not be used in its own default
argument
template <int I = (1*I)> struct S {};
S<1> s;
// C++03 14.1:13a The scope of a template-parameter extends from its point
of declaration until the end of its template.
template <int I1 = I2, int I2 = 1> struct T {};
T<0, 1> t;

When compiled with clang built prior to this commit; the output was:
testcase.cpp:2:22: error: use of undeclared identifier 'I'
template <int I = (1*I)> struct S {};
                     ^
testcase.cpp:5:20: error: use of undeclared identifier 'I2'
template <int I1 = I2, int I2 = 1> struct T {};
                   ^
2 errors generated.

After the commit no errors are generated.

I'm assuming that this was an unexpected side-effect? Would it be possible
for you to investigate? 

My apologies for taking so long to track these down into reproducible test
case. 

Thanks in advance

Peter

> -----Original Message-----
> From: cfe-commits-bounces at cs.uiuc.edu [mailto:cfe-commits-
> bounces at cs.uiuc.edu] On Behalf Of Kaelyn Takata
> Sent: 20 November 2014 22:07
> To: cfe-commits at cs.uiuc.edu
> Subject: r222464 - Wire up delayed typo correction to DiagnoseEmptyLookup
> and set up
> 
> Author: rikka
> Date: Thu Nov 20 16:06:40 2014
> New Revision: 222464
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=222464&view=rev
> Log:
> Wire up delayed typo correction to DiagnoseEmptyLookup and set up
> Sema::ActOnIdExpression to use the new functionality.
> 
> Among other things, this allows recovery in several cases where it
> wasn't possible before (e.g. correcting a mistyped static_cast<>).
> 
> Modified:
>     cfe/trunk/include/clang/Parse/Parser.h
>     cfe/trunk/include/clang/Sema/Sema.h
>     cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
>     cfe/trunk/lib/Parse/ParseDecl.cpp
>     cfe/trunk/lib/Parse/ParseDeclCXX.cpp
>     cfe/trunk/lib/Parse/ParseExpr.cpp
>     cfe/trunk/lib/Parse/ParseExprCXX.cpp
>     cfe/trunk/lib/Parse/ParseObjc.cpp
>     cfe/trunk/lib/Parse/ParseOpenMP.cpp
>     cfe/trunk/lib/Parse/ParseStmt.cpp
>     cfe/trunk/lib/Sema/SemaExpr.cpp
>     cfe/trunk/lib/Sema/SemaStmt.cpp
>     cfe/trunk/test/FixIt/fixit-unrecoverable.cpp
>     cfe/trunk/test/SemaCXX/typo-correction.cpp
>     cfe/trunk/test/SemaTemplate/crash-10438657.cpp
> 
> Modified: cfe/trunk/include/clang/Parse/Parser.h
> URL: http://llvm.org/viewvc/llvm-
>
project/cfe/trunk/include/clang/Parse/Parser.h?rev=222464&r1=222463&r2=22246
> 4&view=diff
>
============================================================================
> ==
> --- cfe/trunk/include/clang/Parse/Parser.h (original)
> +++ cfe/trunk/include/clang/Parse/Parser.h Thu Nov 20 16:06:40 2014
> @@ -334,6 +334,15 @@ private:
>    /// For typos, give a fixit to '='
>    bool isTokenEqualOrEqualTypo();
> 
> +  /// \brief Return the current token to the token stream and make the
> given
> +  /// token the current token.
> +  void UnconsumeToken(Token &Consumed) {
> +      Token Next = Tok;
> +      PP.EnterToken(Consumed);
> +      ConsumeToken();
> +      PP.EnterToken(Next);
> +  }
> +
>    /// ConsumeAnyToken - Dispatch to the right Consume* method based on
the
>    /// current token type.  This should only be used in cases where the
type
> of
>    /// the token really isn't known, e.g. in error recovery.
> @@ -1396,6 +1405,8 @@ private:
> 
>
//===--------------------------------------------------------------------
> ===//
>    // C++ Expressions
> +  ExprResult tryParseCXXIdExpression(CXXScopeSpec &SS, bool
> isAddressOfOperand,
> +                                     Token &Replacement);
>    ExprResult ParseCXXIdExpression(bool isAddressOfOperand = false);
> 
>    bool areTokensAdjacent(const Token &A, const Token &B);
> 
> Modified: cfe/trunk/include/clang/Sema/Sema.h
> URL: http://llvm.org/viewvc/llvm-
>
project/cfe/trunk/include/clang/Sema/Sema.h?rev=222464&r1=222463&r2=222464&v
> iew=diff
>
============================================================================
> ==
> --- cfe/trunk/include/clang/Sema/Sema.h (original)
> +++ cfe/trunk/include/clang/Sema/Sema.h Thu Nov 20 16:06:40 2014
> @@ -3463,7 +3463,7 @@ public:
>        Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
>        UnqualifiedId &Id, bool HasTrailingLParen, bool IsAddressOfOperand,
>        std::unique_ptr<CorrectionCandidateCallback> CCC = nullptr,
> -      bool IsInlineAsmIdentifier = false);
> +      bool IsInlineAsmIdentifier = false, Token *KeywordReplacement =
> nullptr);
> 
>    void DecomposeUnqualifiedId(const UnqualifiedId &Id,
>                                TemplateArgumentListInfo &Buffer,
> @@ -3474,7 +3474,7 @@ public:
>    DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
>                        std::unique_ptr<CorrectionCandidateCallback> CCC,
>                        TemplateArgumentListInfo *ExplicitTemplateArgs =
> nullptr,
> -                      ArrayRef<Expr *> Args = None);
> +                      ArrayRef<Expr *> Args = None, TypoExpr **Out =
> nullptr);
> 
>    ExprResult LookupInObjCMethod(LookupResult &LookUp, Scope *S,
>                                  IdentifierInfo *II,
> 
> Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
> URL: http://llvm.org/viewvc/llvm-
>
project/cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp?rev=222464&r1=222463&r
> 2=222464&view=diff
>
============================================================================
> ==
> --- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp Thu Nov 20 16:06:40 2014
> @@ -336,6 +336,7 @@ void Parser::ParseLexedMethodDeclaration
>          DefArgResult = ParseBraceInitializer();
>        } else
>          DefArgResult = ParseAssignmentExpression();
> +      DefArgResult = Actions.CorrectDelayedTyposInExpr(DefArgResult);
>        if (DefArgResult.isInvalid())
>          Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param,
>                                                 EqualLoc);
> 
> Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
> URL: http://llvm.org/viewvc/llvm-
>
project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=222464&r1=222463&r2=222464&vie
> w=diff
>
============================================================================
> ==
> --- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseDecl.cpp Thu Nov 20 16:06:40 2014
> @@ -302,7 +302,8 @@ unsigned Parser::ParseAttributeArgsCommo
>          Unevaluated.reset(
>              new EnterExpressionEvaluationContext(Actions,
> Sema::Unevaluated));
> 
> -      ExprResult ArgExpr(ParseAssignmentExpression());
> +      ExprResult ArgExpr(
> +
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
>        if (ArgExpr.isInvalid()) {
>          SkipUntil(tok::r_paren, StopAtSemi);
>          return 0;
> @@ -5566,6 +5567,7 @@ void Parser::ParseParameterDeclarationCl
>              DefArgResult = ParseBraceInitializer();
>            } else
>              DefArgResult = ParseAssignmentExpression();
> +          DefArgResult = Actions.CorrectDelayedTyposInExpr(DefArgResult);
>            if (DefArgResult.isInvalid()) {
>              Actions.ActOnParamDefaultArgumentError(Param, EqualLoc);
>              SkipUntil(tok::comma, tok::r_paren, StopAtSemi |
> StopBeforeMatch);
> 
> Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-
>
project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=222464&r1=222463&r2=222464&
> view=diff
>
============================================================================
> ==
> --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Thu Nov 20 16:06:40 2014
> @@ -796,7 +796,7 @@ SourceLocation Parser::ParseDecltypeSpec
>        //   The operand of the decltype specifier is an unevaluated
operand.
>        EnterExpressionEvaluationContext Unevaluated(Actions,
> Sema::Unevaluated,
> 
> nullptr,/*IsDecltype=*/true);
> -      Result = ParseExpression();
> +      Result = Actions.CorrectDelayedTyposInExpr(ParseExpression());
>        if (Result.isInvalid()) {
>          DS.SetTypeSpecError();
>          if (SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch)) {
> 
> Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
> URL: http://llvm.org/viewvc/llvm-
>
project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=222464&r1=222463&r2=222464&vie
> w=diff
>
============================================================================
> ==
> --- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseExpr.cpp Thu Nov 20 16:06:40 2014
> @@ -277,6 +277,7 @@ Parser::ParseRHSOfBinaryExpression(ExprR
>          // 'logical-OR-expression' as we might expect.
>          TernaryMiddle = ParseExpression();
>          if (TernaryMiddle.isInvalid()) {
> +          Actions.CorrectDelayedTyposInExpr(LHS);
>            LHS = ExprError();
>            TernaryMiddle = nullptr;
>          }
> @@ -345,9 +346,11 @@ Parser::ParseRHSOfBinaryExpression(ExprR
>      else
>        RHS = ParseCastExpression(false);
> 
> -    if (RHS.isInvalid())
> +    if (RHS.isInvalid()) {
> +      Actions.CorrectDelayedTyposInExpr(LHS);
>        LHS = ExprError();
> -
> +    }
> +
>      // Remember the precedence of this operator and get the precedence of
> the
>      // operator immediately to the right of the RHS.
>      prec::Level ThisPrec = NextTokPrec;
> @@ -376,8 +379,10 @@ Parser::ParseRHSOfBinaryExpression(ExprR
>                              static_cast<prec::Level>(ThisPrec +
> !isRightAssoc));
>        RHSIsInitList = false;
> 
> -      if (RHS.isInvalid())
> +      if (RHS.isInvalid()) {
> +        Actions.CorrectDelayedTyposInExpr(LHS);
>          LHS = ExprError();
> +      }
> 
>        NextTokPrec = getBinOpPrecedence(Tok.getKind(),
> GreaterThanIsOperator,
>                                         getLangOpts().CPlusPlus11);
> @@ -413,7 +418,9 @@ Parser::ParseRHSOfBinaryExpression(ExprR
>          LHS = Actions.ActOnConditionalOp(OpToken.getLocation(), ColonLoc,
>                                           LHS.get(), TernaryMiddle.get(),
>                                           RHS.get());
> -    }
> +    } else
> +      // Ensure potential typos in the RHS aren't left undiagnosed.
> +      Actions.CorrectDelayedTyposInExpr(RHS);
>    }
>  }
> 
> @@ -441,7 +448,7 @@ class CastExpressionIdValidator : public
>   public:
>    CastExpressionIdValidator(bool AllowTypes, bool AllowNonTypes)
>        : AllowNonTypes(AllowNonTypes) {
> -    WantTypeSpecifiers = AllowTypes;
> +    WantTypeSpecifiers = WantFunctionLikeCasts = AllowTypes;
>    }
> 
>    bool ValidateCandidate(const TypoCorrection &candidate) override {
> @@ -899,13 +906,20 @@ ExprResult Parser::ParseCastExpression(b
>      UnqualifiedId Name;
>      CXXScopeSpec ScopeSpec;
>      SourceLocation TemplateKWLoc;
> +    Token Replacement;
>      auto Validator = llvm::make_unique<CastExpressionIdValidator>(
>          isTypeCast != NotTypeCast, isTypeCast != IsTypeCast);
>      Validator->IsAddressOfOperand = isAddressOfOperand;
>      Name.setIdentifier(&II, ILoc);
> -    Res = Actions.ActOnIdExpression(getCurScope(), ScopeSpec,
> TemplateKWLoc,
> -                                    Name, Tok.is(tok::l_paren),
> -                                    isAddressOfOperand,
> std::move(Validator));
> +    Res = Actions.ActOnIdExpression(
> +        getCurScope(), ScopeSpec, TemplateKWLoc, Name,
> Tok.is(tok::l_paren),
> +        isAddressOfOperand, std::move(Validator),
> +        /*IsInlineAsmIdentifier=*/false, &Replacement);
> +    if (!Res.isInvalid() && !Res.get()) {
> +      UnconsumeToken(Replacement);
> +      return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
> +                                 NotCastExpr, isTypeCast);
> +    }
>      break;
>    }
>    case tok::char_constant:     // constant: character-constant
> 
> Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
> URL: http://llvm.org/viewvc/llvm-
>
project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=222464&r1=222463&r2=222464&
> view=diff
>
============================================================================
> ==
> --- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Thu Nov 20 16:06:40 2014
> @@ -567,6 +567,28 @@ bool Parser::ParseOptionalCXXScopeSpecif
>    return false;
>  }
> 
> +ExprResult Parser::tryParseCXXIdExpression(CXXScopeSpec &SS, bool
> isAddressOfOperand,
> +                                           Token &Replacement) {
> +  SourceLocation TemplateKWLoc;
> +  UnqualifiedId Name;
> +  if (ParseUnqualifiedId(SS,
> +                         /*EnteringContext=*/false,
> +                         /*AllowDestructorName=*/false,
> +                         /*AllowConstructorName=*/false,
> +                         /*ObjectType=*/ParsedType(), TemplateKWLoc,
Name))
> +    return ExprError();
> +
> +  // This is only the direct operand of an & operator if it is not
> +  // followed by a postfix-expression suffix.
> +  if (isAddressOfOperand && isPostfixExpressionSuffixStart())
> +    isAddressOfOperand = false;
> +
> +  return Actions.ActOnIdExpression(getCurScope(), SS, TemplateKWLoc,
Name,
> +                                   Tok.is(tok::l_paren),
> isAddressOfOperand,
> +                                   nullptr,
> /*IsInlineAsmIdentifier=*/false,
> +                                   &Replacement);
> +}
> +
>  /// ParseCXXIdExpression - Handle id-expression.
>  ///
>  ///       id-expression:
> @@ -617,24 +639,17 @@ ExprResult Parser::ParseCXXIdExpression(
>    CXXScopeSpec SS;
>    ParseOptionalCXXScopeSpecifier(SS, ParsedType(),
> /*EnteringContext=*/false);
> 
> -  SourceLocation TemplateKWLoc;
> -  UnqualifiedId Name;
> -  if (ParseUnqualifiedId(SS,
> -                         /*EnteringContext=*/false,
> -                         /*AllowDestructorName=*/false,
> -                         /*AllowConstructorName=*/false,
> -                         /*ObjectType=*/ ParsedType(),
> -                         TemplateKWLoc,
> -                         Name))
> -    return ExprError();
> -
> -  // This is only the direct operand of an & operator if it is not
> -  // followed by a postfix-expression suffix.
> -  if (isAddressOfOperand && isPostfixExpressionSuffixStart())
> -    isAddressOfOperand = false;
> -
> -  return Actions.ActOnIdExpression(getCurScope(), SS, TemplateKWLoc,
Name,
> -                                   Tok.is(tok::l_paren),
> isAddressOfOperand);
> +  Token Replacement;
> +  ExprResult Result = tryParseCXXIdExpression(SS, isAddressOfOperand,
> Replacement);
> +  if (Result.isUnset()) {
> +    // If the ExprResult is valid but null, then typo correction
suggested
> a
> +    // keyword replacement that needs to be reparsed.
> +    UnconsumeToken(Replacement);
> +    Result = tryParseCXXIdExpression(SS, isAddressOfOperand,
Replacement);
> +  }
> +  assert(!Result.isUnset() && "Typo correction suggested a keyword
> replacement "
> +                              "for a previous keyword suggestion");
> +  return Result;
>  }
> 
>  /// ParseLambdaExpression - Parse a C++11 lambda expression.
> 
> Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
> URL: http://llvm.org/viewvc/llvm-
>
project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=222464&r1=222463&r2=222464&vie
> w=diff
>
============================================================================
> ==
> --- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseObjc.cpp Thu Nov 20 16:06:40 2014
> @@ -2170,7 +2170,10 @@ bool Parser::ParseObjCXXMessageReceiver(
>    if (!Actions.isSimpleTypeSpecifier(Tok.getKind())) {
>      //   objc-receiver:
>      //     expression
> -    ExprResult Receiver = ParseExpression();
> +    // Make sure any typos in the receiver are corrected or diagnosed, so
> that
> +    // proper recovery can happen. FIXME: Perhaps filter the corrected
expr
> to
> +    // only the things that are valid ObjC receivers?
> +    ExprResult Receiver =
> Actions.CorrectDelayedTyposInExpr(ParseExpression());
>      if (Receiver.isInvalid())
>        return true;
> 
> 
> Modified: cfe/trunk/lib/Parse/ParseOpenMP.cpp
> URL: http://llvm.org/viewvc/llvm-
>
project/cfe/trunk/lib/Parse/ParseOpenMP.cpp?rev=222464&r1=222463&r2=222464&v
> iew=diff
>
============================================================================
> ==
> --- cfe/trunk/lib/Parse/ParseOpenMP.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseOpenMP.cpp Thu Nov 20 16:06:40 2014
> @@ -741,7 +741,8 @@ OMPClause *Parser::ParseOpenMPVarListCla
>    if (MustHaveTail) {
>      ColonLoc = Tok.getLocation();
>      ConsumeToken();
> -    ExprResult Tail = ParseAssignmentExpression();
> +    ExprResult Tail =
> +        Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
>      if (Tail.isUsable())
>        TailExpr = Tail.get();
>      else
> 
> Modified: cfe/trunk/lib/Parse/ParseStmt.cpp
> URL: http://llvm.org/viewvc/llvm-
>
project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=222464&r1=222463&r2=222464&vie
> w=diff
>
============================================================================
> ==
> --- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseStmt.cpp Thu Nov 20 16:06:40 2014
> @@ -642,6 +642,11 @@ StmtResult Parser::ParseCaseStatement(bo
>      ExprResult LHS;
>      if (!MissingCase) {
>        LHS = ParseConstantExpression();
> +      if (!getLangOpts().CPlusPlus11) {
> +        LHS = Actions.CorrectDelayedTyposInExpr(LHS, [this](class Expr
*E)
> {
> +          return Actions.VerifyIntegerConstantExpression(E);
> +        });
> +      }
>        if (LHS.isInvalid()) {
>          // If constant-expression is parsed unsuccessfully, recover by
> skipping
>          // current case statement (moving to the colon that ends it).
> @@ -1562,7 +1567,7 @@ StmtResult Parser::ParseForStatement(Sou
>      }
>    } else {
>      ProhibitAttributes(attrs);
> -    Value = ParseExpression();
> +    Value = Actions.CorrectDelayedTyposInExpr(ParseExpression());
> 
>      ForEach = isTokIdentifier_in();
> 
> 
> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
> URL: http://llvm.org/viewvc/llvm-
>
project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=222464&r1=222463&r2=222464&view=
> diff
>
============================================================================
> ==
> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Nov 20 16:06:40 2014
> @@ -1673,6 +1673,40 @@ Sema::DecomposeUnqualifiedId(const Unqua
>    }
>  }
> 
> +static void emitEmptyLookupTypoDiagnostic(
> +    const TypoCorrection &TC, Sema &SemaRef, const CXXScopeSpec &SS,
> +    DeclarationName Typo, SourceLocation TypoLoc, ArrayRef<Expr *> Args,
> +    unsigned DiagnosticID, unsigned DiagnosticSuggestID) {
> +  DeclContext *Ctx =
> +      SS.isEmpty() ? nullptr : SemaRef.computeDeclContext(SS, false);
> +  if (!TC) {
> +    // Emit a special diagnostic for failed member lookups.
> +    // FIXME: computing the declaration context might fail here (?)
> +    if (Ctx)
> +      SemaRef.Diag(TypoLoc, diag::err_no_member) << Typo << Ctx
> +                                                 << SS.getRange();
> +    else
> +      SemaRef.Diag(TypoLoc, DiagnosticID) << Typo;
> +    return;
> +  }
> +
> +  std::string CorrectedStr = TC.getAsString(SemaRef.getLangOpts());
> +  bool DroppedSpecifier =
> +      TC.WillReplaceSpecifier() && Typo.getAsString() == CorrectedStr;
> +  unsigned NoteID =
> +      (TC.getCorrectionDecl() &&
> isa<ImplicitParamDecl>(TC.getCorrectionDecl()))
> +          ? diag::note_implicit_param_decl
> +          : diag::note_previous_decl;
> +  if (!Ctx)
> +    SemaRef.diagnoseTypo(TC, SemaRef.PDiag(DiagnosticSuggestID) << Typo,
> +                         SemaRef.PDiag(NoteID));
> +  else
> +    SemaRef.diagnoseTypo(TC, SemaRef.PDiag(diag::err_no_member_suggest)
> +                                 << Typo << Ctx << DroppedSpecifier
> +                                 << SS.getRange(),
> +                         SemaRef.PDiag(NoteID));
> +}
> +
>  /// Diagnose an empty lookup.
>  ///
>  /// \return false if new lookup candidates were found
> @@ -1680,7 +1714,7 @@ bool
>  Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
>                            std::unique_ptr<CorrectionCandidateCallback>
CCC,
>                            TemplateArgumentListInfo *ExplicitTemplateArgs,
> -                          ArrayRef<Expr *> Args) {
> +                          ArrayRef<Expr *> Args, TypoExpr **Out) {
>    DeclarationName Name = R.getLookupName();
> 
>    unsigned diagnostic = diag::err_undeclared_var_use;
> @@ -1797,8 +1831,22 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXS
> 
>    // We didn't find anything, so try to correct for a typo.
>    TypoCorrection Corrected;
> -  if (S && (Corrected = CorrectTypo(R.getLookupNameInfo(),
> R.getLookupKind(),
> -                                    S, &SS, std::move(CCC),
> CTK_ErrorRecovery))) {
> +  if (S && Out) {
> +    SourceLocation TypoLoc = R.getNameLoc();
> +    assert(!ExplicitTemplateArgs &&
> +           "Diagnosing an empty lookup with explicit template args!");
> +    *Out = CorrectTypoDelayed(
> +        R.getLookupNameInfo(), R.getLookupKind(), S, &SS, std::move(CCC),
> +        [=](const TypoCorrection &TC) {
> +          emitEmptyLookupTypoDiagnostic(TC, *this, SS, Name, TypoLoc,
Args,
> +                                        diagnostic, diagnostic_suggest);
> +        },
> +        nullptr, CTK_ErrorRecovery);
> +    if (*Out)
> +      return true;
> +  } else if (S && (Corrected =
> +                       CorrectTypo(R.getLookupNameInfo(),
> R.getLookupKind(), S,
> +                                   &SS, std::move(CCC),
> CTK_ErrorRecovery))) {
>      std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
>      bool DroppedSpecifier =
>          Corrected.WillReplaceSpecifier() && Name.getAsString() ==
> CorrectedStr;
> @@ -1950,7 +1998,7 @@ Sema::ActOnIdExpression(Scope *S, CXXSco
>                          SourceLocation TemplateKWLoc, UnqualifiedId &Id,
>                          bool HasTrailingLParen, bool IsAddressOfOperand,
>                          std::unique_ptr<CorrectionCandidateCallback> CCC,
> -                        bool IsInlineAsmIdentifier) {
> +                        bool IsInlineAsmIdentifier, Token
> *KeywordReplacement) {
>    assert(!(IsAddressOfOperand && HasTrailingLParen) &&
>           "cannot be direct & operand and have a trailing lparen");
>    if (SS.isInvalid())
> @@ -2062,13 +2110,43 @@ Sema::ActOnIdExpression(Scope *S, CXXSco
> 
>      // If this name wasn't predeclared and if this is not a function
>      // call, diagnose the problem.
> -    auto DefaultValidator =
> llvm::make_unique<CorrectionCandidateCallback>();
> +    TypoExpr *TE = nullptr;
> +    auto DefaultValidator =
llvm::make_unique<CorrectionCandidateCallback>(
> +        II, SS.isValid() ? SS.getScopeRep() : nullptr);
>      DefaultValidator->IsAddressOfOperand = IsAddressOfOperand;
>      assert((!CCC || CCC->IsAddressOfOperand == IsAddressOfOperand) &&
>             "Typo correction callback misconfigured");
> -    if (DiagnoseEmptyLookup(S, SS, R,
> -                            CCC ? std::move(CCC) :
> std::move(DefaultValidator)))
> -      return ExprError();
> +    if (CCC) {
> +      // Make sure the callback knows what the typo being diagnosed is.
> +      CCC->setTypoName(II);
> +      if (SS.isValid())
> +        CCC->setTypoNNS(SS.getScopeRep());
> +    }
> +    if (DiagnoseEmptyLookup(
> +            S, SS, R, CCC ? std::move(CCC) : std::move(DefaultValidator),
> +            nullptr, None, getLangOpts().CPlusPlus ? &TE : nullptr)) {
> +      if (TE && KeywordReplacement) {
> +        auto &State = getTypoExprState(TE);
> +        auto BestTC = State.Consumer->getNextCorrection();
> +        if (BestTC.isKeyword()) {
> +          auto *II = BestTC.getCorrectionAsIdentifierInfo();
> +          if (State.DiagHandler)
> +            State.DiagHandler(BestTC);
> +          KeywordReplacement->startToken();
> +          KeywordReplacement->setKind(II->getTokenID());
> +          KeywordReplacement->setIdentifierInfo(II);
> +          KeywordReplacement-
> >setLocation(BestTC.getCorrectionRange().getBegin());
> +          // Clean up the state associated with the TypoExpr, since it
has
> +          // now been diagnosed (without a call to
> CorrectDelayedTyposInExpr).
> +          clearDelayedTypo(TE);
> +          // Signal that a correction to a keyword was performed by
> returning a
> +          // valid-but-null ExprResult.
> +          return (Expr*)nullptr;
> +        }
> +        State.Consumer->resetCorrectionStream();
> +      }
> +      return TE ? TE : ExprError();
> +    }
> 
>      assert(!R.empty() &&
>             "DiagnoseEmptyLookup returned false but added no results");
> @@ -12450,6 +12528,8 @@ void Sema::UpdateMarkingForLValueToRValu
>  }
> 
>  ExprResult Sema::ActOnConstantExpression(ExprResult Res) {
> +  Res = CorrectDelayedTyposInExpr(Res);
> +
>    if (!Res.isUsable())
>      return Res;
> 
> 
> Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
> URL: http://llvm.org/viewvc/llvm-
>
project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=222464&r1=222463&r2=222464&view=
> diff
>
============================================================================
> ==
> --- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaStmt.cpp Thu Nov 20 16:06:40 2014
> @@ -371,6 +371,23 @@ Sema::ActOnCaseStmt(SourceLocation CaseL
>      return StmtError();
>    }
> 
> +  ExprResult LHS =
> +      CorrectDelayedTyposInExpr(LHSVal, [this](class Expr *E) {
> +        if (!getLangOpts().CPlusPlus11)
> +          return VerifyIntegerConstantExpression(E);
> +        if (Expr *CondExpr =
> +                getCurFunction()->SwitchStack.back()->getCond()) {
> +          QualType CondType = CondExpr->getType();
> +          llvm::APSInt TempVal;
> +          return CheckConvertedConstantExpression(E, CondType, TempVal,
> +                                                        CCEK_CaseValue);
> +        }
> +        return ExprError();
> +      });
> +  if (LHS.isInvalid())
> +    return StmtError();
> +  LHSVal = LHS.get();
> +
>    if (!getLangOpts().CPlusPlus11) {
>      // C99 6.8.4.2p3: The expression shall be an integer constant.
>      // However, GCC allows any evaluatable integer expression.
> @@ -388,7 +405,7 @@ Sema::ActOnCaseStmt(SourceLocation CaseL
>      }
>    }
> 
> -  auto LHS = ActOnFinishFullExpr(LHSVal, LHSVal->getExprLoc(), false,
> +  LHS = ActOnFinishFullExpr(LHSVal, LHSVal->getExprLoc(), false,
>                                   getLangOpts().CPlusPlus11);
>    if (LHS.isInvalid())
>      return StmtError();
> 
> Modified: cfe/trunk/test/FixIt/fixit-unrecoverable.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit-
> unrecoverable.cpp?rev=222464&r1=222463&r2=222464&view=diff
>
============================================================================
> ==
> --- cfe/trunk/test/FixIt/fixit-unrecoverable.cpp (original)
> +++ cfe/trunk/test/FixIt/fixit-unrecoverable.cpp Thu Nov 20 16:06:40 2014
> @@ -6,7 +6,5 @@
>  // RUN: %clang_cc1 -fsyntax-only -verify %s
> 
>  float f(int y) {
> -  return static_cst<float>(y); // expected-error{{use of undeclared
> identifier 'static_cst'; did you mean 'static_cast'?}} \
> -  // expected-error{{for function-style cast or type construction}}
> +  return static_cst<float>(y); // expected-error{{use of undeclared
> identifier 'static_cst'; did you mean 'static_cast'?}}
>  }
> -
> 
> Modified: cfe/trunk/test/SemaCXX/typo-correction.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/typo-
> correction.cpp?rev=222464&r1=222463&r2=222464&view=diff
>
============================================================================
> ==
> --- cfe/trunk/test/SemaCXX/typo-correction.cpp (original)
> +++ cfe/trunk/test/SemaCXX/typo-correction.cpp Thu Nov 20 16:06:40 2014
> @@ -209,11 +209,12 @@ namespace PR13051 {
>    };
> 
>    void foo(); // expected-note{{'foo' declared here}}
> -  void g(void(*)());
> -  void g(bool(S<int>::*)() const);
> +  void g(void(*)()); // expected-note{{candidate function not viable}}
> +  void g(bool(S<int>::*)() const); // expected-note{{candidate function
not
> viable}}
> 
>    void test() {
> -    g(&S<int>::tempalte f<int>); // expected-error{{did you mean
> 'template'?}}
> +    g(&S<int>::tempalte f<int>); // expected-error{{did you mean
> 'template'?}} \
> +                                 // expected-error{{no matching function
> for call to 'g'}}
>      g(&S<int>::opeartor bool); // expected-error{{did you mean
> 'operator'?}}
>      g(&S<int>::foo); // expected-error{{no member named 'foo' in
> 'PR13051::S<int>'; did you mean simply 'foo'?}}
>    }
> 
> Modified: cfe/trunk/test/SemaTemplate/crash-10438657.cpp
> URL:
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/crash-
> 10438657.cpp?rev=222464&r1=222463&r2=222464&view=diff
>
============================================================================
> ==
> --- cfe/trunk/test/SemaTemplate/crash-10438657.cpp (original)
> +++ cfe/trunk/test/SemaTemplate/crash-10438657.cpp Thu Nov 20 16:06:40
2014
> @@ -1,6 +1,6 @@
>  // RUN: not %clang_cc1 -fsyntax-only %s 2> %t
>  // RUN: FileCheck %s < %t
> -// CHECK: 10 errors
> +// CHECK: 9 errors
>  template<typename _CharT>
>  class collate : public locale::facet {
> 
> 
> 
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits








More information about the cfe-commits mailing list