]> granicus.if.org Git - clang/commitdiff
Make sure to search semantic scopes and appropriate template-parameter
authorDouglas Gregor <dgregor@apple.com>
Fri, 14 May 2010 04:53:42 +0000 (04:53 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 14 May 2010 04:53:42 +0000 (04:53 +0000)
scopes during unqualified name lookup that has fallen out to namespace
scope. Fixes PR7133.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103766 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaLookup.cpp
test/SemaCXX/nested-name-spec.cpp
test/SemaTemplate/nested-name-spec-template.cpp

index 337a4a3ce3f7dd41ab2675228d748feb2c4f66ee..31c33e963ca7b47c945f41b18b057521b2b82232 100644 (file)
@@ -761,10 +761,6 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
   // 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,21 +774,57 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
       }
     }
 
-    // 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.");
+    if (Found && S->isTemplateParamScope()) {
+      R.resolveKind();
+      return true;
+    }
 
-      // Look into context considering using-directives.
-      if (CppNamespaceLookup(*this, R, Context, Ctx, UDirs))
-        Found = 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;
 
-    if (Found) {
-      R.resolveKind();
-      return true;
+      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())
index 59a8e8c45dc79de266bf3858e6657614afb021de..0dc1097e3867a737738a82d63c197f12cc0c2544 100644 (file)
@@ -228,3 +228,19 @@ namespace test3 {
     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;
+  }
+}
index 9d25a051e8a88fda930a4160d2f153bc73e188f6..54e615b4ab69268c6f5b0610ac5db9e58bd541a3 100644 (file)
@@ -64,3 +64,10 @@ namespace test1 {
   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() { }