diff options
Diffstat (limited to 'gcc/cp/init.c')
-rw-r--r-- | gcc/cp/init.c | 182 |
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) { |