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

Peter Smith peter.smith at arm.com
Wed Dec 3 01:39:18 PST 2014


Thank you very much for the quick turnaround. I’ve rebuilt and the error messages have come back.

 

Peter

 

From: Kaelyn Takata [mailto:rikka at google.com] 
Sent: 02 December 2014 23:36
To: Peter Smith
Cc: cfe-commits at cs.uiuc.edu
Subject: Re: r222464 - Wire up delayed typo correction to DiagnoseEmptyLookup and set up

 

It should be fixed in r223177.

 

On Tue, Dec 2, 2014 at 2:13 PM, Kaelyn Takata <rikka at google.com> wrote:

Yeah I can investigate it. Looks like another situation where TypoExprs (part of the delayed typo correction) are going undiagnosed but for which there were no existing tests covering the associated code paths. Thanks for coming up with a reduced test case!

 

On Tue, Dec 2, 2014 at 8:16 AM, Peter Smith <peter.smith at arm.com> wrote:

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 <http://llvm.org/viewvc/llvm-project?rev=222464&view=rev> &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





_______________________________________________
cfe-commits mailing list
cfe-commits at cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

 

 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20141203/6eb96140/attachment.html>


More information about the cfe-commits mailing list