ahatanak created this revision.
ahatanak added reviewers: rsmith, aaron.ballman.
ahatanak added a project: clang.
Herald added a project: All.
ahatanak requested review of this revision.

This fixes a bug where namespace scopes were being searched before template 
parameter scopes.

Delay searching namespace/file scopes in `Sema::CppLookupName` until all local 
scopes are searched.


Repository:
  rG LLVM Github Monorepo

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
@@ -1300,8 +1300,16 @@
 
   // 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) {
@@ -1385,6 +1393,9 @@
         // If this is a file context, we need to perform unqualified name
         // lookup considering using directives.
         if (Ctx->isFileContext()) {
+          if (!InnermostFileScopeDC)
+            InnermostFileScopeDC = Ctx;
+
           // If we haven't handled using directives yet, do so now.
           if (!VisitedUsingDirectives) {
             // Add using directives from this context up to the top level.
@@ -1397,7 +1408,7 @@
 
             // Find the innermost file scope, so we can add using directives
             // from local scopes.
-            Scope *InnermostFileScope = S;
+            InnermostFileScope = S;
             while (InnermostFileScope &&
                    !isNamespaceOrTranslationUnitScope(InnermostFileScope))
               InnermostFileScope = InnermostFileScope->getParent();
@@ -1408,11 +1419,6 @@
             VisitedUsingDirectives = true;
           }
 
-          if (CppNamespaceLookup(*this, R, Context, Ctx, UDirs)) {
-            R.resolveKind();
-            return true;
-          }
-
           continue;
         }
 
@@ -1428,6 +1434,8 @@
     }
   }
 
+  S = InnermostFileScope;
+
   // Stop if we ran out of scopes.
   // FIXME:  This really, really shouldn't be happening.
   if (!S) return false;
@@ -1446,6 +1454,14 @@
     UDirs.done();
   }
 
+  for (DeclContext *Ctx = InnermostFileScopeDC, *LastCtx = S->getEntity();
+       Ctx && !Ctx->Equals(LastCtx); Ctx = Ctx->getLookupParent())
+    if (Ctx->isFileContext() &&
+        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())
@@ -1456,6 +1472,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) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to