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
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">;
DeclContext *Common = UD->getNominatedNamespace();
while (!Common->Encloses(EffectiveDC))
Common = Common->getParent();
+ Common = Common->getPrimaryContext();
list.push_back(UnqualUsingEntry(UD->getNominatedNamespace(), Common));
}
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());
}
};
--- /dev/null
+// 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}}
+ }
+}