diff options
author | Jakub Jelinek <jakub@redhat.com> | 2009-11-18 10:53:52 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2009-11-18 10:53:52 +0100 |
commit | b25833451bbe9b8a2194598b026cea071f4e9e65 (patch) | |
tree | e08b1ed30e6c41061167a50b2e85f7af35d6e70c /gcc/cp/optimize.c | |
parent | a64333b7ea23dfc1d9d512adfbfec1aeeb9e9366 (diff) | |
download | gcc-b25833451bbe9b8a2194598b026cea071f4e9e65.zip gcc-b25833451bbe9b8a2194598b026cea071f4e9e65.tar.gz gcc-b25833451bbe9b8a2194598b026cea071f4e9e65.tar.bz2 |
re PR c++/3187 (gcc lays down two copies of constructors)
PR c++/3187
* cgraph.h (struct cgraph_node): Add same_body and same_body_alias
fields.
(cgraph_same_body_alias, cgraph_remove_same_body_alias): New
prototypes.
* cgraphunit.c (cgraph_expand_function, cgraph_emit_thunks,
cgraph_materialize_all_clones): Handle same_body aliases.
* cgraph.c (cgraph_allocate_node): New function.
(cgraph_create_node): Use it.
(cgraph_node_for_decl, cgraph_node, cgraph_get_node,
cgraph_node_for_asm, cgraph_remove_node): Handle same_body aliases.
(cgraph_same_body_alias, cgraph_remove_same_body_alias): New
functions.
* lto-cgraph.c (lto_output_node): Stream out same_body aliases.
(input_node): Stream in same_body aliases.
* lto-symtab.c (lto_cgraph_replace_node): Clear node pointers
for same_body aliases.
(lto_symtab_merge_cgraph_nodes_1): Handle same_body aliases.
* cp-tree.h (expand_or_defer_fn_1): New prototype.
* decl2.c (cp_write_global_declarations): Mark as !DECL_EXTERNAL
also all same_body aliases.
* semantics.c (expand_or_defer_fn): Move most of the function
except registering with cgraph to ...
(expand_or_defer_fn_1): ... here. New function.
* optimize.c: Include cgraph.h.
(maybe_clone_body): If in charge parm is not used and both base
and complete clones are created and are not comdat, tell cgraph
they have the same body.
* Make-lang.in (cp/optimize.o): Depend on $(CGRAPH_H).
* g++.dg/abi/mangle26.C: Also match *C2* definition.
* g++.dg/abi/mangle27.C: Likewise.
* g++.dg/abi/mangle28.C: Likewise.
* g++.dg/abi/mangle29.C: Likewise.
From-SVN: r154284
Diffstat (limited to 'gcc/cp/optimize.c')
-rw-r--r-- | gcc/cp/optimize.c | 56 |
1 files changed, 45 insertions, 11 deletions
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c index 662bd4a..c691f0b 100644 --- a/gcc/cp/optimize.c +++ b/gcc/cp/optimize.c @@ -42,6 +42,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-dump.h" #include "gimple.h" #include "tree-iterator.h" +#include "cgraph.h" /* Prototypes. */ @@ -149,8 +150,10 @@ bool maybe_clone_body (tree fn) { tree clone; - tree complete_dtor = NULL_TREE; + tree fns[3]; bool first = true; + bool in_charge_parm_used; + int idx; /* We only clone constructors and destructors. */ if (!DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn) @@ -160,25 +163,40 @@ maybe_clone_body (tree fn) /* Emit the DWARF1 abstract instance. */ (*debug_hooks->deferred_inline_function) (fn); + in_charge_parm_used = CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn)) != NULL; + fns[0] = NULL_TREE; + fns[1] = NULL_TREE; + fns[2] = NULL_TREE; + /* 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; - } + 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 (); /* We know that any clones immediately follow FN in the TYPE_METHODS list. */ push_to_top_level (); - FOR_EACH_CLONE (clone, fn) + for (idx = 0; idx < 3; idx++) { tree parm; tree clone_parm; int parmno; + bool alias = false; struct pointer_map_t *decl_map; + 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); @@ -223,12 +241,25 @@ maybe_clone_body (tree fn) /* 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 (!in_charge_parm_used + && fns[0] + && idx == 1 + && !flag_use_repository + && DECL_INTERFACE_KNOWN (fns[0]) + && !DECL_ONE_ONLY (fns[0]) + && cgraph_same_body_alias (clone, fns[0])) + alias = true; + /* 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); + if (idx == 2) + build_delete_destructor_body (clone, fns[1]); + else if (alias) + /* No need to populate body. */ ; else - { + { /* Remap the parameters. */ decl_map = pointer_map_create (); for (parmno = 0, @@ -291,7 +322,10 @@ maybe_clone_body (tree fn) /* Now, expand this function into RTL, if appropriate. */ finish_function (0); BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn); - expand_or_defer_fn (clone); + if (alias) + expand_or_defer_fn_1 (clone); + else + expand_or_defer_fn (clone); first = false; } pop_from_top_level (); |