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:
parent
c27fb14bda
commit
1ea193c21f
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
|
14
gcc/tree.h
14
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.) */
|
||||
|
|
Loading…
Reference in New Issue