From baa9030de29c31b34559f64817b77f4df0e40d8b Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Fri, 28 Apr 2017 12:30:05 +0000 Subject: [PATCH] [Sema] Avoid an invalid redefinition error that was presented for of a function whose previous definition was typo-corrected rdar://28550928 Differential Revision: https://reviews.llvm.org/D25113 llvm-svn: 301643 --- clang/include/clang/Sema/Sema.h | 8 ++++++++ clang/lib/Sema/SemaDecl.cpp | 11 +++++++++++ clang/test/SemaCXX/typo-correction.cpp | 27 +++++++++++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 4aa016e..19c42a8 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1068,6 +1068,12 @@ public: /// same special member, we should act as if it is not yet declared. llvm::SmallSet 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 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 Args, AssociatedNamespaceSet &AssociatedNamespaces, diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index cffeb0b..054ccb6 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -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) && diff --git a/clang/test/SemaCXX/typo-correction.cpp b/clang/test/SemaCXX/typo-correction.cpp index 48597de..c59ee61 100644 --- a/clang/test/SemaCXX/typo-correction.cpp +++ b/clang/test/SemaCXX/typo-correction.cpp @@ -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() { +} +} -- 2.7.4