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