aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2009-07-12 15:19:03 -0400
committerJason Merrill <jason@gcc.gnu.org>2009-07-12 15:19:03 -0400
commit25357d1ee0ce69a5b1c194e7e1c7b6437c189b01 (patch)
tree43c0739a8937332d11e29f2a24b12fe31e9a6a6d
parentf345f84ae69406344bbc74ff0c72904e317ad4fe (diff)
downloadgcc-25357d1ee0ce69a5b1c194e7e1c7b6437c189b01.zip
gcc-25357d1ee0ce69a5b1c194e7e1c7b6437c189b01.tar.gz
gcc-25357d1ee0ce69a5b1c194e7e1c7b6437c189b01.tar.bz2
re PR c++/40689 ([C++0x]: error with initializer list in N2672)
PR c++/40689 * init.c (build_new_1): Handle initializer list as array initializer. (build_vec_init): Likewise. * typeck.c (cp_build_modify_expr): Likewise. * typeck2.c (process_init_constructor_array): Error rather than abort if too many initializers. From-SVN: r149533
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/init.c39
-rw-r--r--gcc/cp/typeck.c10
-rw-r--r--gcc/cp/typeck2.c7
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist20.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist21.C18
7 files changed, 93 insertions, 13 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index c29e32d..cff424f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,12 @@
+2009-07-12 Jason Merrill <jason@redhat.com>
+
+ PR c++/40689
+ * init.c (build_new_1): Handle initializer list as array initializer.
+ (build_vec_init): Likewise.
+ * typeck.c (cp_build_modify_expr): Likewise.
+ * typeck2.c (process_init_constructor_array): Error rather than abort
+ if too many initializers.
+
2009-07-10 Jakub Jelinek <jakub@redhat.com>
PR c++/40502
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 68ffe3a..19b2489 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -1773,6 +1773,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
/* The type of the new-expression. (This type is always a pointer
type.) */
tree pointer_type;
+ tree non_const_pointer_type;
tree outer_nelts = NULL_TREE;
tree alloc_call, alloc_expr;
/* The address returned by the call to "operator new". This node is
@@ -2076,9 +2077,15 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
}
/* Now use a pointer to the type we've actually allocated. */
- data_addr = fold_convert (pointer_type, data_addr);
+
+ /* But we want to operate on a non-const version to start with,
+ since we'll be modifying the elements. */
+ non_const_pointer_type = build_pointer_type
+ (cp_build_qualified_type (type, TYPE_QUALS (type) & ~TYPE_QUAL_CONST));
+
+ data_addr = fold_convert (non_const_pointer_type, data_addr);
/* Any further uses of alloc_node will want this type, too. */
- alloc_node = fold_convert (pointer_type, alloc_node);
+ alloc_node = fold_convert (non_const_pointer_type, alloc_node);
/* Now initialize the allocated object. Note that we preevaluate the
initialization expression, apart from the actual constructor call or
@@ -2098,12 +2105,32 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
if (array_p)
{
- if (*init)
+ tree vecinit = NULL_TREE;
+ if (*init && VEC_length (tree, *init) == 1
+ && BRACE_ENCLOSED_INITIALIZER_P (VEC_index (tree, *init, 0))
+ && CONSTRUCTOR_IS_DIRECT_INIT (VEC_index (tree, *init, 0)))
+ {
+ tree arraytype, domain;
+ vecinit = VEC_index (tree, *init, 0);
+ if (TREE_CONSTANT (nelts))
+ domain = compute_array_index_type (NULL_TREE, nelts);
+ else
+ {
+ domain = NULL_TREE;
+ if (CONSTRUCTOR_NELTS (vecinit) > 0)
+ warning (0, "non-constant array size in new, unable to "
+ "verify length of initializer-list");
+ }
+ arraytype = build_cplus_array_type (type, domain);
+ vecinit = digest_init (arraytype, vecinit);
+ }
+ else if (*init)
{
if (complain & tf_error)
permerror (input_location, "ISO C++ forbids initialization in array new");
else
return error_mark_node;
+ vecinit = build_tree_list_vec (*init);
}
init_expr
= build_vec_init (data_addr,
@@ -2111,7 +2138,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
MINUS_EXPR, outer_nelts,
integer_one_node,
complain),
- build_tree_list_vec (*init),
+ vecinit,
explicit_value_init_p,
/*from_array=*/0,
complain);
@@ -2270,7 +2297,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
/* A new-expression is never an lvalue. */
gcc_assert (!lvalue_p (rval));
- return rval;
+ return convert (pointer_type, rval);
}
/* Generate a representation for a C++ "new" expression. *PLACEMENT
@@ -2664,6 +2691,7 @@ build_vec_init (tree base, tree maxindex, tree init,
inner_elt_type = strip_array_types (type);
if (init
+ && TREE_CODE (atype) == ARRAY_TYPE
&& (from_array == 2
? (!CLASS_TYPE_P (inner_elt_type)
|| !TYPE_HAS_COMPLEX_ASSIGN_REF (inner_elt_type))
@@ -2679,7 +2707,6 @@ build_vec_init (tree base, tree maxindex, tree init,
brace-enclosed initializers. In this case, digest_init and
store_constructor will handle the semantics for us. */
- gcc_assert (TREE_CODE (atype) == ARRAY_TYPE);
stmt_expr = build2 (INIT_EXPR, atype, base, init);
return stmt_expr;
}
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 871c1d3..6a4802e 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -6202,8 +6202,11 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
{
int from_array;
- if (!same_or_base_type_p (TYPE_MAIN_VARIANT (lhstype),
- TYPE_MAIN_VARIANT (TREE_TYPE (rhs))))
+ if (BRACE_ENCLOSED_INITIALIZER_P (rhs))
+ rhs = digest_init (lhstype, rhs);
+
+ else if (!same_or_base_type_p (TYPE_MAIN_VARIANT (lhstype),
+ TYPE_MAIN_VARIANT (TREE_TYPE (rhs))))
{
if (complain & tf_error)
error ("incompatible types in assignment of %qT to %qT",
@@ -6212,7 +6215,8 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
}
/* Allow array assignment in compiler-generated code. */
- if (!current_function_decl || !DECL_ARTIFICIAL (current_function_decl))
+ else if (!current_function_decl
+ || !DECL_ARTIFICIAL (current_function_decl))
{
/* This routine is used for both initialization and assignment.
Make sure the diagnostic message differentiates the context. */
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index c43fd76..d68383e 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -913,10 +913,9 @@ process_init_constructor_array (tree type, tree init)
/* Vectors are like simple fixed-size arrays. */
len = TYPE_VECTOR_SUBPARTS (type);
- /* There cannot be more initializers than needed as otherwise
- reshape_init would have already rejected the initializer. */
- if (!unbounded)
- gcc_assert (VEC_length (constructor_elt, v) <= len);
+ /* There must not be more initializers than needed. */
+ if (!unbounded && VEC_length (constructor_elt, v) > len)
+ error ("too many initializers for %qT", type);
for (i = 0; VEC_iterate (constructor_elt, v, i, ce); ++i)
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7df599e..a12a5d2 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2009-07-12 Jason Merrill <jason@redhat.com>
+
+ PR c++/40689
+ * g++.dg/cpp0x/initlist20.C: New.
+ * g++.dg/cpp0x/initlist21.C: New.
+
2009-07-12 Ira Rosen <irar@il.ibm.com>
* gcc.dg/vect/no-scevccp-outer-2.c: Expect to vectorize.
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist20.C b/gcc/testsuite/g++.dg/cpp0x/initlist20.C
new file mode 100644
index 0000000..fcdb73f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist20.C
@@ -0,0 +1,17 @@
+// PR c++/40689
+// { dg-options "-std=c++0x" }
+
+class X
+{
+ public:
+ X(): data {1,2,3,4,5} {}
+ private:
+ const short data[5];
+};
+
+int main()
+{
+ const float * pData = new const float[4] { 1.5, 2.5, 3.5, 4.5 };
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist21.C b/gcc/testsuite/g++.dg/cpp0x/initlist21.C
new file mode 100644
index 0000000..9412a08
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist21.C
@@ -0,0 +1,18 @@
+// PR c++/40689
+// { dg-options "-std=c++0x" }
+
+class X
+{
+ public:
+ X(): data {1,2} {} // { dg-error "too many initializers" }
+ private:
+ const short data[1];
+};
+
+int f(int n)
+{
+ const float * pData = new const float[1] { 1.5, 2.5 }; // { dg-error "too many initializers" }
+ pData = new const float[n] { 1.5, 2.5 }; // { dg-warning "array size" }
+
+ return 0;
+}