r185486 - Look for corrections in enclosing namespaces that require a global NestedNameSpecifier.

Kaelyn Uhrain rikka at google.com
Tue Jul 2 16:47:35 PDT 2013


Author: rikka
Date: Tue Jul  2 18:47:35 2013
New Revision: 185486

URL: http://llvm.org/viewvc/llvm-project?rev=185486&view=rev
Log:
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.

Modified:
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/test/FixIt/typo-crash.cpp
    cfe/trunk/test/SemaCXX/pr13394-crash-on-invalid.cpp
    cfe/trunk/test/SemaCXX/typo-correction.cpp

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=185486&r1=185485&r2=185486&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Tue Jul  2 18:47:35 2013
@@ -3496,9 +3496,11 @@ void NamespaceSpecifierSet::AddNamespace
   }
 
   // Add an explicit leading '::' specifier if needed.
-  if (NamespaceDecl *ND =
-        NamespaceDeclChain.empty() ? NULL :
-          dyn_cast_or_null<NamespaceDecl>(NamespaceDeclChain.back())) {
+  if (NamespaceDeclChain.empty()) {
+    NamespaceDeclChain = FullNamespaceDeclChain;
+    NNS = NestedNameSpecifier::GlobalSpecifier(Context);
+  } else if (NamespaceDecl *ND =
+                 dyn_cast_or_null<NamespaceDecl>(NamespaceDeclChain.back())) {
     IdentifierInfo *Name = ND->getIdentifier();
     if (std::find(CurContextIdentifiers.begin(), CurContextIdentifiers.end(),
                   Name) != CurContextIdentifiers.end() ||
@@ -4020,8 +4022,10 @@ TypoCorrection Sema::CorrectTypo(const D
              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 D
         TypoCorrectionConsumer::result_iterator Prev = I;
         Candidate.setCorrectionDecl(TmpRes.getAsSingle<NamedDecl>());
         ++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 D
           // 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<NamedDecl>());
-            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)

Modified: cfe/trunk/test/FixIt/typo-crash.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/typo-crash.cpp?rev=185486&r1=185485&r2=185486&view=diff
==============================================================================
--- cfe/trunk/test/FixIt/typo-crash.cpp (original)
+++ cfe/trunk/test/FixIt/typo-crash.cpp Tue Jul  2 18:47:35 2013
@@ -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'?}}
 }

Modified: cfe/trunk/test/SemaCXX/pr13394-crash-on-invalid.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/pr13394-crash-on-invalid.cpp?rev=185486&r1=185485&r2=185486&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/pr13394-crash-on-invalid.cpp (original)
+++ cfe/trunk/test/SemaCXX/pr13394-crash-on-invalid.cpp Tue Jul  2 18:47:35 2013
@@ -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}}

Modified: cfe/trunk/test/SemaCXX/typo-correction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/typo-correction.cpp?rev=185486&r1=185485&r2=185486&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/typo-correction.cpp (original)
+++ cfe/trunk/test/SemaCXX/typo-correction.cpp Tue Jul  2 18:47:35 2013
@@ -230,6 +230,18 @@ class foo { }; // expected-note{{'foo' d
 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'$}}





More information about the cfe-commits mailing list