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;
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))
{
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)
--- /dev/null
+// 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 ();
+}