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
This commit is contained in:
Ian Lance Taylor 2008-01-18 15:25:02 +00:00 committed by Ian Lance Taylor
parent c27fb14bda
commit 1ea193c21f
8 changed files with 108 additions and 9 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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.) */