[cfe-commits] PATCH: Restart handling of a function declarator if the function name was typo-corrected (issue 4929043)

rikka at google.com rikka at google.com
Fri Aug 19 13:47:05 PDT 2011


Reviewers: chandlerc,

Description:
Not sure if this is the right way (without a major rewrite of
Sema::CorrectTypo and friends) to achieve the goal, but it solves the
issue brought up by Jordy in response to r137966 where an out-of-line
function definition is not rechecked against existing declarations to
see if it is valid after being typo-corrected.

Please review this at http://codereview.appspot.com/4929043/

Affected files:
   M     lib/Sema/SemaDecl.cpp
   M     test/SemaCXX/function-redecl.cpp


-------------- next part --------------
Index: test/SemaCXX/function-redecl.cpp
===================================================================
--- test/SemaCXX/function-redecl.cpp	(revision 138068)
+++ test/SemaCXX/function-redecl.cpp	(working copy)
@@ -54,3 +54,8 @@
 struct X { int f(); };
 struct Y : public X {};
 int Y::f() { return 3; } // expected-error {{out-of-line definition of 'f' does not match any declaration in 'Y'}}
+
+struct J { int typo() const; }; // expected-note {{'typo' declared here}} \
+                                // expected-note {{member declaration nearly matches}}
+int J::typo_() { return 3; } // expected-error {{out-of-line definition of 'typo_' does not match any declaration in 'J'; did you mean 'typo'}} \
+                             // expected-error {{out-of-line definition of 'typo' does not match any declaration in 'J'}}
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp	(revision 138068)
+++ lib/Sema/SemaDecl.cpp	(working copy)
@@ -4204,7 +4204,8 @@
   return AddedAny;
 }
 
-static void DiagnoseInvalidRedeclaration(Sema &S, FunctionDecl *NewFD,
+static bool DiagnoseInvalidRedeclaration(Sema &S, LookupResult &Previous,
+                                         FunctionDecl *NewFD,
                                          bool isFriendDecl) {
   DeclarationName Name = NewFD->getDeclName();
   DeclContext *DC = NewFD->getDeclContext();
@@ -4213,6 +4214,7 @@
   llvm::SmallVector<unsigned, 1> MismatchedParams;
   llvm::SmallVector<std::pair<FunctionDecl*, unsigned>, 1> NearMatches;
   TypoCorrection Correction;
+  bool TypoWasCorrected = false;
   unsigned DiagMsg = isFriendDecl ? diag::err_no_matching_local_friend
                                   : diag::err_member_def_does_not_match;
 
@@ -4239,6 +4241,9 @@
              Correction.getCorrection() != Name) {
     DiagMsg = isFriendDecl ? diag::err_no_matching_local_friend_suggest
                            : diag::err_member_def_does_not_match_suggest;
+    TypoWasCorrected = true;
+    Previous.clear();
+    Previous.setLookupName(Correction.getCorrection());
     for (TypoCorrection::decl_iterator CDecl = Correction.begin(),
                                     CDeclEnd = Correction.end();
          CDecl != CDeclEnd; ++CDecl) {
@@ -4250,11 +4255,12 @@
         unsigned ParamNum =
             MismatchedParams.empty() ? 0 : MismatchedParams.front() + 1;
         NearMatches.push_back(std::make_pair(FD, ParamNum));
+        Previous.addDecl(FD);
       }
     }
   }
 
-  if (Correction)
+  if (TypoWasCorrected)
     S.Diag(NewFD->getLocation(), DiagMsg)
         << Name << DC << Correction.getQuoted(S.getLangOptions())
         << FixItHint::CreateReplacement(
@@ -4278,6 +4284,7 @@
     } else
       S.Diag(FD->getLocation(), diag::note_member_def_close_match);
   }
+  return TypoWasCorrected;
 }
 
 NamedDecl*
@@ -4992,13 +4999,27 @@
           // matches (e.g., those that differ only in cv-qualifiers and
           // whether the parameter types are references).
 
-          DiagnoseInvalidRedeclaration(*this, NewFD, false);
+          if (DiagnoseInvalidRedeclaration(*this, Previous, NewFD, false)) {
+            D.SetIdentifier(Previous.getLookupName().getAsIdentifierInfo(),
+                            D.getIdentifierLoc());
+            return ActOnFunctionDeclarator(S, D, DC, R, TInfo, Previous,
+                                           TemplateParamLists,
+                                           IsFunctionDefinition,
+                                           Redeclaration, AddToScope);
+          }
         }
 
         // Unqualified local friend declarations are required to resolve
         // to something.
       } else if (isFriend && cast<CXXRecordDecl>(CurContext)->isLocalClass()) {
-        DiagnoseInvalidRedeclaration(*this, NewFD, true);
+        if (DiagnoseInvalidRedeclaration(*this, Previous, NewFD, true)) {
+          D.SetIdentifier(Previous.getLookupName().getAsIdentifierInfo(),
+                          D.getIdentifierLoc());
+          return ActOnFunctionDeclarator(S, D, DC, R, TInfo, Previous,
+                                         TemplateParamLists,
+                                         IsFunctionDefinition, Redeclaration,
+                                         AddToScope);
+        }
       }
 
     } else if (!IsFunctionDefinition && D.getCXXScopeSpec().isSet() &&


More information about the cfe-commits mailing list