When mangling an ARRAY_TYPE whose element type is a typedef variant and whose domain is a type-dependent expression, we get an ICE when canonicalize_for_substitution() tries to create a canonical version of this ARRAY_TYPE with its element type being stripped of typedefs.
During this canonicalization we call build_cplus_array_type which builds dependent and non-dependent array types differently. But because at this this point (during mangling) we are outside of a template decl, the function wrongly thinks that the array type being built is non-dependent according to dependent_type_p(). Because it's considered to be non-dependent we build the type with build_array_type() which tries to lay the type out and eventually we ICE because of its dependent TYPE_DOMAIN. So to fix this, the check for type-dependentness in build_cplus_array_type() should not depend on processing_template_decl. This patch makes uses_template_parms() get used instead so that it behaves properly outside of a template context, like during mangling. Does this look OK to commit after bootstrap + regtest? gcc/cp/ChangeLog: PR c++/62212 * tree.c (build_cplus_array_type): Determine type-dependentess with uses_template_parms instead of with dependent_type_p. gcc/testsuite/ChangeLog: PR c++/62212 * g++.dg/template/mangle2.C: New test. --- gcc/cp/tree.c | 5 ++--- gcc/testsuite/g++.dg/template/mangle2.C | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/mangle2.C diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index f784952..5d9de34 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -824,9 +824,8 @@ build_cplus_array_type (tree elt_type, tree index_type) if (elt_type == error_mark_node || index_type == error_mark_node) return error_mark_node; - bool dependent = (processing_template_decl - && (dependent_type_p (elt_type) - || (index_type && dependent_type_p (index_type)))); + bool dependent = (uses_template_parms (elt_type) + || (index_type && uses_template_parms (index_type))); if (elt_type != TYPE_MAIN_VARIANT (elt_type)) /* Start with an array of the TYPE_MAIN_VARIANT. */ diff --git a/gcc/testsuite/g++.dg/template/mangle2.C b/gcc/testsuite/g++.dg/template/mangle2.C new file mode 100644 index 0000000..50b0d9f --- /dev/null +++ b/gcc/testsuite/g++.dg/template/mangle2.C @@ -0,0 +1,19 @@ +// PR c++/62212 +// { dg-do assemble } + +typedef int my_int; + +template<typename T> +struct X { + enum {value = 1}; +}; + +template<typename T> +void f(const my_int(&)[X<T>::value]); + +int main() { + const my_int a[1] = {}; + f<void>(a); +} + +// { dg-final { scan-assembler "_Z1fIvEvRAsr1XIT_E5value_Ki" } } -- 2.8.0.rc3.27.gade0865