Implement P0136R1, Rewording inheriting constructors.
authorJason Merrill <jason@redhat.com>
Wed, 2 Nov 2016 01:50:29 +0000 (21:50 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 2 Nov 2016 01:50:29 +0000 (21:50 -0400)
gcc/c-family/
* c.opt (-fnew-inheriting-ctors): New.
* c-opts.c: Default to on for ABI 11+.
gcc/cp/
* call.c (enum rejection_reason_code): Add rr_inherited_ctor.
(inherited_ctor_rejection): New.
(add_function_candidate): Reject inherited ctors for copying.
(enforce_access): Use strip_inheriting_ctors.
(print_z_candidate): Likewise.  Handle rr_inherited_ctor.
(convert_like_real): Avoid copying inheriting ctor parameters.
(build_over_call): Likewise.  A base ctor inheriting from vbase
has no parms.  Sorry about varargs.
(joust): A local constructor beats inherited with the same convs.
* class.c (add_method): Handle hiding inheriting ctors.
(one_inherited_ctor): Handle new semantics.
(add_implicitly_declared_members): Pass using_decl down.
(build_clone): A base ctor inheriting from vbase has no parms.
* cp-tree.h (DECL_INHERITED_CTOR): Store this instead of the base.
(SET_DECL_INHERITED_CTOR): Likewise.
(DECL_INHERITED_CTOR_BASE): Adjust.
* constexpr.c: Adjust.
* error.c (dump_function_decl): Decorate inheriting ctors.
* init.c (emit_mem_initializers): Suppress access control in
inheriting ctor.
* mangle.c (write_special_name_constructor): Handle new inheriting
ctor mangling.
* method.c (strip_inheriting_ctors, inherited_ctor_binfo)
(ctor_omit_inherited_parms, binfo_inherited_from): New.
(synthesized_method_walk): Use binfo_inherited_from.  Suppress
access control in inheriting ctor.
(deduce_inheriting_ctor): Deleted if ambiguous ctor inheritance.
(maybe_explain_implicit_delete): Explain ambigous ctor inheritance.
(add_one_base_init, do_build_copy_constructor): Adjust.
(locate_fn_flags, explain_implicit_non_constexpr): Adjust.
(implicitly_declare_fn): Adjust.
(get_inherited_ctor): Remove.
* name-lookup.c (do_class_using_decl): Check for indirect ctor
inheritance.
* optimize.c (cdtor_comdat_group): Adjust for new mangling.
(maybe_clone_body): Handle omitted parms in base clone.
(maybe_thunk_body): Don't thunk if base clone omits parms.
* pt.c (tsubst_decl): Adjust.
(instantiate_template_1): Suppress access control in inheriting
ctor.
(fn_type_unification): Do deduction with inherited ctor.
* tree.c (special_function_p): Adjust.
gcc/
* tree-inline.c (copy_tree_body_r): Only copy the taken branch of
a COND_EXPR with constant condition.
libiberty/
* cp-demangle.c (d_ctor_dtor_name): Handle inheriting constructor.

From-SVN: r241765

49 files changed:
gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-opts.c
gcc/c-family/c.opt
gcc/common.opt
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/constexpr.c
gcc/cp/cp-tree.h
gcc/cp/error.c
gcc/cp/init.c
gcc/cp/mangle.c
gcc/cp/method.c
gcc/cp/name-lookup.c
gcc/cp/optimize.c
gcc/cp/pt.c
gcc/cp/tree.c
gcc/doc/invoke.texi
gcc/testsuite/g++.dg/cpp0x/constexpr-inhctor1.C
gcc/testsuite/g++.dg/cpp0x/inh-ctor11.C
gcc/testsuite/g++.dg/cpp0x/inh-ctor11a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/inh-ctor15.C
gcc/testsuite/g++.dg/cpp0x/inh-ctor15a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/inh-ctor3.C
gcc/testsuite/g++.dg/cpp0x/inh-ctor3a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/inh-ctor5.C
gcc/testsuite/g++.dg/cpp0x/inh-ctor9.C
gcc/testsuite/g++.dg/cpp1z/inh-ctor1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/inh-ctor22.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/inh-ctor23.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/inh-ctor24.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/inh-ctor25.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/inh-ctor26.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/inh-ctor27.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/inh-ctor28.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/inh-ctor29.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/inh-ctor30.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/inh-ctor31.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/inh-ctor32.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/inh-ctor33.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/inh-ctor34.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/inh-ctor35.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/inh-ctor35a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/using1.C [new file with mode: 0644]
gcc/tree-inline.c
libiberty/ChangeLog
libiberty/cp-demangle.c
libiberty/testsuite/demangle-expected

index 730dcd343b540e4d47d97d94a9b7ef78eb0e1a65..3a7b71dea6a6362067028352117f63a342cb67d4 100644 (file)
@@ -1,3 +1,8 @@
+2016-11-01  Jason Merrill  <jason@redhat.com>
+
+       * tree-inline.c (copy_tree_body_r): Only copy the taken branch of
+       a COND_EXPR with constant condition.
+
 2016-11-01  Jakub Jelinek  <jakub@redhat.com>
 
        * dwarf2out.c (gen_variable_die): Remove again origin_die variable
index 6457418030224d654ac24d8c79a01f03157f0ecf..efec6e167380b002f4f792259b3383c430ebe4eb 100644 (file)
@@ -1,3 +1,8 @@
+2016-11-01  Jason Merrill  <jason@redhat.com>
+
+       * c.opt (-fnew-inheriting-ctors): New.
+       * c-opts.c: Default to on for ABI 11+.
+
 2016-10-31  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/77948
index 4a0b9952fa691c75fcabf9da4324ef34d24f5f51..de260e7dcee8dc91cd251765cc893e764a6295a0 100644 (file)
@@ -902,6 +902,12 @@ c_common_post_options (const char **pfilename)
   if (flag_abi_version == 0)
     flag_abi_version = 11;
 
+  /* By default, enable the new inheriting constructor semantics along with ABI
+     11.  New and old should coexist fine, but it is a change in what
+     artificial symbols are generated.  */
+  if (!global_options_set.x_flag_new_inheriting_ctors)
+    flag_new_inheriting_ctors = abi_version_at_least (11);
+
   if (cxx_dialect >= cxx11)
     {
       /* If we're allowing C++0x constructs, don't warn about C++98
index 7e86dbf6bb7bac4b476cca2186f5f2984258a098..7d8a7265752b04be4ad4b40d3637f2d394212bc9 100644 (file)
@@ -1362,6 +1362,10 @@ fimplicit-templates
 C++ ObjC++ Var(flag_implicit_templates) Init(1)
 Emit implicit instantiations of templates.
 
+fnew-inheriting-ctors
+C++ ObjC++ Var(flag_new_inheriting_ctors) Init(1)
+Implement C++17 inheriting constructor semantics.
+
 ffriend-injection
 C++ ObjC++ Var(flag_friend_injection)
 Inject friend functions into enclosing namespace.
index 2c2f7ad7aa99151f3f872767af75cb902a4a316a..097cae660de451de59cc8adc2b5e62d9e242ddba 100644 (file)
@@ -907,7 +907,8 @@ Driver Undocumented
 ;     identity, such as ia32 calling convention attributes (stdcall, etc.)
 ;     Default in G++ 6 (set in c_common_post_options).
 ;
-; 11: The version of the ABI that corrects mangling of sizeof... expressions.
+; 11: The version of the ABI that corrects mangling of sizeof... expressions
+;     and introduces new inheriting constructor handling.
 ;     Default in G++ 7.
 ;
 ; Additional positive integers will be assigned as new versions of
index d9ea36b9eb839e528d7a8428a22196e2de8a47b4..5eabdc2c8866593a2ea26cbd89f437630863775d 100644 (file)
@@ -1,3 +1,49 @@
+2016-11-01  Jason Merrill  <jason@redhat.com>
+
+       Implement P0136R1, Rewording inheriting constructors.
+       * call.c (enum rejection_reason_code): Add rr_inherited_ctor.
+       (inherited_ctor_rejection): New.
+       (add_function_candidate): Reject inherited ctors for copying.
+       (enforce_access): Use strip_inheriting_ctors.
+       (print_z_candidate): Likewise.  Handle rr_inherited_ctor.
+       (convert_like_real): Avoid copying inheriting ctor parameters.
+       (build_over_call): Likewise.  A base ctor inheriting from vbase
+       has no parms.  Sorry about varargs.
+       (joust): A local constructor beats inherited with the same convs.
+       * class.c (add_method): Handle hiding inheriting ctors.
+       (one_inherited_ctor): Handle new semantics.
+       (add_implicitly_declared_members): Pass using_decl down.
+       (build_clone): A base ctor inheriting from vbase has no parms.
+       * cp-tree.h (DECL_INHERITED_CTOR): Store this instead of the base.
+       (SET_DECL_INHERITED_CTOR): Likewise.
+       (DECL_INHERITED_CTOR_BASE): Adjust.
+       * constexpr.c: Adjust.
+       * error.c (dump_function_decl): Decorate inheriting ctors.
+       * init.c (emit_mem_initializers): Suppress access control in
+       inheriting ctor.
+       * mangle.c (write_special_name_constructor): Handle new inheriting
+       ctor mangling.
+       * method.c (strip_inheriting_ctors, inherited_ctor_binfo)
+       (ctor_omit_inherited_parms, binfo_inherited_from): New.
+       (synthesized_method_walk): Use binfo_inherited_from.  Suppress
+       access control in inheriting ctor.
+       (deduce_inheriting_ctor): Deleted if ambiguous ctor inheritance.
+       (maybe_explain_implicit_delete): Explain ambigous ctor inheritance.
+       (add_one_base_init, do_build_copy_constructor): Adjust.
+       (locate_fn_flags, explain_implicit_non_constexpr): Adjust.
+       (implicitly_declare_fn): Adjust.
+       (get_inherited_ctor): Remove.
+       * name-lookup.c (do_class_using_decl): Check for indirect ctor
+       inheritance.
+       * optimize.c (cdtor_comdat_group): Adjust for new mangling.
+       (maybe_clone_body): Handle omitted parms in base clone.
+       (maybe_thunk_body): Don't thunk if base clone omits parms.
+       * pt.c (tsubst_decl): Adjust.
+       (instantiate_template_1): Suppress access control in inheriting
+       ctor.
+       (fn_type_unification): Do deduction with inherited ctor.
+       * tree.c (special_function_p): Adjust.
+
 2016-11-01  Jakub Jelinek  <jakub@redhat.com>
 
        * cp-objcp-common.c (cp_decl_dwarf_attribute): Handle DW_AT_inline.
index 4c19d2ffcd381beab145cb04cd8d007a2f332b09..27aa7fdd74b36d1482f4a9aea4aea114490063cf 100644 (file)
@@ -414,6 +414,7 @@ enum rejection_reason_code {
   rr_bad_arg_conversion,
   rr_template_unification,
   rr_invalid_copy,
+  rr_inherited_ctor,
   rr_constraint_failure
 };
 
@@ -689,6 +690,13 @@ invalid_copy_with_fn_template_rejection (void)
   return r;
 }
 
+static struct rejection_reason *
+inherited_ctor_rejection (void)
+{
+  struct rejection_reason *r = alloc_rejection (rr_inherited_ctor);
+  return r;
+}
+
 // Build a constraint failure record, saving information into the
 // template_instantiation field of the rejection. If FN is not a template
 // declaration, the TMPL member is the FN declaration and TARGS is empty.
@@ -2111,6 +2119,18 @@ add_function_candidate (struct z_candidate **candidates,
                }
            }
 
+         /* Don't consider inherited constructors for initialization from an
+            expression of the same or derived type.  */
+         /* FIXME extend to operator=.  */
+         if (i == 0 && len == 1
+             && DECL_INHERITED_CTOR (fn)
+             && reference_related_p (ctype, argtype))
+           {
+             viable = 0;
+             reason = inherited_ctor_rejection ();
+             goto out;
+           }
+
          /* Core issue 899: When [copy-]initializing a temporary to be bound
             to the first parameter of a copy constructor (12.8) called with
             a single argument in the context of direct-initialization,
@@ -3393,32 +3413,40 @@ print_z_candidate (location_t loc, const char *msgstr,
   const char *msg = (msgstr == NULL
                     ? ""
                     : ACONCAT ((msgstr, " ", NULL)));
-  location_t cloc = location_of (candidate->fn);
+  tree fn = candidate->fn;
+  if (flag_new_inheriting_ctors)
+    fn = strip_inheriting_ctors (fn);
+  location_t cloc = location_of (fn);
 
-  if (identifier_p (candidate->fn))
+  if (identifier_p (fn))
     {
       cloc = loc;
       if (candidate->num_convs == 3)
-       inform (cloc, "%s%D(%T, %T, %T) <built-in>", msg, candidate->fn,
+       inform (cloc, "%s%D(%T, %T, %T) <built-in>", msg, fn,
                candidate->convs[0]->type,
                candidate->convs[1]->type,
                candidate->convs[2]->type);
       else if (candidate->num_convs == 2)
-       inform (cloc, "%s%D(%T, %T) <built-in>", msg, candidate->fn,
+       inform (cloc, "%s%D(%T, %T) <built-in>", msg, fn,
                candidate->convs[0]->type,
                candidate->convs[1]->type);
       else
-       inform (cloc, "%s%D(%T) <built-in>", msg, candidate->fn,
+       inform (cloc, "%s%D(%T) <built-in>", msg, fn,
                candidate->convs[0]->type);
     }
-  else if (TYPE_P (candidate->fn))
-    inform (cloc, "%s%T <conversion>", msg, candidate->fn);
+  else if (TYPE_P (fn))
+    inform (cloc, "%s%T <conversion>", msg, fn);
   else if (candidate->viable == -1)
-    inform (cloc, "%s%#D <near match>", msg, candidate->fn);
-  else if (DECL_DELETED_FN (candidate->fn))
-    inform (cloc, "%s%#D <deleted>", msg, candidate->fn);
+    inform (cloc, "%s%#D <near match>", msg, fn);
+  else if (DECL_DELETED_FN (fn))
+    inform (cloc, "%s%#D <deleted>", msg, fn);
   else
-    inform (cloc, "%s%#D", msg, candidate->fn);
+    inform (cloc, "%s%#D", msg, fn);
+  if (fn != candidate->fn)
+    {
+      cloc = location_of (candidate->fn);
+      inform (cloc, "  inherited here");
+    }
   /* Give the user some information about why this candidate failed.  */
   if (candidate->reason != NULL)
     {
@@ -3483,6 +3511,11 @@ print_z_candidate (location_t loc, const char *msgstr,
            diagnose_constraints (cloc, tmpl, args);
          }
          break;
+       case rr_inherited_ctor:
+         inform (cloc, "  an inherited constructor is not a candidate for "
+                 "initialization from an expression of the same or derived "
+                 "type");
+         break;
        case rr_none:
        default:
          /* This candidate didn't have any issues or we failed to
@@ -6338,10 +6371,22 @@ enforce_access (tree basetype_path, tree decl, tree diag_decl,
 {
   gcc_assert (TREE_CODE (basetype_path) == TREE_BINFO);
 
+  if (flag_new_inheriting_ctors
+      && DECL_INHERITED_CTOR (decl))
+    {
+      /* 7.3.3/18: The additional constructors are accessible if they would be
+        accessible when used to construct an object of the corresponding base
+        class.  */
+      decl = strip_inheriting_ctors (decl);
+      basetype_path = TYPE_BINFO (DECL_CONTEXT (decl));
+    }
+
   if (!accessible_p (basetype_path, decl, true))
     {
       if (complain & tf_error)
        {
+         if (flag_new_inheriting_ctors)
+           diag_decl = strip_inheriting_ctors (diag_decl);
          if (TREE_PRIVATE (decl))
            {
              error ("%q#D is private within this context", diag_decl);
@@ -6773,6 +6818,15 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
 
       if (! MAYBE_CLASS_TYPE_P (totype))
        return expr;
+
+      /* Don't introduce copies when passing arguments along to the inherited
+        constructor.  */
+      if (current_function_decl
+         && flag_new_inheriting_ctors
+         && DECL_INHERITED_CTOR (current_function_decl)
+         && TREE_ADDRESSABLE (totype))
+       return expr;
+
       /* Fall through.  */
     case ck_base:
       if (convs->kind == ck_base && !convs->need_temporary_p)
@@ -7800,6 +7854,29 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
       check_function_arguments (input_location, TREE_TYPE (fn), nargs, fargs);
     }
 
+  if (DECL_INHERITED_CTOR (fn))
+    {
+      /* Check for passing ellipsis arguments to an inherited constructor.  We
+        could handle this by open-coding the inherited constructor rather than
+        defining it, but let's not bother now.  */
+      if (!cp_unevaluated_operand
+         && cand->convs[cand->num_convs-1]->ellipsis_p)
+       {
+         if (complain & tf_error)
+           {
+             sorry ("passing arguments to ellipsis of inherited constructor "
+                    "%qD", cand->fn);
+             inform (DECL_SOURCE_LOCATION (cand->fn), "declared here");
+           }
+         return error_mark_node;
+       }
+
+      /* A base constructor inheriting from a virtual base doesn't get the
+        inherited arguments, just this and __vtt.  */
+      if (ctor_omit_inherited_parms (fn))
+       nargs = 2;
+    }
+
   /* Avoid actually calling copy constructors and copy assignment operators,
      if possible.  */
 
@@ -7985,13 +8062,21 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
     }
 
   tree call = build_cxx_call (fn, nargs, argarray, complain|decltype_flag);
-  if (call != error_mark_node
-      && cand->flags & LOOKUP_LIST_INIT_CTOR)
+  if (call == error_mark_node)
+    return call;
+  if (cand->flags & LOOKUP_LIST_INIT_CTOR)
     {
       tree c = extract_call_expr (call);
       /* build_new_op_1 will clear this when appropriate.  */
       CALL_EXPR_ORDERED_ARGS (c) = true;
     }
+  if (current_function_decl
+      && flag_new_inheriting_ctors
+      && DECL_INHERITED_CTOR (current_function_decl)
+      && cand->num_convs)
+    /* Don't introduce copies when passing arguments along to the inherited
+       constructor.  */
+    CALL_FROM_THUNK_P (call) = true;
   return call;
 }
 
@@ -9539,6 +9624,34 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn,
        return winner;
     }
 
+  /* 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) */
+  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)));
+      if (int diff = used2 - used1)
+       {
+         for (i = 0; i < len; ++i)
+           {
+             conversion *t1 = cand1->convs[i + off1];
+             conversion *t2 = cand2->convs[i + off2];
+             if (!same_type_p (t1->type, t2->type))
+               break;
+           }
+         if (i == len)
+           return diff;
+       }
+    }
+
   /* Check whether we can discard a builtin candidate, either because we
      have two identical ones or matching builtin and non-builtin candidates.
 
index 1a379348e5f58524d1c5c6249cd84f3e215b199a..c6b4ed6af3399602f105c13f4e44c57397c3e5a3 100644 (file)
@@ -1016,7 +1016,6 @@ add_method (tree type, tree method, tree using_decl)
   bool complete_p;
   bool insert_p = false;
   tree current_fns;
-  tree fns;
 
   if (method == error_mark_node)
     return false;
@@ -1083,8 +1082,9 @@ add_method (tree type, tree method, tree using_decl)
   current_fns = insert_p ? NULL_TREE : (*method_vec)[slot];
 
   /* Check to see if we've already got this method.  */
