diff options
author | zack <zack@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-12-16 18:23:00 +0000 |
---|---|---|
committer | zack <zack@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-12-16 18:23:00 +0000 |
commit | 805e22b2051e9c6a75377ea6599654d7415da483 (patch) | |
tree | c259697c448b0c6f548f153c48c46a8d7a75970f /gcc/cp/tree.c | |
parent | 2c27ce73ee2229b0871c4ccad2342d8a4be85eff (diff) | |
download | gcc-805e22b2051e9c6a75377ea6599654d7415da483.tar.gz |
Merge basic-improvements-branch to trunk
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@60174 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp/tree.c')
-rw-r--r-- | gcc/cp/tree.c | 56 |
1 files changed, 34 insertions, 22 deletions
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 6c313eba4d8..4c328394114 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -22,6 +22,8 @@ Boston, MA 02111-1307, USA. */ #include "config.h" #include "system.h" +#include "coretypes.h" +#include "tm.h" #include "tree.h" #include "cp-tree.h" #include "flags.h" @@ -299,6 +301,7 @@ build_cplus_new (type, init) tree fn; tree slot; tree rval; + int is_ctor; /* Make sure that we're not trying to create an instance of an abstract class. */ @@ -307,6 +310,11 @@ build_cplus_new (type, init) if (TREE_CODE (init) != CALL_EXPR && TREE_CODE (init) != AGGR_INIT_EXPR) return convert (type, init); + fn = TREE_OPERAND (init, 0); + is_ctor = (TREE_CODE (fn) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL + && DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0))); + slot = build (VAR_DECL, type); DECL_ARTIFICIAL (slot) = 1; DECL_CONTEXT (slot) = current_function_decl; @@ -320,13 +328,18 @@ build_cplus_new (type, init) replaces every AGGR_INIT_EXPR with a copy that uses a fresh temporary slot. Then, expand_expr builds up a call-expression using the new slot. */ - fn = TREE_OPERAND (init, 0); - rval = build (AGGR_INIT_EXPR, type, fn, TREE_OPERAND (init, 1), slot); - TREE_SIDE_EFFECTS (rval) = 1; - AGGR_INIT_VIA_CTOR_P (rval) - = (TREE_CODE (fn) == ADDR_EXPR - && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL - && DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0))); + + /* If we don't need to use a constructor to create an object of this + type, don't mess with AGGR_INIT_EXPR. */ + if (is_ctor || TREE_ADDRESSABLE (type)) + { + rval = build (AGGR_INIT_EXPR, type, fn, TREE_OPERAND (init, 1), slot); + TREE_SIDE_EFFECTS (rval) = 1; + AGGR_INIT_VIA_CTOR_P (rval) = is_ctor; + } + else + rval = init; + rval = build_target_expr (slot, rval); return rval; @@ -2311,33 +2324,32 @@ cp_auto_var_in_fn_p (var, fn) tree cp_copy_res_decl_for_inlining (result, fn, caller, decl_map_, - need_decl, target_exprs) + need_decl, return_slot_addr) tree result, fn, caller; void *decl_map_; int *need_decl; - void *target_exprs; + tree return_slot_addr; { splay_tree decl_map = (splay_tree)decl_map_; - varray_type *texps = (varray_type *)target_exprs; tree var; - int aggregate_return_p; - - /* Figure out whether or not FN returns an aggregate. */ - aggregate_return_p = IS_AGGR_TYPE (TREE_TYPE (result)); - *need_decl = ! aggregate_return_p; - /* If FN returns an aggregate then the caller will always create the - temporary (using a TARGET_EXPR) and the call will be the - initializing expression for the TARGET_EXPR. If we were just to + /* If FN returns an aggregate then the caller will always pass the + address of the return slot explicitly. If we were just to create a new VAR_DECL here, then the result of this function would be copied (bitwise) into the variable initialized by the TARGET_EXPR. That's incorrect, so we must transform any references to the RESULT into references to the target. */ - if (aggregate_return_p) + + /* We should have an explicit return slot iff the return type is + TREE_ADDRESSABLE. See simplify_aggr_init_expr. */ + if (TREE_ADDRESSABLE (TREE_TYPE (result)) + != (return_slot_addr != NULL_TREE)) + abort (); + + *need_decl = !return_slot_addr; + if (return_slot_addr) { - if (VARRAY_ACTIVE_SIZE (*texps) == 0) - abort (); - var = TREE_OPERAND (VARRAY_TOP_TREE (*texps), 0); + var = build_indirect_ref (return_slot_addr, ""); if (! same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (var), TREE_TYPE (result))) abort (); |