]> granicus.if.org Git - clang/commitdiff
Make a somewhat more convincing test case for unqualified lookup through
authorJohn McCall <rjmccall@apple.com>
Tue, 10 Nov 2009 09:20:04 +0000 (09:20 +0000)
committerJohn McCall <rjmccall@apple.com>
Tue, 10 Nov 2009 09:20:04 +0000 (09:20 +0000)
using directives, and fix a bug thereby exposed:  since we're playing
tricks with pointers, we need to make certain we're always using the same
pointers for things.
Also tweak an existing error message.

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

include/clang/Basic/DiagnosticParseKinds.td
lib/Sema/SemaLookup.cpp
test/CXX/dcl.dcl/basic.namespace/namespace.udir/p1.cpp [new file with mode: 0644]

index e173cffdfd2bb48213bedf6ccafa74f6ba4372ef..2d5a502bfeabe86e7d15dfcc73e68a3488f8625f 100644 (file)
@@ -230,7 +230,7 @@ def ext_ellipsis_exception_spec : Extension<
 def err_expected_catch : Error<"expected catch">;
 def err_expected_lbrace_or_comma : Error<"expected '{' or ','">;
 def err_using_namespace_in_class : Error<
-  "'using namespace' in class not allowed">;
+  "'using namespace' is not allowed in classes">;
 def err_ident_in_pseudo_dtor_not_a_type : Error<
   "identifier %0 in pseudo-destructor expression does not name a type">;
 
index f6ae4e147f79bc6e8a208d0062003a80c6b9e2d6..eb7c3fa80e2868522277fb8965b63d7bbd67f624 100644 (file)
@@ -169,6 +169,7 @@ namespace {
       DeclContext *Common = UD->getNominatedNamespace();
       while (!Common->Encloses(EffectiveDC))
         Common = Common->getParent();
+      Common = Common->getPrimaryContext();
       
       list.push_back(UnqualUsingEntry(UD->getNominatedNamespace(), Common));
     }
@@ -187,7 +188,7 @@ namespace {
 
     std::pair<const_iterator,const_iterator>
     getNamespacesFor(DeclContext *DC) const {
-      return std::equal_range(begin(), end(), DC,
+      return std::equal_range(begin(), end(), DC->getPrimaryContext(),
                               UnqualUsingEntry::Comparator());
     }
   };
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udir/p1.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udir/p1.cpp
new file mode 100644 (file)
index 0000000..5b8aadf
--- /dev/null
@@ -0,0 +1,128 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// (this actually occurs before paragraph 1)
+namespace test0 {
+  namespace A {}
+  class B {
+    using namespace A; // expected-error {{'using namespace' is not allowed in classes}}
+  };
+}
+
+
+struct opaque0 {};
+struct opaque1 {};
+
+// Test that names appear as if in deepest common ancestor.
+namespace test1 {
+  namespace A {
+    namespace B {
+      opaque0 foo(); // expected-note {{candidate}}
+    }
+  }
+
+  namespace C {
+    opaque1 foo(); // expected-note {{candidate}}
+
+    opaque1 test() {
+      using namespace A::B;
+      return foo(); // C::foo
+    }
+  }
+
+  opaque1 test() {
+    using namespace A::B;
+    using namespace C;
+    return foo(); // expected-error {{call to 'foo' is ambiguous}}
+  }
+}
+
+// Same thing, but with the directives in namespaces.
+namespace test2 {
+  namespace A {
+    namespace B {
+      opaque0 foo(); // expected-note {{candidate}}
+    }
+  }
+
+  namespace C {
+    opaque1 foo(); // expected-note {{candidate}}
+
+    namespace test {
+      using namespace A::B;
+
+      opaque1 test() {
+        return foo(); // C::foo
+      }
+    }
+  }
+
+  namespace test {
+    using namespace A::B;
+    using namespace C;
+    
+    opaque1 test() {
+      return foo(); // expected-error {{call to 'foo' is ambiguous}}
+    }
+  }
+}
+
+// Transitivity.
+namespace test3 {
+  namespace A {
+    namespace B {
+      opaque0 foo();
+    }
+  }
+  namespace C {
+    using namespace A;
+  }
+
+  opaque0 test0() {
+    using namespace C;
+    using namespace B;
+    return foo();
+  }
+
+  namespace D {
+    using namespace C;
+  }
+  namespace A {
+    opaque1 foo();
+  }
+
+  opaque1 test1() {
+    using namespace D;
+    return foo();
+  }
+}
+
+// Transitivity acts like synthetic using directives.
+namespace test4 {
+  namespace A {
+    namespace B {
+      opaque0 foo(); // expected-note {{candidate}}
+    }
+  }
+  
+  namespace C {
+    using namespace A::B;
+  }
+
+  opaque1 foo(); // expected-note {{candidate}}
+
+  namespace A {
+    namespace D {
+      using namespace C;
+    }
+
+    opaque0 test() {
+      using namespace D;
+      return foo();
+    }
+  }
+
+  opaque0 test() {
+    using namespace A::D;
+    return foo(); // expected-error {{call to 'foo' is ambiguous}}
+  }
+}