From: Richard Smith Date: Mon, 17 Mar 2014 21:46:03 +0000 (+0000) Subject: Don't fold together the name lookup entries for two declarations if they are X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d4d211d3c06bd3df5c9ab1c55e95c571f1997a9d;p=clang Don't fold together the name lookup entries for two declarations if they are declared in different namespaces in the same inline namespace set. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@204082 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index a61af50c48..050e61c1f8 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1381,6 +1381,7 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { if (isa(this)) return false; + // FIXME: Is this correct if one of the decls comes from an inline namespace? if (isa(this) && isa(OldD)) return true; @@ -1407,14 +1408,19 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { // A typedef of an Objective-C class type can replace an Objective-C class // declaration or definition, and vice versa. + // FIXME: Is this correct if one of the decls comes from an inline namespace? if ((isa(this) && isa(OldD)) || (isa(this) && isa(OldD))) return true; - + // For non-function declarations, if the declarations are of the - // same kind then this must be a redeclaration, or semantic analysis - // would not have given us the new declaration. - return this->getKind() == OldD->getKind(); + // same kind and have the same parent then this must be a redeclaration, + // or semantic analysis would not have given us the new declaration. + // Note that inline namespaces can give us two declarations with the same + // name and kind in the same scope but different contexts. + return this->getKind() == OldD->getKind() && + this->getDeclContext()->getRedeclContext()->Equals( + OldD->getDeclContext()->getRedeclContext()); } bool NamedDecl::hasLinkage() const { diff --git a/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp b/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp index 30393961b3..7918e9f861 100644 --- a/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp +++ b/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp @@ -63,3 +63,14 @@ void test3() { Numbers2::f(f); Numbers2::g(f); // expected-error {{no viable conversion from 'float' to 'Numbers::Number'}} } + +namespace inline_ns { + int x; // expected-note 2{{found}} + inline namespace A { // expected-warning {{C++11}} + int x; // expected-note 2{{found}} + int y; // expected-note 2{{found}} + } + int y; // expected-note 2{{found}} + int k1 = x + y; // expected-error 2{{ambiguous}} + int k2 = inline_ns::x + inline_ns::y; // expected-error 2{{ambiguous}} +} diff --git a/test/CXX/dcl.decl/dcl.meaning/p1-0x.cpp b/test/CXX/dcl.decl/dcl.meaning/p1-0x.cpp index 1381076974..41ff3e2823 100644 --- a/test/CXX/dcl.decl/dcl.meaning/p1-0x.cpp +++ b/test/CXX/dcl.decl/dcl.meaning/p1-0x.cpp @@ -30,9 +30,12 @@ namespace inline_namespaces { inline namespace M { void f(); // expected-note {{possible target}} void g(); - extern int m, n; - struct S; struct T; - enum E : int; enum F : int; + extern int m; // expected-note {{candidate}} + extern int n; + struct S; // expected-note {{candidate}} + struct T; + enum E : int; // expected-note {{candidate}} + enum F : int; template void ft(); // expected-note {{here}} template void gt(); // expected-note {{here}} template extern int mt; // expected-note {{here}} expected-warning {{extension}} @@ -44,16 +47,14 @@ namespace inline_namespaces { // When named by unqualified-id, we do *not* look in the inline namespace // set. void f() {} // expected-note {{possible target}} - int m; - struct S {}; - enum E : int {}; + int m; // expected-note {{candidate}} + struct S {}; // expected-note {{candidate}} + enum E : int {}; // expected-note {{candidate}} static_assert(&f != &M::f, ""); // expected-error {{reference to overloaded function could not be resolved}} - static_assert(&m != &M::m, ""); - typedef S X; // expected-note {{previous}} - typedef M::S X; // expected-error {{different type}} - typedef E Y; // expected-note {{previous}} - typedef M::E Y; // expected-error {{different type}} + static_assert(&m != &M::m, ""); // expected-error {{ambiguous}} + typedef S X; // expected-error {{ambiguous}} + typedef E Y; // expected-error {{ambiguous}} // When named by (unqualified) template-id, we do look in the inline // namespace set. See [namespace.def]p8, [temp.explicit]p3,