/* Perform optimizations on tree structure.
   Copyright (C) 1998-2022 Free Software Foundation, Inc.
   Written by Mark Michell (mark@codesourcery.com).

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.

GCC is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "target.h"
#include "cp-tree.h"
#include "stringpool.h"
#include "cgraph.h"
#include "debug.h"
#include "tree-inline.h"
#include "tree-iterator.h"

/* Prototypes.  */

static void update_cloned_parm (tree, tree, bool);

/* CLONED_PARM is a copy of CLONE, generated for a cloned constructor
   or destructor.  Update it to ensure that the source-position for
   the cloned parameter matches that for the original, and that the
   debugging generation code will be able to find the original PARM.  */

static void
update_cloned_parm (tree parm, tree cloned_parm, bool first)
{
  DECL_ABSTRACT_ORIGIN (cloned_parm) = parm;

  /* We may have taken its address.  */
  TREE_ADDRESSABLE (cloned_parm) = TREE_ADDRESSABLE (parm);

  DECL_BY_REFERENCE (cloned_parm) = DECL_BY_REFERENCE (parm);

  /* The definition might have different constness.  */
  TREE_READONLY (cloned_parm) = TREE_READONLY (parm);

  TREE_USED (cloned_parm) = !first || TREE_USED (parm);

  /* The name may have changed from the declaration.  */
  DECL_NAME (cloned_parm) = DECL_NAME (parm);
  DECL_SOURCE_LOCATION (cloned_parm) = DECL_SOURCE_LOCATION (parm);
  TREE_TYPE (cloned_parm) = TREE_TYPE (parm);

  DECL_NOT_GIMPLE_REG_P (cloned_parm) = DECL_NOT_GIMPLE_REG_P (parm);
}

/* Like copy_decl_no_change, but handle DECL_OMP_PRIVATIZED_MEMBER
   properly.  */

static tree
cxx_copy_decl (tree decl, copy_body_data *id)
{
  tree copy = copy_decl_no_change (decl, id);
  if (VAR_P (decl)
      && DECL_HAS_VALUE_EXPR_P (decl)
      && DECL_ARTIFICIAL (decl)
      && DECL_LANG_SPECIFIC (decl)
      && DECL_OMP_PRIVATIZED_MEMBER (decl))
    {
      tree expr = DECL_VALUE_EXPR (copy);
      walk_tree (&expr, copy_tree_body_r, id, NULL);
      SET_DECL_VALUE_EXPR (copy, expr);
    }
  return copy;
}

/* FN is a function in High GIMPLE form that has a complete body and no
   CFG.  CLONE is a function whose body is to be set to a copy of FN,
   mapping argument declarations according to the ARG_MAP splay_tree.  */

static void
clone_body (tree clone, tree fn, void *arg_map)
{
  copy_body_data id;
  tree stmts;

  /* Clone the body, as if we were making an inline call.  But, remap
     the parameters in the callee to the parameters of caller.  */
  memset (&id, 0, sizeof (id));
  id.src_fn = fn;
  id.dst_fn = clone;
  id.src_cfun = DECL_STRUCT_FUNCTION (fn);
  id.decl_map = static_cast<hash_map<tree, tree> *> (arg_map);

  id.copy_decl = cxx_copy_decl;
  id.transform_call_graph_edges = CB_CGE_DUPLICATE;
  id.transform_new_cfg = true;
  id.transform_return_to_modify = false;

  /* We're not inside any EH region.  */
  id.eh_lp_nr = 0;

  stmts = DECL_SAVED_TREE (fn);
  walk_tree (&stmts, copy_tree_body_r, &id, NULL);

  /* Also remap the initializer of any static variables so that they (in
     particular, any label addresses) correspond to the base variant rather
     than the abstract one.  */
  if (DECL_NAME (clone) == base_dtor_identifier
      || DECL_NAME (clone) == base_ctor_identifier)
    {
      unsigned ix;
      tree decl;

      FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (fn), ix, decl)
        walk_tree (&DECL_INITIAL (decl), copy_tree_body_r, &id, NULL);
    }

  append_to_statement_list_force (stmts, &DECL_SAVED_TREE (clone));
}

/* DELETE_DTOR is a delete destructor whose body will be built.
   COMPLETE_DTOR is the corresponding complete destructor.  */

