aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/init.c64
-rw-r--r--gcc/cp/tree.c45
-rw-r--r--gcc/cp/typeck.c2
-rw-r--r--gcc/testsuite/g++.dg/expr/anew4.C3
-rw-r--r--gcc/testsuite/g++.dg/init/value3.C31
-rw-r--r--gcc/testsuite/g++.dg/lookup/new1.C4
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr31146-2.C2
9 files changed, 117 insertions, 46 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index e98283a..f01593d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,14 @@
+2008-07-31 Jason Merrill <jason@redhat.com>
+
+ PR c++/11309
+ * tree.c (build_aggr_init_expr): Split out...
+ (build_cplus_new): ...from here.
+ (stabilize_init): Don't mess with AGGR_INIT_EXPR either.
+ * init.c (build_new_1): new T() means value-initialization,
+ not default-initialization.
+ (build_vec_init): Likewise.
+ (build_value_init_1): Use build_aggr_init_expr.
+
2008-07-30 Dodji Seketeli <dseketel@redhat.com>
PR c++/36767
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index f9a2af8..02d358a 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4742,6 +4742,7 @@ extern tree build_min_nt (enum tree_code, ...);
extern tree build_min_non_dep (enum tree_code, tree, ...);
extern tree build_min_non_dep_call_list (tree, tree, tree);
extern tree build_cplus_new (tree, tree);
+extern tree build_aggr_init_expr (tree, tree);
extern tree get_target_expr (tree);
extern tree build_cplus_array_type (tree, tree);
extern tree build_array_of_n_type (tree, int);
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 3deb85d..5535033 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -347,7 +347,7 @@ build_value_init_1 (tree type, bool have_ctor)
if (CLASS_TYPE_P (type))
{
if (type_has_user_provided_constructor (type) && !have_ctor)
- return build_cplus_new
+ return build_aggr_init_expr
(type,
build_special_member_call (NULL_TREE, complete_ctor_identifier,
NULL_TREE, type, LOOKUP_NORMAL,
@@ -511,7 +511,7 @@ perform_member_init (tree member, tree init)
{
/* Initialization of one array from another. */
finish_expr_stmt (build_vec_init (decl, NULL_TREE, TREE_VALUE (init),
- /*explicit_default_init_p=*/false,
+ /*explicit_value_init_p=*/false,
/* from_array=*/1,
tf_warning_or_error));
}
@@ -1286,7 +1286,7 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain)
if (itype && cp_type_quals (itype) != TYPE_UNQUALIFIED)
itype = TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype);
stmt_expr = build_vec_init (exp, NULL_TREE, init,
- /*explicit_default_init_p=*/false,
+ /*explicit_value_init_p=*/false,
itype && same_type_p (itype,
TREE_TYPE (exp)),
complain);
@@ -2154,19 +2154,19 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
if (is_initialized)
{
bool stable;
+ bool explicit_value_init_p = false;
init_expr = cp_build_indirect_ref (data_addr, NULL, complain);
- if (array_p)
+ if (init == void_zero_node)
{
- bool explicit_default_init_p = false;
+ init = NULL_TREE;
+ explicit_value_init_p = true;
+ }
- if (init == void_zero_node)
- {
- init = NULL_TREE;
- explicit_default_init_p = true;
- }
- else if (init)
+ if (array_p)
+ {
+ if (init)
{
if (complain & tf_error)
permerror ("ISO C++ forbids initialization in array new");
@@ -2179,7 +2179,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
integer_one_node,
complain),
init,
- explicit_default_init_p,
+ explicit_value_init_p,
/*from_array=*/0,
complain);
@@ -2190,17 +2190,19 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
}
else
{
- if (init == void_zero_node)
- init = build_default_init (full_type, nelts);
-
- if (TYPE_NEEDS_CONSTRUCTING (type))
+ if (TYPE_NEEDS_CONSTRUCTING (type) && !explicit_value_init_p)
{
init_expr = build_special_member_call (init_expr,
complete_ctor_identifier,
init, elt_type,
LOOKUP_NORMAL,
complain);
- stable = stabilize_init (init_expr, &init_preeval_expr);
+ }
+ else if (explicit_value_init_p)
+ {
+ /* Something like `new int()'. */
+ init_expr = build2 (INIT_EXPR, full_type,
+ init_expr, build_value_init (full_type));
}
else
{
@@ -2216,8 +2218,8 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
init_expr = cp_build_modify_expr (init_expr, INIT_EXPR, init,
complain);
- stable = stabilize_init (init_expr, &init_preeval_expr);
}
+ stable = stabilize_init (init_expr, &init_preeval_expr);
}
if (init_expr == error_mark_node)
@@ -2662,8 +2664,8 @@ get_temp_regvar (tree type, tree init)
INIT is the (possibly NULL) initializer.
- If EXPLICIT_DEFAULT_INIT_P is true, then INIT must be NULL. All
- elements in the array are default-initialized.
+ If EXPLICIT_VALUE_INIT_P is true, then INIT must be NULL. All
+ elements in the array are value-initialized.
FROM_ARRAY is 0 if we should init everything with INIT
(i.e., every element initialized from INIT).
@@ -2674,7 +2676,7 @@ get_temp_regvar (tree type, tree init)
tree
build_vec_init (tree base, tree maxindex, tree init,
- bool explicit_default_init_p,
+ bool explicit_value_init_p,
int from_array, tsubst_flags_t complain)
{
tree rval;
@@ -2704,7 +2706,7 @@ build_vec_init (tree base, tree maxindex, tree init,
if (maxindex == NULL_TREE || maxindex == error_mark_node)
return error_mark_node;
- if (explicit_default_init_p)
+ if (explicit_value_init_p)
gcc_assert (!init);
inner_elt_type = strip_array_types (atype);
@@ -2840,7 +2842,7 @@ build_vec_init (tree base, tree maxindex, tree init,
We do need to keep going if we're copying an array. */
if (from_array
- || ((TYPE_NEEDS_CONSTRUCTING (type) || explicit_default_init_p)
+ || ((TYPE_NEEDS_CONSTRUCTING (type) || explicit_value_init_p)
&& ! (host_integerp (maxindex, 0)
&& (num_initialized_elts
== tree_low_cst (maxindex, 0) + 1))))
@@ -2889,17 +2891,17 @@ build_vec_init (tree base, tree maxindex, tree init,
("cannot initialize multi-dimensional array with initializer");
elt_init = build_vec_init (build1 (INDIRECT_REF, type, base),
0, 0,
- /*explicit_default_init_p=*/false,
+ explicit_value_init_p,
0, complain);
}
- else if (!TYPE_NEEDS_CONSTRUCTING (type))
- elt_init = (cp_build_modify_expr
- (to, INIT_EXPR,
- build_zero_init (type, size_one_node,
- /*static_storage_p=*/false),
- complain));
+ else if (explicit_value_init_p)
+ elt_init = build2 (INIT_EXPR, type, to,
+ build_value_init (type));
else
- elt_init = build_aggr_init (to, init, 0, complain);
+ {
+ gcc_assert (TYPE_NEEDS_CONSTRUCTING (type));
+ elt_init = build_aggr_init (to, init, 0, complain);
+ }
current_stmt_tree ()->stmts_are_full_exprs_p = 1;
finish_expr_stmt (elt_init);
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 50c3049..4114f86 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -339,15 +339,17 @@ build_aggr_init_array (tree return_type, tree fn, tree slot, int nargs,
}
/* INIT is a CALL_EXPR or AGGR_INIT_EXPR which needs info about its
- target. TYPE is the type that this initialization should appear to
- have.
+ target. TYPE is the type to be initialized.
- Build an encapsulation of the initialization to perform
- and return it so that it can be processed by language-independent
- and language-specific expression expanders. */
+ Build an AGGR_INIT_EXPR to represent the initialization. This function
+ differs from build_cplus_new in that an AGGR_INIT_EXPR can only be used
+ to initialize another object, whereas a TARGET_EXPR can either
+ initialize another object or create its own temporary object, and as a
+ result building up a TARGET_EXPR requires that the type's destructor be
+ callable. */
tree
-build_cplus_new (tree type, tree init)
+build_aggr_init_expr (tree type, tree init)
{
tree fn;
tree slot;
@@ -369,8 +371,6 @@ build_cplus_new (tree type, tree init)
&& TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
&& DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0)));
- slot = build_local_temp (type);
-
/* We split the CALL_EXPR into its function and its arguments here.
Then, in expand_expr, we put them back together. The reason for
this is that this expression might be a default argument
@@ -384,6 +384,8 @@ build_cplus_new (tree type, tree init)
type, don't mess with AGGR_INIT_EXPR. */
if (is_ctor || TREE_ADDRESSABLE (type))
{
+ slot = build_local_temp (type);
+
if (TREE_CODE(init) == CALL_EXPR)
rval = build_aggr_init_array (void_type_node, fn, slot,
call_expr_nargs (init),
@@ -398,6 +400,30 @@ build_cplus_new (tree type, tree init)
else
rval = init;
+ return rval;
+}
+
+/* INIT is a CALL_EXPR or AGGR_INIT_EXPR which needs info about its
+ target. TYPE is the type that this initialization should appear to
+ have.
+
+ Build an encapsulation of the initialization to perform
+ and return it so that it can be processed by language-independent
+ and language-specific expression expanders. */
+
+tree
+build_cplus_new (tree type, tree init)
+{
+ tree rval = build_aggr_init_expr (type, init);
+ tree slot;
+
+ if (TREE_CODE (rval) == AGGR_INIT_EXPR)
+ slot = AGGR_INIT_EXPR_SLOT (rval);
+ else if (TREE_CODE (rval) == CALL_EXPR)
+ slot = build_local_temp (type);
+ else
+ return rval;
+
rval = build_target_expr (slot, rval);
TARGET_EXPR_IMPLICIT_P (rval) = 1;
@@ -2687,7 +2713,8 @@ stabilize_init (tree init, tree *initp)
return true;
if (TREE_CODE (t) == INIT_EXPR
- && TREE_CODE (TREE_OPERAND (t, 1)) != TARGET_EXPR)
+ && TREE_CODE (TREE_OPERAND (t, 1)) != TARGET_EXPR
+ && TREE_CODE (TREE_OPERAND (t, 1)) != AGGR_INIT_EXPR)
{
TREE_OPERAND (t, 1) = stabilize_expr (TREE_OPERAND (t, 1), initp);
return true;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index ba1d028..feb6b5f 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -6114,7 +6114,7 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
from_array = TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE
? 1 + (modifycode != INIT_EXPR): 0;
return build_vec_init (lhs, NULL_TREE, newrhs,
- /*explicit_default_init_p=*/false,
+ /*explicit_value_init_p=*/false,
from_array, complain);
}
diff --git a/gcc/testsuite/g++.dg/expr/anew4.C b/gcc/testsuite/g++.dg/expr/anew4.C
index d86d525..4ce1d88 100644
--- a/gcc/testsuite/g++.dg/expr/anew4.C
+++ b/gcc/testsuite/g++.dg/expr/anew4.C
@@ -1,5 +1,4 @@
-// { dg-do run { xfail *-*-* } }
-// XFAILed until PR2123 is fixed
+// { dg-do run }
// PR 11228: array operator new, with zero-initialization and a variable sized array.
// Regression test for PR
// Author: Matt Austern <austern@apple.com>
diff --git a/gcc/testsuite/g++.dg/init/value3.C b/gcc/testsuite/g++.dg/init/value3.C
new file mode 100644
index 0000000..487baab
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/value3.C
@@ -0,0 +1,31 @@
+// Testcase for value-initialization in new-expressions.
+// { dg-do run }
+
+#include <stdlib.h>
+#include <string.h>
+
+// Make sure that we return memory that isn't already set to 0.
+void *operator new(size_t s)
+{
+ void *p = malloc (s);
+ memset (p, 42, s);
+ return p;
+}
+
+struct A { A() {} ~A() {} };
+struct B { A a; int i; };
+
+int main()
+{
+ B *p = new B();
+ if (p->i != 0)
+ abort();
+
+ p = new B[2]();
+ if (p[0].i != 0 || p[1].i != 0)
+ abort();
+
+ B(*p2)[2] = new B[2][2]();
+ if (p2[0][0].i != 0 || p2[0][1].i != 0)
+ abort();
+}
diff --git a/gcc/testsuite/g++.dg/lookup/new1.C b/gcc/testsuite/g++.dg/lookup/new1.C
index b9d0bef..ae11213 100644
--- a/gcc/testsuite/g++.dg/lookup/new1.C
+++ b/gcc/testsuite/g++.dg/lookup/new1.C
@@ -4,10 +4,10 @@
int main() {
int i;
- void* operator new(unsigned s, int* p);
+ void* operator new(__SIZE_TYPE__ s, int* p);
int* e = new(&i) int; // { dg-error "no matching function" }
int* f = new int;
return 0;
}
-// { dg-excess-errors "operator new" }
+// { dg-error "candidate" "" { target *-*-* } 0 }
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr31146-2.C b/gcc/testsuite/g++.dg/tree-ssa/pr31146-2.C
index 0fd6027..d2edb19 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/pr31146-2.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr31146-2.C
@@ -20,5 +20,5 @@ double foo (void)
return v.a[2];
}
-/* { dg-final { scan-tree-dump "Replaced .*iftmp.* != 0B. with .1" "forwprop1" } } */
+/* { dg-final { scan-tree-dump "Replaced .* != 0B. with .1" "forwprop1" } } */
/* { dg-final { cleanup-tree-dump "forwprop1" } } */