PR c++/81866 - ICE with member template and default targ.
authorJason Merrill <jason@redhat.com>
Wed, 3 Apr 2019 21:51:36 +0000 (17:51 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 3 Apr 2019 21:51:36 +0000 (17:51 -0400)
This testcase manages to find a way to look up the partial instantiation of
B for the default argument of C before we've created the partial
instantiation of B as part of the normal instantiation of the members of A.
Which we can deal with, but we were getting confused because the partial
instantiation was stored with a RECORD_TYPE specialization rather than
TEMPLATE_DECL.

* pt.c (tsubst_template_decl): Handle getting a type from
retrieve_specialization.

From-SVN: r270138

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

index 91d1431..888b431 100644 (file)
@@ -1,5 +1,9 @@
 2019-04-03  Jason Merrill  <jason@redhat.com>
 
+       PR c++/81866 - ICE with member template and default targ.
+       * pt.c (tsubst_template_decl): Handle getting a type from
+       retrieve_specialization.
+
        PR c++/86586 - -fcompare-debug=-Wsign-compare.
        * typeck.c (cp_build_binary_op): Don't fold for -Wsign-compare.
 
index 2b92b60..9cb29d2 100644 (file)
@@ -13266,7 +13266,13 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t complain,
       hash = hash_tmpl_and_args (t, full_args);
       spec = retrieve_specialization (t, full_args, hash);
       if (spec != NULL_TREE)
-       return spec;
+       {
+         if (TYPE_P (spec))
+           /* Type partial instantiations are stored as the type by
+              lookup_template_class_1, not here as the template.  */
+           spec = CLASSTYPE_TI_TEMPLATE (spec);
+         return spec;
+       }
     }
 
   /* Make a new template decl.  It will be similar to the
diff --git a/gcc/testsuite/g++.dg/template/memtmpl6.C b/gcc/testsuite/g++.dg/template/memtmpl6.C
new file mode 100644 (file)
index 0000000..9ce35ab
--- /dev/null
@@ -0,0 +1,13 @@
+// PR c++/81866
+
+template<class>
+struct A {
+  template<class> struct C;
+  template<class> struct B;
+  template<class T = B<int> > struct C {};
+};
+
+int main() {
+  A<int>::C<> ac;
+  return 0;
+}