summaryrefslogtreecommitdiff
path: root/gcc/cp/tree.c
diff options
context:
space:
mode:
authorzack <zack@138bc75d-0d04-0410-961f-82ee72b054a4>2002-12-16 18:23:00 +0000
committerzack <zack@138bc75d-0d04-0410-961f-82ee72b054a4>2002-12-16 18:23:00 +0000
commit805e22b2051e9c6a75377ea6599654d7415da483 (patch)
treec259697c448b0c6f548f153c48c46a8d7a75970f /gcc/cp/tree.c
parent2c27ce73ee2229b0871c4ccad2342d8a4be85eff (diff)
downloadgcc-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.c56
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 ();