diff options
author | Mark Mitchell <mark@codesourcery.com> | 2006-12-05 21:33:20 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2006-12-05 21:33:20 +0000 |
commit | 762397797c7ad0027a174c3dded91b08c6e1fa58 (patch) | |
tree | 615ab278e6376f78e4fd3323c4d3270ec787283e /gcc | |
parent | 8424e0d8b1ab427cd5801a6774109bff1860bfa0 (diff) | |
download | gcc-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/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/decl.c | 95 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/crash62.C | 6 |
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" } +} |