In trying to decide if the constraints on the partial specialization subsume those on the primary template, we consider whether any of the constraints on the primary template imply the type constraint typename list<Seqs...>. We don't have any matching constraints on the primary template, so we look to see if there are any non-atomic constraints that we might be able to decompose in order to produce a match. This function doesn't know how to handle the pack expansion Sequence<Seqs>... and so it crashes.
A pack expansion isn't really atomic, but it also won't decompose any further, so treating it as non-atomic here leads to an infinite loop; treating it as atomic, as 6.1 did, fixes the testcase. Tested x86_64-pc-linux-gnu, applying to trunk and 6.
commit 5b8341e2a06c9dead76cba2485a2e0633badbac0 Author: Jason Merrill <ja...@redhat.com> Date: Thu Aug 11 11:15:13 2016 -0400 PR c++/73456 - ICE with constrained parameter pack. * logic.cc (non_atomic_constraint_p): Handle EXPR_PACK_EXPANSION. diff --git a/gcc/cp/logic.cc b/gcc/cp/logic.cc index dda98df..b86e740 100644 --- a/gcc/cp/logic.cc +++ b/gcc/cp/logic.cc @@ -305,6 +305,9 @@ non_atomic_constraint_p (tree t) case ICONV_CONSTR: case DEDUCT_CONSTR: case EXCEPT_CONSTR: + /* A pack expansion isn't atomic, but it can't decompose to prove an + atom, so it shouldn't cause analyze_atom to return undecided. */ + case EXPR_PACK_EXPANSION: return false; case CHECK_CONSTR: case PARM_CONSTR: diff --git a/gcc/testsuite/g++.dg/concepts/variadic4.C b/gcc/testsuite/g++.dg/concepts/variadic4.C new file mode 100644 index 0000000..d20fa7d --- /dev/null +++ b/gcc/testsuite/g++.dg/concepts/variadic4.C @@ -0,0 +1,20 @@ +// PR c++/73456 +// { dg-options "-std=c++1z -fconcepts" } + +template<typename...> struct list {}; + +template<typename Seq> +concept bool Sequence = true; + +template<Sequence... Seqs> +struct zip; + +template<Sequence... Seqs> + requires requires { typename list<Seqs...>; } +// main.cpp:12:8: internal compiler error: in non_atomic_constraint_p, at cp/logic.cc:315 +struct zip<Seqs...> {}; + +int main() +{ + zip<list<>, list<int>> {}; +}