The issue here was that check_array_designated_initializer did constant folding to produce a constant index, but then left the un-folded value behind to confuse complete_array_type. Fixed by updating ce->value with the folded value. We should also use fold_non_dependent_expr, and handle dependent designators.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit 095a2dc5c8523e01367d9604f1e47849f7b4dcd9 Author: Jason Merrill <ja...@redhat.com> Date: Thu Apr 5 13:10:01 2018 -0400 PR c++/85136 - ICE with designated init in template. * decl.c (maybe_deduce_size_from_array_init): Handle dependent designated initializer. (check_array_designated_initializer): Update ce->index with the constant value. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 489dcc0a8ed..86251f51eb4 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5415,12 +5415,15 @@ check_array_designated_initializer (constructor_elt *ce, ce->index, true); if (ce_index && INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (ce_index)) - && (TREE_CODE (ce_index = maybe_constant_value (ce_index)) + && (TREE_CODE (ce_index = fold_non_dependent_expr (ce_index)) == INTEGER_CST)) { /* A C99 designator is OK if it matches the current index. */ if (wi::to_wide (ce_index) == index) - return true; + { + ce->index = ce_index; + return true; + } else sorry ("non-trivial designated initializers not supported"); } @@ -5463,8 +5466,12 @@ maybe_deduce_size_from_array_init (tree decl, tree init) constructor_elt *ce; HOST_WIDE_INT i; FOR_EACH_VEC_SAFE_ELT (v, i, ce) - if (!check_array_designated_initializer (ce, i)) - failure = 1; + { + if (instantiation_dependent_expression_p (ce->index)) + return; + if (!check_array_designated_initializer (ce, i)) + failure = 1; + } } if (failure) diff --git a/gcc/testsuite/g++.dg/ext/desig11.C b/gcc/testsuite/g++.dg/ext/desig11.C new file mode 100644 index 00000000000..34bfbe1044e --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/desig11.C @@ -0,0 +1,15 @@ +// PR c++/85136 +// { dg-options "" } + +enum { e }; + +template<int I> void f() +{ + const int x[] = { [e] = 0 }; + const int y[] = { [I] = 0 }; +} + +int main() +{ + f<0>(); +}