r226334 - Fix a case where delayed typo correction should have resolved an

Kaelyn Takata rikka at google.com
Fri Jan 16 14:11:04 PST 2015


Author: rikka
Date: Fri Jan 16 16:11:04 2015
New Revision: 226334

URL: http://llvm.org/viewvc/llvm-project?rev=226334&view=rev
Log:
Fix a case where delayed typo correction should have resolved an
ambiguity but wasn't.

In the new test case, "click" wasn't being corrected properly because
Sema::ClassifyName would call CorrectTypo for "click" then later
Sema::DiagnoseEmptyLookup would call CorrectTypoDelayed for the same use
of "click" (the former by the parser needing to determine what the
identifier is so it knows how to parse the statement, i.e. is it the
beginning of a declaration or an expression). CorrectTypo would record
that typo correction for "click" failed and CorrectTypoDelayed would see
that and not even try to correct the typo, even though in this case
CorrectTypo failed due to an ambiguity (both "Click" and "clock" having
an edit distance of one from "click") that could be resolved with more
information. The fix is two-fold:
  1) Have CorrectTypo not record failed corrections if the reason for
     the failure was two or more corrections with the same edit
     distance, and
  2) Make the CorrectionCandidateCallback used by
     Parser::ParseCastExpression reject FunctionDecl candidates when the
     next token after the identifier is a ".", "=", or "->" since
     functions cannot be assigned to and do not have members that can be
     referenced.

The reason for two correction spots is that from r222549 until r224375
landed, the first correction attempt would fail completely but the
second would suggest "clock" while having the note point to the
declaration of "Click".

Modified:
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/test/SemaCXX/typo-correction-delayed.cpp

Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=226334&r1=226333&r2=226334&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Fri Jan 16 16:11:04 2015
@@ -446,8 +446,8 @@ ExprResult Parser::ParseCastExpression(b
 namespace {
 class CastExpressionIdValidator : public CorrectionCandidateCallback {
  public:
-  CastExpressionIdValidator(bool AllowTypes, bool AllowNonTypes)
-      : AllowNonTypes(AllowNonTypes) {
+  CastExpressionIdValidator(Token Next, bool AllowTypes, bool AllowNonTypes)
+      : NextToken(Next), AllowNonTypes(AllowNonTypes) {
     WantTypeSpecifiers = WantFunctionLikeCasts = AllowTypes;
   }
 
@@ -458,11 +458,24 @@ class CastExpressionIdValidator : public
 
     if (isa<TypeDecl>(ND))
       return WantTypeSpecifiers;
-    return AllowNonTypes &&
-           CorrectionCandidateCallback::ValidateCandidate(candidate);
+
+    if (!AllowNonTypes || !CorrectionCandidateCallback::ValidateCandidate(candidate))
+      return false;
+
+    if (!(NextToken.is(tok::equal) || NextToken.is(tok::arrow) ||
+          NextToken.is(tok::period)))
+      return true;
+
+    for (auto *C : candidate) {
+      NamedDecl *ND = C->getUnderlyingDecl();
+      if (isa<ValueDecl>(ND) && !isa<FunctionDecl>(ND))
+        return true;
+    }
+    return false;
   }
 
  private:
+  Token NextToken;
   bool AllowNonTypes;
 };
 }
@@ -908,7 +921,7 @@ ExprResult Parser::ParseCastExpression(b
     SourceLocation TemplateKWLoc;
     Token Replacement;
     auto Validator = llvm::make_unique<CastExpressionIdValidator>(
-        isTypeCast != NotTypeCast, isTypeCast != IsTypeCast);
+        Tok, isTypeCast != NotTypeCast, isTypeCast != IsTypeCast);
     Validator->IsAddressOfOperand = isAddressOfOperand;
     Validator->WantRemainingKeywords = Tok.isNot(tok::r_paren);
     Name.setIdentifier(&II, ILoc);

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=226334&r1=226333&r2=226334&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Fri Jan 16 16:11:04 2015
@@ -4284,7 +4284,7 @@ TypoCorrection Sema::CorrectTypo(const D
   // Record the failure's location if needed and return an empty correction. If
   // this was an unqualified lookup and we believe the callback object did not
   // filter out possible corrections, also cache the failure for the typo.
-  return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
+  return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure && !SecondBestTC);
 }
 
 /// \brief Try to "correct" a typo in the source code by finding
@@ -4337,9 +4337,7 @@ TypoExpr *Sema::CorrectTypoDelayed(
   TypoCorrection Empty;
   auto Consumer = makeTypoCorrectionConsumer(
       TypoName, LookupKind, S, SS, std::move(CCC), MemberContext,
-      EnteringContext, OPT,
-      /*SearchModules=*/(Mode == CTK_ErrorRecovery) && getLangOpts().Modules &&
-          getLangOpts().ModulesSearchAll);
+      EnteringContext, OPT, Mode == CTK_ErrorRecovery);
 
   if (!Consumer || Consumer->empty())
     return nullptr;

Modified: cfe/trunk/test/SemaCXX/typo-correction-delayed.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/typo-correction-delayed.cpp?rev=226334&r1=226333&r2=226334&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/typo-correction-delayed.cpp (original)
+++ cfe/trunk/test/SemaCXX/typo-correction-delayed.cpp Fri Jan 16 16:11:04 2015
@@ -157,3 +157,13 @@ namespace PR22092 {
 a = b ? : 0;  // expected-error {{C++ requires a type specifier for all declarations}} \
               // expected-error-re {{use of undeclared identifier 'b'{{$}}}}
 }
+
+extern long clock (void);
+struct Pointer {
+  void set_xpos(int);
+  void set_ypos(int);
+};
+void MovePointer(Pointer &Click, int x, int y) {  // expected-note 2 {{'Click' declared here}}
+  click.set_xpos(x);  // expected-error {{use of undeclared identifier 'click'; did you mean 'Click'?}}
+  click.set_ypos(x);  // expected-error {{use of undeclared identifier 'click'; did you mean 'Click'?}}
+}





More information about the cfe-commits mailing list