[llvm-branch-commits] [clang] 7c327db - Part of C++ DR 39: a class member lookup is not ambiguous if it finds the

Richard Smith via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Nov 25 17:07:40 PST 2020


Author: Richard Smith
Date: 2020-11-25T17:03:11-08:00
New Revision: 7c327db3ef73d771bc022d0723672fc356dc9017

URL: https://github.com/llvm/llvm-project/commit/7c327db3ef73d771bc022d0723672fc356dc9017
DIFF: https://github.com/llvm/llvm-project/commit/7c327db3ef73d771bc022d0723672fc356dc9017.diff

LOG: Part of C++ DR 39: a class member lookup is not ambiguous if it finds the
same type in multiple base classes.

Not even if the type is introduced by distinct declarations (for
example, two typedef declarations, or a typedef and a class definition).

Added: 
    

Modified: 
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Sema/SemaLookup.cpp
    clang/test/CXX/drs/dr3xx.cpp
    clang/test/CXX/temp/temp.res/temp.local/p3.cpp
    clang/test/SemaCXX/member-name-lookup.cpp
    clang/test/SemaTemplate/dependent-base-classes.cpp
    clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp
    clang/test/SemaTemplate/temp.cpp
    clang/test/SemaTemplate/typename-specifier-4.cpp
    clang/www/cxx_dr_status.html

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 2e479307ce22..f2b2b1d3ab6f 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8640,6 +8640,8 @@ def err_ambiguous_member_multiple_subobjects : Error<
 def err_ambiguous_member_multiple_subobject_types : Error<
   "member %0 found in multiple base classes of 
diff erent types">;
 def note_ambiguous_member_found : Note<"member found by ambiguous name lookup">;
+def note_ambiguous_member_type_found : Note<
+  "member type %0 found by ambiguous name lookup">;
 def err_ambiguous_reference : Error<"reference to %0 is ambiguous">;
 def note_ambiguous_candidate : Note<"candidate found by name lookup is %q0">;
 def err_ambiguous_tag_hiding : Error<"a type named %0 is hidden by a "

diff  --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 9a1312af42eb..16dd8f510596 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -2228,11 +2228,10 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
 
   // Determine whether two sets of members contain the same members, as
   // required by C++ [class.member.lookup]p6.
-  auto HasSameDeclarations = [IDNS,
-                              TemplateNameLookup](DeclContextLookupResult A,
-                                                  DeclContextLookupResult B) {
+  auto HasSameDeclarations = [&](DeclContextLookupResult A,
+                                 DeclContextLookupResult B) {
     using Iterator = DeclContextLookupResult::iterator;
-    using Result = const Decl *;
+    using Result = const void *;
 
     auto Next = [&](Iterator &It, Iterator End) -> Result {
       while (It != End) {
@@ -2252,14 +2251,15 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
           if (auto *TD = getAsTemplateNameDecl(ND))
             ND = TD;
 
-        // FIXME: Per C++ [class.member.lookup]p3:
-        //   type declarations (including injected-class-names are replaced by the
-        //   types they designate
-        // So two 
diff erent typedef declarations with the same name from two
-        // 
diff erent base classes declaring the same type do not introduce an
-        // ambiguity.
+        // C++ [class.member.lookup]p3:
+        //   type declarations (including injected-class-names) are replaced by
+        //   the types they designate
+        if (const TypeDecl *TD = dyn_cast<TypeDecl>(ND->getUnderlyingDecl())) {
+          QualType T = Context.getTypeDeclType(TD);
+          return T.getCanonicalType().getAsOpaquePtr();
+        }
 
-        return cast<NamedDecl>(ND->getUnderlyingDecl()->getCanonicalDecl());
+        return ND->getUnderlyingDecl()->getCanonicalDecl();
       }
       return nullptr;
     };
@@ -2509,13 +2509,23 @@ void Sema::DiagnoseAmbiguousLookup(LookupResult &Result) {
       << Name << LookupRange;
 
     CXXBasePaths *Paths = Result.getBasePaths();
-    std::set<Decl *> DeclsPrinted;
+    std::set<const NamedDecl *> DeclsPrinted;
     for (CXXBasePaths::paths_iterator Path = Paths->begin(),
                                       PathEnd = Paths->end();
          Path != PathEnd; ++Path) {
-      Decl *D = Path->Decls.front();
-      if (DeclsPrinted.insert(D).second)
-        Diag(D->getLocation(), diag::note_ambiguous_member_found);
+      const NamedDecl *D = Path->Decls.front();
+      if (!D->isInIdentifierNamespace(Result.getIdentifierNamespace()))
+        continue;
+      if (DeclsPrinted.insert(D).second) {
+        if (const auto *TD = dyn_cast<TypedefNameDecl>(D->getUnderlyingDecl()))
+          Diag(D->getLocation(), diag::note_ambiguous_member_type_found)
+              << TD->getUnderlyingType();
+        else if (const auto *TD = dyn_cast<TypeDecl>(D->getUnderlyingDecl()))
+          Diag(D->getLocation(), diag::note_ambiguous_member_type_found)
+              << Context.getTypeDeclType(TD);
+        else
+          Diag(D->getLocation(), diag::note_ambiguous_member_found);
+      }
     }
     break;
   }

diff  --git a/clang/test/CXX/drs/dr3xx.cpp b/clang/test/CXX/drs/dr3xx.cpp
index cec9acf63a9e..06aa885d236e 100644
--- a/clang/test/CXX/drs/dr3xx.cpp
+++ b/clang/test/CXX/drs/dr3xx.cpp
@@ -137,13 +137,17 @@ namespace dr305 { // dr305: no
 #endif
 }
 
-namespace dr306 { // dr306: no
-  // FIXME: dup 39
-  // FIXME: This should be accepted.
-  struct A { struct B {}; }; // expected-note 2{{member}}
-  struct C { typedef A::B B; }; // expected-note {{member}}
+namespace dr306 { // dr306: dup 39
+  struct A { struct B {}; };
+  struct C { typedef A::B B; };
   struct D : A, A::B, C {};
-  D::B b; // expected-error {{found in multiple base classes of 
diff erent types}}
+  D::B b;
+
+  struct X {}; // expected-note {{member type 'dr306::X' found}}
+  template<typename T> struct Y { typedef T X; }; // expected-note {{member type 'const dr306::X' found}}
+  template<typename T> struct Z : X, Y<T> {};
+  Z<X>::X zx;
+  Z<const X>::X zcx; // expected-error {{member 'X' found in multiple base classes of 
diff erent types}}
 }
 
 // dr307: na

