Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -1031,6 +1031,12 @@ /// currently being copy-initialized. Can be empty. llvm::SmallVector CurrentParameterCopyTypes; + /// 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); @@ -3012,6 +3018,8 @@ const PartialDiagnostic &PrevNote, bool ErrorRecovery = true); + void MarkTypoCorrectedFunctionDefinition(const NamedDecl *F); + void FindAssociatedClassesAndNamespaces(SourceLocation InstantiationLoc, ArrayRef Args, AssociatedNamespaceSet &AssociatedNamespaces, Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -7191,6 +7191,10 @@ } // 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 @@ -7288,6 +7292,8 @@ if ((*I)->getCanonicalDecl() == Canonical) Correction.setCorrectionDecl(*I); + // Let Sema know about the correction. + SemaRef.MarkTypoCorrectedFunctionDefinition(Result); SemaRef.diagnoseTypo( Correction, SemaRef.PDiag(IsLocalFriend @@ -11315,6 +11321,11 @@ 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: test/SemaCXX/typo-correction.cpp =================================================================== --- test/SemaCXX/typo-correction.cpp +++ test/SemaCXX/typo-correction.cpp @@ -679,3 +679,33 @@ sizeof(c0is0)]; // expected-error {{use of undeclared identifier}} }; } + +namespace { +class Foo { + int* create_process(int pid); // expected-note {{'create_process' declared here}} +}; + +int *Foo::create_process2(int pid) { // expected-error {{out-of-line definition of 'create_process2' does not match any declaration in '(anonymous namespace)::Foo'; did you mean 'create_process'?}} + return 0; +} + +// Expected no redefinition error here. +int *Foo::create_process(int pid) { // expected-note {{previous definition is here}} + return 0; +} + +int *Foo::create_process(int pid) { // expected-error {{redefinition of 'create_process'}} + return 0; +} + +namespace test { +void create_test(); // expected-note {{'create_test' declared here}} +} + +void test::create_test2() { // expected-error {{out-of-line definition of 'create_test2' does not match any declaration in namespace '(anonymous namespace)::test'; did you mean 'create_test'?}} +} + +// Expected no redefinition error here. +void test::create_test() { +} +}