From: Kaelyn Uhrain Date: Tue, 2 Jul 2013 23:47:35 +0000 (+0000) Subject: Look for corrections in enclosing namespaces that require a global NestedNameSpecifier. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=caa16dd469b6f7bfb5bce05afd8772f5d4196322;p=clang Look for corrections in enclosing namespaces that require a global NestedNameSpecifier. CorrectTypo will now see and consider those corrections that are effectively shadowed by other declarations in a closer context when resolved via an unqualified lookup. This involves adding any parent namespaces to the set of namespaces as fully-qualified name specifiers, and also adding potential corrections that passed name lookup but were rejected by the given CorrectionCandidateCallback into the set of failed corrections that should be tried with the set of namespace specifiers. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@185486 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index dbf66711af..d12d1a39a3 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -3496,9 +3496,11 @@ void NamespaceSpecifierSet::AddNamespace(NamespaceDecl *ND) { } // Add an explicit leading '::' specifier if needed. - if (NamespaceDecl *ND = - NamespaceDeclChain.empty() ? NULL : - dyn_cast_or_null(NamespaceDeclChain.back())) { + if (NamespaceDeclChain.empty()) { + NamespaceDeclChain = FullNamespaceDeclChain; + NNS = NestedNameSpecifier::GlobalSpecifier(Context); + } else if (NamespaceDecl *ND = + dyn_cast_or_null(NamespaceDeclChain.back())) { IdentifierInfo *Name = ND->getIdentifier(); if (std::find(CurContextIdentifiers.begin(), CurContextIdentifiers.end(), Name) != CurContextIdentifiers.end() || @@ -4020,8 +4022,10 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, TRD != TRDEnd; ++TRD) Candidate.addCorrectionDecl(*TRD); ++I; - if (!isCandidateViable(CCC, Candidate)) + if (!isCandidateViable(CCC, Candidate)) { + QualifiedResults.push_back(Candidate); DI->second.erase(Prev); + } break; } @@ -4029,8 +4033,10 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, TypoCorrectionConsumer::result_iterator Prev = I; Candidate.setCorrectionDecl(TmpRes.getAsSingle()); ++I; - if (!isCandidateViable(CCC, Candidate)) + if (!isCandidateViable(CCC, Candidate)) { + QualifiedResults.push_back(Candidate); DI->second.erase(Prev); + } break; } @@ -4066,18 +4072,12 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, // Any corrections added below will be validated in subsequent // iterations of the main while() loop over the Consumer's contents. switch (TmpRes.getResultKind()) { - case LookupResult::Found: { - TypoCorrection TC(*QRI); - TC.setCorrectionDecl(TmpRes.getAsSingle()); - TC.setCorrectionSpecifier(NI->NameSpecifier); - TC.setQualifierDistance(NI->EditDistance); - Consumer.addCorrection(TC); - break; - } + case LookupResult::Found: case LookupResult::FoundOverloaded: { TypoCorrection TC(*QRI); TC.setCorrectionSpecifier(NI->NameSpecifier); TC.setQualifierDistance(NI->EditDistance); + TC.setCallbackDistance(0); // Reset the callback distance for (LookupResult::iterator TRD = TmpRes.begin(), TRDEnd = TmpRes.end(); TRD != TRDEnd; ++TRD) diff --git a/test/FixIt/typo-crash.cpp b/test/FixIt/typo-crash.cpp index c154e3baba..0ff160e448 100644 --- a/test/FixIt/typo-crash.cpp +++ b/test/FixIt/typo-crash.cpp @@ -19,11 +19,12 @@ namespace PR12297 { namespace B { typedef short T; - T global(); // expected-note {{'A::B::global' declared here}} + T global(); // expected-note {{'::PR12297::global' declared here}} } } using namespace A::B; - T A::global(); // expected-error {{out-of-line definition of 'global' does not match any declaration in namespace 'PR12297::A'; did you mean 'A::B::global'?}} + // FIXME: Adding '::PR12297::' is not needed as removing 'A::' is sufficient + T A::global(); // expected-error {{out-of-line definition of 'global' does not match any declaration in namespace 'PR12297::A'; did you mean '::PR12297::global'?}} } diff --git a/test/SemaCXX/pr13394-crash-on-invalid.cpp b/test/SemaCXX/pr13394-crash-on-invalid.cpp index 413c52af85..a198340d6f 100644 --- a/test/SemaCXX/pr13394-crash-on-invalid.cpp +++ b/test/SemaCXX/pr13394-crash-on-invalid.cpp @@ -8,8 +8,10 @@ namespace stretch_v1 { } namespace gatekeeper_v1 { namespace gatekeeper_factory_v1 { - struct closure_t { // expected-note {{'closure_t' declared here}} - gatekeeper_v1::closure_t* create(); // expected-error {{no type named 'closure_t' in namespace 'gatekeeper_v1'; did you mean 'closure_t'?}} + struct closure_t { // expected-note {{'::gatekeeper_v1::gatekeeper_factory_v1::closure_t' declared here}} + // FIXME: Just remove the original 'gatekeeper_v1::' name specifier + // instead of adding a fully-qualified name specifier to 'closure_t' + gatekeeper_v1::closure_t* create(); // expected-error {{no type named 'closure_t' in namespace 'gatekeeper_v1'; did you mean '::gatekeeper_v1::gatekeeper_factory_v1::closure_t'?}} }; } gatekeeper_v1::closure_t *x; // expected-error {{no type named 'closure_t' in namespace 'gatekeeper_v1}} diff --git a/test/SemaCXX/typo-correction.cpp b/test/SemaCXX/typo-correction.cpp index 3d40d842f0..62d870c826 100644 --- a/test/SemaCXX/typo-correction.cpp +++ b/test/SemaCXX/typo-correction.cpp @@ -230,6 +230,18 @@ class foo { }; // expected-note{{'foo' declared here}} class bar : boo { }; // expected-error{{unknown class name 'boo'; did you mean 'foo'?}} } +namespace outer { + void somefunc(); // expected-note{{'::outer::somefunc' declared here}} + void somefunc(int, int); // expected-note{{'::outer::somefunc' declared here}} + + namespace inner { + void somefunc(int) { + someFunc(); // expected-error{{use of undeclared identifier 'someFunc'; did you mean '::outer::somefunc'?}} + someFunc(1, 2); // expected-error{{use of undeclared identifier 'someFunc'; did you mean '::outer::somefunc'?}} + } + } +} + namespace bogus_keyword_suggestion { void test() { status = "OK"; // expected-error-re{{use of undeclared identifier 'status'$}}