-  for (fns = current_fns; fns; fns = OVL_NEXT (fns))
+  for (tree *p = &current_fns; *p; )
     {
+      tree fns = *p;
       tree fn = OVL_CURRENT (fns);
       tree fn_type;
       tree method_type;
@@ -1092,12 +1092,14 @@ add_method (tree type, tree method, tree using_decl)
       tree parms2;
 
       if (TREE_CODE (fn) != TREE_CODE (method))
-       continue;
+       goto cont;
 
       /* Two using-declarations can coexist, we'll complain about ambiguity in
         overload resolution.  */
-      if (using_decl && TREE_CODE (fns) == OVERLOAD && OVL_USED (fns))
-       continue;
+      if (using_decl && TREE_CODE (fns) == OVERLOAD && OVL_USED (fns)
+         /* Except handle inherited constructors specially.  */
+         && ! DECL_CONSTRUCTOR_P (fn))
+       goto cont;
 
       /* [over.load] Member function declarations with the
         same name and the same parameter types cannot be
@@ -1131,7 +1133,7 @@ add_method (tree type, tree method, tree using_decl)
              == FUNCTION_REF_QUALIFIED (method_type))
          && (type_memfn_quals (fn_type) != type_memfn_quals (method_type)
              || type_memfn_rqual (fn_type) != type_memfn_rqual (method_type)))
-         continue;
+         goto cont;
 
       /* For templates, the return type and template parameters
         must be identical.  */
@@ -1140,7 +1142,7 @@ add_method (tree type, tree method, tree using_decl)
                            TREE_TYPE (method_type))
              || !comp_template_parms (DECL_TEMPLATE_PARMS (fn),
                                       DECL_TEMPLATE_PARMS (method))))
