/* Handle initialization things in C++.
- Copyright (C) 1987, 89, 92-98, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1987, 89, 92-98, 1999, 2000 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
#include "toplev.h"
#include "ggc.h"
-static void expand_aggr_vbase_init_1 PROTO((tree, tree, tree, tree));
-static void construct_virtual_bases PROTO((tree, tree, tree, tree, tree));
-static void expand_aggr_init_1 PROTO((tree, tree, tree, tree, int));
-static void expand_default_init PROTO((tree, tree, tree, tree, int));
-static tree build_vec_delete_1 PROTO((tree, tree, tree, tree, tree,
- int));
-static void perform_member_init PROTO((tree, tree, tree, int));
-static void sort_base_init PROTO((tree, tree *, tree *));
-static tree build_builtin_delete_call PROTO((tree));
-static int member_init_ok_or_else PROTO((tree, tree, const char *));
-static void expand_virtual_init PROTO((tree, tree));
-static tree sort_member_init PROTO((tree));
-static tree initializing_context PROTO((tree));
-static tree build_java_class_ref PROTO((tree));
-static void expand_cleanup_for_base PROTO((tree, tree));
-static tree get_temp_regvar PROTO((tree, tree));
+static void expand_aggr_vbase_init_1 PARAMS ((tree, tree, tree, tree));
+static void construct_virtual_bases PARAMS ((tree, tree, tree, tree, tree));
+static void expand_aggr_init_1 PARAMS ((tree, tree, tree, tree, int));
+static void expand_default_init PARAMS ((tree, tree, tree, tree, int));
+static tree build_vec_delete_1 PARAMS ((tree, tree, tree, tree, int));
+static void perform_member_init PARAMS ((tree, tree, tree, int));
+static void sort_base_init PARAMS ((tree, tree *, tree *));
+static tree build_builtin_delete_call PARAMS ((tree));
+static int member_init_ok_or_else PARAMS ((tree, tree, const char *));
+static void expand_virtual_init PARAMS ((tree, tree));
+static tree sort_member_init PARAMS ((tree));
+static tree initializing_context PARAMS ((tree));
+static tree build_java_class_ref PARAMS ((tree));
+static void expand_cleanup_for_base PARAMS ((tree, tree));
+static tree get_temp_regvar PARAMS ((tree, tree));
+static tree dfs_initialize_vtbl_ptrs PARAMS ((tree, void *));
/* Set up local variable for this file. MUST BE CALLED AFTER
INIT_DECL_PROCESSING. */
/* Define the structure that holds header information for
arrays allocated via operator new. */
- BI_header_type = make_lang_type (RECORD_TYPE);
+ BI_header_type = make_aggr_type (RECORD_TYPE);
nelts_identifier = get_identifier ("nelts");
fields[0] = build_lang_decl (FIELD_DECL, nelts_identifier, sizetype);
+
+ /* Use the biggest alignment supported by the target to prevent operator
+ new from returning misaligned pointers. */
+ TYPE_ALIGN (BI_header_type) = BIGGEST_ALIGNMENT;
finish_builtin_type (BI_header_type, "__new_cookie", fields,
- 0, double_type_node);
+ 0, BI_header_type);
BI_header_size = size_in_bytes (BI_header_type);
ggc_add_tree_root (&BI_header_type, 1);
ggc_add_tree_root (&BI_header_size, 1);
}
-/* Subroutine of emit_base_init. For BINFO, initialize all the
- virtual function table pointers, except those that come from
- virtual base classes. Initialize binfo's vtable pointer, if
- INIT_SELF is true. CAN_ELIDE is true when we know that all virtual
- function table pointers in all bases have been initialized already,
- probably because their constructors have just be run. ADDR is the
- pointer to the object whos vtables we are going to initialize.
+/* Called from initialize_vtbl_ptrs via dfs_walk. */
- REAL_BINFO is usually the same as BINFO, except when addr is not of
- pointer to the type of the real derived type that we want to
- initialize for. This is the case when addr is a pointer to a sub
- object of a complete object, and we only want to do part of the
- complete object's initialization of vtable pointers. This is done
- for all virtual table pointers in virtual base classes. REAL_BINFO
- is used to find the BINFO_VTABLE that we initialize with. BINFO is
- used for conversions of addr to subobjects.
+static tree
+dfs_initialize_vtbl_ptrs (binfo, data)
+ tree binfo;
+ void *data;
+{
+ if (!BINFO_PRIMARY_MARKED_P (binfo)
+ && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
+ {
+ tree base_ptr = TREE_VALUE ((tree) data);
- BINFO_TYPE (real_binfo) must be BINFO_TYPE (binfo).
+ if (TREE_VIA_VIRTUAL (binfo))
+ base_ptr = convert_pointer_to_vbase (BINFO_TYPE (binfo),
+ base_ptr);
+ else
+ base_ptr
+ = build_vbase_path (PLUS_EXPR,
+ build_pointer_type (BINFO_TYPE (binfo)),
+ base_ptr,
+ binfo,
+ /*nonnull=*/1);
- Relies upon binfo being inside TYPE_BINFO (TREE_TYPE (TREE_TYPE
- (addr))). */
+ expand_virtual_init (binfo, base_ptr);
+ }
+
+ SET_BINFO_MARKED (binfo);
+
+ return NULL_TREE;
+}
+
+/* Initialize all the vtable pointers for the hierarchy dominated by
+ TYPE. */
void
-expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr)
- tree real_binfo, binfo, addr;
- int init_self, can_elide;
+initialize_vtbl_ptrs (type, addr)
+ tree type;
+ tree addr;
{
- tree real_binfos = BINFO_BASETYPES (real_binfo);
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = real_binfos ? TREE_VEC_LENGTH (real_binfos) : 0;
-
- push_momentary ();
- for (i = 0; i < n_baselinks; i++)
- {
- tree real_base_binfo = TREE_VEC_ELT (real_binfos, i);
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- int is_not_base_vtable
- = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (real_binfo));
- if (! TREE_VIA_VIRTUAL (real_base_binfo))
- expand_direct_vtbls_init (real_base_binfo, base_binfo,
- is_not_base_vtable, can_elide, addr);
- }
-#if 0
- /* Before turning this on, make sure it is correct. */
- if (can_elide && ! BINFO_MODIFIED (binfo))
- return;
-#endif
- /* Should we use something besides CLASSTYPE_VFIELDS? */
- if (init_self && CLASSTYPE_VFIELDS (BINFO_TYPE (real_binfo)))
- {
- tree base_ptr = convert_pointer_to_real (binfo, addr);
- expand_virtual_init (real_binfo, base_ptr);
- }
- pop_momentary ();
+ tree list = build_tree_list (type, addr);
+
+ /* Walk through the hierarchy, initializing the vptr in each base
+ class. We do these in pre-order because under the new ABI we
+ can't find the virtual bases for a class until we've initialized
+ the vtbl for that class. */
+ dfs_walk_real (TYPE_BINFO (type), dfs_initialize_vtbl_ptrs,
+ NULL, dfs_unmarked_real_bases_queue_p, list);
+ dfs_walk (TYPE_BINFO (type), dfs_unmark,
+ dfs_marked_real_bases_queue_p, type);
+ if (TYPE_USES_VIRTUAL_BASECLASSES (type))
+ expand_indirect_vtbls_init (TYPE_BINFO (type), addr);
}
+
\f
/* 348 - 351 */
/* Subroutine of emit_base_init. */
decl = build_component_ref (current_class_ref, name, NULL_TREE, explicit);
+ if (decl == error_mark_node)
+ return;
+
/* Deal with this here, as we will get confused if we try to call the
assignment op for an anonymous union. This can happen in a
synthesized copy constructor. */
if (ANON_AGGR_TYPE_P (type))
{
init = build (INIT_EXPR, type, decl, TREE_VALUE (init));
- TREE_SIDE_EFFECTS (init) = 1;
finish_expr_stmt (init);
}
else if (TYPE_NEEDS_CONSTRUCTING (type)
/* Since `init' is already a TREE_LIST on the current_member_init_list,
only build it into one if we aren't already a list. */
if (init != NULL_TREE && TREE_CODE (init) != TREE_LIST)
- init = build_expr_list (NULL_TREE, init);
+ init = build_tree_list (NULL_TREE, init);
if (explicit
&& TREE_CODE (type) == ARRAY_TYPE
this constructor is the top-level constructor called. */
if (TREE_VIA_VIRTUAL (binfo))
{
- tree v = CLASSTYPE_VBASECLASSES (t);
- while (BINFO_TYPE (v) != BINFO_TYPE (binfo))
- v = TREE_CHAIN (v);
-
+ tree v = BINFO_FOR_VBASE (BINFO_TYPE (binfo), t);
vbases = tree_cons (v, TREE_VALUE (x), vbases);
continue;
}
Note that emit_base_init does *not* initialize virtual base
classes. That is done specially, elsewhere. */
-void
+tree
emit_base_init (t)
tree t;
{
rbase_init_list = TREE_CHAIN (rbase_init_list);
}
- /* Initialize all the virtual function table fields that
- do come from virtual base classes. */
- if (TYPE_USES_VIRTUAL_BASECLASSES (t))
- expand_indirect_vtbls_init (t_binfo, current_class_ref, current_class_ptr);
-
- /* Initialize all the virtual function table fields that
- do not come from virtual base classes. */
- expand_direct_vtbls_init (t_binfo, t_binfo, 1, 1, current_class_ptr);
+ /* Initialize the vtable pointers for the class. */
+ initialize_vtbl_ptrs (t, current_class_ptr);
for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member))
{
mem_init_list = TREE_CHAIN (mem_init_list);
}
- base_init_expr = finish_init_stmts (stmt_expr, compound_stmt);
-
/* All the implicit try blocks we built up will be zapped
when we come to a real binding contour boundary. */
+ return finish_init_stmts (stmt_expr, compound_stmt);
}
/* Check that all fields are properly initialized after
tree vtbl, vtbl_ptr;
tree vtype, vtype_binfo;
- /* This code is crusty. Should be simple, like:
- vtbl = BINFO_VTABLE (binfo);
- */
- vtype = DECL_CONTEXT (CLASSTYPE_VFIELD (type));
+ /* Compute the location of the vtable. */
+ vtype = DECL_CONTEXT (TYPE_VFIELD (type));
vtype_binfo = get_binfo (vtype, TREE_TYPE (TREE_TYPE (decl)), 0);
- vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (CLASSTYPE_VFIELD (type)), binfo));
- assemble_external (vtbl);
- TREE_USED (vtbl) = 1;
- vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
+ vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (TYPE_VFIELD (type)), binfo));
+
+ if (TREE_CODE (vtbl) == VAR_DECL)
+ {
+ assemble_external (vtbl);
+ TREE_USED (vtbl) = 1;
+ vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
+ }
+ else
+ /* Under the new ABI, secondary vtables are stored with the
+ primary vtable. So, the BINFO_VTABLE may be an expression for
+ computing the secondary vtable, rather than the secondary
+ vtable itself. */
+ my_friendly_assert (merge_primary_and_secondary_vtables_p (),
+ 20000220);
+
+ /* Under the new ABI, we need to point into the middle of the
+ vtable. */
+ if (vbase_offsets_in_vtable_p ())
+ vtbl = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl,
+ size_extra_vtbl_entries (binfo));
+
+ /* Compute the location of the vtpr. */
decl = convert_pointer_to_real (vtype_binfo, decl);
vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, NULL_PTR), vtype);
if (vtbl_ptr == error_mark_node)
return;
- /* Have to convert VTBL since array sizes may be different. */
+ /* Assign the vtable to the vptr. */
vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0);
finish_expr_stmt (build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl));
}
/* Call the destructor. */
expr = (build_scoped_method_call
(current_class_ref, binfo, dtor_identifier,
- build_expr_list (NULL_TREE, integer_zero_node)));
+ build_tree_list (NULL_TREE, integer_zero_node)));
if (flag)
expr = fold (build (COND_EXPR, void_type_node,
truthvalue_conversion (flag),
/* Construct the virtual base-classes of THIS_REF (whose address is
THIS_PTR). The object has the indicated TYPE. The construction
actually takes place only if FLAG is non-zero. INIT_LIST is list
- of initialization for constructor to perform. */
+ of initializations for constructors to perform. */
static void
construct_virtual_bases (type, this_ref, this_ptr, init_list, flag)
tree flag;
{
tree vbases;
- tree result;
- tree if_stmt;
/* If there are no virtual baseclasses, we shouldn't even be here. */
my_friendly_assert (TYPE_USES_VIRTUAL_BASECLASSES (type), 19990621);
/* First set the pointers in our object that tell us where to find
our virtual baseclasses. */
- if_stmt = begin_if_stmt ();
- finish_if_stmt_cond (flag, if_stmt);
- result = init_vbase_pointers (type, this_ptr);
- /* The RESULT will contain entries on the momentary obstack. They
- must live until the end of this function; we use them in the loop
- below. */
- push_momentary ();
- if (result)
- finish_expr_stmt (build_compound_expr (result));
- finish_then_clause (if_stmt);
- finish_if_stmt ();
+ if (!vbase_offsets_in_vtable_p ())
+ {
+ tree if_stmt;
+ tree result;
+
+ if_stmt = begin_if_stmt ();
+ finish_if_stmt_cond (flag, if_stmt);
+ result = init_vbase_pointers (type, this_ptr);
+ if (result)
+ finish_expr_stmt (build_compound_expr (result));
+ finish_then_clause (if_stmt);
+ finish_if_stmt ();
+ }
/* Now, run through the baseclasses, initializing each. */
for (vbases = CLASSTYPE_VBASECLASSES (type); vbases;
vbases = TREE_CHAIN (vbases))
{
- tree tmp = purpose_member (vbases, result);
tree inner_if_stmt;
tree compound_stmt;
+ tree exp;
/* If there are virtual base classes with destructors, we need to
emit cleanups to destroy them if an exception is thrown during
inner_if_stmt = begin_if_stmt ();
finish_if_stmt_cond (flag, inner_if_stmt);
compound_stmt = begin_compound_stmt (/*has_no_scope=*/1);
- expand_aggr_vbase_init_1 (vbases, this_ref,
- TREE_OPERAND (TREE_VALUE (tmp), 0),
- init_list);
+
+ /* Compute the location of the virtual base. If we're
+ constructing virtual bases, then we must be the most derived
+ class. Therefore, we don't have to look up the virtual base;
+ we already know where it is. */
+ exp = build (PLUS_EXPR,
+ TREE_TYPE (this_ptr),
+ this_ptr,
+ BINFO_OFFSET (vbases));
+ exp = build1 (NOP_EXPR,
+ build_pointer_type (BINFO_TYPE (vbases)),
+ exp);
+
+ expand_aggr_vbase_init_1 (vbases, this_ref, exp, init_list);
finish_compound_stmt (/*has_no_scope=*/1, compound_stmt);
- finish_then_clause (if_stmt);
+ finish_then_clause (inner_if_stmt);
finish_if_stmt ();
expand_cleanup_for_base (vbases, flag);
}
-
- /* Undo the call to push_momentary above. */
- pop_momentary ();
}
/* Find the context in which this FIELD can be initialized. */
&& ! current_template_parms
&& ! vec_binfo_member (basetype,
TYPE_BINFO_BASETYPES (type))
- && ! binfo_member (basetype, CLASSTYPE_VBASECLASSES (type)))
+ && ! BINFO_FOR_VBASE (basetype, type))
{
if (IDENTIFIER_CLASS_VALUE (name))
goto try_member;
tree *stmt_expr_p;
tree *compound_stmt_p;
{
- push_momentary ();
*stmt_expr_p = begin_stmt_expr ();
*compound_stmt_p = begin_compound_stmt (/*has_no_scope=*/1);
}
tree stmt_expr;
tree compound_stmt;
{
- pop_momentary ();
- stmt_expr
- = finish_stmt_expr (stmt_expr,
- finish_compound_stmt (/*has_no_scope=*/1,
- compound_stmt));
+ finish_compound_stmt (/*has_no_scope=*/1, compound_stmt);
+ stmt_expr = finish_stmt_expr (stmt_expr);
/* To avoid spurious warnings about unused values, we set
TREE_USED. */
If `init' is a CONSTRUCTOR, then we emit a warning message,
explaining that such initializations are invalid.
- ALIAS_THIS is nonzero iff we are initializing something which is
- essentially an alias for current_class_ref. In this case, the base
- constructor may move it on us, and we must keep track of such
- deviations.
-
If INIT resolves to a CALL_EXPR which happens to return
something of the type we are looking for, then we know
that we can safely use that call to perform the
init = TREE_VALUE (parms);
}
else
- parms = build_expr_list (NULL_TREE, init);
+ parms = build_tree_list (NULL_TREE, init);
if (TYPE_USES_VIRTUAL_BASECLASSES (type))
{
from TRUE_EXP. In constructors, we don't know anything about
the value being initialized.
- ALIAS_THIS serves the same purpose it serves for expand_aggr_init.
-
FLAGS is just passes to `build_method_call'. See that function for
its description. */
expand_decl_init (exp);
}
else
- {
- tree t = build (INIT_EXPR, type, exp, init);
- TREE_SIDE_EFFECTS (t) = 1;
- finish_expr_stmt (t);
- }
+ finish_expr_stmt (build (INIT_EXPR, type, exp, init));
return;
}
else
return NULL_TREE;
}
-
+
\f
/* This code could just as well go in `class.c', but is placed here for
modularity. */
/* The code in instantiate_type which will process this
expects to encounter OVERLOADs, not raw functions. */
t = ovl_cons (t, NULL_TREE);
-
+
return build (OFFSET_REF,
unknown_type_node,
decl,
basetype = DECL_CONTEXT (member);
base = current_class_ptr;
-
+
if (get_base_distance (basetype, TREE_TYPE (TREE_TYPE (base)), 0, &basetype_path) < 0)
{
error_not_base_type (basetype, TREE_TYPE (TREE_TYPE (base)));
basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (TREE_TYPE (member)));
addr = convert_pointer_to (basetype, addr);
member = cp_convert (ptrdiff_type_node, member);
-
+
/* Pointer to data members are offset by one, so that a null
pointer with a real value of 0 is distinguishable from an
offset of the first member of a structure. */
{
mark_used (global_delete_fndecl);
return build_call (global_delete_fndecl,
- void_type_node, build_expr_list (NULL_TREE, addr));
+ void_type_node, build_tree_list (NULL_TREE, addr));
}
\f
/* Generate a C++ "new" expression. DECL is either a TREE_LIST
tree nelts = NULL_TREE, t;
int has_array = 0;
- tree pending_sizes = NULL_TREE;
-
if (decl == error_mark_node)
return error_mark_node;
{
tree absdcl = TREE_VALUE (decl);
tree last_absdcl = NULL_TREE;
- int old_immediate_size_expand = 0;
if (current_function_decl
&& DECL_CONSTRUCTOR_P (current_function_decl))
- {
- old_immediate_size_expand = immediate_size_expand;
- immediate_size_expand = 0;
- }
+ my_friendly_assert (immediate_size_expand == 0, 19990926);
nelts = integer_one_node;
type = groktypename (decl);
if (! type || type == error_mark_node)
- {
- immediate_size_expand = old_immediate_size_expand;
- return error_mark_node;
- }
-
- if (current_function_decl
- && DECL_CONSTRUCTOR_P (current_function_decl))
- {
- pending_sizes = get_pending_sizes ();
- immediate_size_expand = old_immediate_size_expand;
- }
+ return error_mark_node;
}
else if (TREE_CODE (decl) == IDENTIFIER_NODE)
{
if (processing_template_decl)
{
if (has_array)
- t = min_tree_cons (min_tree_cons (NULL_TREE, type, NULL_TREE),
- build_min_nt (ARRAY_REF, NULL_TREE, nelts),
- NULL_TREE);
+ t = tree_cons (tree_cons (NULL_TREE, type, NULL_TREE),
+ build_min_nt (ARRAY_REF, NULL_TREE, nelts),
+ NULL_TREE);
else
t = type;
rval = build (NEW_EXPR, build_pointer_type (type), placement, t, init);
NEW_EXPR_USE_GLOBAL (rval) = use_global_new;
TREE_SIDE_EFFECTS (rval) = 1;
+ rval = build_new_1 (rval);
+ if (rval == error_mark_node)
+ return error_mark_node;
/* Wrap it in a NOP_EXPR so warn_if_unused_value doesn't complain. */
rval = build1 (NOP_EXPR, TREE_TYPE (rval), rval);
TREE_NO_UNUSED_WARNING (rval) = 1;
- if (pending_sizes)
- rval = build_compound_expr (chainon (pending_sizes,
- build_expr_list (NULL_TREE, rval)));
-
return rval;
}
class_decl = IDENTIFIER_GLOBAL_VALUE (name);
if (class_decl == NULL_TREE)
{
- push_permanent_obstack ();
class_decl = build_decl (VAR_DECL, name, TREE_TYPE (jclass_node));
TREE_STATIC (class_decl) = 1;
DECL_EXTERNAL (class_decl) = 1;
DECL_IGNORED_P (class_decl) = 1;
pushdecl_top_level (class_decl);
make_decl_rtl (class_decl, NULL_PTR, 1);
- pop_obstacks ();
}
return class_decl;
}
&& TREE_TYPE (TREE_VALUE (placement)) == ptr_type_node));
if (use_cookie)
- {
- tree extra = BI_header_size;
-
- size = size_binop (PLUS_EXPR, size, extra);
- }
+ size = size_binop (PLUS_EXPR, size, BI_header_size);
if (has_array)
{
/* Allocate the object. */
- if (! has_array && ! placement && flag_this_is_variable > 0
- && TYPE_NEEDS_CONSTRUCTING (true_type) && init != void_type_node)
- {
- if (init == NULL_TREE || TREE_CODE (init) == TREE_LIST)
- rval = NULL_TREE;
- else
- {
- error ("constructors take parameter lists");
- return error_mark_node;
- }
- }
- else if (! placement && TYPE_FOR_JAVA (true_type))
+ if (! placement && TYPE_FOR_JAVA (true_type))
{
tree class_addr, alloc_decl;
tree class_decl = build_java_class_ref (true_type);
}
else
{
- int susp = 0;
-
- if (flag_exceptions)
- /* We will use RVAL when generating an exception handler for
- this new-expression, so we must save it. */
- susp = suspend_momentary ();
-
rval = build_op_new_call
(code, true_type, tree_cons (NULL_TREE, size, placement),
LOOKUP_NORMAL | (use_global_new * LOOKUP_GLOBAL));
rval = cp_convert (build_pointer_type (true_type), rval);
-
- if (flag_exceptions)
- resume_momentary (susp);
}
/* unless an allocation function is declared with an empty excep-
build_component_ref (cookie, nelts_identifier,
NULL_TREE, 0),
nelts);
- TREE_SIDE_EFFECTS (exp1) = 1;
rval = cp_convert (build_pointer_type (true_type), rval);
rval = build_compound_expr
(tree_cons (NULL_TREE, exp1,
- build_expr_list (NULL_TREE, rval)));
+ build_tree_list (NULL_TREE, rval)));
}
if (rval == error_mark_node)
TREE_HAS_CONSTRUCTOR (rval) = 1;
}
else
- rval = build (VEC_INIT_EXPR, TREE_TYPE (rval),
- save_expr (rval), init, nelts);
+ rval = (build_vec_init
+ (NULL_TREE,
+ save_expr (rval),
+ build_binary_op (MINUS_EXPR, nelts, integer_one_node),
+ init,
+ /*from_array=*/0));
/* If any part of the object initialization terminates by throwing an
exception and a suitable deallocation function can be found, the
tree cleanup, fn = NULL_TREE;
int flags = LOOKUP_NORMAL | (use_global_new * LOOKUP_GLOBAL);
- /* All cleanups must last longer than normal. */
- int yes = suspend_momentary ();
-
/* The Standard is unclear here, but the right thing to do
is to use the same method for finding deallocation
functions that we use for finding allocation functions. */
cleanup = build_op_delete_call (dcode, alloc_node, size, flags, fn);
- resume_momentary (yes);
-
/* Ack! First we allocate the memory. Then we set our sentry
variable to true, and expand a cleanup that deletes the memory
if sentry is true. Then we run the constructor and store the
begin = get_target_expr (boolean_true_node);
sentry = TREE_OPERAND (begin, 0);
- yes = suspend_momentary ();
TREE_OPERAND (begin, 2)
= build (COND_EXPR, void_type_node, sentry,
cleanup, void_zero_node);
- resume_momentary (yes);
rval = get_target_expr (rval);
end = build (MODIFY_EXPR, TREE_TYPE (sentry),
sentry, boolean_false_node);
- TREE_SIDE_EFFECTS (end) = 1;
buf = TREE_OPERAND (rval, 0);
}
\f
static tree
-build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
- use_global_delete)
+build_vec_delete_1 (base, maxindex, type, auto_delete_vec, use_global_delete)
tree base, maxindex, type;
- tree auto_delete_vec, auto_delete;
+ tree auto_delete_vec;
int use_global_delete;
{
tree virtual_size;
/* The below is short by BI_header_size */
virtual_size = fold (size_binop (MULT_EXPR, size_exp, maxindex));
- tbase = build_decl (VAR_DECL, NULL_TREE, ptype);
+ tbase = create_temporary_var (ptype);
tbase_init = build_modify_expr (tbase, NOP_EXPR,
fold (build (PLUS_EXPR, ptype,
base,
controller = build (BIND_EXPR, void_type_node, tbase, NULL_TREE, NULL_TREE);
TREE_SIDE_EFFECTS (controller) = 1;
- if (auto_delete != integer_zero_node
- && auto_delete != integer_two_node)
- {
- tree base_tbd = cp_convert (ptype,
- build_binary_op (MINUS_EXPR,
- cp_convert (ptr_type_node, base),
- BI_header_size));
- /* This is the real size */
- virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size);
- body = build_expr_list (NULL_TREE,
- build_x_delete (base_tbd,
- 2 | use_global_delete,
- virtual_size));
- body = build (COND_EXPR, void_type_node,
- build (BIT_AND_EXPR, integer_type_node,
- auto_delete, integer_one_node),
- body, integer_zero_node);
- }
- else
- body = NULL_TREE;
+ body = NULL_TREE;
body = tree_cons (NULL_TREE,
- build_delete (ptype, tbase, auto_delete,
+ build_delete (ptype, tbase, integer_two_node,
LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1),
body);
deallocate_expr = build_x_delete (base_tbd,
2 | use_global_delete,
virtual_size);
- if (auto_delete_vec != integer_one_node)
- deallocate_expr = build (COND_EXPR, void_type_node,
- build (BIT_AND_EXPR, integer_type_node,
- auto_delete_vec, integer_one_node),
- deallocate_expr, integer_zero_node);
+ deallocate_expr = fold (build (COND_EXPR, void_type_node,
+ fold (build (BIT_AND_EXPR,
+ integer_type_node,
+ auto_delete_vec,
+ integer_one_node)),
+ deallocate_expr, integer_zero_node));
}
if (loop && deallocate_expr != integer_zero_node)
body = loop;
/* Outermost wrapper: If pointer is null, punt. */
- body = build (COND_EXPR, void_type_node,
- build (NE_EXPR, boolean_type_node, base, integer_zero_node),
- body, integer_zero_node);
+ body = fold (build (COND_EXPR, void_type_node,
+ fold (build (NE_EXPR, boolean_type_node, base,
+ integer_zero_node)),
+ body, integer_zero_node));
body = build1 (NOP_EXPR, void_type_node, body);
if (controller)
decl = create_temporary_var (type);
if (building_stmt_tree ())
add_decl_stmt (decl);
- DECL_REGISTER (decl) = 1;
if (!building_stmt_tree ())
DECL_RTL (decl) = assign_temp (type, 2, 0, 1);
finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
tree compound_stmt;
int destroy_temps;
tree try_block = NULL_TREE;
- tree try_body;
+ tree try_body = NULL_TREE;
int num_initialized_elts = 0;
maxindex = cp_convert (ptrdiff_type_node, maxindex);
if (maxindex == error_mark_node)
return error_mark_node;
- if (current_function_decl == NULL_TREE)
- {
- rval = make_tree_vec (3);
- TREE_VEC_ELT (rval, 0) = base;
- TREE_VEC_ELT (rval, 1) = maxindex;
- TREE_VEC_ELT (rval, 2) = init;
- return rval;
- }
-
type = TREE_TYPE (TREE_TYPE (base));
ptype = build_pointer_type (type);
size = size_in_bytes (type);
/* Clear out INIT so that we don't get confused below. */
init = NULL_TREE;
-
- if (obey_regdecls && !building_stmt_tree ())
- use_variable (DECL_RTL (base));
}
else if (from_array)
{
build (PLUS_EXPR, build_pointer_type (type),
base2, size)));
- if (obey_regdecls && !building_stmt_tree ())
- {
- use_variable (DECL_RTL (base));
- if (base2)
- use_variable (DECL_RTL (base2));
- }
-
finish_compound_stmt (/*has_no_scope=*/1, do_body);
finish_do_body (do_stmt);
finish_do_stmt (build (NE_EXPR, boolean_type_node,
iterator),
type,
/*auto_delete_vec=*/integer_zero_node,
- /*auto_delete=*/integer_zero_node,
/*use_global_delete=*/0);
finish_cleanup (e, try_block);
}
- if (obey_regdecls && !building_stmt_tree ())
- {
- use_variable (DECL_RTL (iterator));
- use_variable (DECL_RTL (rval));
- }
-
/* The value of the array initialization is the address of the
first element in the array. */
finish_expr_stmt (rval);
return error_mark_node;
}
return build_vec_delete (addr, array_type_nelts (type),
- auto_delete, integer_zero_node,
- use_global_delete);
+ auto_delete, use_global_delete);
}
else
{
passed_auto_delete = auto_delete;
expr = build_method_call
- (ref, dtor_identifier, build_expr_list (NULL_TREE, passed_auto_delete),
+ (ref, dtor_identifier, build_tree_list (NULL_TREE, passed_auto_delete),
NULL_TREE, flags);
if (do_delete)
cond = NULL_TREE;
if (cond)
- exprstmt = build_expr_list (NULL_TREE, cond);
+ exprstmt = build_tree_list (NULL_TREE, cond);
if (base_binfo
&& ! TREE_VIA_VIRTUAL (base_binfo)
expr = build_scoped_method_call
(ref, base_binfo, dtor_identifier,
- build_expr_list (NULL_TREE, this_auto_delete));
+ build_tree_list (NULL_TREE, this_auto_delete));
exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
}
expr = build_scoped_method_call
(ref, base_binfo, dtor_identifier,
- build_expr_list (NULL_TREE, integer_zero_node));
+ build_tree_list (NULL_TREE, integer_zero_node));
exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
}
BASE is the expression that should yield the store to be deleted.
This function expands (or synthesizes) these calls itself.
AUTO_DELETE_VEC says whether the container (vector) should be deallocated.
- AUTO_DELETE say whether each item in the container should be deallocated.
This also calls delete for virtual baseclasses of elements of the vector.
be worth bothering.) */
tree
-build_vec_delete (base, maxindex, auto_delete_vec, auto_delete,
- use_global_delete)
+build_vec_delete (base, maxindex, auto_delete_vec, use_global_delete)
tree base, maxindex;
- tree auto_delete_vec, auto_delete;
+ tree auto_delete_vec;
int use_global_delete;
{
tree type;
return error_mark_node;
}
- return build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
+ return build_vec_delete_1 (base, maxindex, type, auto_delete_vec,
use_global_delete);
}