/* Handle initialization things in C++.
Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000 Free Software Foundation, Inc.
+ 1999, 2000, 2001 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
static void perform_member_init PARAMS ((tree, tree, int));
static void sort_base_init PARAMS ((tree, tree, tree *, tree *));
static tree build_builtin_delete_call PARAMS ((tree));
-static int member_init_ok_or_else PARAMS ((tree, tree, const char *));
+static int member_init_ok_or_else PARAMS ((tree, tree, tree));
static void expand_virtual_init PARAMS ((tree, tree));
static tree sort_member_init PARAMS ((tree, tree));
static tree initializing_context PARAMS ((tree));
{
tree fields[1];
- minus_one_node = build_int_2 (-1, -1);
-
/* Define the structure that holds header information for
arrays allocated via operator new. */
BI_header_type = make_aggr_type (RECORD_TYPE);
/* Constructors */
-/* Called from initialize_vtbl_ptrs via dfs_walk. */
+/* Called from initialize_vtbl_ptrs via dfs_walk. BINFO is the base
+ which we want to initialize the vtable pointer for, DATA is
+ TREE_LIST whose TREE_VALUE is the this ptr expression. */
static tree
dfs_initialize_vtbl_ptrs (binfo, data)
tree binfo;
void *data;
{
- if (!BINFO_PRIMARY_MARKED_P (binfo)
+ if ((!BINFO_PRIMARY_P (binfo) || TREE_VIA_VIRTUAL (binfo))
&& CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
{
tree base_ptr = TREE_VALUE ((tree) data);
- 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);
+ base_ptr = build_base_path (PLUS_EXPR, base_ptr, binfo, /*nonnull=*/1);
expand_virtual_init (binfo, base_ptr);
}
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. */
+ class. We do these in pre-order because 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 we're not using thunks, we may need to adjust the deltas in
- the vtable to handle virtual base classes correctly. When we are
- using thunks, we either use construction vtables (which are
- preloaded with the right answers) or nothing (in which case
- vitual function calls sometimes don't work right.) */
- if (TYPE_USES_VIRTUAL_BASECLASSES (type) && !flag_vtable_thunks)
- fixup_all_virtual_upcast_offsets (addr);
}
/* [dcl.init]:
anything with a CONSTRUCTOR for arrays here, as that would imply
copy-initialization. */
return NULL_TREE;
- else if (AGGREGATE_TYPE_P (type))
+ else if (AGGREGATE_TYPE_P (type) && !TYPE_PTRMEMFUNC_P (type))
{
/* This is a default initialization of an aggregate, but not one of
non-POD class type. We cleverly notice that the initialization
/* --if T is a reference type, no initialization is performed. */
return NULL_TREE;
else
- init = integer_zero_node;
+ {
+ init = integer_zero_node;
+
+ if (TREE_CODE (type) == ENUMERAL_TYPE)
+ /* We must make enumeral types the right type. */
+ init = fold (build1 (NOP_EXPR, type, init));
+ }
init = digest_init (type, init, 0);
return init;
tree vbases = NULL_TREE;
/* First walk through and splice out vbase and invalid initializers.
- Also replace names with binfos. */
+ Also replace types with binfos. */
last = tree_cons (NULL_TREE, NULL_TREE, base_init_list);
for (x = TREE_CHAIN (last); x; x = TREE_CHAIN (x))
{
tree basetype = TREE_PURPOSE (x);
- tree binfo = NULL_TREE;
+ tree binfo = (TREE_CODE (basetype) == TREE_VEC
+ ? basetype : binfo_or_else (basetype, t));
+
+ if (binfo == NULL_TREE)
+ /* BASETYPE might be an inaccessible direct base (because it
+ is also an indirect base). */
+ continue;
- if (basetype == NULL_TREE)
+ if (TREE_VIA_VIRTUAL (binfo))
{
- /* Initializer for single base class. Must not
- use multiple inheritance or this is ambiguous. */
- switch (n_baseclasses)
- {
- case 0:
- cp_error ("`%T' does not have a base class to initialize",
- current_class_type);
- return;
- case 1:
- break;
- default:
- cp_error ("unnamed initializer ambiguous for `%T' which uses multiple inheritance",
- current_class_type);
- return;
- }
- binfo = TREE_VEC_ELT (binfos, 0);
+ /* Virtual base classes are special cases. Their
+ initializers are recorded with this constructor, and they
+ are used when this constructor is the top-level
+ constructor called. */
+ tree v = binfo_for_vbase (BINFO_TYPE (binfo), t);
+ vbases = tree_cons (v, TREE_VALUE (x), vbases);
}
- else if (is_aggr_type (basetype, 1))
+ else
{
- binfo = binfo_or_else (basetype, t);
- if (binfo == NULL_TREE)
- continue;
-
- /* Virtual base classes are special cases. Their initializers
- are recorded with this constructor, and they are used when
- this constructor is the top-level constructor called. */
- if (TREE_VIA_VIRTUAL (binfo))
- {
- tree v = binfo_for_vbase (BINFO_TYPE (binfo), t);
- vbases = tree_cons (v, TREE_VALUE (x), vbases);
- continue;
- }
- else
- {
- /* Otherwise, if it is not an immediate base class, complain. */
- for (i = n_baseclasses-1; i >= 0; i--)
- if (BINFO_TYPE (binfo) == BINFO_TYPE (TREE_VEC_ELT (binfos, i)))
- break;
- if (i < 0)
- {
- cp_error ("`%T' is not an immediate base class of `%T'",
- basetype, current_class_type);
- continue;
- }
- }
+ /* Otherwise, it must be an immediate base class. */
+ my_friendly_assert
+ (same_type_p (BINFO_TYPE (BINFO_INHERITANCE_CHAIN (binfo)),
+ t), 20011113);
+
+ TREE_PURPOSE (x) = binfo;
+ TREE_CHAIN (last) = x;
+ last = x;
}
- else
- my_friendly_abort (365);
-
- TREE_PURPOSE (x) = binfo;
- TREE_CHAIN (last) = x;
- last = x;
}
TREE_CHAIN (last) = NULL_TREE;
If there is a need for a call to a constructor, we must surround
that call with a pushlevel/poplevel pair, since we are technically
- at the PARM level of scope.
-
- Note that emit_base_init does *not* initialize virtual base
- classes. That is done specially, elsewhere. */
+ at the PARM level of scope. */
void
emit_base_init (mem_init_list, base_init_list)
if (init != void_list_node)
{
- member = convert_pointer_to_real (base_binfo, current_class_ptr);
+ member = build_base_path (PLUS_EXPR, current_class_ptr,
+ base_binfo, 1);
expand_aggr_init_1 (base_binfo, NULL_TREE,
- build_indirect_ref (member, NULL_PTR), init,
+ build_indirect_ref (member, NULL), init,
LOOKUP_NORMAL);
}
build_vtbl_address (binfo)
tree binfo;
{
+ tree binfo_for = binfo;
tree vtbl;
+ if (BINFO_VPTR_INDEX (binfo) && TREE_VIA_VIRTUAL (binfo)
+ && BINFO_PRIMARY_P (binfo))
+ /* If this is a virtual primary base, then the vtable we want to store
+ is that for the base this is being used as the primary base of. We
+ can't simply skip the initialization, because we may be expanding the
+ inits of a subobject constructor where the virtual base layout
+ can be different. */
+ while (BINFO_PRIMARY_BASE_OF (binfo_for))
+ binfo_for = BINFO_PRIMARY_BASE_OF (binfo_for);
+
/* Figure out what vtable BINFO's vtable is based on, and mark it as
used. */
- vtbl = get_vtbl_decl_for_binfo (binfo);
+ vtbl = get_vtbl_decl_for_binfo (binfo_for);
assemble_external (vtbl);
TREE_USED (vtbl) = 1;
/* Now compute the address to use when initializing the vptr. */
- vtbl = BINFO_VTABLE (binfo);
+ vtbl = BINFO_VTABLE (binfo_for);
if (TREE_CODE (vtbl) == VAR_DECL)
{
vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
expand_virtual_init (binfo, decl)
tree binfo, decl;
{
- tree type = BINFO_TYPE (binfo);
tree vtbl, vtbl_ptr;
- tree vtype, vtype_binfo;
tree vtt_index;
- /* Compute the location of the vtable. */
- vtype = DECL_CONTEXT (TYPE_VFIELD (type));
- vtype_binfo = get_binfo (vtype, TREE_TYPE (TREE_TYPE (decl)), 0);
-
/* Compute the initializer for vptr. */
vtbl = build_vtbl_address (binfo);
- /* Under the new ABI, we may get this vptr from a VTT, if this is a
- subobject constructor or subobject destructor. */
+ /* We may get this vptr from a VTT, if this is a subobject
+ constructor or subobject destructor. */
vtt_index = BINFO_VPTR_INDEX (binfo);
if (vtt_index)
{
tree vtt_parm;
/* Compute the value to use, when there's a VTT. */
- vtt_parm = DECL_VTT_PARM (current_function_decl);
+ vtt_parm = current_vtt_parm;
vtbl2 = build (PLUS_EXPR,
TREE_TYPE (vtt_parm),
vtt_parm,
the vtt_parm in the case of the non-subobject constructor. */
vtbl = build (COND_EXPR,
TREE_TYPE (vtbl),
- DECL_USE_VTT_PARM (current_function_decl),
+ build (EQ_EXPR, boolean_type_node,
+ current_in_charge_parm, integer_zero_node),
vtbl2,
vtbl);
}
/* 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;
+ vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, NULL),
+ TREE_TYPE (binfo));
+ my_friendly_assert (vtbl_ptr != error_mark_node, 20010730);
/* Assign the vtable to the vptr. */
vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0);
tree binfo, exp, addr, init_list;
{
tree init = purpose_member (binfo, init_list);
- tree ref = build_indirect_ref (addr, NULL_PTR);
+ tree ref = build_indirect_ref (addr, NULL);
if (init)
init = TREE_VALUE (init);
/* 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 (!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))
member_init_ok_or_else (field, type, member_name)
tree field;
tree type;
- const char *member_name;
+ tree member_name;
{
if (field == error_mark_node)
return 0;
if (field == NULL_TREE || initializing_context (field) != type)
{
- cp_error ("class `%T' does not have any field named `%s'", type,
+ cp_error ("class `%T' does not have any field named `%D'", type,
member_name);
return 0;
}
if (TREE_STATIC (field))
{
- cp_error ("field `%#D' is static; only point of initialization is its declaration",
+ cp_error ("field `%#D' is static; the only point of initialization is its definition",
field);
return 0;
}
return 1;
}
-/* If NAME is a viable field name for the aggregate DECL,
- and PARMS is a viable parameter list, then expand an _EXPR
- which describes this initialization.
+/* EXP is an expression of aggregate type. NAME is an IDENTIFIER_NODE
+ which names a field, or it is a _TYPE node or TYPE_DECL which names
+ a base for that type. INIT is a parameter list for that field's or
+ base's constructor. Check the validity of NAME, and return a
+ TREE_LIST of the base _TYPE or FIELD_DECL and the INIT. EXP is used
+ only to get its type. If NAME is invalid, return NULL_TREE and
+ issue a diagnostic.
- Note that we do not need to chase through the class's base classes
- to look for NAME, because if it's in that list, it will be handled
- by the constructor for that base class.
-
- We do not yet have a fixed-point finder to instantiate types
- being fed to overloaded constructors. If there is a unique
- constructor, then argument types can be got from that one. */
+ An old style unnamed direct single base construction is permitted,
+ where NAME is NULL. */
tree
expand_member_init (exp, name, init)
return NULL_TREE;
type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
+ my_friendly_assert (IS_AGGR_TYPE (type), 20011113);
- if (name && TYPE_P (name))
+ if (!name)
{
- basetype = name;
- name = TYPE_IDENTIFIER (name);
+ /* This is an obsolete unnamed base class initializer. The
+ parser will already have warned about its use. */
+ switch (CLASSTYPE_N_BASECLASSES (type))
+ {
+ case 0:
+ cp_error ("unnamed initializer for `%T', which has no base classes",
+ type);
+ return NULL_TREE;
+ case 1:
+ basetype = TYPE_BINFO_BASETYPE (type, 0);
+ break;
+ default:
+ cp_error ("unnamed initializer for `%T', which uses multiple inheritance",
+ type);
+ return NULL_TREE;
+ }
}
- else if (name && TREE_CODE (name) == TYPE_DECL)
+ else if (TYPE_P (name))
{
- basetype = TYPE_MAIN_VARIANT (TREE_TYPE (name));
- name = DECL_NAME (name);
+ basetype = name;
+ name = TYPE_NAME (name);
}
-
- if (name == NULL_TREE && IS_AGGR_TYPE (type))
- switch (CLASSTYPE_N_BASECLASSES (type))
- {
- case 0:
- error ("base class initializer specified, but no base class to initialize");
- return NULL_TREE;
- case 1:
- basetype = TYPE_BINFO_BASETYPE (type, 0);
- break;
- default:
- error ("initializer for unnamed base class ambiguous");
- cp_error ("(type `%T' uses multiple inheritance)", type);
- return NULL_TREE;
- }
+ else if (TREE_CODE (name) == TYPE_DECL)
+ basetype = TYPE_MAIN_VARIANT (TREE_TYPE (name));
my_friendly_assert (init != NULL_TREE, 0);
- /* The grammar should not allow fields which have names that are
- TYPENAMEs. Therefore, if the field has a non-NULL TREE_TYPE, we
- may assume that this is an attempt to initialize a base class
- member of the current type. Otherwise, it is an attempt to
- initialize a member field. */
-
if (init == void_type_node)
init = NULL_TREE;
- if (name == NULL_TREE || basetype)
+ if (basetype)
{
- if (name == NULL_TREE)
- {
-#if 0
- if (basetype)
- name = TYPE_IDENTIFIER (basetype);
- else
- {
- error ("no base class to initialize");
- return;
- }
-#endif
- }
- else if (basetype != type
- && ! current_template_parms
- && ! vec_binfo_member (basetype,
- TYPE_BINFO_BASETYPES (type))
- && ! binfo_for_vbase (basetype, type))
+ if (current_template_parms)
+ ;
+ else if (vec_binfo_member (basetype, TYPE_BINFO_BASETYPES (type)))
+ /* A direct base. */;
+ else if (binfo_for_vbase (basetype, type))
+ /* A virtual base. */;
+ else
{
- if (IDENTIFIER_CLASS_VALUE (name))
- goto try_member;
if (TYPE_USES_VIRTUAL_BASECLASSES (type))
- cp_error ("type `%T' is not an immediate or virtual basetype for `%T'",
- basetype, type);
+ cp_error ("type `%D' is not a direct or virtual base of `%T'",
+ name, type);
else
- cp_error ("type `%T' is not an immediate basetype for `%T'",
- basetype, type);
+ cp_error ("type `%D' is not a direct base of `%T'",
+ name, type);
return NULL_TREE;
}
}
else
{
- try_member:
field = lookup_field (type, name, 1, 0);
- if (! member_init_ok_or_else (field, type, IDENTIFIER_POINTER (name)))
+ if (! member_init_ok_or_else (field, type, name))
return NULL_TREE;
init = build_tree_list (field, init);
cp_error ("bad array initializer");
return error_mark_node;
}
- if (CP_TYPE_QUALS (type) != TYPE_UNQUALIFIED)
+ if (cp_type_quals (type) != TYPE_UNQUALIFIED)
{
TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
if (init)
if (DECL_P (name))
name = DECL_NAME (name);
- if (type == fake_std_node)
- return build_x_function_call (do_scoped_id (name, 0), parmlist,
- current_class_ref);
if (TREE_CODE (type) == NAMESPACE_DECL)
return build_x_function_call (lookup_namespace_name (type, name),
parmlist, current_class_ref);
tree ns = lookup_name (type, 0);
if (ns && TREE_CODE (ns) == NAMESPACE_DECL)
{
- return build_x_function_call (build_offset_ref (type, name), parmlist, current_class_ref);
+ return build_x_function_call (build_offset_ref (type, name),
+ parmlist, current_class_ref);
}
}
{
tree newtype = build_qualified_type (type, TYPE_QUALS (oldtype));
decl = convert_force (build_pointer_type (newtype), olddecl, 0);
- decl = build_indirect_ref (decl, NULL_PTR);
+ decl = build_indirect_ref (decl, NULL);
}
}
if (TREE_CODE (name) == TEMPLATE_DECL)
return name;
- if (type == fake_std_node)
- return do_scoped_id (name, 0);
-
if (processing_template_decl || uses_template_parms (type))
return build_min_nt (SCOPE_REF, type, name);
if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE)
base = build_scoped_ref (base, TYPE_OFFSET_BASETYPE (type));
- addr = build_unary_op (ADDR_EXPR, base, 0);
- addr = convert_pointer_to (basetype, addr);
+ /* Don't check access on the conversion; we might be after a member
+ promoted by an access- or using-declaration, and we have already
+ checked access for the member itself. */
+ basetype = lookup_base (TREE_TYPE (base), basetype, ba_ignore, NULL);
+ expr = build_base_path (PLUS_EXPR, base, basetype, 1);
- if (addr == error_mark_node)
+ if (expr == error_mark_node)
return error_mark_node;
expr = build (COMPONENT_REF, TREE_TYPE (member),
- build_indirect_ref (addr, NULL_PTR), member);
+ expr, member);
return convert_from_reference (expr);
}
}
basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (TREE_TYPE (member)));
- addr = convert_pointer_to (basetype, addr);
+ basetype = lookup_base (TREE_TYPE (TREE_TYPE (addr)),
+ basetype, ba_check, NULL);
+ addr = build_base_path (PLUS_EXPR, addr, basetype, 1);
+
member = cp_convert (ptrdiff_type_node, member);
- if (!flag_new_abi)
- /* 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. */
- member = cp_build_binary_op (MINUS_EXPR, member,
- cp_convert (ptrdiff_type_node,
- integer_one_node));
-
return build1 (INDIRECT_REF, type,
build (PLUS_EXPR, build_pointer_type (type),
addr, member));
}
else
{
- int flags = pedantic ? WANT_INT : (WANT_INT | WANT_ENUM);
- if (build_expr_type_conversion (flags, this_nelts, 0)
+ if (build_expr_type_conversion (WANT_INT | WANT_ENUM,
+ this_nelts, 0)
== NULL_TREE)
pedwarn ("size in array new must have integral type");
build_java_class_ref (type)
tree type;
{
- tree name, class_decl;
+ tree name = NULL_TREE, class_decl;
static tree CL_suffix = NULL_TREE;
if (CL_suffix == NULL_TREE)
CL_suffix = get_identifier("class$");
if (jclass_node == NULL_TREE)
{
- jclass_node = IDENTIFIER_GLOBAL_VALUE (get_identifier("jclass"));
+ jclass_node = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jclass"));
if (jclass_node == NULL_TREE)
- fatal("call to Java constructor, while `jclass' undefined");
+ fatal_error ("call to Java constructor, while `jclass' undefined");
+
jclass_node = TREE_TYPE (jclass_node);
}
- name = build_static_name (type, CL_suffix);
+
+ /* Mangle the class$ field */
+ {
+ tree field;
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ if (DECL_NAME (field) == CL_suffix)
+ {
+ mangle_decl (field);
+ name = DECL_ASSEMBLER_NAME (field);
+ break;
+ }
+ if (!field)
+ internal_error ("can't find class$");
+ }
+
class_decl = IDENTIFIER_GLOBAL_VALUE (name);
if (class_decl == NULL_TREE)
{
DECL_ARTIFICIAL (class_decl) = 1;
DECL_IGNORED_P (class_decl) = 1;
pushdecl_top_level (class_decl);
- make_decl_rtl (class_decl, NULL_PTR, 1);
+ make_decl_rtl (class_decl, NULL);
}
return class_decl;
}
{
tree cookie_size;
- if (flag_new_abi)
- {
- /* Under the new ABI, we need to allocate an additional max
- (sizeof (size_t), alignof (true_type)) bytes. */
- tree sizetype_size;
- tree type_align;
-
- sizetype_size = size_in_bytes (sizetype);
- type_align = size_int (TYPE_ALIGN_UNIT (type));
- if (INT_CST_LT_UNSIGNED (type_align, sizetype_size))
- cookie_size = sizetype_size;
- else
- cookie_size = type_align;
- }
+ /* We need to allocate an additional max (sizeof (size_t), alignof
+ (true_type)) bytes. */
+ tree sizetype_size;
+ tree type_align;
+
+ sizetype_size = size_in_bytes (sizetype);
+ type_align = size_int (TYPE_ALIGN_UNIT (type));
+ if (INT_CST_LT_UNSIGNED (type_align, sizetype_size))
+ cookie_size = sizetype_size;
else
- {
- if (TYPE_ALIGN (type) > TYPE_ALIGN (BI_header_type))
- return size_int (TYPE_ALIGN_UNIT (type));
- else
- return size_in_bytes (BI_header_type);
- }
+ cookie_size = type_align;
return cookie_size;
}
beginning of the storage allocated for an array-new expression in
order to store the number of elements. */
tree cookie_size = NULL_TREE;
+ /* True if the function we are calling is a placement allocation
+ function. */
+ bool placement_allocation_fn_p;
placement = TREE_OPERAND (exp, 0);
type = TREE_OPERAND (exp, 1);
if (!has_array || !TYPE_VEC_NEW_USES_COOKIE (true_type))
use_cookie = 0;
/* When using placement new, users may not realize that they need
- the extra storage. Under the old ABI, we don't allocate the
- cookie whenever they use one placement argument of type `void
- *'. Under the new ABI, we require that the operator called be
+ the extra storage. We require that the operator called be
the global placement operator delete[]. */
else if (placement && !TREE_CHAIN (placement)
&& same_type_p (TREE_TYPE (TREE_VALUE (placement)),
ptr_type_node))
- use_cookie = (!flag_new_abi || !use_global_new);
+ use_cookie = !use_global_new;
/* Otherwise, we need the cookie. */
else
use_cookie = 1;
tree class_addr, alloc_decl;
tree class_decl = build_java_class_ref (true_type);
tree class_size = size_in_bytes (true_type);
- static char alloc_name[] = "_Jv_AllocObject";
+ static const char alloc_name[] = "_Jv_AllocObject";
use_java_new = 1;
alloc_decl = IDENTIFIER_GLOBAL_VALUE (get_identifier (alloc_name));
if (alloc_decl == NULL_TREE)
- fatal("call to Java constructor, while `%s' undefined", alloc_name);
+ fatal_error ("call to Java constructor with `%s' undefined",
+ alloc_name);
+
class_addr = build1 (ADDR_EXPR, jclass_node, class_decl);
alloc_call = (build_function_call
(alloc_decl,
if (alloc_call == error_mark_node)
return error_mark_node;
- if (alloc_call == NULL_TREE)
- abort ();
+ /* The ALLOC_CALL should be a CALL_EXPR, and the first operand
+ should be the address of a known FUNCTION_DECL. */
+ my_friendly_assert (TREE_CODE (alloc_call) == CALL_EXPR, 20000521);
+ t = TREE_OPERAND (alloc_call, 0);
+ my_friendly_assert (TREE_CODE (t) == ADDR_EXPR, 20000521);
+ t = TREE_OPERAND (t, 0);
+ my_friendly_assert (TREE_CODE (t) == FUNCTION_DECL, 20000521);
+ /* Now, check to see if this function is actually a placement
+ allocation function. This can happen even when PLACEMENT is NULL
+ because we might have something like:
+
+ struct S { void* operator new (size_t, int i = 0); };
+
+ A call to `new S' will get this allocation function, even though
+ there is no explicit placement argument. If there is more than
+ one argument, or there are variable arguments, then this is a
+ placement allocation function. */
+ placement_allocation_fn_p
+ = (type_num_arguments (TREE_TYPE (t)) > 1 || varargs_function_p (t));
/* unless an allocation function is declared with an empty excep-
tion-specification (_except.spec_), throw(), it indicates failure to
tree cookie;
/* Store the number of bytes allocated so that we can know how
- many elements to destroy later. */
- if (flag_new_abi)
- {
- /* Under the new ABI, we use the last sizeof (size_t) bytes
- to store the number of elements. */
- cookie = build (MINUS_EXPR, build_pointer_type (sizetype),
- alloc_node, size_in_bytes (sizetype));
- cookie = build_indirect_ref (cookie, NULL_PTR);
- }
- else
- {
- cookie = build (MINUS_EXPR, build_pointer_type (BI_header_type),
- alloc_node, cookie_size);
- cookie = build_indirect_ref (cookie, NULL_PTR);
- cookie = build_component_ref (cookie, nelts_identifier,
- NULL_TREE, 0);
- }
+ many elements to destroy later. We use the last sizeof
+ (size_t) bytes to store the number of elements. */
+ cookie = build (MINUS_EXPR, build_pointer_type (sizetype),
+ alloc_node, size_in_bytes (sizetype));
+ cookie = build_indirect_ref (cookie, NULL);
+
cookie_expr = build (MODIFY_EXPR, void_type_node, cookie, nelts);
TREE_SIDE_EFFECTS (cookie_expr) = 1;
}
init_expr = NULL_TREE;
if (TYPE_NEEDS_CONSTRUCTING (type) || init)
{
- init_expr = build_indirect_ref (alloc_node, NULL_PTR);
+ init_expr = build_indirect_ref (alloc_node, NULL);
if (init == void_zero_node)
init = build_default_init (full_type);
flags |= LOOKUP_SPECULATIVELY;
cleanup = build_op_delete_call (dcode, alloc_node, size, flags,
- alloc_call);
+ (placement_allocation_fn_p
+ ? alloc_call : NULL_TREE));
/* Ack! First we allocate the memory. Then we set our sentry
variable to true, and expand a cleanup that deletes the memory
if (building_stmt_tree ())
add_decl_stmt (decl);
if (!building_stmt_tree ())
- DECL_RTL (decl) = assign_temp (type, 2, 0, 1);
+ SET_DECL_RTL (decl, assign_temp (type, 2, 0, 1));
finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
return decl;
if_stmt = begin_if_stmt ();
finish_if_stmt_cond (build (NE_EXPR, boolean_type_node,
- iterator, minus_one_node),
+ iterator, integer_minus_one_node),
if_stmt);
/* Otherwise, loop through the elements. */
finish_do_body (do_stmt);
finish_do_stmt (build (NE_EXPR, boolean_type_node,
build_unary_op (PREDECREMENT_EXPR, iterator, 0),
- minus_one_node),
+ integer_minus_one_node),
do_stmt);
finish_then_clause (if_stmt);
{
tree member;
tree expr;
- tree ref;
if (addr == error_mark_node)
return error_mark_node;
/* throw away const and volatile on target type of addr */
addr = convert_force (build_pointer_type (type), addr, 0);
- ref = build_indirect_ref (addr, NULL_PTR);
}
else if (TREE_CODE (type) == ARRAY_TYPE)
{
if (TREE_SIDE_EFFECTS (addr))
addr = save_expr (addr);
- if (TREE_CONSTANT (addr))
- addr = convert_pointer_to (type, addr);
- else
- addr = convert_force (build_pointer_type (type), addr, 0);
-
- ref = build_indirect_ref (addr, NULL_PTR);
+ addr = convert_force (build_pointer_type (type), addr, 0);
}
my_friendly_assert (IS_AGGR_TYPE (type), 220);
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
{
- if (auto_delete == sfk_base_destructor)
+ if (auto_delete != sfk_deleting_destructor)
return void_zero_node;
return build_op_delete_call
tree do_delete = NULL_TREE;
tree ifexp;
+ /* For `::delete x', we must not use the deleting destructor
+ since then we would not be sure to get the global `operator
+ delete'. */
if (use_global_delete && auto_delete == sfk_deleting_destructor)
{
+ /* We will use ADDR multiple times so we must save it. */
+ addr = save_expr (addr);
/* Delete the object. */
do_delete = build_builtin_delete_call (addr);
/* Otherwise, treat this like a complete object destructor
call. */
auto_delete = sfk_complete_destructor;
}
+ /* If the destructor is non-virtual, there is no deleting
+ variant. Instead, we must explicitly call the appropriate
+ `operator delete' here. */
+ else if (!DECL_VIRTUAL_P (CLASSTYPE_DESTRUCTORS (type))
+ && auto_delete == sfk_deleting_destructor)
+ {
+ /* We will use ADDR multiple times so we must save it. */
+ addr = save_expr (addr);
+ /* Build the call. */
+ do_delete = build_op_delete_call (DELETE_EXPR,
+ addr,
+ c_sizeof_nowarn (type),
+ LOOKUP_NORMAL,
+ NULL_TREE);
+ /* Call the complete object destructor. */
+ auto_delete = sfk_complete_destructor;
+ }
- expr = build_dtor_call (ref, auto_delete, flags);
+ expr = build_dtor_call (build_indirect_ref (addr, NULL),
+ auto_delete, flags);
if (do_delete)
expr = build (COMPOUND_EXPR, void_type_node, expr, do_delete);
int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (type);
tree base_binfo = n_baseclasses > 0 ? TREE_VEC_ELT (binfos, 0) : NULL_TREE;
tree exprstmt = NULL_TREE;
+ tree ref = build_indirect_ref (addr, NULL);
/* Set this again before we call anything, as we might get called
recursively. */
tree cookie_addr;
type = strip_array_types (TREE_TYPE (type));
- if (flag_new_abi)
- {
- cookie_addr = build (MINUS_EXPR,
- build_pointer_type (sizetype),
- base,
- TYPE_SIZE_UNIT (sizetype));
- maxindex = build_indirect_ref (cookie_addr, NULL_PTR);
- }
- else
- {
- tree cookie;
-
- cookie_addr = build (MINUS_EXPR, build_pointer_type (BI_header_type),
- base, get_cookie_size (type));
- cookie = build_indirect_ref (cookie_addr, NULL_PTR);
- maxindex = build_component_ref (cookie, nelts_identifier,
- NULL_TREE, 0);
- }
+ cookie_addr = build (MINUS_EXPR,
+ build_pointer_type (sizetype),
+ base,
+ TYPE_SIZE_UNIT (sizetype));
+ maxindex = build_indirect_ref (cookie_addr, NULL);
}
else if (TREE_CODE (type) == ARRAY_TYPE)
{