In committee review of the rule to restore effective hiding in
overload resolution between a base constructor with a default argument
and a derived constructor without, it was observed that what we were
doing doesn't properly handle the case where both constructors are
from bases, just one more derived.  This patch fixes that.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit ae6d87429550f4354730e17113d4b0fb32d96571
Author: Jason Merrill <ja...@redhat.com>
Date:   Fri Mar 3 14:47:09 2017 -1000

            Core issues 2273 and 2277
    
            * call.c (joust): Adjust using-declaration tiebreaker to handle
            the intermediate base case.
            * method.c (strip_inheriting_ctors): Just return the argument if
            !flag_new_inheriting_ctors.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index dc629b96..5afec4f 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -9735,20 +9735,26 @@ joust (struct z_candidate *cand1, struct z_candidate 
*cand2, bool warn,
        }
     }
 
-  /* or, if not that, F2 is from a using-declaration, F1 is not, and the
-     conversion sequences are equivalent.
-     (proposed in http://lists.isocpp.org/core/2016/10/1142.php) */
+  /* F1 is a member of a class D, F2 is a member of a base class B of D, and
+     for all arguments the corresponding parameters of F1 and F2 have the same
+     type (CWG 2273/2277). */
   if (DECL_P (cand1->fn) && DECL_CLASS_SCOPE_P (cand1->fn)
       && !DECL_CONV_FN_P (cand1->fn)
       && DECL_P (cand2->fn) && DECL_CLASS_SCOPE_P (cand2->fn)
       && !DECL_CONV_FN_P (cand2->fn))
     {
-      bool used1 = (DECL_INHERITED_CTOR (cand1->fn)
-                   || (BINFO_TYPE (cand1->access_path)
-                       != DECL_CONTEXT (cand1->fn)));
-      bool used2 = (DECL_INHERITED_CTOR (cand2->fn)
-                   || (BINFO_TYPE (cand2->access_path)
-                       != DECL_CONTEXT (cand2->fn)));
+      tree base1 = DECL_CONTEXT (strip_inheriting_ctors (cand1->fn));
+      tree base2 = DECL_CONTEXT (strip_inheriting_ctors (cand2->fn));
+
+      bool used1 = false;
+      bool used2 = false;
+      if (base1 == base2)
+       /* No difference.  */;
+      else if (DERIVED_FROM_P (base1, base2))
+       used1 = true;
+      else if (DERIVED_FROM_P (base2, base1))
+       used2 = true;
+
       if (int diff = used2 - used1)
        {
          for (i = 0; i < len; ++i)
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index beb0a24..f6024cd 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -498,7 +498,8 @@ forward_parm (tree parm)
 tree
 strip_inheriting_ctors (tree dfn)
 {
-  gcc_assert (flag_new_inheriting_ctors);
+  if (!flag_new_inheriting_ctors)
+    return dfn;
   tree fn = dfn;
   while (tree inh = DECL_INHERITED_CTOR (fn))
     {
diff --git a/gcc/testsuite/g++.dg/overload/using5.C 
b/gcc/testsuite/g++.dg/overload/using5.C
new file mode 100644
index 0000000..ad17c78
--- /dev/null
+++ b/gcc/testsuite/g++.dg/overload/using5.C
@@ -0,0 +1,28 @@
+// Core issues 2273, 2277
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+  A(int, int = 0);
+  static void f(int = 0);
+};
+
+struct B: A
+{
+  using A::A;
+  B(int);
+
+  using A::f;
+  static void f();
+};
+
+struct C: B {
+  using B::B;
+  using B::f;
+};
+  
+int main()
+{
+  C c (42);
+  c.f();
+}

Reply via email to