c++: DR2303, ambiguous base deduction [PR97453]
authorkamlesh kumar <kamleshbhalui@gmail.com>
Mon, 2 Nov 2020 15:10:21 +0000 (20:40 +0530)
committerJason Merrill <jason@redhat.com>
Tue, 3 Nov 2020 19:36:24 +0000 (14:36 -0500)
When there are two possible matches and one is a base of the other, choose
the derived class rather than fail.

gcc/cp/ChangeLog

2020-10-21  Kamlesh Kumar  <kamleshbhalui@gmail.com>
    Jason Merrill  <jason@redhat.com>

PR c++/97453
DR2303
* pt.c (get_template_base): Consider closest base in template
deduction when base of base also matches.

gcc/testsuite/ChangeLog

2020-10-21  Kamlesh Kumar  <kamleshbhalui@gmail.com>

* g++.dg/DRs/dr2303.C: New test.

gcc/cp/pt.c
gcc/testsuite/g++.dg/DRs/dr2303.C [new file with mode: 0644]

index b782fb535ebbd4646fa3626834503434cbbdd427..f401c75b9e507a8c2f4a13049d9257fbdd2222f2 100644 (file)
@@ -22699,8 +22699,20 @@ get_template_base (tree tparms, tree targs, tree parm, tree arg,
             applies.  */
          if (rval && !same_type_p (r, rval))
            {
-             *result = NULL_TREE;
-             return tbr_ambiguous_baseclass;
+             /* [temp.deduct.call]/4.3: If there is a class C that is a
+                (direct or indirect) base class of D and derived (directly or
+                indirectly) from a class B and that would be a valid deduced
+                A, the deduced A cannot be B or pointer to B, respectively. */
+             if (DERIVED_FROM_P (r, rval))
+               /* Ignore r.  */
+               continue;
+             else if (DERIVED_FROM_P (rval, r))
+               /* Ignore rval.  */;
+             else
+               {
+                 *result = NULL_TREE;
+                 return tbr_ambiguous_baseclass;
+               }
            }
 
          rval = r;
diff --git a/gcc/testsuite/g++.dg/DRs/dr2303.C b/gcc/testsuite/g++.dg/DRs/dr2303.C
new file mode 100644 (file)
index 0000000..b6acb6e
--- /dev/null
@@ -0,0 +1,37 @@
+// DR 2303
+// PR c++/97453
+// { dg-do compile { target c++11 } }
+
+template <typename... T> struct A;
+template <> struct A<>
+{
+};
+template <typename T, typename... Ts> struct A<T, Ts...> : A<Ts...>
+{
+};
+struct B : A<int, int>
+{
+};
+
+struct C : A<int, int>, A<int> //  { dg-warning "direct base .A<int>. inaccessible in .C. due to ambiguity" }
+{
+};
+
+struct D : A<int>, A<int, int> //  { dg-warning "direct base .A<int>. inaccessible in .D. due to ambiguity" }
+{
+};
+template <typename... T>
+void
+f (const A<T...> &)
+{
+  static_assert (sizeof...(T) == 2, "it should duduce to A<int,int>");
+}
+
+
+void
+g ()
+{
+  f (B{});
+  f (C{});
+  f (D{});
+}