PR c++/80174 - ICE with partial specialization of member template.
authorJason Merrill <jason@redhat.com>
Sat, 17 Jun 2017 02:27:52 +0000 (22:27 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Sat, 17 Jun 2017 02:27:52 +0000 (22:27 -0400)
PR c++/71747
* pt.c (get_partial_spec_bindings): Only coerce innermost args.

From-SVN: r249319

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/g++.dg/template/partial-specialization6.C [new file with mode: 0644]

index 48a9cf698fe34494da5fc49631dcfccea72d48bf..330f0f205a0c685e7b2fb24f08db889fc2ab650a 100644 (file)
@@ -1,5 +1,9 @@
 2017-06-16  Jason Merrill  <jason@redhat.com>
 
+       PR c++/80174 - ICE with partial specialization of member template.
+       PR c++/71747
+       * pt.c (get_partial_spec_bindings): Only coerce innermost args.
+
        PR c++/80831 - ICE with -fsyntax-only.
        * decl2.c (c_parse_final_cleanups): Use cgraph_node::get_create.
 
index 3dad0fc67417708d4525d6186b9d200bbbc254b1..0a5816303472f216734f1a5cbb78881853750f4a 100644 (file)
@@ -21672,9 +21672,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 (file)
index 0000000..51a1590
--- /dev/null
@@ -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;
+};