aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/optimize.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2009-11-18 10:53:52 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2009-11-18 10:53:52 +0100
commitb25833451bbe9b8a2194598b026cea071f4e9e65 (patch)
treee08b1ed30e6c41061167a50b2e85f7af35d6e70c /gcc/cp/optimize.c
parenta64333b7ea23dfc1d9d512adfbfec1aeeb9e9366 (diff)
downloadgcc-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.c56
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 ();