]> granicus.if.org Git - clang/commitdiff
<rdar://problem/13540899> Collect using directives from all of the semantic contexts...
authorDouglas Gregor <dgregor@apple.com>
Mon, 8 Apr 2013 23:11:25 +0000 (23:11 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 8 Apr 2013 23:11:25 +0000 (23:11 +0000)
This fixes a regression I introduced in r178136, where we would not
consider the using directives from the semantic declaration contexts
that aren't represented by the lexical scopes (Scope) when performing
unqualified name lookup. This lead to horribly funny diagnostics like
"no identifier named 'foo'; did you mean 'foo'?".

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

lib/Sema/SemaLookup.cpp
test/CXX/basic/basic.lookup/basic.lookup.unqual/p14.cpp

index df9fdeb40d6caddcf51cd98cbd2976268efa2467..ebe28944062c0b76021fec89e4eef018ecc4df86 100644 (file)
@@ -884,6 +884,8 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
   //   }
   // }
   //
+  UnqualUsingDirectiveSet UDirs;
+  bool VisitedUsingDirectives = false;
   DeclContext *OutsideOfTemplateParamDC = 0;
   for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) {
     DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity());
@@ -957,9 +959,24 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
         // If this is a file context, we need to perform unqualified name
         // lookup considering using directives.
         if (Ctx->isFileContext()) {
-          UnqualUsingDirectiveSet UDirs;
-          UDirs.visit(Ctx, Ctx);
-          UDirs.done();
+          // 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())
+              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();
+
+            VisitedUsingDirectives = true;
+          }
 
           if (CppNamespaceLookup(*this, R, Context, Ctx, UDirs)) {
             R.resolveKind();
@@ -994,11 +1011,11 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
   //
   // FIXME: Cache this sorted list in Scope structure, and DeclContext, so we
   // don't build it for each lookup!
-
-  UnqualUsingDirectiveSet UDirs;
-  UDirs.visitScopeChain(Initial, S);
-  UDirs.done();
-
+  if (!VisitedUsingDirectives) {
+    UDirs.visitScopeChain(Initial, S);
+    UDirs.done();
+  }
+  
   // Lookup namespace scope, and global scope.
   // Unqualified name lookup in C++ requires looking into scopes
   // that aren't strictly lexical, and therefore we walk through the
index 7da3087e7d6e300e819f4f45130abef57a515941..272ad8568c9edfc7c9ec2c50c2f3a3a019061e85 100644 (file)
@@ -47,3 +47,22 @@ class Other {
 void Other::foo(YFloat a, YFloat b) {
   YFloat c = a - b;
 }
+
+// <rdar://problem/13540899>
+namespace Other {
+  void other_foo();
+}
+
+namespace M2 {
+  using namespace Other;
+
+  namespace MInner {
+    class Bar { 
+      void bar();
+    };
+  }
+}
+
+void M2::MInner::Bar::bar() {
+  other_foo();
+}