aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2007-06-12 17:47:37 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2007-06-12 17:47:37 +0000
commit058dcc25b74ed4d171182311a12d27272844ee16 (patch)
tree10cbad9d2cb8a5b2d59d7944bd237eecb6610348 /gcc/cp
parent52a39a4c5db03b2e614f4bde1632e025348d1ebe (diff)
downloadgcc-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/ChangeLog6
-rw-r--r--gcc/cp/init.c77
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;
}