]> granicus.if.org Git - clang/commitdiff
[Sema] Avoid an invalid redefinition error that was presented for
authorAlex Lorenz <arphaman@gmail.com>
Fri, 28 Apr 2017 12:30:05 +0000 (12:30 +0000)
committerAlex Lorenz <arphaman@gmail.com>
Fri, 28 Apr 2017 12:30:05 +0000 (12:30 +0000)
of a function whose previous definition was typo-corrected

rdar://28550928

Differential Revision: https://reviews.llvm.org/D25113

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@301643 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/Sema.h
lib/Sema/SemaDecl.cpp
test/SemaCXX/typo-correction.cpp

index 4aa016e278f5c6e458025695eab4a26876c65a62..19c42a8c56bc8f8760a5ea39e7b96a6b152a6d54 100644 (file)
@@ -1068,6 +1068,12 @@ public:
   /// same special member, we should act as if it is not yet declared.
   llvm::SmallSet<SpecialMemberDecl, 4> SpecialMembersBeingDeclared;
 
+  /// The function definitions which were renamed as part of typo-correction
+  /// to match their respective declarations. We want to keep track of them
+  /// to ensure that we don't emit a "redefinition" error if we encounter a
+  /// correctly named definition after the renamed definition.
+  llvm::SmallPtrSet<const NamedDecl *, 4> TypoCorrectedFunctionDefinitions;
+
   void ReadMethodPool(Selector Sel);
   void updateOutOfDateSelector(Selector Sel);
 
@@ -3117,6 +3123,8 @@ public:
                     const PartialDiagnostic &PrevNote,
                     bool ErrorRecovery = true);
 
+  void MarkTypoCorrectedFunctionDefinition(const NamedDecl *F);
+
   void FindAssociatedClassesAndNamespaces(SourceLocation InstantiationLoc,
                                           ArrayRef<Expr *> Args,
                                    AssociatedNamespaceSet &AssociatedNamespaces,
index cffeb0bc7f5c71a91ee933ad1bf04149b426ee09..054ccb64cbec255aedf3334b69fe5e403a5a891f 100644 (file)
@@ -7424,6 +7424,10 @@ class DifferentNameValidatorCCC : public CorrectionCandidateCallback {
 
 } // end anonymous namespace
 
+void Sema::MarkTypoCorrectedFunctionDefinition(const NamedDecl *F) {
+  TypoCorrectedFunctionDefinitions.insert(F);
+}
+
 /// \brief Generate diagnostics for an invalid function redeclaration.
 ///
 /// This routine handles generating the diagnostic messages for an invalid
@@ -7521,6 +7525,8 @@ static NamedDecl *DiagnoseInvalidRedeclaration(
         if ((*I)->getCanonicalDecl() == Canonical)
           Correction.setCorrectionDecl(*I);
 
+      // Let Sema know about the correction.
+      SemaRef.MarkTypoCorrectedFunctionDefinition(Result);
       SemaRef.diagnoseTypo(
           Correction,
           SemaRef.PDiag(IsLocalFriend
@@ -11732,6 +11738,11 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD,
   if (canRedefineFunction(Definition, getLangOpts()))
     return;
 
+  // Don't emit an error when this is redifinition of a typo-corrected
+  // definition.
+  if (TypoCorrectedFunctionDefinitions.count(Definition))
+    return;
+
   // If we don't have a visible definition of the function, and it's inline or
   // a template, skip the new definition.
   if (SkipBody && !hasVisibleDefinition(Definition) &&
index 48597ded1528a7a4d59dea987efc05078779e3a6..c59ee618f9299a56498f112456707453fd5b0243 100644 (file)
@@ -679,3 +679,30 @@ int g() {
       sizeof(c0is0)]; // expected-error {{use of undeclared identifier}}
 };
 }
+
+namespace avoidRedundantRedefinitionErrors {
+class Class {
+  void function(int pid); // expected-note {{'function' declared here}}
+};
+
+void Class::function2(int pid) { // expected-error {{out-of-line definition of 'function2' does not match any declaration in 'avoidRedundantRedefinitionErrors::Class'; did you mean 'function'?}}
+}
+
+// Expected no redefinition error here.
+void Class::function(int pid) { // expected-note {{previous definition is here}}
+}
+
+void Class::function(int pid) { // expected-error {{redefinition of 'function'}}
+}
+
+namespace ns {
+void create_test(); // expected-note {{'create_test' declared here}}
+}
+
+void ns::create_test2() { // expected-error {{out-of-line definition of 'create_test2' does not match any declaration in namespace 'avoidRedundantRedefinitionErrors::ns'; did you mean 'create_test'?}}
+}
+
+// Expected no redefinition error here.
+void ns::create_test() {
+}
+}