diff options
author | carrot <carrot@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-09-13 15:06:47 +0000 |
---|---|---|
committer | carrot <carrot@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-09-13 15:06:47 +0000 |
commit | e2932b0d6cab74ef56599547a959a7adc4e8cb47 (patch) | |
tree | c33161e4390d228cbf153604c37cea1ed8022aba | |
parent | a4f7c8f77479aa46ba7962e91b975c0492386a6d (diff) | |
download | gcc-e2932b0d6cab74ef56599547a959a7adc4e8cb47.tar.gz |
* cp/optimize.c (build_delete_destructor_body): New function.
(maybe_clone_body): Call build_delete_destructor_body for
deleting destructor.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@151673 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/optimize.c | 161 |
2 files changed, 114 insertions, 54 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d98d4154af8..d6befec6499 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2009-09-13 Wei Guozhi <carrot@google.com> + + PR c++/3187 + * cp/optimize.c (build_delete_destructor_body): New function. + (maybe_clone_body): Call build_delete_destructor_body for + deleting destructor. + 2009-09-10 Jason Merrill <jason@redhat.com> * repo.c (extract_string, get_base_filename, init_repo): constify. diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c index c9d6cebb817..abd38f8666c 100644 --- a/gcc/cp/optimize.c +++ b/gcc/cp/optimize.c @@ -1,5 +1,5 @@ /* Perform optimizations on tree structure. - Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2007, 2008 + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc. Written by Mark Michell (mark@codesourcery.com). @@ -106,6 +106,41 @@ clone_body (tree clone, tree fn, void *arg_map) 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 call_dtor, call_delete; + tree parm = DECL_ARGUMENTS (delete_dtor); + tree virtual_size = cxx_sizeof (current_class_type); + + /* Call the corresponding complete destructor. */ + gcc_assert (complete_dtor); + call_dtor = build_cxx_call (complete_dtor, 1, &parm); + add_stmt (call_dtor); + + add_stmt (build_stmt (0, LABEL_EXPR, cdtor_label)); + + /* Call the delete function. */ + call_delete = build_op_delete_call (DELETE_EXPR, current_class_ptr, + virtual_size, + /*global_p=*/false, + /*placement=*/NULL_TREE, + /*alloc_fn=*/NULL_TREE); + add_stmt (call_delete); + + /* Return the address of the object. */ + if (targetm.cxx.cdtor_returns_this ()) + { + tree val = DECL_ARGUMENTS (delete_dtor); + val = build2 (MODIFY_EXPR, TREE_TYPE (val), + DECL_RESULT (delete_dtor), val); + add_stmt (build_stmt (0, RETURN_EXPR, val)); + } +} + /* 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. */ @@ -114,6 +149,7 @@ bool maybe_clone_body (tree fn) { tree clone; + tree complete_dtor = NULL_TREE; bool first = true; /* We only clone constructors and destructors. */ @@ -124,6 +160,15 @@ maybe_clone_body (tree fn) /* Emit the DWARF1 abstract instance. */ (*debug_hooks->deferred_inline_function) (fn); + /* Look for the complete destructor which may be used to build the + delete destructor. */ + FOR_EACH_CLONE (clone, fn) + if (DECL_NAME (clone) == complete_dtor_identifier) + { + complete_dtor = clone; + break; + } + /* We know that any clones immediately follow FN in the TYPE_METHODS list. */ push_to_top_level (); @@ -176,59 +221,67 @@ maybe_clone_body (tree fn) /* Start processing the function. */ start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED); - /* Remap the parameters. */ - decl_map = pointer_map_create (); - for (parmno = 0, - parm = DECL_ARGUMENTS (fn), - clone_parm = DECL_ARGUMENTS (clone); - parm; - ++parmno, - parm = TREE_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)); - *pointer_map_insert (decl_map, 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; - *pointer_map_insert (decl_map, parm) = clone_parm; - clone_parm = TREE_CHAIN (clone_parm); - } - /* Otherwise, map the VTT parameter to `NULL'. */ - else - *pointer_map_insert (decl_map, parm) - = fold_convert (TREE_TYPE (parm), null_pointer_node); - } - /* Map other parameters to their equivalents in the cloned - function. */ - else - { - *pointer_map_insert (decl_map, parm) = clone_parm; - clone_parm = TREE_CHAIN (clone_parm); - } - } - - if (targetm.cxx.cdtor_returns_this ()) - { - parm = DECL_RESULT (fn); - clone_parm = DECL_RESULT (clone); - *pointer_map_insert (decl_map, parm) = clone_parm; - } - /* Clone the body. */ - clone_body (clone, fn, decl_map); - - /* Clean up. */ - pointer_map_destroy (decl_map); + /* Build the delete destructor by calling complete destructor + and delete function. */ + if (DECL_NAME (clone) == deleting_dtor_identifier) + build_delete_destructor_body (clone, complete_dtor); + else + { + /* Remap the parameters. */ + decl_map = pointer_map_create (); + for (parmno = 0, + parm = DECL_ARGUMENTS (fn), + clone_parm = DECL_ARGUMENTS (clone); + parm; + ++parmno, + parm = TREE_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)); + *pointer_map_insert (decl_map, 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; + *pointer_map_insert (decl_map, parm) = clone_parm; + clone_parm = TREE_CHAIN (clone_parm); + } + /* Otherwise, map the VTT parameter to `NULL'. */ + else + *pointer_map_insert (decl_map, parm) + = fold_convert (TREE_TYPE (parm), null_pointer_node); + } + /* Map other parameters to their equivalents in the cloned + function. */ + else + { + *pointer_map_insert (decl_map, parm) = clone_parm; + clone_parm = TREE_CHAIN (clone_parm); + } + } + + if (targetm.cxx.cdtor_returns_this ()) + { + parm = DECL_RESULT (fn); + clone_parm = DECL_RESULT (clone); + *pointer_map_insert (decl_map, parm) = clone_parm; + } + + /* Clone the body. */ + clone_body (clone, fn, decl_map); + + /* Clean up. */ + pointer_map_destroy (decl_map); + } /* The clone can throw iff the original function can throw. */ cp_function_chain->can_throw = !TREE_NOTHROW (fn); |