-       continue;
+       goto cont;
 
       if (! DECL_STATIC_FUNCTION_P (fn))
        parms1 = TREE_CHAIN (parms1);
@@ -1178,18 +1180,38 @@ add_method (tree type, tree method, tree using_decl)
                    mangle_decl (method);
                }
              cgraph_node::record_function_versions (fn, method);
-             continue;
+             goto cont;
            }
-         if (DECL_INHERITED_CTOR_BASE (method))
+         if (DECL_INHERITED_CTOR (method))
            {
-             if (DECL_INHERITED_CTOR_BASE (fn))
+             if (DECL_INHERITED_CTOR (fn))
                {
+                 tree basem = DECL_INHERITED_CTOR_BASE (method);
+                 tree basef = DECL_INHERITED_CTOR_BASE (fn);
+                 if (flag_new_inheriting_ctors)
+                   {
+                     if (basem == basef)
+                       {
+                         /* Inheriting the same constructor along different
+                            paths, combine them.  */
+                         SET_DECL_INHERITED_CTOR
+                           (fn, ovl_cons (DECL_INHERITED_CTOR (method),
+                                          DECL_INHERITED_CTOR (fn)));
+                         /* Adjust deletedness and such.  */
+                         deduce_inheriting_ctor (fn);
+                         /* And discard the new one.  */
+                         return false;
+                       }
+                     else
+                       /* Inherited ctors can coexist until overload
+                          resolution.  */
+                       goto cont;
+                   }
                  error_at (DECL_SOURCE_LOCATION (method),
-                           "%q#D inherited from %qT", method,
-                           DECL_INHERITED_CTOR_BASE (method));
+                           "%q#D", method);
                  error_at (DECL_SOURCE_LOCATION (fn),
                            "conflicts with version inherited from %qT",
-                           DECL_INHERITED_CTOR_BASE (fn));
+                           basef);
                }
              /* Otherwise defer to the other function.  */
              return false;
@@ -1200,6 +1222,13 @@ add_method (tree type, tree method, tree using_decl)
                /* Defer to the local function.  */
                return false;
            }
+         else if (flag_new_inheriting_ctors
+                  && DECL_INHERITED_CTOR (fn))
+           {
+             /* Hide the inherited constructor.  */
+             *p = OVL_NEXT (fns);
+             continue;
+           }
          else
            {
              error ("%q+#D cannot be overloaded", method);
@@ -1212,6 +1241,12 @@ add_method (tree type, tree method, tree using_decl)
             will crash while processing the definitions.  */
          return false;
        }
+
+    cont:
+      if (TREE_CODE (fns) == OVERLOAD)
+       p = &OVL_CHAIN (fns);
+      else
+       break;
     }
 
   /* A class should never have more than one destructor.  */
@@ -3308,10 +3343,19 @@ one_inheriting_sig (tree t, tree ctor, tree *parms, int nparms)
    constructor CTOR.  */
 
 static void
-one_inherited_ctor (tree ctor, tree t)
+one_inherited_ctor (tree ctor, tree t, tree using_decl)
 {
   tree parms = FUNCTION_FIRST_USER_PARMTYPE (ctor);
 
+  if (flag_new_inheriting_ctors)
+    {
+      ctor = implicitly_declare_fn (sfk_inheriting_constructor,
+                                   t, /*const*/false, ctor, parms);
+      add_method (t, ctor, using_decl);
+      TYPE_HAS_USER_CONSTRUCTOR (t) = true;
+      return;
+    }
+
   tree *new_parms = XALLOCAVEC (tree, list_length (parms));
   int i = 0;
   for (; parms && parms != void_list_node; parms = TREE_CHAIN (parms))
@@ -3412,7 +3456,7 @@ add_implicitly_declared_members (tree t, tree* access_decls,
          input_location = DECL_SOURCE_LOCATION (using_decl);
          if (ctor_list)
            for (; ctor_list; ctor_list = OVL_NEXT (ctor_list))
-             one_inherited_ctor (OVL_CURRENT (ctor_list), t);
+             one_inherited_ctor (OVL_CURRENT (ctor_list), t, using_decl);
          *access_decls = TREE_CHAIN (*access_decls);
          input_location = loc;
        }
@@ -4772,6 +4816,11 @@ build_clone (tree fn, tree name)
        }
     }
 
