In the new inherited constructor framework, base inheriting
constructor variants don't retain the parameters inherited from a
virtual base constructor, since that constructor won't actually be
called from there; it will be called directly by the complete object
constructor.

Previously, I had cut off DECL_ARGUMENTS and the argument list, but
left these omitted parameters in TYPE_ARG_TYPES.  This constituted
lying to the compiler, and it got its revenge.

This patch also removes the omitted parameters from TYPE_ARG_TYPES,
and then adjusts overloading and mangling to refer to the parameters
from the maybe-in-charge variant instead.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit d133cc9358be1b81147584b37a85ba58a5027d24
Author: Jason Merrill <ja...@redhat.com>
Date:   Tue Feb 14 12:25:06 2017 -0500

            PR c++/79464 - ICE in IPA with omitted constructor parms
    
            * class.c (build_clone): Also omit parms from TYPE_ARG_TYPES.
            (adjust_clone_args): Adjust.
            (add_method): Remember omitted parms.
            * call.c (add_function_candidate): Likewise.
            * mangle.c (write_method_parms): Likewise.
            * method.c (ctor_omit_inherited_parms): Return false if there are no
            parms to omit.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 718438c..154509b 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -2005,7 +2005,11 @@ add_function_candidate (struct z_candidate **candidates,
      considered in overload resolution.  */
   if (DECL_CONSTRUCTOR_P (fn))
     {
-      parmlist = skip_artificial_parms_for (fn, parmlist);
+      if (ctor_omit_inherited_parms (fn))
+       /* Bring back parameters omitted from an inherited ctor.  */
+       parmlist = FUNCTION_FIRST_USER_PARMTYPE (DECL_ORIGIN (fn));
+      else
+       parmlist = skip_artificial_parms_for (fn, parmlist);
       skip = num_artificial_parms_for (fn);
       if (skip > 0 && first_arg != NULL_TREE)
        {
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 7ec07c9..1442b55 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -1149,6 +1149,12 @@ add_method (tree type, tree method, tree using_decl)
       if (! DECL_STATIC_FUNCTION_P (method))
        parms2 = TREE_CHAIN (parms2);
 
+      /* Bring back parameters omitted from an inherited ctor.  */
+      if (ctor_omit_inherited_parms (fn))
+       parms1 = FUNCTION_FIRST_USER_PARMTYPE (DECL_ORIGIN (fn));
+      if (ctor_omit_inherited_parms (method))
+       parms2 = FUNCTION_FIRST_USER_PARMTYPE (DECL_ORIGIN (method));
+
       if (compparms (parms1, parms2)
          && (!DECL_CONV_FN_P (fn)
              || same_type_p (TREE_TYPE (fn_type),
@@ -4761,6 +4767,10 @@ build_clone (tree fn, tree name)
        DECL_VINDEX (clone) = NULL_TREE;
     }
 
+  bool ctor_omit_inherited_parms_p = ctor_omit_inherited_parms (clone);
+  if (ctor_omit_inherited_parms_p)
+    gcc_assert (DECL_HAS_IN_CHARGE_PARM_P (clone));
+
   /* If there was an in-charge parameter, drop it from the function
      type.  */
   if (DECL_HAS_IN_CHARGE_PARM_P (clone))
@@ -4780,8 +4790,12 @@ build_clone (tree fn, tree name)
       if (DECL_HAS_VTT_PARM_P (fn)
          && ! DECL_NEEDS_VTT_PARM_P (clone))
        parmtypes = TREE_CHAIN (parmtypes);
-       /* If this is subobject constructor or destructor, add the vtt
-        parameter.  */
+      if (ctor_omit_inherited_parms_p)
+       {
+         /* If we're omitting inherited parms, that just leaves the VTT.  */
+         gcc_assert (DECL_NEEDS_VTT_PARM_P (clone));
+         parmtypes = tree_cons (NULL_TREE, vtt_parm_type, void_list_node);
+       }
       TREE_TYPE (clone)
        = build_method_type_directly (basetype,
                                      TREE_TYPE (TREE_TYPE (clone)),
@@ -4818,7 +4832,7 @@ build_clone (tree fn, tree name)
 
   /* A base constructor inheriting from a virtual base doesn't get the
      arguments.  */
-  if (ctor_omit_inherited_parms (clone))
+  if (ctor_omit_inherited_parms_p)
     DECL_CHAIN (DECL_CHAIN (DECL_ARGUMENTS (clone))) = NULL_TREE;
 
   for (parms = DECL_ARGUMENTS (clone); parms; parms = DECL_CHAIN (parms))
@@ -4965,6 +4979,13 @@ adjust_clone_args (tree decl)
           decl_parms = TREE_CHAIN (decl_parms),
             clone_parms = TREE_CHAIN (clone_parms))
        {
+         if (clone_parms == void_list_node)
+           {
+             gcc_assert (decl_parms == clone_parms
+                         || ctor_omit_inherited_parms (clone));
+             break;
+           }
+
          gcc_assert (same_type_p (TREE_TYPE (decl_parms),
                                   TREE_TYPE (clone_parms)));
 
@@ -4999,7 +5020,7 @@ adjust_clone_args (tree decl)
              break;
            }
        }
-      gcc_assert (!clone_parms);
+      gcc_assert (!clone_parms || clone_parms == void_list_node);
     }
 }
 
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 3ead33e..8b30f42 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -2740,6 +2740,10 @@ write_method_parms (tree parm_types, const int method_p, 
const tree decl)
          parm_types = TREE_CHAIN (parm_types);
          parm_decl = DECL_CHAIN (parm_decl);
        }
+
+      if (decl && ctor_omit_inherited_parms (decl))
+       /* Bring back parameters omitted from an inherited ctor.  */
+       parm_types = FUNCTION_FIRST_USER_PARMTYPE (DECL_ORIGIN (decl));
     }
 
   for (first_parm_type = parm_types;
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index a6a9b4e..beb0a24 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -575,6 +575,9 @@ ctor_omit_inherited_parms (tree fn)
   if (!DECL_BASE_CONSTRUCTOR_P (fn)
       || !CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn)))
     return false;
+  if (FUNCTION_FIRST_USER_PARMTYPE (DECL_ORIGIN (fn)) == void_list_node)
+    /* No user-declared parameters to omit.  */
+    return false;
   tree binfo = inherited_ctor_binfo (fn);
   for (; binfo; binfo = BINFO_INHERITANCE_CHAIN (binfo))
     if (BINFO_VIRTUAL_P (binfo))
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor23.C 
b/gcc/testsuite/g++.dg/cpp1z/inh-ctor23.C
index c0cf040..fe2c2eb 100644
--- a/gcc/testsuite/g++.dg/cpp1z/inh-ctor23.C
+++ b/gcc/testsuite/g++.dg/cpp1z/inh-ctor23.C
@@ -1,6 +1,6 @@
 // Testcase from P0136
 // { dg-do compile { target c++11 } }
-// { dg-options "-fnew-inheriting-ctors -fdump-tree-gimple" }
+// { dg-options "-fnew-inheriting-ctors -fdump-tree-gimple -O2 -fno-inline" }
 
 struct W { W(int); };
 struct V: W { using W::W; };

Reply via email to