static void
build_delete_destructor_body (tree delete_dtor, tree complete_dtor)
{
  tree parm = DECL_ARGUMENTS (delete_dtor);
  tree virtual_size = cxx_sizeof (current_class_type);

  /* Call the delete function.  */
  tree call_delete = build_op_delete_call (DELETE_EXPR, current_class_ptr,
					   virtual_size,
					   /*global_p=*/false,
					   /*placement=*/NULL_TREE,
					   /*alloc_fn=*/NULL_TREE,
					   tf_warning_or_error);

  tree op = get_callee_fndecl (call_delete);
  if (op && DECL_P (op) && destroying_delete_p (op))
    {
      /* The destroying delete will handle calling complete_dtor.  */
      add_stmt (call_delete);
    }
  else
    {
      /* Call the corresponding complete destructor.  */
      gcc_assert (complete_dtor);
      tree call_dtor = build_cxx_call (complete_dtor, 1, &parm,
				       tf_warning_or_error);

      /* Operator delete must be called, whether or not the dtor throws.  */
      add_stmt (build2 (TRY_FINALLY_EXPR, void_type_node,
			call_dtor, call_delete));
    }

  /* Return the address of the object.
     ??? How is it useful to return an invalid address?  */
  maybe_return_this ();
}

/* Return name of comdat group for complete and base ctor (or dtor)
   that have the same body.  If dtor is virtual, deleting dtor goes
   into this comdat group as well.  */

static tree
cdtor_comdat_group (tree complete, tree base)
{
  tree complete_name = DECL_ASSEMBLER_NAME (complete);
  tree base_name = DECL_ASSEMBLER_NAME (base);
  char *grp_name;
  const char *p, *q;
  bool diff_seen = false;
  size_t idx;
  gcc_assert (IDENTIFIER_LENGTH (complete_name)
	      == IDENTIFIER_LENGTH (base_name));
  grp_name = XALLOCAVEC (char, IDENTIFIER_LENGTH (complete_name) + 1);
  p = IDENTIFIER_POINTER (complete_name);
  q = IDENTIFIER_POINTER (base_name);
  for (idx = 0; idx < IDENTIFIER_LENGTH (complete_name); idx++)
    if (p[idx] == q[idx])
      grp_name[idx] = p[idx];
    else
      {
	gcc_assert (!diff_seen
		    && idx > 0
		    && (p[idx - 1] == 'C' || p[idx - 1] == 'D'
			|| p[idx - 1] == 'I')
		    && p[idx] == '1'
		    && q[idx] == '2');
	grp_name[idx] = '5';
	diff_seen = true;
      }
  grp_name[idx] = '\0';
  gcc_assert (diff_seen);
  return get_identifier (grp_name);
}

/* Returns true iff we can make the base and complete [cd]tor aliases of
   the same symbol rather than separate functions.  */

static bool
can_alias_cdtor (tree fn)
{
  /* If aliases aren't supported by the assembler, fail.  */
  if (!TARGET_SUPPORTS_ALIASES)
    return false;

  /* We can't use an alias if there are virtual bases.  */
  if (CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn)))
    return false;
  gcc_assert (DECL_MAYBE_IN_CHARGE_CDTOR_P (fn));
  /* Don't use aliases for weak/linkonce definitions unless we can put both
     symbols in the same COMDAT group.  */
  return (DECL_INTERFACE_KNOWN (fn)
	  && (SUPPORTS_ONE_ONLY || !DECL_WEAK (fn))
	  && (!DECL_ONE_ONLY (fn)
	      || (HAVE_COMDAT_GROUP && DECL_WEAK (fn))));
}

/* FN is a [cd]tor, fns is a pointer to an array of length 3.  Fill fns
   with pointers to the base, complete, and deleting variants.  */

static void
populate_clone_array (tree fn, tree *fns)
{
  tree clone;

  fns[0] = NULL_TREE;
  fns[1] = NULL_TREE;
  fns[2] = NULL_TREE;

  FOR_EACH_CLONE (clone, fn)
    if (DECL_NAME (clone) == complete_dtor_identifier
	|| DECL_NAME (clone) == complete_ctor_identifier)
      fns[1] = clone;
    else if (DECL_NAME (clone) == base_dtor_identifier
	     || DECL_NAME (clone) == base_ctor_identifier)
      fns[0] = clone;
    else if (DECL_NAME (clone) == deleting_dtor_identifier)
      fns[2] = clone;
    else
      gcc_unreachable ();
}