+  /* A base constructor inheriting from a virtual base doesn't get the
+     arguments.  */
+  if (ctor_omit_inherited_parms (fn))
+    DECL_CHAIN (DECL_CHAIN (DECL_ARGUMENTS (clone))) = NULL_TREE;
+
   for (parms = DECL_ARGUMENTS (clone); parms; parms = DECL_CHAIN (parms))
     {
       DECL_CONTEXT (parms) = clone;
index 1ebd647e7d1c5a0a975e859c8f661771cc4c9e17..43457d2463fc5c14cab11c56049c419eae39d82c 100644 (file)
@@ -171,13 +171,13 @@ is_valid_constexpr_fn (tree fun, bool complain)
 {
   bool ret = true;
 
-  if (DECL_INHERITED_CTOR_BASE (fun)
+  if (DECL_INHERITED_CTOR (fun)
       && TREE_CODE (fun) == TEMPLATE_DECL)
     {
       ret = false;
       if (complain)
        error ("inherited constructor %qD is not constexpr",
-              get_inherited_ctor (fun));
+              DECL_INHERITED_CTOR (fun));
     }
   else
     {
index 45224dcfc4295f873ceaf597a138855718fd23f0..d3a5aeb785ba614eaf7fea3d2d00b41aebb71085 100644 (file)
@@ -2730,12 +2730,21 @@ struct GTY(()) lang_decl {
   (LANG_DECL_FN_CHECK (NODE)->context = (THUNKS))
 
 /* If NODE, a FUNCTION_DECL, is a C++11 inheriting constructor, then this
-   is the base it inherits from.  */
-#define DECL_INHERITED_CTOR_BASE(NODE) \
-  (DECL_CONSTRUCTOR_P (NODE) ? LANG_DECL_FN_CHECK (NODE)->context : NULL_TREE)
+   is the constructor it inherits from.  */
+#define DECL_INHERITED_CTOR(NODE) \
+  (DECL_DECLARES_FUNCTION_P (NODE) && DECL_CONSTRUCTOR_P (NODE) \
+   ? LANG_DECL_FN_CHECK (NODE)->context : NULL_TREE)
+
+/* And this is the base that constructor comes from.  */
+#define DECL_INHERITED_CTOR_BASE(NODE)                 \
+  (DECL_INHERITED_CTOR (NODE)                          \
+   ? DECL_CONTEXT (flag_new_inheriting_ctors           \
+                  ? strip_inheriting_ctors (NODE)      \
+                  : DECL_INHERITED_CTOR (NODE))        \
+   : NULL_TREE)
 
 /* Set the inherited base.  */
-#define SET_DECL_INHERITED_CTOR_BASE(NODE,INH) \
+#define SET_DECL_INHERITED_CTOR(NODE,INH) \
   (LANG_DECL_FN_CHECK (NODE)->context = (INH))
 
 /* Nonzero if NODE is a thunk, rather than an ordinary function.  */
@@ -6036,7 +6045,9 @@ extern tree get_copy_ctor                 (tree, tsubst_flags_t);
 extern tree get_copy_assign                    (tree);
 extern tree get_default_ctor                   (tree);
 extern tree get_dtor                           (tree, tsubst_flags_t);
-extern tree get_inherited_ctor                 (tree);
+extern tree strip_inheriting_ctors             (tree);
+extern tree inherited_ctor_binfo               (tree);
+extern bool ctor_omit_inherited_parms          (tree);
 extern tree locate_ctor                                (tree);
 extern tree implicitly_declare_fn               (special_function_kind, tree,
                                                 bool, tree, tree);
index 917a448ad34f025dcf5413123d846af88d2805d6..aa92a7e6a6b5784068cd1eb68cd488663016ad72 100644 (file)
@@ -1617,6 +1617,13 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int flags)
             pp_cxx_requires_clause (pp, reqs);
 
       dump_substitution (pp, t, template_parms, template_args, flags);
+
+      if (tree base = DECL_INHERITED_CTOR_BASE (t))
+       {
+         pp_cxx_ws_string (pp, "[inherited from");
+         dump_type (pp, base, TFF_PLAIN_IDENTIFIER);
+         pp_character (pp, ']');
+       }
     }
   else if (template_args)
     {
index 2418a9d48c1914856977bc0a268af7a547406590..5eba4c3e18cfd12e7d84ef72c91224d8a5470428 100644 (file)
@@ -1117,7 +1117,7 @@ emit_mem_initializers (tree mem_inits)
     }
 
   if (DECL_DEFAULTED_FN (current_function_decl)
-      && ! DECL_INHERITED_CTOR_BASE (current_function_decl))
+      && ! DECL_INHERITED_CTOR (current_function_decl))
     flags |= LOOKUP_DEFAULTED;
 
   /* Sort the mem-initializers into the order in which the
@@ -1138,6 +1138,13 @@ emit_mem_initializers (tree mem_inits)
       if (arguments == error_mark_node)
        continue;
 
+      /* Suppress access control when calling the inherited ctor.  */
+      bool inherited_base = (DECL_INHERITED_CTOR (current_function_decl)
+                            && flag_new_inheriting_ctors
+                            && arguments);
+      if (inherited_base)
+       push_deferring_access_checks (dk_deferred);
+
       if (arguments == NULL_TREE)
        {
          /* If these initializations are taking place in a copy constructor,
@@ -1172,6 +1179,9 @@ emit_mem_initializers (tree mem_inits)
        /* C++14 DR1658 Means we do not have to construct vbases of
           abstract classes.  */
        construct_virtual_base (subobject, arguments);
+
+      if (inherited_base)
+       pop_deferring_access_checks ();
     }
   in_base_initializer = 0;
 
index cb2f260c2d1f38b40225b3b6d579cfdf53b7dba9..f3b2fe3ee8de2107081a4783e50e0d53b49734b7 100644 (file)
@@ -1786,18 +1786,25 @@ write_identifier (const char *identifier)
 static void
 write_special_name_constructor (const tree ctor)
 {
+  write_char ('C');
+  bool new_inh = (flag_new_inheriting_ctors
+                 && DECL_INHERITED_CTOR (ctor));
+  if (new_inh)
+    write_char ('I');
   if (DECL_BASE_CONSTRUCTOR_P (ctor))
-    write_string ("C2");
+    write_char ('2');
   /* This is the old-style "[unified]" constructor.
      In some cases, we may emit this function and call
      it from the clones in order to share code and save space.  */
   else if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (ctor))
-    write_string ("C4");
+    write_char ('4');
   else
     {
       gcc_assert (DECL_COMPLETE_CONSTRUCTOR_P (ctor));
-      write_string ("C1");
+      write_char ('1');
     }
+  if (new_inh)
+    write_type (DECL_INHERITED_CTOR_BASE (ctor));
 }
 
 /* Handle destructor productions of non-terminal <special-name>.
index 73a670b59c86e107643d1bb947e6c7605f7a8882..73d42b19d55af4aa45f68072eb84a078d2721369 100644 (file)
@@ -492,6 +492,118 @@ forward_parm (tree parm)
   return exp;
 }
 
+/* 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;
+}
+
 /* Subroutine of do_build_copy_constructor: Add a mem-initializer for BINFO
    given the parameter or parameters PARM, possibly inherited constructor
    base INH, or move flag MOVE_P.  */
