ahatanak updated this revision to Diff 542150.
ahatanak added a comment.

- Defer collecting using directives until lookup into local scopes is done.
- Simplify the second loop.
- Add more comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D147283/new/

https://reviews.llvm.org/D147283

Files:
  clang/lib/Sema/SemaLookup.cpp
  clang/test/SemaCXX/namespace.cpp

Index: clang/test/SemaCXX/namespace.cpp
===================================================================
--- clang/test/SemaCXX/namespace.cpp
+++ clang/test/SemaCXX/namespace.cpp
@@ -96,3 +96,12 @@
 
   }
 }
+
+namespace N0 {
+  template <typename T> class S;
+  template <typename S2> class C;
+}
+
+template <typename S> class N0::C {
+  void foo(S c) {}
+};
Index: clang/lib/Sema/SemaLookup.cpp
===================================================================
--- clang/lib/Sema/SemaLookup.cpp
+++ clang/lib/Sema/SemaLookup.cpp
@@ -1298,13 +1298,20 @@
   // }
   //
   UnqualUsingDirectiveSet UDirs(*this);
-  bool VisitedUsingDirectives = false;
   bool LeftStartingScope = false;
 
   // When performing a scope lookup, we want to find local extern decls.
   FindLocalExternScope FindLocals(R);
+  Scope *InnermostFileScope = nullptr;
+  DeclContext *InnermostFileScopeDC = nullptr;
+
+  for (; S; S = S->getParent()) {
+    if (isNamespaceOrTranslationUnitScope(S)) {
+      if (!InnermostFileScope)
+        InnermostFileScope = S;
+      continue;
+    }
 
-  for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) {
     bool SearchNamespaceScope = true;
     // Check whether the IdResolver has anything in this scope.
     for (; I != IEnd && S->isDeclScope(*I); ++I) {
@@ -1387,33 +1394,17 @@
         // If this is a file context, we need to perform unqualified name
         // lookup considering using directives.
         if (Ctx->isFileContext()) {
-          // If we haven't handled using directives yet, do so now.
-          if (!VisitedUsingDirectives) {
-            // Add using directives from this context up to the top level.
-            for (DeclContext *UCtx = Ctx; UCtx; UCtx = UCtx->getParent()) {
-              if (UCtx->isTransparentContext())
-                continue;
-
-              UDirs.visit(UCtx, UCtx);
-            }
-
-            // Find the innermost file scope, so we can add using directives
-            // from local scopes.
-            Scope *InnermostFileScope = S;
-            while (InnermostFileScope &&
-                   !isNamespaceOrTranslationUnitScope(InnermostFileScope))
-              InnermostFileScope = InnermostFileScope->getParent();
-            UDirs.visitScopeChain(Initial, InnermostFileScope);
-
-            UDirs.done();
+          if (InnermostFileScopeDC)
+            continue;
 
-            VisitedUsingDirectives = true;
-          }
+          InnermostFileScopeDC = Ctx;
 
-          if (CppNamespaceLookup(*this, R, Context, Ctx, UDirs)) {
-            R.resolveKind();
-            return true;
-          }
+          // Find the innermost file scope, so we can add using directives
+          // from local scopes.
+          InnermostFileScope = S;
+          while (InnermostFileScope &&
+                 !isNamespaceOrTranslationUnitScope(InnermostFileScope))
+            InnermostFileScope = InnermostFileScope->getParent();
 
           continue;
         }
@@ -1430,6 +1421,8 @@
     }
   }
 
+  S = InnermostFileScope;
+
   // Stop if we ran out of scopes.
   // FIXME:  This really, really shouldn't be happening.
   if (!S) return false;
@@ -1443,11 +1436,45 @@
   //
   // FIXME: Cache this sorted list in Scope structure, and DeclContext, so we
   // don't build it for each lookup!
-  if (!VisitedUsingDirectives) {
-    UDirs.visitScopeChain(Initial, S);
-    UDirs.done();
+
+  // Add using directives from the innermost file scope context up to the top
+  // level.
+  for (DeclContext *UCtx = InnermostFileScopeDC; UCtx;
+       UCtx = UCtx->getParent()) {
+    if (UCtx->isTransparentContext())
+      continue;
+
+    UDirs.visit(UCtx, UCtx);
   }
 
+  // Add using directives from local scopes.
+  UDirs.visitScopeChain(Initial, S);
+  UDirs.done();
+
+  // Search the file scope DCs between the innermost file scope DC and the DC
+  // corresponding to the innermost file scope. This is needed, for example, in
+  // the following case where namespace 'N' cannot be found on the scope stack:
+  //
+  // namespace N {
+  // struct B {
+  //   B(int);
+  // };
+  // typedef B typedef_B;
+  // struct D : B {
+  //   D();
+  // };
+  // }
+  //
+  // N::D::D() : typedef_B(0) {}
+
+  for (DeclContext *Ctx = InnermostFileScopeDC, *LastCtx = S->getEntity();
+       Ctx && !Ctx->Equals(LastCtx); Ctx = Ctx->getLookupParent())
+    if (!Ctx->isTransparentContext() &&
+        CppNamespaceLookup(*this, R, Context, Ctx, UDirs)) {
+      R.resolveKind();
+      return true;
+    }
+
   // If we're not performing redeclaration lookup, do not look for local
   // extern declarations outside of a function scope.
   if (!R.isForRedeclaration())
@@ -1458,6 +1485,9 @@
   // that aren't strictly lexical, and therefore we walk through the
   // context as well as walking through the scopes.
   for (; S; S = S->getParent()) {
+    if (!isNamespaceOrTranslationUnitScope(S))
+      continue;
+
     // Check whether the IdResolver has anything in this scope.
     bool Found = false;
     for (; I != IEnd && S->isDeclScope(*I); ++I) {
@@ -1471,11 +1501,6 @@
       }
     }
 
-    if (Found && S->isTemplateParamScope()) {
-      R.resolveKind();
-      return true;
-    }
-
     DeclContext *Ctx = S->getLookupEntity();
     if (Ctx) {
       DeclContext *OuterCtx = findOuterContext(S);
@@ -1489,14 +1514,13 @@
         // 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->isTemplateParamScope())) {
-          assert(Ctx->isFileContext() &&
-              "We should have been looking only at file context here already.");
+        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;
-        }
+        // Look into context considering using-directives.
+        if (CppNamespaceLookup(*this, R, Context, Ctx, UDirs))
+          Found = true;
 
         if (Found) {
           R.resolveKind();
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to