/* FN is a constructor or destructor, and there are FUNCTION_DECLs
   cloned from it nearby.  Instead of cloning this body, leave it
   alone and create tiny one-call bodies for the cloned
   FUNCTION_DECLs.  These clones are sibcall candidates, and their
   resulting code will be very thunk-esque.  */

static bool
maybe_thunk_body (tree fn, bool force)
{
  tree bind, block, call, clone, clone_result, fn_parm, fn_parm_typelist;
  tree last_arg, modify, *args;
  int parmno, vtt_parmno, max_parms;
  tree fns[3];

  if (!force && !flag_declone_ctor_dtor)
    return 0;

  /* If function accepts variable arguments, give up.  */
  last_arg = tree_last (TYPE_ARG_TYPES (TREE_TYPE (fn)));
  if (last_arg != void_list_node)
    return 0;

  /* If we got this far, we've decided to turn the clones into thunks.  */

  /* We're going to generate code for fn, so it is no longer "abstract."
     Also make the unified ctor/dtor private to either the translation unit
     (for non-vague linkage ctors) or the COMDAT group (otherwise).  */

  populate_clone_array (fn, fns);

  /* Can happen during error recovery (c++/71464).  */
  if (!fns[0] || !fns[1])
    return 0;

  /* 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))
    {
      TREE_PUBLIC (fn) = false;
      DECL_EXTERNAL (fn) = false;
      DECL_INTERFACE_KNOWN (fn) = true;
    }
  else if (HAVE_COMDAT_GROUP)
    {
      /* At eof, defer creation of mangling aliases temporarily.  */
      bool save_defer_mangling_aliases = defer_mangling_aliases;
      defer_mangling_aliases = true;
      tree comdat_group = cdtor_comdat_group (fns[1], fns[0]);
      defer_mangling_aliases = save_defer_mangling_aliases;
      cgraph_node::get_create (fns[0])->set_comdat_group (comdat_group);
      cgraph_node::get_create (fns[1])->add_to_same_comdat_group
	(cgraph_node::get_create (fns[0]));
      symtab_node::get (fn)->add_to_same_comdat_group
	(symtab_node::get (fns[0]));
      if (fns[2])
	/* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is
	   virtual, it goes into the same comdat group as well.  */
	cgraph_node::get_create (fns[2])->add_to_same_comdat_group
	  (symtab_node::get (fns[0]));
      /* Emit them now that the thunks are same comdat group aliases.  */
      if (!save_defer_mangling_aliases)
	generate_mangling_aliases ();
      TREE_PUBLIC (fn) = false;
      DECL_EXTERNAL (fn) = false;
      DECL_INTERFACE_KNOWN (fn) = true;
      /* function_and_variable_visibility doesn't want !PUBLIC decls to
	 have these flags set.  */
      DECL_WEAK (fn) = false;
      DECL_COMDAT (fn) = false;
    }

  /* Find the vtt_parm, if present.  */
  for (vtt_parmno = -1, parmno = 0, fn_parm = DECL_ARGUMENTS (fn);
       fn_parm;
       ++parmno, fn_parm = TREE_CHAIN (fn_parm))
    {
      if (DECL_ARTIFICIAL (fn_parm)
	  && DECL_NAME (fn_parm) == vtt_parm_identifier)
	{
	  /* Compensate for removed in_charge parameter.  */
	  vtt_parmno = parmno;
	  break;
	}
    }

  /* Allocate an argument buffer for build_cxx_call().
     Make sure it is large enough for any of the clones.  */
  max_parms = 0;
  FOR_EACH_CLONE (clone, fn)
    {
      int length = list_length (DECL_ARGUMENTS (fn));
      if (length > max_parms)
        max_parms = length;
    }
  args = XALLOCAVEC (tree, max_parms);

  /* We know that any clones immediately follow FN in TYPE_FIELDS.  */
  FOR_EACH_CLONE (clone, fn)
    {
      tree clone_parm;

      /* If we've already generated a body for this clone, avoid
	 duplicating it.  (Is it possible for a clone-list to grow after we
	 first see it?)  */
      if (DECL_SAVED_TREE (clone) || TREE_ASM_WRITTEN (clone))
	continue;

      /* Start processing the function.  */
      start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED);

      if (clone == fns[2])
	{
	  for (clone_parm = DECL_ARGUMENTS (clone); clone_parm;
	       clone_parm = TREE_CHAIN (clone_parm))
	    DECL_ABSTRACT_ORIGIN (clone_parm) = NULL_TREE;
	  /* Build the delete destructor by calling complete destructor and
	     delete function.  */
	  build_delete_destructor_body (clone, fns[1]);
	}
      else
	{
	  /* Walk parameter lists together, creating parameter list for
	     call to original function.  */
	  for (parmno = 0,
		 fn_parm = DECL_ARGUMENTS (fn),
		 fn_parm_typelist = TYPE_ARG_TYPES (TREE_TYPE (fn)),
		 clone_parm = DECL_ARGUMENTS (clone);
	       fn_parm;
	       ++parmno,
		 fn_parm = TREE_CHAIN (fn_parm))
	    {
	      if (parmno == vtt_parmno && ! DECL_HAS_VTT_PARM_P (clone))
		{
		  gcc_assert (fn_parm_typelist);
		  /* Clobber argument with formal parameter type.  */
		  args[parmno]
		    = convert (TREE_VALUE (fn_parm_typelist),
			       null_pointer_node);
		}
	      else if (parmno == 1 && DECL_HAS_IN_CHARGE_PARM_P (fn))
		{
		  tree in_charge
		    = copy_node (in_charge_arg_for_name (DECL_NAME (clone)));
		  args[parmno] = in_charge;
		}
	      /* Map other parameters to their equivalents in the cloned
		 function.  */
	      else
		{
		  gcc_assert (clone_parm);
		  DECL_ABSTRACT_ORIGIN (clone_parm) = NULL;
		  args[parmno] = clone_parm;
		  /* Clear TREE_ADDRESSABLE on thunk arguments.  */
		  TREE_ADDRESSABLE (clone_parm) = 0;
		  clone_parm = TREE_CHAIN (clone_parm);
		}
	      if (fn_parm_typelist)
		fn_parm_typelist = TREE_CHAIN (fn_parm_typelist);
	    }

	  /* We built this list backwards; fix now.  */
	  mark_used (fn);
	  call = build_cxx_call (fn, parmno, args, tf_warning_or_error);
	  /* Arguments passed to the thunk by invisible reference should
	     be transmitted to the callee unchanged.  Do not create a
	     temporary and invoke the copy constructor.  The thunking
	     transformation must not introduce any constructor calls.  */
	  CALL_FROM_THUNK_P (call) = 1;
	  block = make_node (BLOCK);
	  if (targetm.cxx.cdtor_returns_this ())
	    {
	      clone_result = DECL_RESULT (clone);
	      modify = build2 (MODIFY_EXPR, TREE_TYPE (clone_result),
			       clone_result, call);
	      modify = build1 (RETURN_EXPR, void_type_node, modify);
	      add_stmt (modify);
	    }
	  else
	    {
	      add_stmt (call);
	    }
	  bind = c_build_bind_expr (DECL_SOURCE_LOCATION (clone),
				    block, cur_stmt_list);
	  DECL_SAVED_TREE (clone) = push_stmt_list ();
	  add_stmt (bind);
	}

      DECL_ABSTRACT_ORIGIN (clone) = NULL;
      expand_or_defer_fn (finish_function (/*inline_p=*/false));
    }
  return 1;
}

