C++ PATCH for c++/85049, ICE with integer_sequence

Message ID CADzB+2kdTR=PR8g2+ctUej2bSsAyD3dkHsQYOPb8c8f7fBzb_A@mail.gmail.com
State New
Headers show
Series
  • C++ PATCH for c++/85049, ICE with integer_sequence
Related show

Commit Message

Jason Merrill March 26, 2018, 2:37 p.m.
In this testcase, we tried to deduce template arguments between
__integer_pack(sizeof...(_Types)) and an empty argument list.  This
breaks, and we shouldn't try anyway, since that's very much a
non-deduced context.  So let's skip over packs that aren't actual
template parameter packs.

Tested x86_64-pc-linux-gnu, applying to trunk.

Patch

commit f5e979b7434f372028215a9209f4b8076fab97d7
Author: Jason Merrill <jason@redhat.com>
Date:   Sat Mar 24 07:45:02 2018 -0400

            PR c++/85049 - ICE with __integer_pack.
    
            * pt.c (unify_pack_expansion): Don't try to deduce generated packs.
            * cp-tree.h (TEMPLATE_PARM_P): New.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index c8f4bc43fa3..db79338035d 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4554,6 +4554,12 @@  more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
        || TREE_CODE (NODE) == TYPE_DECL		\
        || TREE_CODE (NODE) == TEMPLATE_DECL))
 
+/* Nonzero for a raw template parameter node.  */
+#define TEMPLATE_PARM_P(NODE)					\
+  (TREE_CODE (NODE) == TEMPLATE_TYPE_PARM			\
+   || TREE_CODE (NODE) == TEMPLATE_TEMPLATE_PARM		\
+   || TREE_CODE (NODE) == TEMPLATE_PARM_INDEX)
+
 /* Mark NODE as a template parameter.  */
 #define SET_DECL_TEMPLATE_PARM_P(NODE) \
   (DECL_LANG_FLAG_0 (NODE) = 1)
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 9cf03f45e24..d6cce3e67da 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -20645,6 +20645,11 @@  unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
       tree parm_pack = TREE_VALUE (pack);
       int idx, level;
 
+      /* Only template parameter packs can be deduced, not e.g. function
+	 parameter packs or __bases or __integer_pack.  */
+      if (!TEMPLATE_PARM_P (parm_pack))
+	continue;
+
       /* Determine the index and level of this parameter pack.  */
       template_parm_level_and_index (parm_pack, &level, &idx);
       if (level < levels)
diff --git a/gcc/testsuite/g++.dg/ext/integer-pack3.C b/gcc/testsuite/g++.dg/ext/integer-pack3.C
new file mode 100644
index 00000000000..d3ed1363016
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/integer-pack3.C
@@ -0,0 +1,21 @@ 
+// PR c++/85049
+// { dg-do compile { target c++11 } }
+
+typedef __SIZE_TYPE__ size_t;
+template<typename _Tp, _Tp... _Idx>
+struct integer_sequence
+{
+  typedef _Tp value_type;
+  static constexpr size_t size() noexcept { return sizeof...(_Idx); }
+};
+template<typename _Tp, _Tp _Num>
+using make_integer_sequence = integer_sequence<_Tp, __integer_pack(_Num)...>;
+template<size_t _Num>
+using make_index_sequence = make_integer_sequence<size_t, _Num>;
+template<typename... _Types>
+using index_sequence_for = make_index_sequence<sizeof...(_Types)>;
+template <typename...>
+struct tuple {};
+template <typename... Ts>
+int get(tuple<index_sequence_for<Ts...>, Ts...>);
+int x = get(tuple<index_sequence_for<>>{});