diff options
author | Jason Merrill <jason@yorick.cygnus.com> | 1997-12-04 10:03:02 +0000 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 1997-12-04 05:03:02 -0500 |
commit | 2face51965e6d4b7980ec9f6da0b6a19cf878f99 (patch) | |
tree | 598ae7a81d707d3612751f1b9b0a87e219a30894 | |
parent | 11f39cf45fe48480da4e44327767f0ac7e77d30e (diff) | |
download | gcc-2face51965e6d4b7980ec9f6da0b6a19cf878f99.zip gcc-2face51965e6d4b7980ec9f6da0b6a19cf878f99.tar.gz gcc-2face51965e6d4b7980ec9f6da0b6a19cf878f99.tar.bz2 |
init.c (build_new): Use a TARGET_EXPR instead of SAVE_EXPR for alloc_expr.
* init.c (build_new): Use a TARGET_EXPR instead of SAVE_EXPR for
alloc_expr.
* call.c (build_op_delete_call): Adjust.
From-SVN: r16939
-rw-r--r-- | gcc/cp/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/cp/call.c | 8 | ||||
-rw-r--r-- | gcc/cp/init.c | 70 |
3 files changed, 64 insertions, 18 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6b9737d..c7c56d3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,9 @@ Wed Dec 3 20:02:39 1997 Jason Merrill <jason@yorick.cygnus.com> + * init.c (build_new): Use a TARGET_EXPR instead of SAVE_EXPR for + alloc_expr. + * call.c (build_op_delete_call): Adjust. + * except.c (expand_end_catch_block): Lose rethrow region. (expand_start_catch_block): Likewise. (expand_end_catch_block): Don't expand_leftover_cleanups. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 4e66a30..827e904 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -5148,8 +5148,9 @@ build_op_delete_call (code, addr, size, flags) is the allocation expression, so extract the info we need from it. Obviously, if the build_new process changes this may have to change as well. */ - /* The SAVE_EXPR. */ - tree t = TREE_OPERAND (addr, 0); + + /* The NOP_EXPR. */ + tree t = TREE_OPERAND (addr, 1); /* The CALL_EXPR. */ t = TREE_OPERAND (t, 0); /* The function. */ @@ -5158,6 +5159,9 @@ build_op_delete_call (code, addr, size, flags) argtypes = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (argtypes))); /* The second argument. */ args = TREE_CHAIN (TREE_OPERAND (t, 1)); + + /* Pull the dummy var out of the TARGET_EXPR for use in our call. */ + addr = TREE_OPERAND (addr, 0); } else { diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 186b6c3..b275a3a 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -2248,7 +2248,7 @@ build_new (placement, decl, init, use_global_new) { tree type, true_type, size, rval; tree nelts; - tree alloc_expr; + tree alloc_expr, alloc_node; int has_array = 0; enum tree_code code = NEW_EXPR; int use_cookie, nothrow, check_new; @@ -2527,17 +2527,11 @@ build_new (placement, decl, init, use_global_new) } check_new = flag_check_new || nothrow; - if (flag_exceptions && rval) + if ((check_new || flag_exceptions) && rval) { - /* This must last longer so we can use it in the cleanup. - The subexpressions don't need to last, because we won't look at - them when expanding the cleanup. */ - int yes = suspend_momentary (); - alloc_expr = rval = save_expr (rval); - resume_momentary (yes); + alloc_expr = get_target_expr (rval); + alloc_node = rval = TREE_OPERAND (alloc_expr, 0); } - else if (check_new && rval) - alloc_expr = rval = save_expr (rval); else alloc_expr = NULL_TREE; @@ -2726,8 +2720,8 @@ build_new (placement, decl, init, use_global_new) the memory in which the object was being constructed. */ if (flag_exceptions && alloc_expr) { - enum tree_code dcode = has_array? VEC_DELETE_EXPR : DELETE_EXPR; - tree cleanup, args = NULL_TREE; + enum tree_code dcode = has_array ? VEC_DELETE_EXPR : DELETE_EXPR; + tree cleanup; int flags = LOOKUP_NORMAL | (use_global_new * LOOKUP_GLOBAL); /* All cleanups must last longer than normal. */ @@ -2739,18 +2733,53 @@ build_new (placement, decl, init, use_global_new) /* Copy size to the saveable obstack. */ size = copy_node (size); - cleanup = build_op_delete_call (dcode, alloc_expr, size, flags); + /* If we have a new-placement, we need to pass the alloc TARGET_EXPR + to build_op_delete_call so it can extract the args. */ + cleanup = build_op_delete_call + (dcode, placement ? alloc_expr : alloc_node, size, flags); resume_momentary (yes); + /* Ack! First we allocate the memory. Then we set our sentry + variable to true, and expand a cleanup that deletes the memory + if sentry is true. Then we run the constructor and store the + returned pointer in buf. Then we clear sentry and return buf. */ + if (cleanup) { +#if 0 + /* Disable this until flow is fixed so that it doesn't + think the initialization of sentry is a dead write. */ + tree end, sentry, begin, buf, t = TREE_TYPE (rval); + + begin = get_target_expr (boolean_true_node); + sentry = TREE_OPERAND (begin, 0); + + yes = suspend_momentary (); + TREE_OPERAND (begin, 2) + = build (COND_EXPR, void_type_node, sentry, + cleanup, void_zero_node); + resume_momentary (yes); + + rval = get_target_expr (rval); + + end = build (MODIFY_EXPR, TREE_TYPE (sentry), + sentry, boolean_false_node); + TREE_SIDE_EFFECTS (end) = 1; + + buf = TREE_OPERAND (rval, 0); + + rval = build (COMPOUND_EXPR, t, begin, + build (COMPOUND_EXPR, t, rval, + build (COMPOUND_EXPR, t, end, buf))); +#else /* FIXME: this is a workaround for a crash due to overlapping exception regions. Cleanups shouldn't really happen here. */ rval = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (rval), rval); rval = build (TRY_CATCH_EXPR, TREE_TYPE (rval), rval, cleanup); rval = build (COMPOUND_EXPR, TREE_TYPE (rval), alloc_expr, rval); +#endif } } } @@ -2759,14 +2788,23 @@ build_new (placement, decl, init, use_global_new) done: - if (check_new && alloc_expr && rval != alloc_expr) + if (alloc_expr && rval == alloc_node) + { + rval = TREE_OPERAND (alloc_expr, 1); + alloc_expr = NULL_TREE; + } + + if (check_new && alloc_expr) { /* Did we modify the storage? */ - tree ifexp = build_binary_op (NE_EXPR, alloc_expr, + tree ifexp = build_binary_op (NE_EXPR, alloc_node, integer_zero_node, 1); - rval = build_conditional_expr (ifexp, rval, alloc_expr); + rval = build_conditional_expr (ifexp, rval, alloc_node); } + if (alloc_expr) + rval = build (COMPOUND_EXPR, TREE_TYPE (rval), alloc_expr, rval); + if (rval && TREE_TYPE (rval) != build_pointer_type (type)) { /* The type of new int [3][3] is not int *, but int [3] * */ |