@@ -505,7 +617,7 @@ add_one_base_init (tree binfo, tree parm, bool move_p, tree inh,
     {
       /* An inheriting constructor only has a mem-initializer for
         the base it inherits from.  */
-      if (BINFO_TYPE (binfo) != inh)
+      if (!binfo_inherited_from (TYPE_BINFO (current_class_type), binfo, inh))
        return member_init_list;
 
       tree *p = &init;
@@ -537,7 +649,7 @@ do_build_copy_constructor (tree fndecl)
   tree parm = FUNCTION_FIRST_USER_PARM (fndecl);
   bool move_p = DECL_MOVE_CONSTRUCTOR_P (fndecl);
   bool trivial = trivial_fn_p (fndecl);
-  tree inh = DECL_INHERITED_CTOR_BASE (fndecl);
+  tree inh = DECL_INHERITED_CTOR (fndecl);
 
   if (!inh)
     parm = convert_from_reference (parm);
@@ -901,7 +1013,7 @@ locate_fn_flags (tree type, tree name, tree argtype, int flags,
     {
       if (TREE_CODE (argtype) == TREE_LIST)
        {
-         for (tree elt = argtype; elt != void_list_node;
+         for (tree elt = argtype; elt && elt != void_list_node;
               elt = TREE_CHAIN (elt))
            {
              tree type = TREE_VALUE (elt);
@@ -996,25 +1108,6 @@ get_copy_assign (tree type)
   return fn;
 }
 
-/* Locate the inherited constructor of constructor CTOR.  */
-
-tree
-get_inherited_ctor (tree ctor)
-{
-  gcc_assert (DECL_INHERITED_CTOR_BASE (ctor));
-
-  push_deferring_access_checks (dk_no_check);
-  tree fn = locate_fn_flags (DECL_INHERITED_CTOR_BASE (ctor),
-                            complete_ctor_identifier,
-                            FUNCTION_FIRST_USER_PARMTYPE (ctor),
-                            LOOKUP_NORMAL|LOOKUP_SPECULATIVE,
-                            tf_none);
-  pop_deferring_access_checks ();
-  if (fn == error_mark_node)
-    return NULL_TREE;
-  return fn;
-}
-
 /* walk_tree helper function for is_trivially_xible.  If *TP is a call,
    return it if it calls something other than a trivial special member
    function.  */
@@ -1330,7 +1423,7 @@ static void
 synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
                         tree *spec_p, bool *trivial_p, bool *deleted_p,
                         bool *constexpr_p, bool diag,
-                        tree inherited_base, tree inherited_parms)
+                        tree inheriting_ctor, tree inherited_parms)
 {
   tree binfo, base_binfo, scope, fnname, rval, argtype;
   bool move_p, copy_arg_p, assign_p, expected_trivial, check_vdtor;
@@ -1389,7 +1482,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
     }
 
   gcc_assert ((sfk == sfk_inheriting_constructor)
-             == (inherited_base != NULL_TREE));
+             == (inheriting_ctor != NULL_TREE));
 
   /* If that user-written default constructor would satisfy the
      requirements of a constexpr constructor (7.1.5), the
@@ -1465,7 +1558,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
   scope = push_scope (ctype);
 
   flags = LOOKUP_NORMAL|LOOKUP_SPECULATIVE;
-  if (!inherited_base)
+  if (!inheriting_ctor)
     flags |= LOOKUP_DEFAULTED;
 
   complain = diag ? tf_warning_or_error : tf_none;
@@ -1485,13 +1578,25 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
        /* We'll handle virtual bases below.  */
        continue;
 
+      bool inherited_binfo = false;
+
       if (copy_arg_p)
        argtype = build_stub_type (basetype, quals, move_p);
-      else if (basetype == inherited_base)
-       argtype = inherited_parms;
+      else if ((inherited_binfo
+               = binfo_inherited_from (binfo, base_binfo, inheriting_ctor)))
+       {
+         /* Don't check access on the inherited constructor.  */
+         argtype = inherited_parms;
+         if (flag_new_inheriting_ctors)
+           push_deferring_access_checks (dk_deferred);
+       }
       rval = locate_fn_flags (base_binfo, fnname, argtype, flags, complain);
-      if (inherited_base)
-       argtype = NULL_TREE;
+      if (inherited_binfo)
+       {
+         if (flag_new_inheriting_ctors)
+           pop_deferring_access_checks ();
+         argtype = NULL_TREE;
+       }
 
       process_subob_fn (rval, spec_p, trivial_p, deleted_p,
                        constexpr_p, diag, basetype);
@@ -1547,9 +1652,24 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
       FOR_EACH_VEC_ELT (*vbases, i, base_binfo)
        {
          tree basetype = BINFO_TYPE (base_binfo);
+         bool inherited_binfo = false;
+
          if (copy_arg_p)
            argtype = build_stub_type (basetype, quals, move_p);
+         else if ((inherited_binfo
+                   = binfo_inherited_from (binfo, base_binfo, inheriting_ctor)))
+           {
+             argtype = inherited_parms;
+             if (flag_new_inheriting_ctors)
+               push_deferring_access_checks (dk_deferred);
+           }
          rval = locate_fn_flags (base_binfo, fnname, argtype, flags, complain);
+         if (inherited_binfo)
+           {
+             if (flag_new_inheriting_ctors)
+               pop_deferring_access_checks ();
+             argtype = NULL_TREE;
+           }
 
          process_subob_fn (rval, spec_p, trivial_p, deleted_p,
                            constexpr_p, diag, basetype);
@@ -1598,7 +1718,7 @@ get_defaulted_eh_spec (tree decl)
   bool const_p = CP_TYPE_CONST_P (non_reference (parm_type));
   tree spec = empty_except_spec;
   synthesized_method_walk (ctype, sfk, const_p, &spec, NULL, NULL,
-                          NULL, false, DECL_INHERITED_CTOR_BASE (decl),
+                          NULL, false, DECL_INHERITED_CTOR (decl),
                           parms);
   return spec;
 }
@@ -1657,6 +1777,17 @@ maybe_explain_implicit_delete (tree decl)
                  decl, ctype);
          informed = true;
        }
+      else if (sfk == sfk_inheriting_constructor)
+       {
+         tree binfo = inherited_ctor_binfo (decl);
+         if (TREE_CODE (binfo) != TREE_BINFO)
+           {
+             inform (DECL_SOURCE_LOCATION (decl),
+                     "%q#D inherits from multiple base subobjects",
+                     decl);
+             informed = true;
+           }
+       }
       if (!informed)
        {
          tree parms = FUNCTION_FIRST_USER_PARMTYPE (decl);
@@ -1668,7 +1799,7 @@ maybe_explain_implicit_delete (tree decl)
 
          synthesized_method_walk (ctype, sfk, const_p,
                                   &raises, NULL, &deleted_p, NULL, false,
-                                  DECL_INHERITED_CTOR_BASE (decl), parms);
+                                  DECL_INHERITED_CTOR (decl), parms);
          if (deleted_p)
            {
              inform (DECL_SOURCE_LOCATION (decl),
@@ -1676,7 +1807,7 @@ maybe_explain_implicit_delete (tree decl)
                      "definition would be ill-formed:", decl);
              synthesized_method_walk (ctype, sfk, const_p,
                                       NULL, NULL, NULL, NULL, true,
-                                      DECL_INHERITED_CTOR_BASE (decl), parms);
+                                      DECL_INHERITED_CTOR (decl), parms);
            }
          else if (!comp_except_specs
                   (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl)),
@@ -1709,7 +1840,7 @@ explain_implicit_non_constexpr (tree decl)
   synthesized_method_walk (DECL_CLASS_CONTEXT (decl),
                           special_function_p (decl), const_p,
                           NULL, NULL, NULL, &dummy, true,
-                          DECL_INHERITED_CTOR_BASE (decl),
+                          DECL_INHERITED_CTOR (decl),
                           FUNCTION_FIRST_USER_PARMTYPE (decl));
 }
 
@@ -1720,14 +1851,17 @@ explain_implicit_non_constexpr (tree decl)
 void
 deduce_inheriting_ctor (tree decl)
 {
-  gcc_assert (DECL_INHERITED_CTOR_BASE (decl));
+  gcc_assert (DECL_INHERITED_CTOR (decl));
   tree spec;
   bool trivial, constexpr_, deleted;
   synthesized_method_walk (DECL_CONTEXT (decl), sfk_inheriting_constructor,
                           false, &spec, &trivial, &deleted, &constexpr_,
                           /*diag*/false,
-                          DECL_INHERITED_CTOR_BASE (decl),
+                          DECL_INHERITED_CTOR (decl),
                           FUNCTION_FIRST_USER_PARMTYPE (decl));
+  if (TREE_CODE (inherited_ctor_binfo (decl)) != TREE_BINFO)
+    /* Inherited the same constructor from different base subobjects.  */
+    deleted = true;
   DECL_DELETED_FN (decl) = deleted;
   TREE_TYPE (decl) = build_exception_variant (TREE_TYPE (decl), spec);
 }
@@ -1828,9 +1962,6 @@ implicitly_declare_fn (special_function_kind kind, tree type,
       gcc_unreachable ();
     }
 
-  tree inherited_base = (inherited_ctor
-                        ? DECL_CONTEXT (inherited_ctor)
-                        : NULL_TREE);
   bool trivial_p = false;
 
   if (inherited_ctor && TREE_CODE (inherited_ctor) == TEMPLATE_DECL)
@@ -1846,12 +1977,12 @@ implicitly_declare_fn (special_function_kind kind, tree type,
       raises = unevaluated_noexcept_spec ();
       synthesized_method_walk (type, kind, const_p, NULL, &trivial_p,
                               &deleted_p, &constexpr_p, false,
-                              inherited_base, inherited_parms);
+                              inherited_ctor, inherited_parms);
     }
   else
     synthesized_method_walk (type, kind, const_p, &raises, &trivial_p,
                             &deleted_p, &constexpr_p, false,
-                            inherited_base, inherited_parms);
+                            inherited_ctor, inherited_parms);
   /* Don't bother marking a deleted constructor as constexpr.  */
   if (deleted_p)
     constexpr_p = false;
