OSDN Git Service

PR c++/33407
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 18 Jan 2008 15:25:02 +0000 (15:25 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 18 Jan 2008 15:25:02 +0000 (15:25 +0000)
./:
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@131629 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/c-decl.c
gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/init/new26.C [new file with mode: 0644]
gcc/tree-inline.c
gcc/tree.h

index 8099410..a4c939c 100644 (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
index 9237a75..860b337 100644 (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);
        }
index 030232b..91909a1 100644 (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
index 11a5c47..4b2a55f 100644 (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
index 3e7ee20..cc3ec9c 100644 (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
diff --git a/gcc/testsuite/g++.dg/init/new26.C b/gcc/testsuite/g++.dg/init/new26.C
new file mode 100644 (file)
index 0000000..541de30
--- /dev/null
@@ -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;
+}
index 6ac367e..1fe0847 100644 (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
index f61085d..52cb973 100644 (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.) */