PATCH [DR2303][PR97453]

kamlesh kumar kamleshbhalui@gmail.com
Wed Oct 21 10:32:27 GMT 2020


gcc/cp/ChangeLog
-----------------------------------

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

PR c++/97453
* pt.c (get_template_base): Implement DR2303,
Consider closest base while 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

--------------------------------------------------

As part of this patch I Implemented fix for below defect report in cwg
https://wg21.cmeerw.net/cwg/issue2303 .
Reg tested on x86_64 and did not found any failure.
Patch summary: Remove base of base from list of bases

created a hash_set from list of bases and then iterate over each
element of hash_set and find its  list of bases and remove this from
hash_set if present.
and finally, deduction succeeds if in hash_set remains only single
element or it's empty.
otherwise deduction is ambiguous.
-------------------------------------------------------
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index dc664ec3798..7adf461e108 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -22643,8 +22643,9 @@ static enum template_base_result
 get_template_base (tree tparms, tree targs, tree parm, tree arg,
     bool explain_p, tree *result)
 {
-  tree rval = NULL_TREE;
+  *result = NULL_TREE;
   tree binfo;
+  hash_set<tree> binfo_set;

   gcc_assert (RECORD_OR_UNION_CODE_P (TREE_CODE (arg)));

@@ -22659,31 +22660,51 @@ get_template_base (tree tparms, tree targs,
tree parm, tree arg,
   /* Walk in inheritance graph order.  The search order is not
      important, and this avoids multiple walks of virtual bases.  */
   for (binfo = TREE_CHAIN (binfo); binfo; binfo = TREE_CHAIN (binfo))
-    {
-      tree r = try_class_unification (tparms, targs, parm,
-       BINFO_TYPE (binfo), explain_p);
-
-      if (r)
- {
-   /* If there is more than one satisfactory baseclass, then:
-
-        [temp.deduct.call]
+     {
+       tree r = try_class_unification (tparms, targs, parm,
+                       BINFO_TYPE (binfo), explain_p);
+       if (r)
+         {
+           binfo_set.add(r);
+         }
+     }

-       If they yield more than one possible deduced A, the type
-       deduction fails.
+  /* If there is more than one satisfactory baseclass, then:
+     [temp.deduct.call]
+          If they yield more than one possible deduced A, the type
+          deduction fails.
+     However, 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.  */
+  for (hash_set<tree>::iterator it = binfo_set.begin();
+                                it != binfo_set.end(); ++it)
+    {
+      binfo = TYPE_BINFO (*it);
+      for (binfo = TREE_CHAIN (binfo); binfo; binfo = TREE_CHAIN (binfo))
+        {
+          tree r = try_class_unification (tparms, targs, parm,
+                          BINFO_TYPE (binfo), explain_p);
+          if (r && binfo_set.contains(r))
+            {
+              binfo_set.remove(r);
+            }
+        }
+    }

-      applies.  */
-   if (rval && !same_type_p (r, rval))
-     {
-       *result = NULL_TREE;
-       return tbr_ambiguous_baseclass;
-     }
+  if (binfo_set.elements() > 1)
+    {
+      return tbr_ambiguous_baseclass;
+    }

-   rval = r;
- }
+  if (binfo_set.is_empty())
+    {
+      return tbr_success;
     }

-  *result = rval;
+  if (binfo_set.elements() == 1)
+    {
+      *result = *binfo_set.begin();
+    }
   return tbr_success;
 }

diff --git a/gcc/testsuite/g++.dg/DRs/dr2303.C
b/gcc/testsuite/g++.dg/DRs/dr2303.C
new file mode 100644
index 00000000000..b4c23332358
--- /dev/null
+++ b/gcc/testsuite/g++.dg/DRs/dr2303.C
@@ -0,0 +1,20 @@
+// 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> {};
+
+template <typename... T>
+void f(const A<T...> &) {
+  static_assert(sizeof...(T) == 2, "it should duduce to A<int,int>");
+}
+
+void g() {
+  f(B{});
+}
--------------------------------

./kamlesh


More information about the Gcc-patches mailing list