@@ -1902,7 +2033,7 @@ implicitly_declare_fn (special_function_kind kind, tree type,
     {
       tree *p = &DECL_ARGUMENTS (fn);
       int index = 1;
-      for (tree parm = inherited_parms; parm != void_list_node;
+      for (tree parm = inherited_parms; parm && parm != void_list_node;
           parm = TREE_CHAIN (parm))
        {
          *p = cp_build_parm_decl (NULL_TREE, TREE_VALUE (parm));
@@ -1912,7 +2043,7 @@ implicitly_declare_fn (special_function_kind kind, tree type,
          DECL_CONTEXT (*p) = fn;
          p = &DECL_CHAIN (*p);
        }
-      SET_DECL_INHERITED_CTOR_BASE (fn, inherited_base);
+      SET_DECL_INHERITED_CTOR (fn, inherited_ctor);
       DECL_NONCONVERTING_P (fn) = DECL_NONCONVERTING_P (inherited_ctor);
       /* A constructor so declared has the same access as the corresponding
         constructor in X.  */
index 023ed87098f1c4e9b6e55aaac76242146414d038..e574c271194add28b85011df627f8617411ea94c 100644 (file)
@@ -3421,6 +3421,12 @@ do_class_using_decl (tree scope, tree name)
              return NULL_TREE;
            }
        }
+      else if (name == ctor_identifier
+              && BINFO_INHERITANCE_CHAIN (BINFO_INHERITANCE_CHAIN (binfo)))
+       {
+         error ("cannot inherit constructors from indirect base %qT", scope);
+         return NULL_TREE;
+       }
       else if (!name_dependent_p)
        {
          decl = lookup_member (binfo, name, 0, false, tf_warning_or_error);
index e2032c1d90ef633111e5c81da7aab0fab0fae912..b926ef7ad6ca76dfe59c22e3f9fc7ace40cd3beb 100644 (file)
@@ -166,7 +166,8 @@ cdtor_comdat_group (tree complete, tree base)
       {
        gcc_assert (!diff_seen
                    && idx > 0
-                   && (p[idx - 1] == 'C' || p[idx - 1] == 'D')
+                   && (p[idx - 1] == 'C' || p[idx - 1] == 'D'
+                       || p[idx - 1] == 'I')
                    && p[idx] == '1'
                    && q[idx] == '2');
        grp_name[idx] = '5';
@@ -259,6 +260,11 @@ maybe_thunk_body (tree fn, bool force)
      (for non-vague linkage ctors) or the COMDAT group (otherwise).  */
 
   populate_clone_array (fn, fns);
+
+  /* Don't use thunks if the base clone omits inherited parameters.  */
+  if (ctor_omit_inherited_parms (fns[0]))
+    return 0;
+
   DECL_ABSTRACT_P (fn) = false;
   if (!DECL_WEAK (fn))
     {
@@ -490,7 +496,7 @@ maybe_clone_body (tree fn)
        parm = DECL_CHAIN (parm);
       if (DECL_HAS_VTT_PARM_P (clone))
        clone_parm = DECL_CHAIN (clone_parm);
-      for (; parm;
+      for (; parm && clone_parm;
           parm = DECL_CHAIN (parm), clone_parm = DECL_CHAIN (clone_parm))
        /* Update this parameter.  */
        update_cloned_parm (parm, clone_parm, first);
@@ -616,7 +622,8 @@ maybe_clone_body (tree fn)
               else
                 {
                   decl_map->put (parm, clone_parm);
-                  clone_parm = DECL_CHAIN (clone_parm);
+                 if (clone_parm)
+                   clone_parm = DECL_CHAIN (clone_parm);
                 }
             }
 
index 73522131b6343664c9b065c46f53369ec43f1bde..e5134487816b976a8cb14c346243d73e493c4ba8 100644 (file)
@@ -12056,7 +12056,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
            maybe_retrofit_in_chrg (r);
            if (DECL_CONSTRUCTOR_P (r))
              grok_ctor_properties (ctx, r);
-           if (DECL_INHERITED_CTOR_BASE (r))
+           if (DECL_INHERITED_CTOR (r))
              deduce_inheriting_ctor (r);
            /* If this is an instantiation of a member template, clone it.
               If it isn't, that'll be handled by
@@ -17663,11 +17663,16 @@ instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain)
   DECL_TI_ARGS (fndecl) = targ_ptr;
 
   /* Now we know the specialization, compute access previously
-     deferred.  */
-  push_access_scope (fndecl);
-  if (!perform_deferred_access_checks (complain))
-    access_ok = false;
-  pop_access_scope (fndecl);
+     deferred.  Do no access control for inheriting constructors,
+     as we already checked access for the inherited constructor.  */
+  if (!(flag_new_inheriting_ctors
+       && DECL_INHERITED_CTOR (fndecl)))
+    {
+      push_access_scope (fndecl);
+      if (!perform_deferred_access_checks (complain))
+       access_ok = false;
+      pop_access_scope (fndecl);
+    }
   pop_deferring_access_checks ();
 
   /* If we've just instantiated the main entry point for a function,
@@ -17825,6 +17830,11 @@ fn_type_unification (tree fn,
   static int deduction_depth;
   struct pending_template *old_last_pend = last_pending_template;
   struct tinst_level *old_error_tinst = last_error_tinst_level;
+
+  tree orig_fn = fn;
+  if (flag_new_inheriting_ctors)
+    fn = strip_inheriting_ctors (fn);
+
   tree tparms = DECL_INNERMOST_TEMPLATE_PARMS (fn);
   tree tinst;
   tree r = error_mark_node;
@@ -18113,6 +18123,11 @@ fn_type_unification (tree fn,
          }
     }
 
+  /* After doing deduction with the inherited constructor, actually return an
+     instantiation of the inheriting constructor.  */
+  if (orig_fn != fn)
+    decl = instantiate_template (orig_fn, targs, complain);
+
   r = decl;
 
  fail:
index 03eef0030d07d29f5854c85faf452e566c94c794..ac15d67eafb27c3f0fed8b5d2228e99ef9a94dcc 100644 (file)
@@ -4282,7 +4282,7 @@ special_function_p (const_tree decl)
   /* Rather than doing all this stuff with magic names, we should
      probably have a field of type `special_function_kind' in
      DECL_LANG_SPECIFIC.  */
-  if (DECL_INHERITED_CTOR_BASE (decl))
+  if (DECL_INHERITED_CTOR (decl))
     return sfk_inheriting_constructor;
   if (DECL_COPY_CONSTRUCTOR_P (decl))
     return sfk_copy_constructor;
index fd783bf862df9033bb8c4ac9f309fab2ab099e05..ad9304fdeff0bb30105bfcb7af17c628e18dcf1a 100644 (file)
@@ -199,6 +199,7 @@ in the following sections.
 -fno-implicit-templates @gol
 -fno-implicit-inline-templates @gol
 -fno-implement-inlines  -fms-extensions @gol
+-fnew-inheriting-ctors @gol
 -fno-nonansi-builtins  -fnothrow-opt  -fno-operator-names @gol
 -fno-optional-diags  -fpermissive @gol
 -fno-pretty-templates @gol
@@ -2220,6 +2221,10 @@ Version 10, which first appeared in G++ 6.1, adds mangling of
 attributes that affect type identity, such as ia32 calling convention
 attributes (e.g. @samp{stdcall}).
 
+Version 11, which first appeared in G++ 7, corrects the mangling of
+sizeof... expressions.  It also implies
+@option{-fnew-inheriting-ctors}.
+
 See also @option{-Wabi}.
 
 @item -fabi-compat-version=@var{n}
@@ -2413,6 +2418,13 @@ errors if these functions are not inlined everywhere they are called.
 Disable Wpedantic warnings about constructs used in MFC, such as implicit
 int and getting a pointer to member function via non-standard syntax.
 
+@item -fnew-inheriting-ctors
+@opindex fnew-inheriting-ctors
+Enable the P0136 adjustment to the semantics of C++11 constructor
+inheritance.  This is part of C++17 but also considered to be a Defect
+Report against C++11 and C++14.  This flag is enabled by default
+unless @option{-fabi-version=10} or lower is specified.
+
 @item -fno-nonansi-builtins
 @opindex fno-nonansi-builtins
 Disable built-in declarations of functions that are not mandated by
index ee8757f4dcf464a90ac9072312217f8683835819..98691101e860b90d6779cceaeb48ac479b0b9730 100644 (file)
@@ -9,7 +9,7 @@ struct A
 
 struct B : A
 {
-  using A::A;                  // { dg-error "A::i" }
+  using A::A;                  // { dg-prune-output "A::i" }
 };
 
-constexpr B b(0);              // { dg-error "B::B" }
+constexpr B b(0);              // { dg-error "" }
index 228e8ec6609130ae0b01c83969e515d0f075c713..4fc67a4a56a5be6d2760344458ed23a3ef9fe594 100644 (file)
@@ -1,4 +1,5 @@
 // { dg-do compile { target c++11 } }
+// { dg-options -fno-new-inheriting-ctors }
 
 struct A
 {
diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor11a.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor11a.C
new file mode 100644 (file)
index 0000000..61b251e
--- /dev/null
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++11 } }
+// { dg-options -fnew-inheriting-ctors }
+
+struct A
+{
+  A(int, ...);
+};
+
+struct B: A
+{
+  using A::A;
+};
+
+B b1(42);
+B b2(42, 1.0);                 // { dg-bogus "ellipsis" "" { xfail *-*-* } }
index c2d33bff4ffe5cd34c497d8fb49f8ec2bbaf3a30..a0b518c19d34f99fb910684d25410c0eb30ba8ef 100644 (file)
@@ -2,6 +2,7 @@
 // constructors was a deliberate choice.
 
 // { dg-do compile { target c++11 } }
+// { dg-options -fno-new-inheriting-ctors }
 
 struct A { A(int); };
 struct B: public A
diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor15a.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor15a.C
new file mode 100644 (file)
index 0000000..a9abb84
--- /dev/null
@@ -0,0 +1,14 @@
+// P0136 caused us to start inheriting base copy constructors.
+// { dg-do compile { target c++11 } }
+// { dg-options -fnew-inheriting-ctors }
+
+struct A { A(int); };
+struct B: public A
+{
+  using A::A;
+};
+
+A a (42);
+
+B b1 (24);                     // inherited
+B b2 (a);                      // also inherited now
index e8dc84d32ec8394a238d2fb30dce294943351593..8cbeed6604792e5176f745f39db83d488c2add27 100644 (file)
@@ -1,4 +1,5 @@
 // { dg-do compile { target c++11 } }
+// { dg-options -fno-new-inheriting-ctors }
 
 struct B1 {
   B1(int);
diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor3a.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor3a.C
new file mode 100644 (file)
index 0000000..c9b4ea1
--- /dev/null
@@ -0,0 +1,21 @@
+// { dg-do compile { target c++11 } }
+// { dg-options -fnew-inheriting-ctors }
+
+struct B1 {
+  B1(int);
+};
+struct B2 {
+  B2(int);
+};
+struct D1 : B1, B2 {
+  using B1::B1;
+  using B2::B2;
+};                             // ambiguous
+struct D2 : B1, B2 {
+  using B1::B1;
+  using B2::B2;
+  D2(int);    // OK: user declaration supersedes both implicit declarations
+};
+
+D2 d2(42);
+D1 d1(42);                     // { dg-error "ambiguous" }
index 8c79c833a32233abef0b2b280799ae0928cf6b4f..d0038c16a142f6dbb3d7bda2efc3e11def0f32f9 100644 (file)
@@ -15,7 +15,7 @@ void test() {
   D1 e;                    // { dg-error "deleted" } D1 has no default constructor
 }
 struct D2 : B2 {
-  using B2::B2;            // { dg-error "no match" } implicitly declares D2(double)
+  using B2::B2;            // { dg-error "B1::B1" }
   B1 b;
 };
 D2 f(1.0);         // { dg-error "deleted" } B1 has no default constructor
index 676605db9e936e39550f42938afa51faaca0e1bb..5bfdd499d46cec4bb51b7c25f2c1e8359f8a8700 100644 (file)
@@ -9,7 +9,7 @@ protected:
 
 struct B: A
 {
-  using A::A;                  // { dg-message "protected" }
+  using A::A;
 };
 
 B b(42);                       // { dg-error "this context" }
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor1.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor1.C
new file mode 100644 (file)
index 0000000..bf9df41
--- /dev/null
@@ -0,0 +1,5 @@
+// { dg-do compile { target c++11 } }
+
+struct A { };
+struct B: A { };
+struct C: B { using A::A; };   // { dg-error "direct" }
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor22.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor22.C
new file mode 100644 (file)
index 0000000..02ec58a
--- /dev/null
@@ -0,0 +1,33 @@
+// Testcase from P0136
+// { dg-do compile { target c++11 } }
+
+struct B1 {
+  template <class... Ts>
+  B1(int, Ts...) { }
+};
+
+struct B2 {
+  B2(double) { }
+};
+
+int get();
+
+struct D1 : B1 {               // { dg-message "B1::B1" }
+  using B1::B1;  // inherits B1(int, ...)
+  int x;
+  int y = get();
+};
+
+void test() {
+  D1 d(2, 3, 4); // OK: B1 is initialized by calling B1(2, 3, 4),
+  // then d.x is default-initialized (no initialization is performed),
+  // then d.y is initialized by calling get()
+  D1 e;          // { dg-error "" } D1 has a deleted default constructor
+}
+
+struct D2 : B2 {
+  using B2::B2;                        // { dg-message "B1::B1" }
+  B1 b;
+};
+
+D2 f(1.0);       // { dg-error "" } B1 has no default constructor
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor23.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor23.C
new file mode 100644 (file)
index 0000000..0c862f7
--- /dev/null
@@ -0,0 +1,19 @@
+// Testcase from P0136
+// { dg-do compile { target c++11 } }
+// { dg-options "-fnew-inheriting-ctors -fdump-tree-gimple" }
+
+struct W { W(int); };
+struct V: W { using W::W; };
+struct X : virtual V { using V::V; X() = delete; };
+struct Y : X { using X::X; };
+struct Z : Y, virtual V { using Y::Y; };
+Z z(0); // OK: initialization of Y does not invoke default constructor of X
+
+// Check that we're passing this and __vtt along to the Y inheriting
+// constructor, but not the int parameter.
+// { dg-final { scan-assembler "_ZN1YCI21WEi" } }
+// { dg-final { scan-tree-dump "Y::Y ._2, _3.;" "gimple" } }
+
+// And that we *are* passing the int along to V::V.
+// { dg-final { scan-assembler "_ZN1VCI21WEi" } }
+// { dg-final { scan-tree-dump "V::V .this, _1.;" "gimple" } }
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor24.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor24.C
new file mode 100644 (file)
index 0000000..2145019
--- /dev/null
@@ -0,0 +1,27 @@
+// Testcase from P0136
+// { dg-do compile { target c++11 } }
+// { dg-options -fnew-inheriting-ctors }
+
+struct A { A(int); };
+struct B : A { using A::A; };
+
+struct C1 : B { using B::B; };
+struct C2 : B { using B::B; };
+
+struct D1 : C1, C2 {
+  using C1::C1;
+  using C2::C2;
+};
+
+struct V1 : virtual B { using B::B; };
+struct V2 : virtual B { using B::B; };
+
+struct D2 : V1, V2 {
+  using V1::V1;
+  using V2::V2;
+};
+
+D1 d1(0); // { dg-error "" } ambiguous
+D2 d2(0); // OK: initializes virtual B base class, which initializes the A base
+          // class then initializes the V1 and V2 base classes as if by a
+          // defaulted default constructor
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor25.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor25.C
new file mode 100644 (file)
index 0000000..66cd2da
--- /dev/null
@@ -0,0 +1,9 @@
+// Testcase from P0136
+// { dg-do compile { target c++11 } }
+
+struct M { M(); M(int); };
+struct N : M { using M::M; };
+struct O : M {};
+struct P : N, O { using N::N; using O::O; };
+P p(0); // OK: use M(0) to initialize N's base class,
+        // use M() to initialize O's base class
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor26.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor26.C
new file mode 100644 (file)
index 0000000..28dc332
--- /dev/null
@@ -0,0 +1,17 @@
+// Testcase from P0136
+// { dg-do compile { target c++11 } }
+// { dg-options -fnew-inheriting-ctors }
+
+struct A {
+  template<typename T> A(T, typename T::type = 0);
+  A(int);
+};
+struct B : A {
+  using A::A;
+  B(int);
+};
+B b(42L); // now calls B(int), used to call B<long>(long),
+          // which called A(int) due to substitution failure
+          // in A<long>(long).
+
+// { dg-final { scan-assembler "_ZN1BC1Ei" } }
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor27.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor27.C
new file mode 100644 (file)
index 0000000..97f2634
--- /dev/null
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+  A(int = 0);
+};
+
+struct B: A
+{
+  B();
+  using A::A;
+};
+
+B b1(1);
+B b;
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor28.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor28.C
new file mode 100644 (file)
index 0000000..55e1d8c
--- /dev/null
@@ -0,0 +1,7 @@
+// { dg-do compile { target c++11 } }
+// { dg-options -fnew-inheriting-ctors }
+
+struct V { V(int); };
+struct W : virtual V { using V::V; };
+struct X : virtual W, virtual V { using W::W; };
+X x(0);
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor29.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor29.C
new file mode 100644 (file)
index 0000000..97f2634
--- /dev/null
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+  A(int = 0);
+};
+
+struct B: A
+{
+  B();
+  using A::A;
+};
+
+B b1(1);
+B b;
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor30.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor30.C
new file mode 100644 (file)
index 0000000..494dd91
--- /dev/null
@@ -0,0 +1,17 @@
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+  A(double);
+};
+
+struct B: A
+{
+  B(short);
+  using A::A;
+};
+
+int main()
+{
+  B b(1);                      // { dg-error "ambiguous" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor31.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor31.C
new file mode 100644 (file)
index 0000000..3ce080d
--- /dev/null
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++11 } }
+
+struct B;
+struct A
+{
+  A(const B&, int = 0);
+};
+
+struct B: A
+{
+  using A::A;
+};
+
+extern B b;
+B b2{b};
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor32.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor32.C
new file mode 100644 (file)
index 0000000..7ce85b0
--- /dev/null
@@ -0,0 +1,16 @@
+// { dg-do compile { target c++11 } }
+
+struct B;
+struct A
+{
+  A(const B&, int = 0);
+};
+
+struct B: A
+{
+  using A::A;
+  B(B&);
+};
+
+extern const B b;
+B b2{b};                       // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor33.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor33.C
new file mode 100644 (file)
index 0000000..0e85207
--- /dev/null
@@ -0,0 +1,23 @@
+// { dg-do link { target c++11 } }
+// { dg-options -fnew-inheriting-ctors }
+
+struct A
+{
+  A() { }
+  A(const A&);                 // should never be called
+};
+
+struct B
+{
+  B(A) { }
+};
+
+struct C: B
+{
+  using B::B;
+};
+
+int main()
+{
+  C c{A()};
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor34.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor34.C
new file mode 100644 (file)
index 0000000..f47b2a4
--- /dev/null
@@ -0,0 +1,18 @@
+// { dg-do compile { target c++11 } }
+// { dg-options -fnew-inheriting-ctors }
+
+class A
+{
+  A(int);
+  friend void f();
+};
+
+struct B: A
+{
+  using A::A;
+};
+
+void f()
+{
+  B b(42);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor35.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor35.C
new file mode 100644 (file)
index 0000000..87f4452
--- /dev/null
@@ -0,0 +1,21 @@
+// Core 1715
+// { dg-do compile { target c++11 } }
+// { dg-options -fno-new-inheriting-ctors }
+
+template<class T> struct S {
+private:
+  typedef int X;
+  friend struct B;
+};
+
+struct B {
+  template<class T> B(T, typename T::X);
+};
+
+struct D: B {
+  using B::B;                  // { dg-prune-output "private" }
+};
+
+S<int> s;
+B b(s, 2); // Okay, thanks to friendship.
+D d(s, 2); // { dg-error "" } was an error before P0136
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor35a.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor35a.C
new file mode 100644 (file)
index 0000000..47f69de
--- /dev/null
@@ -0,0 +1,21 @@
+// Core 1715
+// { dg-do compile { target c++11 } }
+// { dg-options -fnew-inheriting-ctors }
+
+template<class T> struct S {
+private:
+  typedef int X;
+  friend struct B;
+};
+
+struct B {
+  template<class T> B(T, typename T::X);
+};
+
+struct D: B {
+  using B::B;
+};
+
+S<int> s;
+B b(s, 2); // Okay, thanks to friendship.
+D d(s, 2); // Now OK as well.
diff --git a/gcc/testsuite/g++.dg/cpp1z/using1.C b/gcc/testsuite/g++.dg/cpp1z/using1.C
new file mode 100644 (file)
index 0000000..1ed939d
--- /dev/null
@@ -0,0 +1,23 @@
+// Test for hiding of used base functions when all the conversion sequences are
+// equivalent, needed to avoid a regression on inherited default ctors.
+
+struct A
+{
+  void f(short,int=0);
+  void g(char,int=0);
+};
+
+struct B:A
+{
+  using A::f;
+  void f(short);
+  using A::g;
+  void g(short);
+};
+
+int main()
+{
+  B().f(1);                    // OK, derived f hides base f for single arg
+  B().f(1,2);                  // OK, base f can still be called with two args
+  B().g(1);                    // { dg-error "" } signatures differ, ambiguous
+}
index de5e575708012b738ce507a1915abcdee2be700f..6899d2a8736c443835877e5fed3e30c4a45f971d 100644 (file)
@@ -1045,6 +1045,7 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data)
   copy_body_data *id = (copy_body_data *) data;
   tree fn = id->src_fn;
   tree new_block;
+  bool copied = false;
 
   /* Begin by recognizing trees that we'll completely rewrite for the
      inlining context.  Our output for these trees is completely
@@ -1241,10 +1242,40 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data)
          *walk_subtrees = 0;
          return NULL;
        }
+      else if (TREE_CODE (*tp) == COND_EXPR)
+       {
+         tree cond = TREE_OPERAND (*tp, 0);
+         walk_tree (&cond, copy_tree_body_r, data, NULL);
+         tree folded = fold (cond);
+         if (TREE_CODE (folded) == INTEGER_CST)
+           {
+             /* Only copy the taken branch; for a C++ base constructor clone
+                inherited from a virtual base, copying the other branch leads
+                to references to parameters that were optimized away.  */
+             tree branch = (integer_nonzerop (folded)
+                            ? TREE_OPERAND (*tp, 1)
+                            : TREE_OPERAND (*tp, 2));
+             tree type = TREE_TYPE (*tp);
+             if (VOID_TYPE_P (type)
+                 || type == TREE_TYPE (branch))
+               {
+                 *tp = branch;
+                 return copy_tree_body_r (tp, walk_subtrees, data);
+               }
+           }
+         /* Avoid copying the condition twice.  */
+         copy_tree_r (tp, walk_subtrees, NULL);
+         TREE_OPERAND (*tp, 0) = cond;
+         walk_tree (&TREE_OPERAND (*tp, 1), copy_tree_body_r, data, NULL);
+         walk_tree (&TREE_OPERAND (*tp, 2), copy_tree_body_r, data, NULL);
+         *walk_subtrees = 0;
+         copied = true;
+       }
 
       /* Here is the "usual case".  Copy this tree node, and then
         tweak some special cases.  */
