diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f01593df6dfe..db536e4d9d30 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,9 @@ 2008-07-31 Jason Merrill + PR c++/36633 + * init.c (build_new_1): Don't convert pointer to the data type + until we're actually going to treat it as that type. + PR c++/11309 * tree.c (build_aggr_init_expr): Split out... (build_cplus_new): ...from here. diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 5535033e1be6..c6d63b840969 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -2055,11 +2055,9 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, return rval; } - /* While we're working, use a pointer to the type we've actually - allocated. Store the result of the call in a variable so that we - can use it more than once. */ - full_pointer_type = build_pointer_type (full_type); - alloc_expr = get_target_expr (build_nop (full_pointer_type, alloc_call)); + /* Store the result of the allocation call in a variable so that we can + use it more than once. */ + alloc_expr = get_target_expr (alloc_call); alloc_node = TARGET_EXPR_SLOT (alloc_expr); /* Strip any COMPOUND_EXPRs from ALLOC_CALL. */ @@ -2111,16 +2109,17 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, tree size_ptr_type; /* Adjust so we're pointing to the start of the object. */ - data_addr = get_target_expr (build2 (POINTER_PLUS_EXPR, full_pointer_type, - alloc_node, cookie_size)); + data_addr = build2 (POINTER_PLUS_EXPR, TREE_TYPE (alloc_node), + alloc_node, cookie_size); /* Store the number of bytes allocated so that we can know how many elements to destroy later. We use the last sizeof (size_t) bytes to store the number of elements. */ - cookie_ptr = fold_build1 (NEGATE_EXPR, sizetype, size_in_bytes (sizetype)); + cookie_ptr = size_binop (MINUS_EXPR, cookie_size, size_in_bytes (sizetype)); + cookie_ptr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (alloc_node), + alloc_node, cookie_ptr); size_ptr_type = build_pointer_type (sizetype); - cookie_ptr = build2 (POINTER_PLUS_EXPR, size_ptr_type, - fold_convert (size_ptr_type, data_addr), cookie_ptr); + cookie_ptr = fold_convert (size_ptr_type, cookie_ptr); cookie = cp_build_indirect_ref (cookie_ptr, NULL, complain); cookie_expr = build2 (MODIFY_EXPR, sizetype, cookie, nelts); @@ -2134,11 +2133,10 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, cookie = cp_build_indirect_ref (cookie_ptr, NULL, complain); cookie = build2 (MODIFY_EXPR, sizetype, cookie, - size_in_bytes(elt_type)); + size_in_bytes (elt_type)); cookie_expr = build2 (COMPOUND_EXPR, TREE_TYPE (cookie_expr), cookie, cookie_expr); } - data_addr = TARGET_EXPR_SLOT (data_addr); } else { @@ -2146,6 +2144,10 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, data_addr = alloc_node; } + /* Now use a pointer to the type we've actually allocated. */ + full_pointer_type = build_pointer_type (full_type); + data_addr = fold_convert (full_pointer_type, data_addr); + /* Now initialize the allocated object. Note that we preevaluate the initialization expression, apart from the actual constructor call or assignment--we do this because we want to delay the allocation as long @@ -2241,11 +2243,13 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, /* 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, - globally_qualified_p, - (placement_allocation_fn_p - ? alloc_call : NULL_TREE), - alloc_fn); + cleanup = (build_op_delete_call + (dcode, + fold_convert (full_pointer_type, alloc_node), + size, + globally_qualified_p, + placement_allocation_fn_p ? alloc_call : NULL_TREE, + alloc_fn)); if (!cleanup) /* We're done. */; @@ -2300,7 +2304,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, if (cookie_expr) rval = build2 (COMPOUND_EXPR, TREE_TYPE (rval), cookie_expr, rval); - if (rval == alloc_node) + if (rval == data_addr) /* If we don't have an initializer or a cookie, strip the TARGET_EXPR and return the call (which doesn't need to be adjusted). */ rval = TARGET_EXPR_INITIAL (alloc_expr); diff --git a/gcc/testsuite/g++.dg/tree-ssa/new1.C b/gcc/testsuite/g++.dg/tree-ssa/new1.C new file mode 100644 index 000000000000..a859f0ac3775 --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/new1.C @@ -0,0 +1,42 @@ +// PR c++/36633 + +/* { dg-do compile } */ +/* { dg-options "-O2 -Wall -fdump-tree-forwprop1" } */ +// No particular reason for choosing forwprop1 dump to look at. + +struct B { ~B() {} }; +struct D : public B {}; +//struct D {}; + +struct my_deleter +{ + void operator()(D * d) + { + // delete [] d; + } +}; + +struct smart_ptr +{ + smart_ptr(D * ptr) : p(ptr) { } + ~smart_ptr() { d(p); } + D * p; + my_deleter d; +}; + +int +test01() +{ + smart_ptr p(new D[7]); + + return 0; +} + +int main() +{ + test01(); + return 0; +} + +/* { dg-final { scan-tree-dump-not "= .* \\+ -" "forwprop1" } } */ +/* { dg-final { cleanup-tree-dump "forwprop1" } } */