PR c++/34862
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 12 Feb 2008 16:25:47 +0000 (16:25 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 12 Feb 2008 16:25:47 +0000 (16:25 +0000)
* init.c (build_new_1): Don't create placement_expr before
constructing alloc_call.  Verify that the pointer is passed by
value to operator new.

* g++.dg/init/new27.C: New test.

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

gcc/cp/ChangeLog
gcc/cp/init.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/init/new27.C [new file with mode: 0644]

index c11dcd5..943eef3 100644 (file)
@@ -1,3 +1,10 @@
+2008-02-12  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/34862
+       * init.c (build_new_1): Don't create placement_expr before
+       constructing alloc_call.  Verify that the pointer is passed by
+       value to operator new.
+
 2008-02-11  Jason Merrill  <jason@redhat.com>
 
        PR c++/35097
index ec59207..040b335 100644 (file)
@@ -1800,7 +1800,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_expr;
+  tree placement_expr = NULL_TREE;
   /* True if the function we are calling is a placement allocation
      function.  */
   bool placement_allocation_fn_p;
@@ -1892,19 +1892,6 @@ 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_EXPR.  */
-  if (processing_template_decl
-      || placement == NULL_TREE
-      || TREE_CHAIN (placement) != NULL_TREE
-      || TREE_CODE (TREE_TYPE (TREE_VALUE (placement))) != POINTER_TYPE)
-    placement_expr = NULL_TREE;
-  else
-    {
-      placement_expr = get_target_expr (TREE_VALUE (placement));
-      placement = tree_cons (NULL_TREE, placement_expr, NULL_TREE);
-    }
-
   /* Allocate the object.  */
   if (! placement && TYPE_FOR_JAVA (elt_type))
     {
@@ -1999,6 +1986,28 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
 
   gcc_assert (alloc_fn != NULL_TREE);
 
+  /* If PLACEMENT is a simple pointer type and is not passed by reference,
+     then copy it into PLACEMENT_EXPR.  */
+  if (!processing_template_decl
+      && placement != NULL_TREE
+      && TREE_CHAIN (placement) == NULL_TREE
+      && TREE_CODE (TREE_TYPE (TREE_VALUE (placement))) == POINTER_TYPE
+      && TREE_CODE (alloc_call) == CALL_EXPR
+      && call_expr_nargs (alloc_call) == 2
+      && TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (alloc_call, 0))) == INTEGER_TYPE
+      && TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (alloc_call, 1))) == POINTER_TYPE)
+    {
+      tree placement_arg = CALL_EXPR_ARG (alloc_call, 1);
+
+      if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (placement_arg)))
+         || VOID_TYPE_P (TREE_TYPE (TREE_TYPE (placement_arg))))
+       {
+         placement_expr = get_target_expr (TREE_VALUE (placement));
+         CALL_EXPR_ARG (alloc_call, 1)
+           = convert (TREE_TYPE (placement_arg), placement_expr);
+       }
+    }
+
   /* In the simple case, we can stop now.  */
   pointer_type = build_pointer_type (type);
   if (!cookie_size && !is_initialized)
index 4ac1835..091bb28 100644 (file)
@@ -1,3 +1,8 @@
+2008-02-12  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/34862
+       * g++.dg/init/new27.C: New test.
+
 2008-02-11  Paolo Carlini  <pcarlini@suse.de>
 
        PR c++/35077
diff --git a/gcc/testsuite/g++.dg/init/new27.C b/gcc/testsuite/g++.dg/init/new27.C
new file mode 100644 (file)
index 0000000..a6271c9
--- /dev/null
@@ -0,0 +1,40 @@
+// PR c++/34862
+// { dg-do run }
+// { dg-options "-O2" }
+
+typedef __SIZE_TYPE__ size_t;
+extern "C" void abort ();
+
+struct T
+{
+  void *operator new (size_t, char *&);
+  T () { i[0] = 1; i[1] = 2; }
+  int i[2];
+};
+
+void *
+T::operator new (size_t size, char *&p)
+{
+  void *o = (void *) p;
+  p += size;
+  return o;
+}
+
+T *
+f (char *&x)
+{
+  return new (x) T ();
+}
+
+char buf[10 * sizeof (T)] __attribute__((aligned (__alignof (T))));
+
+int
+main ()
+{
+  char *p = buf;
+  T *t = f (p);
+  if (p != buf + sizeof (T))
+    abort ();
+  if (t->i[0] != 1 || t->i[1] != 2)
+    abort ();
+}