-      copy_tree_r (tp, walk_subtrees, NULL);
+      if (!copied)
+       copy_tree_r (tp, walk_subtrees, NULL);
 
       /* If EXPR has block defined, map it to newly constructed block.
          When inlining we want EXPRs without block appear in the block
index 73cbcc41c60cbd07cb9b7355ef69fb944e2107e9..bb4dee41a550ccba9aa447058e2c61b6a20ab4d6 100644 (file)
@@ -1,3 +1,7 @@
+2016-11-01  Jason Merrill  <jason@redhat.com>
+
+       * cp-demangle.c (d_ctor_dtor_name): Handle inheriting constructor.
+
 2016-10-31  Mark Wielaard  <mjw@redhat.com>
 
        * cplus-dem.c (ada_demangle): Initialize demangled to NULL and
index a843dc38f98c42ea0e6fd7a27d307d37dad27035..46382ccee22e2d4c96c92feee50af7c7fcb4b836 100644 (file)
@@ -2168,6 +2168,13 @@ d_ctor_dtor_name (struct d_info *di)
     case 'C':
       {
        enum gnu_v3_ctor_kinds kind;
+       int inheriting = 0;
+
+       if (d_peek_next_char (di) == 'I')
+         {
+           inheriting = 1;
+           d_advance (di, 1);
+         }
 
        switch (d_peek_next_char (di))
          {
@@ -2189,7 +2196,12 @@ d_ctor_dtor_name (struct d_info *di)
          default:
            return NULL;
          }
+
        d_advance (di, 2);
+
+       if (inheriting)
+         cplus_demangle_type (di);
+
        return d_make_ctor (di, kind, di->last_name);
       }
 
index a5a658a7095948fd17edf5a11bfb88a1b83d8f05..a56776355bfe0cbb53993b6b0e15e8bcfb7a644a 100644 (file)
@@ -4592,3 +4592,7 @@ __t2m05B500000000000000000_
 
 __10%0__S4_0T0T0
 %0<>::%0(%0<>)
+
+# Inheriting constructor
+_ZN1DCI11BEi
+D::B(int)