diff  --git a/clang/test/CXX/temp/temp.res/temp.local/p3.cpp b/clang/test/CXX/temp/temp.res/temp.local/p3.cpp
index 63c40fb57690..ac03c7280828 100644
--- a/clang/test/CXX/temp/temp.res/temp.local/p3.cpp
+++ b/clang/test/CXX/temp/temp.res/temp.local/p3.cpp
@@ -1,6 +1,8 @@
 // RUN: %clang_cc1 -verify %s
 
-template <class T> struct Base { // expected-note 4 {{member found by ambiguous name lookup}}
+template <class T> struct Base {
+  // expected-note at -1 2{{member type 'Base<int>' found by ambiguous name lookup}}
+  // expected-note at -2 2{{member type 'Base<char>' found by ambiguous name lookup}}
   static void f();
 }; 
 

diff  --git a/clang/test/SemaCXX/member-name-lookup.cpp b/clang/test/SemaCXX/member-name-lookup.cpp
index 01491693deac..cfd00b35421e 100644
--- a/clang/test/SemaCXX/member-name-lookup.cpp
+++ b/clang/test/SemaCXX/member-name-lookup.cpp
@@ -20,14 +20,14 @@ struct B : A {
 
   enum E2 { enumerator2 };
 
-  enum E3 { enumerator3 }; // expected-note 2{{member found by ambiguous name lookup}}
+  enum E3 { enumerator3 }; // expected-note 2{{member type 'B::E3' found by ambiguous name lookup}}
 };
 
 struct C : A {
   int c; // expected-note 2{{member found by ambiguous name lookup}}
   int d; // expected-note 2{{member found by ambiguous name lookup}}
 
-  enum E3 { enumerator3_2 }; // expected-note 2{{member found by ambiguous name lookup}}
+  enum E3 { enumerator3_2 }; // expected-note 2{{member type 'C::E3' found by ambiguous name lookup}}
 };
 
 struct D : B, C {
@@ -71,14 +71,14 @@ struct B2 : virtual A {
 
   enum E2 { enumerator2 };
 
-  enum E3 { enumerator3 }; // expected-note 2 {{member found by ambiguous name lookup}}
+  enum E3 { enumerator3 }; // expected-note 2 {{member type 'B2::E3' found by ambiguous name lookup}}
 };
 
 struct C2 : virtual A {
   int c;
   int d; // expected-note 2{{member found by ambiguous name lookup}}
 
-  enum E3 { enumerator3_2 }; // expected-note 2{{member found by ambiguous name lookup}}
+  enum E3 { enumerator3_2 }; // expected-note 2{{member type 'C2::E3' found by ambiguous name lookup}}
 };
 
 struct D2 : B2, C2 { 
@@ -132,11 +132,11 @@ void G::test_virtual_lookup() {
 
 
 struct HasMemberType1 {
-  struct type { }; // expected-note{{member found by ambiguous name lookup}}
+  struct type { }; // expected-note{{member type 'HasMemberType1::type' found by ambiguous name lookup}}
 };
 
 struct HasMemberType2 {
-  struct type { }; // expected-note{{member found by ambiguous name lookup}}
+  struct type { }; // expected-note{{member type 'HasMemberType2::type' found by ambiguous name lookup}}
 };
 
 struct HasAnotherMemberType : HasMemberType1, HasMemberType2 { 

diff  --git a/clang/test/SemaTemplate/dependent-base-classes.cpp b/clang/test/SemaTemplate/dependent-base-classes.cpp
index f8f36b2a077d..09f475f8bde9 100644
--- a/clang/test/SemaTemplate/dependent-base-classes.cpp
+++ b/clang/test/SemaTemplate/dependent-base-classes.cpp
@@ -64,11 +64,11 @@ namespace PR6031 {
 namespace Ambig {
   template<typename T>
   struct Base1 {
-    typedef int type; // expected-note{{member found by ambiguous name lookup}}
+    typedef int type; // expected-note{{member type 'int' found by ambiguous name lookup}}
   };
 
   struct Base2 {
-    typedef float type; // expected-note{{member found by ambiguous name lookup}}
+    typedef float type; // expected-note{{member type 'float' found by ambiguous name lookup}}
   };
 
   template<typename T>

diff  --git a/clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp b/clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp
index cb497176ff0e..14e43868e83d 100644
--- a/clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp
+++ b/clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp
@@ -304,8 +304,8 @@ static_assert(sizeof(B<int>) == sizeof(A<int>::NameFromBase), "");
 }
 
 namespace two_types_in_base {
-template <typename T> struct A { typedef T NameFromBase; }; // expected-note {{member found by ambiguous name lookup}}
-template <typename T> struct B { struct NameFromBase { T m; }; }; // expected-note {{member found by ambiguous name lookup}}
+template <typename T> struct A { typedef T NameFromBase; }; // expected-note {{member type 'int' found by ambiguous name lookup}}
+template <typename T> struct B { struct NameFromBase { T m; }; }; // expected-note {{member type 'two_types_in_base::B<int>::NameFromBase' found by ambiguous name lookup}}
 template <typename T> struct C : A<T>, B<T> {
   NameFromBase m; // expected-error {{member 'NameFromBase' found in multiple base classes of 
diff erent types}} expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
 };

diff  --git a/clang/test/SemaTemplate/temp.cpp b/clang/test/SemaTemplate/temp.cpp
index a8a2daeac31b..ae0f0174d9d4 100644
--- a/clang/test/SemaTemplate/temp.cpp
+++ b/clang/test/SemaTemplate/temp.cpp
@@ -8,8 +8,8 @@ namespace test0 {
 
 // PR7252
 namespace test1 {
-  namespace A { template<typename T> struct Base { typedef T t; }; } // expected-note 3{{member}}
-  namespace B { template<typename T> struct Base { typedef T t; }; } // expected-note {{member found}}
+  namespace A { template<typename T> struct Base { typedef T t; }; } // expected-note {{member type 'test1::A::Base<char>' found}} expected-note 2{{declared here}}
+  namespace B { template<typename T> struct Base { typedef T t; }; } // expected-note {{member type 'test1::B::Base<int>' found}}
 
   template<typename T> struct Derived : A::Base<char>, B::Base<int> {
     typename Derived::Base<float>::t x; // expected-error {{found in multiple base classes of 
diff erent types}}

diff  --git a/clang/test/SemaTemplate/typename-specifier-4.cpp b/clang/test/SemaTemplate/typename-specifier-4.cpp
index 2856c99b6ddf..7aa2b8da5108 100644
--- a/clang/test/SemaTemplate/typename-specifier-4.cpp
+++ b/clang/test/SemaTemplate/typename-specifier-4.cpp
@@ -107,8 +107,8 @@ namespace PR6268 {
 }
 
 namespace PR6463 {
-  struct B { typedef int type; }; // expected-note 2{{member found by ambiguous name lookup}}
-  struct C { typedef int type; }; // expected-note 2{{member found by ambiguous name lookup}}
+  struct B { typedef int type; }; // expected-note 2{{member type 'int' found by ambiguous name lookup}}
+  struct C { typedef const int type; }; // expected-note 2{{member type 'const int' found by ambiguous name lookup}}
 
   template<typename T>
   struct A : B, C { 

diff  --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index 89e4fe0f7dc9..f7e4e98ccf4a 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -1877,7 +1877,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
     <td><a href="https://wg21.link/cwg306">306</a></td>
     <td>CD1</td>
     <td>Ambiguity by class name injection</td>
-    <td class="none" align="center">No</td>
+    <td class="none" align="center">Duplicate of <a href="#39">39</a></td>
   </tr>
   <tr id="307">
     <td><a href="https://wg21.link/cwg307">307</a></td>


        


More information about the llvm-branch-commits mailing list