Patchwork [C++,RFC,/] Another recursive template instantiation issue (c++/51488, etc)

login
register
mail settings
Submitter Paolo Carlini
Date Aug. 23, 2013, 1:13 p.m.
Message ID <52175FE1.9060409@oracle.com>
Download mbox | patch
Permalink /patch/269448/
State New
Headers show

Comments

Paolo Carlini - Aug. 23, 2013, 1:13 p.m.
Hi,

besides the issue discussed a bit some time ago, we have got in Bugzilla 
a number of other issues, all essentially dups of each other (modulo 
irrelevant details, AFAICS)

     c++/51488
     c++/53618
     c++/58059
     c++/56163 (this is two bugs, the second one is dup of c++/55843)

In these the infinite recursion involves instantiate_class_template_1 
but via most_specialized_class (c++/51488 has a backtrace) thus at the 
beginning of the function, and we don't catch it.

To explain *in practice* what I mean, the attached patchlet p avoid all 
these crashes (+ passes the testsuite as-is modulo an XPASS for line 8 
of template/recurse.C).

Unfortunately, at the time I didn't follow in detail the implementation 
of the push_tinst_level mechanism, now I see it used many times with 
little variations, thus I definitely need further guidance (my patchlet 
is loosely inspired by the use in maybe_instantiate_noexcept). In 
particular, I fear memory leaks or mismanagement (I see a ggc_free 
(tinst); in instantiate_alias_template which I don't fully understand).

Also, I wonder if we could provide more detailed information...

Thanks in advance!
Paolo.

///////////////////////////

Patch

Index: pt.c
===================================================================
--- pt.c	(revision 201927)
+++ pt.c	(working copy)
@@ -8658,7 +8658,15 @@  instantiate_class_template_1 (tree type)
 
   /* Determine what specialization of the original template to
      instantiate.  */
-  t = most_specialized_class (type, templ, tf_warning_or_error);
+
+  if (push_tinst_level (type))
+    {
+      t = most_specialized_class (type, templ, tf_warning_or_error);
+      pop_tinst_level ();
+    }
+  else
+    t = error_mark_node;
+
   if (t == error_mark_node)
     {
       TYPE_BEING_DEFINED (type) = 1;