return 0;
}
+/* for_each_template_parm any_fn callback for complex_alias_template_p. */
+
+static int
+complex_pack_expansion_r (tree t, void *data_)
+{
+ /* An alias template with a pack expansion that expands a pack from the
+ enclosing class needs to be considered complex, to avoid confusion with
+ the same pack being used as an argument to the alias's own template
+ parameter (91966). */
+ if (!PACK_EXPANSION_P (t))
+ return 0;
+ struct uses_all_template_parms_data &data
+ = *(struct uses_all_template_parms_data*)data_;
+ for (tree pack = PACK_EXPANSION_PARAMETER_PACKS (t); pack;
+ pack = TREE_CHAIN (pack))
+ {
+ tree parm_pack = TREE_VALUE (pack);
+ if (!TEMPLATE_PARM_P (parm_pack))
+ continue;
+ int idx, level;
+ template_parm_level_and_index (parm_pack, &level, &idx);
+ if (level < data.level)
+ return 1;
+ }
+ return 0;
+}
+
static bool
complex_alias_template_p (const_tree tmpl)
{
for (int i = 0; i < len; ++i)
data.seen[i] = false;
- for_each_template_parm (pat, uses_all_template_parms_r, &data, NULL, true);
+ if (for_each_template_parm (pat, uses_all_template_parms_r, &data,
+ NULL, true, complex_pack_expansion_r))
+ return true;
for (int i = 0; i < len; ++i)
if (!data.seen[i])
return true;
--- /dev/null
+// PR c++/91966
+// { dg-do compile { target c++11 } }
+
+// Reduced to this include-free example. Further reduction is hard: Either
+// the bug(?) disappears, or the program becomes meaningless.
+
+template<class...>
+struct list {};
+
+struct nil;
+
+////////////////////////////////////////////////////////////////////////////////
+
+template<int n>
+struct number {
+ constexpr /*implicit*/ operator int() const { return n; }
+ using type = number<n>;
+};
+
+using false_ = number<0>;
+using true_ = number<1>;
+
+static_assert(!false_{}, "");
+static_assert(true_{}, "");
+
+template<int... ns> using numbers = list<number<ns>...>;
+
+////////////////////////////////////////////////////////////////////////////////
+
+template<class lhs, class rhs>
+struct less_impl;
+
+template<int lhs, int rhs>
+struct less_impl<number<lhs>, number<rhs>>
+ : number<(lhs < rhs)> {};
+
+template<class lhs, class rhs> using less = typename less_impl<lhs, rhs>::type;
+
+////////////////////////////////////////////////////////////////////////////////
+
+template<class v0, class... vs>
+struct sum_impl {
+ static_assert(sizeof...(vs) == 0, "see specialization");
+ using type = v0;
+};
+
+template<int v0, int v1, class... vs>
+struct sum_impl<number<v0>, number<v1>, vs...>
+ : sum_impl<number<v0 + v1>, vs...> {};
+
+template<class... nums> using sum = typename sum_impl<nums...>::type;
+
+////////////////////////////////////////////////////////////////////////////////
+
+template<class num>
+struct conditional_impl {
+ static_assert(num{}, "see specialization");
+
+ template<class T, class F>
+ using type = T;
+};
+
+template<>
+struct conditional_impl<false_> {
+ template<class T, class F>
+ using type = F;
+};
+
+template<class num, class T, class F>
+using conditional = typename conditional_impl<num>::template type<T, F>;
+
+////////////////////////////////////////////////////////////////////////////////
+
+template<class seq>
+struct min_filter_impl;
+
+template<class... nums>
+struct min_filter_impl<list<nums...>> {
+ template<class num>
+ using count_better_mins = sum<less<nums, num>...>;
+
+ using type = list<conditional<count_better_mins<nums>, nil, nums>...>;
+
+//using debug = list<conditional<count_better_mins<nums>, nil, void>...>;
+
+// error: expansion pattern 'conditional<typename sum_impl<less<nums, nums>...>::type, nil, void>' contains no parameter packs
+
+};
+
+template<class seq> using min_filter = typename min_filter_impl<seq>::type;
+
+////////////////////////////////////////////////////////////////////////////////
+
+void test_min_filter() {
+ using computed = min_filter<numbers<2, 7, 2>>;
+ using expected = list<number<2>, nil, number<2>>;
+ (void)(computed{} = expected{});// compiles for identical types
+
+// error: no match for 'operator=' (operand types are 'computed' {aka 'list<number<2>, number<7>, number<2> >'} and 'expected' {aka 'list<number<2>, nil, number<2> >'})
+
+}
+
+int main() {}