diff options
author | Ian Lance Taylor <iant@google.com> | 2007-06-12 17:47:37 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2007-06-12 17:47:37 +0000 |
commit | 058dcc25b74ed4d171182311a12d27272844ee16 (patch) | |
tree | 10cbad9d2cb8a5b2d59d7944bd237eecb6610348 /gcc/cp | |
parent | 52a39a4c5db03b2e614f4bde1632e025348d1ebe (diff) | |
download | gcc-058dcc25b74ed4d171182311a12d27272844ee16.zip gcc-058dcc25b74ed4d171182311a12d27272844ee16.tar.gz gcc-058dcc25b74ed4d171182311a12d27272844ee16.tar.bz2 |
re PR libstdc++/29286 (placement new does not change the dynamic type as it should)
./: PR libstdc++/29286
* tree.def: Add CHANGE_DYNAMIC_TYPE_EXPR.
* tree.h (CHANGE_DYNAMIC_TYPE_NEW_TYPE): Define.
(CHANGE_DYNAMIC_TYPE_LOCATION): Define.
(DECL_NO_TBAA_P): Define.
(struct tree_decl_common): Add no_tbaa_flag field.
* tree-ssa-structalias.c (struct variable_info): Add
no_tbaa_pruning field.
(new_var_info): Initialize no_tbaa_pruning field.
(unify_nodes): Copy no_tbaa_pruning field.
(find_func_aliases): Handle CHANGE_DYNAMIC_TYPE_EXPR.
(dump_solution_for_var): Print no_tbaa_pruning flag.
(set_uids_in_ptset): Add no_tbaa_pruning parameter. Change all
callers.
(compute_tbaa_pruning): New static function.
(compute_points_to_sets): Remove CHANGE_DYNAMIC_TYPE_EXPR nodes.
Call compute_tbaa_pruning.
* tree-ssa-alias.c (may_alias_p): Test no_tbaa_flag for pointers.
* gimplify.c (gimplify_expr): Handle CHANGE_DYNAMIC_TYPE_EXPR.
* gimple-low.c (lower_stmt): Likewise.
* tree-gimple.c (is_gimple_stmt): Likewise.
* tree-ssa-operands.c (get_expr_operands): Likewise.
* tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Likewise.
* tree-inline.c (estimate_num_insns_1): Likewise.
(copy_result_decl_to_var): Likewise.
* expr.c (expand_expr_real_1): Likewise.
* tree-pretty-print.c (dump_generic_node): Likewise.
* tree-inline.c (copy_decl_to_var): Copy DECL_NO_TBAA_P flag.
* omp-low.c (omp_copy_decl_2): Likewise.
* print-tree.c (print_node): Print DECL_NO_TBAA_P flag.
* doc/c-tree.texi (Expression trees): Document
CHANGE_DYNAMIC_TYPE_EXPR.
cp/:
PR libstdc++/29286
* init.c (avoid_placement_new_aliasing): New static function.
(build_new_1): Call it.
testsuite/:
PR libstdc++/29286
* g++.dg/init/new16.C: New test.
* g++.dg/init/new17.C: New test.
* g++.dg/init/new18.C: New test.
* g++.dg/init/new19.C: New test.
Co-Authored-By: Daniel Berlin <dberlin@dberlin.org>
From-SVN: r125653
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/init.c | 77 |
2 files changed, 81 insertions, 2 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3f010ae..f9ca050 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2007-06-12 Ian Lance Taylor <iant@google.com> + + PR libstdc++/29286 + * init.c (avoid_placement_new_aliasing): New static function. + (build_new_1): Call it. + 2007-06-11 Rafael Avila de Espindola <espindola@google.com> * cp-objcp-common.h (LANG_HOOKS_SIGNED_TYPE): Remove. diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 3023cf0..aecbed9 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1,6 +1,7 @@ /* Handle initialization things in C++. Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 + Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. @@ -1564,6 +1565,55 @@ build_raw_new_expr (tree placement, tree type, tree nelts, tree init, return new_expr; } +/* Make sure that there are no aliasing issues with T, a placement new + expression applied to PLACEMENT, by recording the change in dynamic + type. If placement new is inlined, as it is with libstdc++, and if + the type of the placement new differs from the type of the + placement location itself, then alias analysis may think it is OK + to interchange writes to the location from before the placement new + and from after the placement new. We have to prevent type-based + alias analysis from applying. PLACEMENT may be NULL, which means + that we couldn't capture it in a temporary variable, in which case + we use a memory clobber. */ + +static tree +avoid_placement_new_aliasing (tree t, tree placement) +{ + tree type_change; + + if (processing_template_decl) + return t; + + /* If we are not using type based aliasing, we don't have to do + anything. */ + if (!flag_strict_aliasing) + return t; + + /* If we have a pointer and a location, record the change in dynamic + type. Otherwise we need a general memory clobber. */ + if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE + && placement != NULL_TREE + && TREE_CODE (TREE_TYPE (placement)) == POINTER_TYPE) + type_change = build_stmt (CHANGE_DYNAMIC_TYPE_EXPR, + TREE_TYPE (t), + placement); + else + { + /* Build a memory clobber. */ + type_change = build_stmt (ASM_EXPR, + build_string (0, ""), + NULL_TREE, + NULL_TREE, + tree_cons (NULL_TREE, + build_string (6, "memory"), + NULL_TREE)); + + ASM_VOLATILE_P (type_change) = 1; + } + + return build2 (COMPOUND_EXPR, TREE_TYPE (t), type_change, t); +} + /* Generate code for a new-expression, including calling the "operator new" function, initializing the object, and, if an exception occurs during construction, cleaning up. The arguments are as for @@ -1607,6 +1657,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, beginning of the storage allocated for an array-new expression in order to store the number of elements. */ tree cookie_size = NULL_TREE; + tree placement_var; /* True if the function we are calling is a placement allocation function. */ bool placement_allocation_fn_p; @@ -1700,6 +1751,20 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, alloc_fn = NULL_TREE; + /* If PLACEMENT is a simple pointer type, then copy it into + PLACEMENT_VAR. */ + if (processing_template_decl + || placement == NULL_TREE + || TREE_CHAIN (placement) != NULL_TREE + || TREE_CODE (TREE_TYPE (TREE_VALUE (placement))) != POINTER_TYPE) + placement_var = NULL_TREE; + else + { + placement_var = get_temp_regvar (TREE_TYPE (TREE_VALUE (placement)), + TREE_VALUE (placement)); + placement = tree_cons (NULL_TREE, placement_var, NULL_TREE); + } + /* Allocate the object. */ if (! placement && TYPE_FOR_JAVA (elt_type)) { @@ -1792,7 +1857,12 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, /* 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); + { + rval = build_nop (pointer_type, alloc_call); + if (placement != NULL) + rval = avoid_placement_new_aliasing (rval, placement_var); + 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 @@ -2052,6 +2122,9 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, /* A new-expression is never an lvalue. */ gcc_assert (!lvalue_p (rval)); + if (placement != NULL) + rval = avoid_placement_new_aliasing (rval, placement_var); + return rval; } |