aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/init.c')
-rw-r--r--gcc/cp/init.c182
1 files changed, 89 insertions, 93 deletions
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index e7d62934d6d..1207510cf27 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -218,7 +218,7 @@ build_default_init (type)
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
@@ -696,10 +696,7 @@ sort_base_init (t, base_init_list, rbase_ptr, vbase_ptr)
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)
@@ -863,7 +860,7 @@ expand_virtual_init (binfo, decl)
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,
@@ -875,7 +872,8 @@ expand_virtual_init (binfo, decl)
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);
}
@@ -1954,14 +1952,6 @@ resolve_offset_ref (exp)
addr = convert_pointer_to (basetype, addr);
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));
@@ -2224,20 +2214,18 @@ build_java_class_ref (type)
}
/* Mangle the class$ field, new and old ABI */
- if (flag_new_abi)
- {
- tree field;
- for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
- if (DECL_NAME (field) == CL_suffix)
- {
- name = mangle_decl (field);
- break;
- }
- if (!field)
- internal_error ("Can't find class$");
+ {
+ 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$");
}
- else
- name = build_static_name (type, CL_suffix);
class_decl = IDENTIFIER_GLOBAL_VALUE (name);
if (class_decl == NULL_TREE)
@@ -2264,27 +2252,17 @@ get_cookie_size (type)
{
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;
- }
+ /* 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
- {
- 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;
}
@@ -2315,6 +2293,9 @@ build_new_1 (exp)
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);
@@ -2386,7 +2367,7 @@ build_new_1 (exp)
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;
@@ -2440,8 +2421,25 @@ build_new_1 (exp)
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
@@ -2481,23 +2479,13 @@ build_new_1 (exp)
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. 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);
+
cookie_expr = build (MODIFY_EXPR, void_type_node, cookie, nelts);
TREE_SIDE_EFFECTS (cookie_expr) = 1;
}
@@ -2568,7 +2556,8 @@ build_new_1 (exp)
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
@@ -2812,7 +2801,7 @@ get_temp_regvar (type, init)
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;
@@ -3187,7 +3176,6 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
{
tree member;
tree expr;
- tree ref;
if (addr == error_mark_node)
return error_mark_node;
@@ -3216,7 +3204,6 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
/* 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)
{
@@ -3241,8 +3228,6 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
addr = save_expr (addr);
addr = convert_force (build_pointer_type (type), addr, 0);
-
- ref = build_indirect_ref (addr, NULL_PTR);
}
my_friendly_assert (IS_AGGR_TYPE (type), 220);
@@ -3266,16 +3251,39 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
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_PTR),
+ auto_delete, flags);
if (do_delete)
expr = build (COMPOUND_EXPR, void_type_node, expr, do_delete);
@@ -3299,6 +3307,7 @@ build_delete (type, addr, auto_delete, flags, use_global_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_PTR);
/* Set this again before we call anything, as we might get called
recursively. */
@@ -3412,24 +3421,11 @@ build_vec_delete (base, maxindex, auto_delete_vec, use_global_delete)
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_PTR);
}
else if (TREE_CODE (type) == ARRAY_TYPE)
{