aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2008-01-18 15:25:02 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2008-01-18 15:25:02 +0000
commit1ea193c21f060b7e7837138122b24c9d07f57d57 (patch)
treef599ef6905608f93f1d83e94f82e9ef89480d5b3 /gcc
parentc27fb14bda0b2c82c0fe8413e3e2f805c1d58975 (diff)
downloadgcc-1ea193c21f060b7e7837138122b24c9d07f57d57.zip
gcc-1ea193c21f060b7e7837138122b24c9d07f57d57.tar.gz
gcc-1ea193c21f060b7e7837138122b24c9d07f57d57.tar.bz2
re PR c++/33407 (C++ operator new and new expression do not change dynamic type)
PR c++/33407 ./: * tree.h (DECL_IS_OPERATOR_NEW): Define. (struct tree_function_decl): Add new field operator_new_flag. * tree-inline.c (expand_call_inline): When inlining a call to operator new, force the return value to go into a variable, and set DECL_NO_TBAA_P on that variable. * c-decl.c (merge_decls): Merge DECL_IS_OPERATOR_NEW flag. cp/: * decl.c (duplicate_decls): Copy DECL_IS_OPERATOR_NEW flag. (grok_op_properties): For NEW_EXPR and VEC_NEW_EXPR set DECL_IS_OPERATOR_NEW flag. testsuite/: * g++.dg/init/new26.C: New test. From-SVN: r131629
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/c-decl.c4
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/decl.c9
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/init/new26.C44
-rw-r--r--gcc/tree-inline.c24
-rw-r--r--gcc/tree.h14
8 files changed, 108 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8099410..a4c939c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+2008-01-18 Ian Lance Taylor <iant@google.com>
+
+ PR c++/33407
+ * tree.h (DECL_IS_OPERATOR_NEW): Define.
+ (struct tree_function_decl): Add new field operator_new_flag.
+ * tree-inline.c (expand_call_inline): When inlining a call to
+ operator new, force the return value to go into a variable, and
+ set DECL_NO_TBAA_P on that variable.
+ * c-decl.c (merge_decls): Merge DECL_IS_OPERATOR_NEW flag.
+
2008-01-18 Uros Bizjak <ubizjak@gmail.com>
PR debug/34484
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 9237a75..860b337 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -1,6 +1,7 @@
/* Process declarations and variables for C compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ Free Software Foundation, Inc.
This file is part of GCC.
@@ -1740,6 +1741,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
+ DECL_IS_OPERATOR_NEW (newdecl) |= DECL_IS_OPERATOR_NEW (olddecl);
DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl);
DECL_IS_NOVOPS (newdecl) |= DECL_IS_NOVOPS (olddecl);
}
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 030232b..91909a1 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2008-01-18 Ian Lance Taylor <iant@google.com>
+
+ PR c++/33407
+ * decl.c (duplicate_decls): Copy DECL_IS_OPERATOR_NEW flag.
+ (grok_op_properties): For NEW_EXPR and VEC_NEW_EXPR set
+ DECL_IS_OPERATOR_NEW flag.
+
2008-01-16 Richard Guenther <rguenther@suse.de>
PR c++/33819
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 11a5c47..4b2a55f 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -1,6 +1,7 @@
/* Process declarations and variables for C++ compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
@@ -1804,6 +1805,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
TREE_NOTHROW (newdecl) |= TREE_NOTHROW (olddecl);
DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
+ DECL_IS_OPERATOR_NEW (newdecl) |= DECL_IS_OPERATOR_NEW (olddecl);
DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl);
/* Keep the old RTL. */
COPY_DECL_RTL (olddecl, newdecl);
@@ -9761,7 +9763,10 @@ grok_op_properties (tree decl, bool complain)
}
if (operator_code == NEW_EXPR || operator_code == VEC_NEW_EXPR)
- TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
+ {
+ TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
+ DECL_IS_OPERATOR_NEW (decl) = 1;
+ }
else if (operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR)
TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
else
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 3e7ee20..cc3ec9c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2008-01-18 Ian Lance Taylor <iant@google.com>
+
+ PR c++/33407
+ * g++.dg/init/new26.C: New test.
+
2008-01-18 Richard Guenther <rguenther@suse.de>
PR middle-end/34801
diff --git a/gcc/testsuite/g++.dg/init/new26.C b/gcc/testsuite/g++.dg/init/new26.C
new file mode 100644
index 0000000..541de30
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/new26.C
@@ -0,0 +1,44 @@
+// PR c++/33407
+// { dg-do run }
+// { dg-options "-O2 -fstrict-aliasing" }
+
+extern "C" void * malloc(__SIZE_TYPE__);
+extern "C" void abort(void);
+
+void *p;
+void __attribute__((noinline)) init(void)
+{
+ p = malloc(4);
+}
+
+inline void *operator new(__SIZE_TYPE__)
+{
+ return p;
+}
+
+inline void operator delete (void*) {}
+
+int * __attribute__((noinline)) doit(int n)
+{
+ float *q;
+ int *r;
+
+ for (int i=0; i<n; ++i)
+ {
+ q = new float;
+ *q = 1.0;
+ delete q;
+ r = new int;
+ *r = 1;
+ }
+
+ return r;
+}
+
+int main()
+{
+ init();
+ if (*doit(1) != 1)
+ abort();
+ return 0;
+}
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 6ac367e..1fe0847 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -2567,7 +2567,7 @@ expand_call_inline (basic_block bb, tree stmt, tree *tp, void *data)
{
copy_body_data *id;
tree t;
- tree use_retvar;
+ tree retvar, use_retvar;
tree fn;
struct pointer_map_t *st;
tree return_slot;
@@ -2769,9 +2769,27 @@ expand_call_inline (basic_block bb, tree stmt, tree *tp, void *data)
else
modify_dest = NULL;
+ /* If we are inlining a call to the C++ operator new, we don't want
+ to use type based alias analysis on the return value. Otherwise
+ we may get confused if the compiler sees that the inlined new
+ function returns a pointer which was just deleted. See bug
+ 33407. */
+ if (DECL_IS_OPERATOR_NEW (fn))
+ {
+ return_slot = NULL;
+ modify_dest = NULL;
+ }
+
/* Declare the return variable for the function. */
- declare_return_variable (id, return_slot,
- modify_dest, &use_retvar);
+ retvar = declare_return_variable (id, return_slot,
+ modify_dest, &use_retvar);
+
+ if (DECL_IS_OPERATOR_NEW (fn))
+ {
+ gcc_assert (TREE_CODE (retvar) == VAR_DECL
+ && POINTER_TYPE_P (TREE_TYPE (retvar)));
+ DECL_NO_TBAA_P (retvar) = 1;
+ }
/* This is it. Duplicate the callee body. Assume callee is
pre-gimplified. Note that we must not alter the caller
diff --git a/gcc/tree.h b/gcc/tree.h
index f61085d..52cb973 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1,6 +1,7 @@
/* Front-end tree definitions for GNU compiler.
Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ Free Software Foundation, Inc.
This file is part of GCC.
@@ -3241,6 +3242,12 @@ struct tree_decl_non_common GTY(())
not an alias. */
#define DECL_IS_MALLOC(NODE) (FUNCTION_DECL_CHECK (NODE)->function_decl.malloc_flag)
+/* Nonzero in a FUNCTION_DECL means this function should be treated as
+ C++ operator new, meaning that it returns a pointer for which we
+ should not use type based aliasing. */
+#define DECL_IS_OPERATOR_NEW(NODE) \
+ (FUNCTION_DECL_CHECK (NODE)->function_decl.operator_new_flag)
+
/* Nonzero in a FUNCTION_DECL means this function may return more
than once. */
#define DECL_IS_RETURNS_TWICE(NODE) \
@@ -3345,16 +3352,17 @@ struct tree_function_decl GTY(())
unsigned novops_flag : 1;
unsigned returns_twice_flag : 1;
unsigned malloc_flag : 1;
+ unsigned operator_new_flag : 1;
unsigned pure_flag : 1;
unsigned declared_inline_flag : 1;
unsigned regdecl_flag : 1;
- unsigned inline_flag : 1;
+ unsigned inline_flag : 1;
unsigned no_instrument_function_entry_exit : 1;
unsigned no_limit_stack : 1;
unsigned disregard_inline_limits : 1;
- /* 5 bits left */
+ /* 4 bits left */
};
/* For a TYPE_DECL, holds the "original" type. (TREE_TYPE has the copy.) */