]> granicus.if.org Git - clang/commitdiff
Don't fold together the name lookup entries for two declarations if they are
authorRichard Smith <richard-llvm@metafoo.co.uk>
Mon, 17 Mar 2014 21:46:03 +0000 (21:46 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Mon, 17 Mar 2014 21:46:03 +0000 (21:46 +0000)
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

lib/AST/Decl.cpp
test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp
test/CXX/dcl.decl/dcl.meaning/p1-0x.cpp

index a61af50c480e4bcb14068a001c0072a680d71a1c..050e61c1f87cdae9bafd0e8c96a9e139c1244448 100644 (file)
@@ -1381,6 +1381,7 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const {
   if (isa<ObjCMethodDecl>(this))
     return false;
 
+  // FIXME: Is this correct if one of the decls comes from an inline namespace?
   if (isa<ObjCInterfaceDecl>(this) && isa<ObjCCompatibleAliasDecl>(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<TypedefNameDecl>(this) && isa<ObjCInterfaceDecl>(OldD)) ||
       (isa<ObjCInterfaceDecl>(this) && isa<TypedefNameDecl>(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 {
index 30393961b3f38bcffc7d7d0a2f4165c83bfa097a..7918e9f861e4a44f81761797a5d8c31798a3a9ce 100644 (file)
@@ -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}}
+}
index 1381076974389154ab2fcc5aa258c3044c682638..41ff3e28237106807c5e3f6d0d0e226319b236ed 100644 (file)
@@ -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<typename T> void ft(); // expected-note {{here}}
       template<typename T> void gt(); // expected-note {{here}}
       template<typename T> 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,