From 9aa757df38212968d0a1d6a68ec48a17042f395c Mon Sep 17 00:00:00 2001 From: jason Date: Mon, 17 Nov 2003 19:39:46 +0000 Subject: [PATCH] * init.c (build_new_1): Preevaluate placement args. * call.c (build_op_delete_call): Don't expose placement args to overload resolution. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@73677 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 6 ++++ gcc/cp/call.c | 14 ++++++--- gcc/cp/init.c | 56 ++++++++++++++++++++++------------ gcc/testsuite/g++.dg/init/placement2.C | 19 ++++++++++++ 4 files changed, 71 insertions(+), 24 deletions(-) create mode 100644 gcc/testsuite/g++.dg/init/placement2.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5a5dc78b928..e143dea0ec9 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2003-11-17 Jason Merrill + + * init.c (build_new_1): Preevaluate placement args. + * call.c (build_op_delete_call): Don't expose placement args to + overload resolution. + 2003-11-16 Jason Merrill * Make-lang.in (c++.tags): Create TAGS.sub files in each directory diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 07622ab37cd..354eb8bb71a 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -3824,10 +3824,6 @@ build_op_delete_call (enum tree_code code, tree addr, tree size, /* Find the allocation function that is being called. */ call_expr = placement; - /* Sometimes we have a COMPOUND_EXPR, rather than a simple - CALL_EXPR. */ - while (TREE_CODE (call_expr) == COMPOUND_EXPR) - call_expr = TREE_OPERAND (call_expr, 1); /* Extract the function. */ alloc_fn = get_callee_fndecl (call_expr); my_friendly_assert (alloc_fn != NULL_TREE, 20020327); @@ -3910,7 +3906,15 @@ build_op_delete_call (enum tree_code code, tree addr, tree size, args = tree_cons (NULL_TREE, addr, build_tree_list (NULL_TREE, size)); - return build_function_call (fn, args); + if (placement) + { + /* The placement args might not be suitable for overload + resolution at this point, so build the call directly. */ + mark_used (fn); + return build_cxx_call (fn, args, args); + } + else + return build_function_call (fn, args); } /* If we are doing placement delete we do nothing if we don't find a diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 735215377a3..332c518c76c 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -2060,13 +2060,22 @@ build_new_1 (tree exp) if (alloc_call == error_mark_node) return error_mark_node; - /* The ALLOC_CALL should be a CALL_EXPR -- or a COMPOUND_EXPR whose - right-hand-side is ultimately a CALL_EXPR -- and the first - operand should be the address of a known FUNCTION_DECL. */ - t = alloc_call; - while (TREE_CODE (t) == COMPOUND_EXPR) - t = TREE_OPERAND (t, 1); - alloc_fn = get_callee_fndecl (t); + /* In the simple case, we can stop now. */ + pointer_type = build_pointer_type (type); + if (!cookie_size && !is_initialized) + return build_nop (pointer_type, alloc_call); + + /* 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)); + alloc_node = TARGET_EXPR_SLOT (alloc_expr); + + /* Strip any COMPOUND_EXPRs from ALLOC_CALL. */ + while (TREE_CODE (alloc_call) == COMPOUND_EXPR) + alloc_call = TREE_OPERAND (alloc_call, 1); + alloc_fn = get_callee_fndecl (alloc_call); my_friendly_assert (alloc_fn != NULL_TREE, 20020325); /* Now, check to see if this function is actually a placement @@ -2083,6 +2092,27 @@ build_new_1 (tree exp) = (type_num_arguments (TREE_TYPE (alloc_fn)) > 1 || varargs_function_p (alloc_fn)); + /* Preevaluate the placement args so that we don't reevaluate them for a + placement delete. */ + if (placement_allocation_fn_p) + { + tree inits = NULL_TREE; + t = TREE_CHAIN (TREE_OPERAND (alloc_call, 1)); + for (; t; t = TREE_CHAIN (t)) + if (TREE_SIDE_EFFECTS (TREE_VALUE (t))) + { + tree init; + TREE_VALUE (t) = stabilize_expr (TREE_VALUE (t), &init); + if (inits) + inits = build (COMPOUND_EXPR, void_type_node, inits, init); + else + inits = init; + } + if (inits) + alloc_expr = build (COMPOUND_EXPR, TREE_TYPE (alloc_expr), inits, + alloc_expr); + } + /* unless an allocation function is declared with an empty excep- tion-specification (_except.spec_), throw(), it indicates failure to allocate storage by throwing a bad_alloc exception (clause _except_, @@ -2096,18 +2126,6 @@ build_new_1 (tree exp) nothrow = TYPE_NOTHROW_P (TREE_TYPE (alloc_fn)); check_new = (flag_check_new || nothrow) && ! use_java_new; - /* In the simple case, we can stop now. */ - pointer_type = build_pointer_type (type); - if (!cookie_size && !is_initialized) - return build_nop (pointer_type, alloc_call); - - /* 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)); - alloc_node = TARGET_EXPR_SLOT (alloc_expr); - if (cookie_size) { tree cookie; diff --git a/gcc/testsuite/g++.dg/init/placement2.C b/gcc/testsuite/g++.dg/init/placement2.C new file mode 100644 index 00000000000..bca741575c8 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/placement2.C @@ -0,0 +1,19 @@ +// { dg-do run } + +void* operator new (unsigned int sz, void*) { return operator new (sz); } +void operator delete (void* p, void*) { operator delete (p); } + +struct A { A() { throw 1; } }; + +int c; +void *f() { ++c; return 0; } + +int main() +{ + try + { + new (f()) A; + } + catch (...) {} + return c != 1; +} -- 2.11.0