+/* Strip all inheriting constructors, if any, to return the original
+ constructor from a (possibly indirect) base class. */
+
+tree
+strip_inheriting_ctors (tree fn)
+{
+ gcc_assert (flag_new_inheriting_ctors);
+ while (tree inh = DECL_INHERITED_CTOR (fn))
+ {
+ inh = OVL_CURRENT (inh);
+ fn = inh;
+ }
+ return fn;
+}
+
+/* Find the binfo for the base subobject of BINFO being initialized by
+ inherited constructor FNDECL (a member of a direct base of BINFO). */
+
+static tree inherited_ctor_binfo (tree, tree);
+static tree
+inherited_ctor_binfo_1 (tree binfo, tree fndecl)
+{
+ tree base = DECL_CONTEXT (fndecl);
+ tree base_binfo;
+ for (int i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+ if (BINFO_TYPE (base_binfo) == base)
+ return inherited_ctor_binfo (base_binfo, fndecl);
+
+ gcc_unreachable();
+}
+
+/* Find the binfo for the base subobject of BINFO being initialized by
+ inheriting constructor FNDECL (a member of BINFO), or BINFO if FNDECL is not
+ an inheriting constructor. */
+
+static tree
+inherited_ctor_binfo (tree binfo, tree fndecl)
+{
+ tree inh = DECL_INHERITED_CTOR (fndecl);
+ if (!inh)
+ return binfo;
+
+ tree results = NULL_TREE;
+ for (; inh; inh = OVL_NEXT (inh))
+ {
+ tree one = inherited_ctor_binfo_1 (binfo, OVL_CURRENT (inh));
+ if (!results)
+ results = one;
+ else if (one != results)
+ results = tree_cons (NULL_TREE, one, results);
+ }
+ return results;
+}
+
+/* Find the binfo for the base subobject being initialized by inheriting
+ constructor FNDECL, or NULL_TREE if FNDECL is not an inheriting
+ constructor. */
+
+tree
+inherited_ctor_binfo (tree fndecl)
+{
+ if (!DECL_INHERITED_CTOR (fndecl))
+ return NULL_TREE;
+ tree binfo = TYPE_BINFO (DECL_CONTEXT (fndecl));
+ return inherited_ctor_binfo (binfo, fndecl);
+}
+
+/* True if we should omit all user-declared parameters from constructor FN,
+ because it is a base clone of a ctor inherited from a virtual base. */
+
+bool
+ctor_omit_inherited_parms (tree fn)
+{
+ if (!flag_new_inheriting_ctors)
+ /* We only optimize away the parameters in the new model. */
+ return false;
+ if (!DECL_BASE_CONSTRUCTOR_P (fn)
+ || !CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn)))
+ return false;
+ tree binfo = inherited_ctor_binfo (fn);
+ for (; binfo; binfo = BINFO_INHERITANCE_CHAIN (binfo))
+ if (BINFO_VIRTUAL_P (binfo))
+ return true;
+ return false;
+}
+
+/* True iff constructor(s) INH inherited into BINFO initializes INIT_BINFO.
+ This can be true for multiple virtual bases as well as one direct
+ non-virtual base. */
+
+static bool
+binfo_inherited_from (tree binfo, tree init_binfo, tree inh)
+{
+ /* inh is an OVERLOAD if we inherited the same constructor along
+ multiple paths, check all of them. */
+ for (; inh; inh = OVL_NEXT (inh))
+ {
+ tree fn = OVL_CURRENT (inh);
+ tree base = DECL_CONTEXT (fn);
+ tree base_binfo = NULL_TREE;
+ for (int i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+ if (BINFO_TYPE (base_binfo) == base)
+ break;
+ if (base_binfo == init_binfo
+ || (flag_new_inheriting_ctors
+ && binfo_inherited_from (base_binfo, init_binfo,
+ DECL_INHERITED_CTOR (fn))))
+ return true;
+ }
+ return false;
+}
+