[cfe-commits] r103766 - in /cfe/trunk: lib/Sema/SemaLookup.cpp test/SemaCXX/nested-name-spec.cpp test/SemaTemplate/nested-name-spec-template.cpp

Douglas Gregor dgregor at apple.com
Thu May 13 21:53:42 PDT 2010


Author: dgregor
Date: Thu May 13 23:53:42 2010
New Revision: 103766

URL: http://llvm.org/viewvc/llvm-project?rev=103766&view=rev
Log:
Make sure to search semantic scopes and appropriate template-parameter
scopes during unqualified name lookup that has fallen out to namespace
scope. Fixes PR7133.

Modified:
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/test/SemaCXX/nested-name-spec.cpp
    cfe/trunk/test/SemaTemplate/nested-name-spec-template.cpp

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=103766&r1=103765&r2=103766&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Thu May 13 23:53:42 2010
@@ -761,10 +761,6 @@
   // context as well as walking through the scopes.
 
   for (; S; S = S->getParent()) {
-    DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity());
-    if (Ctx && Ctx->isTransparentContext())
-      continue;
-
     // Check whether the IdResolver has anything in this scope.
     bool Found = false;
     for (; I != IEnd && S->isDeclScope(DeclPtrTy::make(*I)); ++I) {
@@ -778,23 +774,59 @@
       }
     }
 
-    // If we have a context, and it's not a context stashed in the
-    // template parameter scope for an out-of-line definition, also
-    // look into that context.
-    if (Ctx && !(Found && S && S->isTemplateParamScope())) {
-      assert(Ctx->isFileContext() &&
-             "We should have been looking only at file context here already.");
-
-      // Look into context considering using-directives.
-      if (CppNamespaceLookup(*this, R, Context, Ctx, UDirs))
-        Found = true;
-    }
-
-    if (Found) {
+    if (Found && S->isTemplateParamScope()) {
       R.resolveKind();
       return true;
     }
 
+    DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity());
+    if (!Ctx && S->isTemplateParamScope() && OutsideOfTemplateParamDC &&
+        S->getParent() && !S->getParent()->isTemplateParamScope()) {
+      // We've just searched the last template parameter scope and
+      // found nothing, so look into the the contexts between the
+      // lexical and semantic declaration contexts returned by
+      // findOuterContext(). This implements the name lookup behavior
+      // of C++ [temp.local]p8.
+      Ctx = OutsideOfTemplateParamDC;
+      OutsideOfTemplateParamDC = 0;
+    }
+    
+    if (Ctx) {
+      DeclContext *OuterCtx;
+      bool SearchAfterTemplateScope;
+      llvm::tie(OuterCtx, SearchAfterTemplateScope) = findOuterContext(S);
+      if (SearchAfterTemplateScope)
+        OutsideOfTemplateParamDC = OuterCtx;
+
+      for (; Ctx && !Ctx->Equals(OuterCtx); Ctx = Ctx->getLookupParent()) {
+        // We do not directly look into transparent contexts, since
+        // those entities will be found in the nearest enclosing
+        // non-transparent context.
+        if (Ctx->isTransparentContext())
+          continue;
+        
+        // If we have a context, and it's not a context stashed in the
+        // template parameter scope for an out-of-line definition, also
+        // look into that context.
+        if (!(Found && S && S->isTemplateParamScope())) {
+          assert(Ctx->isFileContext() &&
+              "We should have been looking only at file context here already.");
+          
+          // Look into context considering using-directives.
+          if (CppNamespaceLookup(*this, R, Context, Ctx, UDirs))
+            Found = true;
+        }
+        
+        if (Found) {
+          R.resolveKind();
+          return true;
+        }
+        
+        if (R.isForRedeclaration() && !Ctx->isTransparentContext())
+          return false;
+      }
+    }
+
     if (R.isForRedeclaration() && Ctx && !Ctx->isTransparentContext())
       return false;
   }

Modified: cfe/trunk/test/SemaCXX/nested-name-spec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/nested-name-spec.cpp?rev=103766&r1=103765&r2=103766&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/nested-name-spec.cpp (original)
+++ cfe/trunk/test/SemaCXX/nested-name-spec.cpp Thu May 13 23:53:42 2010
@@ -228,3 +228,19 @@
     A::execute(path); // expected-error {{incomplete type 'test3::A' named in nested name specifier}}
   }
 }
+
+namespace PR7133 {
+  namespace A {
+    class Foo;
+  }
+
+  namespace A {
+    namespace B {
+      bool foo(Foo &);
+    }
+  }
+
+  bool A::B::foo(Foo &) {
+    return false;
+  }
+}

Modified: cfe/trunk/test/SemaTemplate/nested-name-spec-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/nested-name-spec-template.cpp?rev=103766&r1=103765&r2=103766&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/nested-name-spec-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/nested-name-spec-template.cpp Thu May 13 23:53:42 2010
@@ -64,3 +64,10 @@
   template <class T>
   T pair<T>::* const pair<T>::mem_array[2] = { &pair<T>::x, &pair<T>::y };
 }
+
+typedef int T;
+namespace N1 {
+  template<typename T> T f0();
+}
+
+template<typename T> T N1::f0() { }





More information about the cfe-commits mailing list