aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2006-12-05 21:33:20 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2006-12-05 21:33:20 +0000
commit762397797c7ad0027a174c3dded91b08c6e1fa58 (patch)
tree615ab278e6376f78e4fd3323c4d3270ec787283e /gcc
parent8424e0d8b1ab427cd5801a6774109bff1860bfa0 (diff)
downloadgcc-762397797c7ad0027a174c3dded91b08c6e1fa58.zip
gcc-762397797c7ad0027a174c3dded91b08c6e1fa58.tar.gz
gcc-762397797c7ad0027a174c3dded91b08c6e1fa58.tar.bz2
re PR c++/29728 (ICE on invalid initializer in template function)
PR c++/29728 * decl.c (check_array_designated_initializer): New function. (maybe_deduce_size_from_array_init): Use it. (reshape_init_array): Likewise. PR c++/29728 * g++.dg/template/crash62.C: New test. From-SVN: r119558
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/decl.c95
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/template/crash62.C6
4 files changed, 82 insertions, 31 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 8c57d4f..d9de361 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2006-12-05 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/29728
+ * decl.c (check_array_designated_initializer): New function.
+ (maybe_deduce_size_from_array_init): Use it.
+ (reshape_init_array): Likewise.
+
2006-12-05 Aldy Hernandez <aldyh@redhat.com>
Merge from gimple-tuples-branch.
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 8a55e41..1edd7ea 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -4092,6 +4092,30 @@ grok_reference_init (tree decl, tree type, tree init, tree *cleanup)
return NULL_TREE;
}
+/* Designated initializers in arrays are not supported in GNU C++.
+ The parser cannot detect this error since it does not know whether
+ a given brace-enclosed initializer is for a class type or for an
+ array. This function checks that CE does not use a designated
+ initializer. If it does, an error is issued. Returns true if CE
+ is valid, i.e., does not have a designated initializer. */
+
+static bool
+check_array_designated_initializer (const constructor_elt *ce)
+{
+ /* Designated initializers for array elements arenot supported. */
+ if (ce->index)
+ {
+ /* The parser only allows identifiers as designated
+ intializers. */
+ gcc_assert (TREE_CODE (ce->index) == IDENTIFIER_NODE);
+ error ("name %qD used in a GNU-style designated "
+ "initializer for an array", ce->index);
+ return false;
+ }
+
+ return true;
+}
+
/* When parsing `int a[] = {1, 2};' we don't know the size of the
array until we finish parsing the initializer. If that's the
situation we're in, update DECL accordingly. */
@@ -4109,32 +4133,52 @@ maybe_deduce_size_from_array_init (tree decl, tree init)
But let's leave it here to ease the eventual merge. */
int do_default = !DECL_EXTERNAL (decl);
tree initializer = init ? init : DECL_INITIAL (decl);
- int failure = cp_complete_array_type (&TREE_TYPE (decl), initializer,
- do_default);
+ int failure = 0;
- if (failure == 1)
+ /* Check that there are no designated initializers in INIT, as
+ those are not supported in GNU C++, and as the middle-end
+ will crash if presented with a non-numeric designated
+ initializer. */
+ if (initializer && TREE_CODE (initializer) == CONSTRUCTOR)
{
- error ("initializer fails to determine size of %qD", decl);
- TREE_TYPE (decl) = error_mark_node;
+ VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (initializer);
+ constructor_elt *ce;
+ HOST_WIDE_INT i;
+ for (i = 0;
+ VEC_iterate (constructor_elt, v, i, ce);
+ ++i)
+ if (!check_array_designated_initializer (ce))
+ failure = 1;
}
- else if (failure == 2)
+
+ if (!failure)
{
- if (do_default)
+ failure = cp_complete_array_type (&TREE_TYPE (decl), initializer,
+ do_default);
+ if (failure == 1)
{
- error ("array size missing in %qD", decl);
+ error ("initializer fails to determine size of %qD", decl);
+ TREE_TYPE (decl) = error_mark_node;
+ }
+ else if (failure == 2)
+ {
+ if (do_default)
+ {
+ error ("array size missing in %qD", decl);
+ TREE_TYPE (decl) = error_mark_node;
+ }
+ /* If a `static' var's size isn't known, make it extern as
+ well as static, so it does not get allocated. If it's not
+ `static', then don't mark it extern; finish_incomplete_decl
+ will give it a default size and it will get allocated. */
+ else if (!pedantic && TREE_STATIC (decl) && !TREE_PUBLIC (decl))
+ DECL_EXTERNAL (decl) = 1;
+ }
+ else if (failure == 3)
+ {
+ error ("zero-size array %qD", decl);
TREE_TYPE (decl) = error_mark_node;
}
- /* If a `static' var's size isn't known, make it extern as
- well as static, so it does not get allocated. If it's not
- `static', then don't mark it extern; finish_incomplete_decl
- will give it a default size and it will get allocated. */
- else if (!pedantic && TREE_STATIC (decl) && !TREE_PUBLIC (decl))
- DECL_EXTERNAL (decl) = 1;
- }
- else if (failure == 3)
- {
- error ("zero-size array %qD", decl);
- TREE_TYPE (decl) = error_mark_node;
}
cp_apply_type_quals_to_decl (cp_type_quals (TREE_TYPE (decl)), decl);
@@ -4346,18 +4390,7 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d)
{
tree elt_init;
- if (d->cur->index)
- {
- /* Handle array designated initializers (GNU extension). */
- if (TREE_CODE (d->cur->index) == IDENTIFIER_NODE)
- {
- error ("name %qD used in a GNU-style designated "
- "initializer for an array", d->cur->index);
- }
- else
- gcc_unreachable ();
- }
-
+ check_array_designated_initializer (d->cur);
elt_init = reshape_init_r (elt_type, d, /*first_initializer_p=*/false);
if (elt_init == error_mark_node)
return error_mark_node;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index dc199b6..d7bae48 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2006-12-05 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/29728
+ * g++.dg/template/crash62.C: New test.
+
2006-12-05 Paul Thomas <pault@gcc.gnu.org>
PR fortran/30003
diff --git a/gcc/testsuite/g++.dg/template/crash62.C b/gcc/testsuite/g++.dg/template/crash62.C
new file mode 100644
index 0000000..bd8a0f4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/crash62.C
@@ -0,0 +1,6 @@
+// PR c++/29728
+
+template<int> void foo()
+{
+ int a[] = { X: 0 }; // { dg-error "designated initializer" }
+}