/* FN is a function that has a complete body.  Clone the body as
   necessary.  Returns nonzero if there's no longer any need to
   process the main body.  */

bool
maybe_clone_body (tree fn)
{
  tree comdat_group = NULL_TREE;
  tree clone;
  tree fns[3];
  bool first = true;
  int idx;
  bool need_alias = false;

  /* We only clone constructors and destructors.  */
  if (!DECL_MAYBE_IN_CHARGE_CDTOR_P (fn))
    return 0;

  populate_clone_array (fn, fns);

  /* Remember if we can't have multiple clones for some reason.  We need to
     check this before we remap local static initializers in clone_body.  */
  if (!tree_versionable_function_p (fn))
    need_alias = true;

  /* We know that any clones immediately follow FN in the TYPE_FIELDS
     list.  */
  push_to_top_level ();
  for (idx = 0; idx < 3; idx++)
    {
      tree parm;
      tree clone_parm;

      clone = fns[idx];
      if (!clone)
	continue;      

      /* Update CLONE's source position information to match FN's.  */
      DECL_SOURCE_LOCATION (clone) = DECL_SOURCE_LOCATION (fn);
      DECL_DECLARED_INLINE_P (clone) = DECL_DECLARED_INLINE_P (fn);
      DECL_DECLARED_CONSTEXPR_P (clone) = DECL_DECLARED_CONSTEXPR_P (fn);
      DECL_COMDAT (clone) = DECL_COMDAT (fn);
      DECL_WEAK (clone) = DECL_WEAK (fn);

      /* We don't copy the comdat group from fn to clone because the assembler
	 name of fn was corrupted by write_mangled_name by adding *INTERNAL*
	 to it. By doing so, it also corrupted the comdat group. */
      if (DECL_ONE_ONLY (fn))
	cgraph_node::get_create (clone)->set_comdat_group (cxx_comdat_group (clone));
      DECL_USE_TEMPLATE (clone) = DECL_USE_TEMPLATE (fn);
      DECL_EXTERNAL (clone) = DECL_EXTERNAL (fn);
      DECL_INTERFACE_KNOWN (clone) = DECL_INTERFACE_KNOWN (fn);
      DECL_NOT_REALLY_EXTERN (clone) = DECL_NOT_REALLY_EXTERN (fn);
      TREE_PUBLIC (clone) = TREE_PUBLIC (fn);
      DECL_VISIBILITY (clone) = DECL_VISIBILITY (fn);
      DECL_VISIBILITY_SPECIFIED (clone) = DECL_VISIBILITY_SPECIFIED (fn);
      DECL_DLLIMPORT_P (clone) = DECL_DLLIMPORT_P (fn);
      DECL_ATTRIBUTES (clone) = copy_list (DECL_ATTRIBUTES (fn));
      DECL_DISREGARD_INLINE_LIMITS (clone) = DECL_DISREGARD_INLINE_LIMITS (fn);
      set_decl_section_name (clone, fn);

      /* Adjust the parameter names and locations.  */
      parm = DECL_ARGUMENTS (fn);
      clone_parm = DECL_ARGUMENTS (clone);
      /* Update the `this' parameter, which is always first.  */
      update_cloned_parm (parm, clone_parm, first);
      parm = DECL_CHAIN (parm);
      clone_parm = DECL_CHAIN (clone_parm);
      if (DECL_HAS_IN_CHARGE_PARM_P (fn))
	parm = DECL_CHAIN (parm);
      if (DECL_HAS_VTT_PARM_P (fn))
	parm = DECL_CHAIN (parm);
      if (DECL_HAS_VTT_PARM_P (clone))
	clone_parm = DECL_CHAIN (clone_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);
    }

  bool can_alias = can_alias_cdtor (fn);

  /* If we decide to turn clones into thunks, they will branch to fn.
     Must have original function available to call.  */
  if (!can_alias && maybe_thunk_body (fn, need_alias))
    {
      pop_from_top_level ();
      /* We still need to emit the original function.  */
      return 0;
    }

  /* Emit the DWARF1 abstract instance.  */
  (*debug_hooks->deferred_inline_function) (fn);

  /* We know that any clones immediately follow FN in the TYPE_FIELDS. */
  for (idx = 0; idx < 3; idx++)
    {
      tree parm;
      tree clone_parm;
      int parmno;
      hash_map<tree, tree> *decl_map;
      bool alias = false;

      clone = fns[idx];
      if (!clone)
	continue;

      /* Start processing the function.  */
      start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED);

      /* Tell cgraph if both ctors or both dtors are known to have
	 the same body.  */
      if (can_alias
	  && fns[0]
	  && idx == 1
	  && cgraph_node::get_create (fns[0])->create_same_body_alias
	       (clone, fns[0]))
	{
	  alias = true;
	  if (DECL_ONE_ONLY (fns[0]))
	    {
	      /* For comdat base and complete cdtors put them
		 into the same, *[CD]5* comdat group instead of
		 *[CD][12]*.  */
	      comdat_group = cdtor_comdat_group (fns[1], fns[0]);
	      cgraph_node::get_create (fns[0])->set_comdat_group (comdat_group);
	      if (symtab_node::get (clone)->same_comdat_group)
		symtab_node::get (clone)->remove_from_same_comdat_group ();
	      symtab_node::get (clone)->add_to_same_comdat_group
		(symtab_node::get (fns[0]));
	    }
	}

      /* Build the delete destructor by calling complete destructor
         and delete function.  */
      if (idx == 2)
	{
	  build_delete_destructor_body (clone, fns[1]);
	  /* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is
	     virtual, it goes into the same comdat group as well.  */
	  if (comdat_group)
	    cgraph_node::get_create (clone)->add_to_same_comdat_group
	      (symtab_node::get (fns[0]));
	}
      else if (alias)
	/* No need to populate body.  */ ;
      else
	{
	  /* If we can't have multiple copies of FN (say, because there's a
	     static local initialized with the address of a label), we need
	     to use an alias for the complete variant.  */
	  if (idx == 1 && need_alias)
	    {
	      if (DECL_STRUCT_FUNCTION (fn)->cannot_be_copied_set)
		sorry (DECL_STRUCT_FUNCTION (fn)->cannot_be_copied_reason, fn);
	      else
		sorry ("making multiple clones of %qD", fn);
	    }

          /* Remap the parameters.  */
          decl_map = new hash_map<tree, tree>;
          for (parmno = 0,
                parm = DECL_ARGUMENTS (fn),
                clone_parm = DECL_ARGUMENTS (clone);
              parm;
              ++parmno,
                parm = DECL_CHAIN (parm))
            {
              /* Map the in-charge parameter to an appropriate constant.  */
              if (DECL_HAS_IN_CHARGE_PARM_P (fn) && parmno == 1)
                {
                  tree in_charge;
                  in_charge = in_charge_arg_for_name (DECL_NAME (clone));
                  decl_map->put (parm, in_charge);
                }
              else if (DECL_ARTIFICIAL (parm)
                       && DECL_NAME (parm) == vtt_parm_identifier)
                {
                  /* For a subobject constructor or destructor, the next
                     argument is the VTT parameter.  Remap the VTT_PARM
                     from the CLONE to this parameter.  */
                  if (DECL_HAS_VTT_PARM_P (clone))
                    {
                      DECL_ABSTRACT_ORIGIN (clone_parm) = parm;
                      decl_map->put (parm, clone_parm);
                      clone_parm = DECL_CHAIN (clone_parm);
                    }
                  /* Otherwise, map the VTT parameter to `NULL'.  */
                  else
		    {
		      tree t
			= fold_convert (TREE_TYPE (parm), null_pointer_node);
		      decl_map->put (parm, t);
		    }
                }
              /* Map other parameters to their equivalents in the cloned
                 function.  */
              else
                {
		  tree replacement;
		  if (clone_parm)
		    {
		      replacement = clone_parm;
		      clone_parm = DECL_CHAIN (clone_parm);
		    }
		  else
		    {
		      /* Inheriting ctors can omit parameters from the base
			 clone.  Replace them with null lvalues.  */
		      tree reftype = build_reference_type (TREE_TYPE (parm));
		      replacement = fold_convert (reftype, null_pointer_node);
		      replacement = convert_from_reference (replacement);
		    }
                  decl_map->put (parm, replacement);
                }
            }

          if (targetm.cxx.cdtor_returns_this ())
            {
              parm = DECL_RESULT (fn);
              clone_parm = DECL_RESULT (clone);
              decl_map->put (parm, clone_parm);
            }

          /* Clone the body.  */
          clone_body (clone, fn, decl_map);

          /* Clean up.  */
          delete decl_map;
        }

      /* The clone can throw iff the original function can throw.  */
      cp_function_chain->can_throw = !TREE_NOTHROW (fn);

      /* Now, expand this function into RTL, if appropriate.  */
      finish_function (/*inline_p=*/false);
      BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn);
      if (alias)
	{
	  if (expand_or_defer_fn_1 (clone))
	    emit_associated_thunks (clone);
	  /* We didn't generate a body, so remove the empty one.  */
	  DECL_SAVED_TREE (clone) = NULL_TREE;
	}
      else
	expand_or_defer_fn (clone);
      first = false;
    }
  pop_from_top_level ();

  /* We don't need to process the original function any further.  */
  return 1;
}
