My patch for 71747 missed this case; we only want to consider the innermost args in the call to coerce_template_parms, just like in unification and comparison.
Tested x86_64-pc-linux-gnu, applying to trunk and 7.
commit 33e24de5519e868a915ccee6fcfee362870930f6 Author: Jason Merrill <ja...@redhat.com> Date: Thu Jun 15 18:00:47 2017 -0400 PR c++/80174 - ICE with partial specialization of member template. PR c++/71747 * pt.c (get_partial_spec_bindings): Only coerce innermost args. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 8a61b74..b055507 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -21676,9 +21676,11 @@ get_partial_spec_bindings (tree tmpl, tree spec_tmpl, tree args) `T' is `A' but unify () does not check whether `typename T::X' is `int'. */ spec_args = tsubst (spec_args, deduced_args, tf_none, NULL_TREE); - spec_args = coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (tmpl), - spec_args, tmpl, - tf_none, false, false); + + if (spec_args != error_mark_node) + spec_args = coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (tmpl), + INNERMOST_TEMPLATE_ARGS (spec_args), + tmpl, tf_none, false, false); pop_tinst_level (); diff --git a/gcc/testsuite/g++.dg/template/partial-specialization6.C b/gcc/testsuite/g++.dg/template/partial-specialization6.C new file mode 100644 index 0000000..51a1590 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/partial-specialization6.C @@ -0,0 +1,28 @@ +// PR c++/80174 + +typedef unsigned char uint8_t; + +template <typename T> +struct HighestMaxFieldIdx { + static const uint8_t maxFieldIdx = T::fieldIdx; +}; + +template <typename This> +struct Outer { + + template <uint8_t _fieldIdx, typename T, T This::*field> + struct Varint {}; + + + template <uint8_t _fieldIdx, uint8_t This::*field> + struct Varint<_fieldIdx, uint8_t, field> { + static const uint8_t fieldIdx = _fieldIdx; + }; +}; + +struct Msg { + uint8_t a; + + static const uint8_t t + = HighestMaxFieldIdx<Outer<Msg>::Varint<1, uint8_t, &Msg::a> >::maxFieldIdx; +};