diff mbox

[C++] PR 51448, 53618, 58059

Message ID 53B333AF.1020707@oracle.com
State New
Headers show

Commit Message

Paolo Carlini July 1, 2014, 10:18 p.m. UTC
Hi,

some time ago I started analyzing the bugs in Bugzilla involving crashes 
for too deep recursive template instantiation and figured out that this 
subset is probably the simplest to tackle 
(https://gcc.gnu.org/ml/gcc-patches/2013-08/msg01348.html). All these 
crashes involve instantiate_class_template_1 *before* the existing 
push_tinst_level check, via most_specialized_class, and I think it makes 
sense to protect it in a way very similar to that used in 
maybe_instantiate_noexcept. Lately I also tried simply moving the 
existing check before most_specialized_class and it mostly worked for 
C++, but regressions showed up in the libstdc++-v3 testsuite (mostly in 
20_util). As regards the testcases, template/recurse.C is tweaked 
because the diagnostic about template instantiation depth exceed is 
exactly the same but isn't duplicated anymore.

Anyway, tested x86_64-linux.

Thanks,
Paolo.

/////////////////////////
/cp
2014-07-01  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/51488
	PR c++/53618
	PR c++/58059
	* pt.c (instantiate_class_template_1): Call push_tinst_level /
	pop_tinst_level around most_specialized_class.

/testsuite
2014-07-01  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/51488
	PR c++/53618
	PR c++/58059
	* g++.dg/cpp0x/template-recurse1.C: New.
	* g++.dg/template/recurse4.C: Likewise.
	* g++.dg/template/recurse.C: Adjust.

Comments

Paolo Carlini July 2, 2014, 3:06 p.m. UTC | #1
.. consider this patch withdrawn. I believe that something is going 
wrong indeed as part of most_specialized_instantiation but the details 
need to be figured out. I'm now focusing on fn_type_unification via 
get_bindings.

Paolo.
Paolo Carlini July 2, 2014, 3:15 p.m. UTC | #2
Hi again,

On 07/02/2014 05:06 PM, Paolo Carlini wrote:
> .. consider this patch withdrawn. I believe that something is going 
> wrong indeed as part of most_specialized_instantiation but the details 
> need to be figured out. I'm now focusing on fn_type_unification via 
> get_bindings.
In fact my typo above most_specialized_instantiation vs most_specialized 
class reveals something: we don't seem to have an analogous for 
*classes*  of the mechanism implemented in fn_type_unification for 
functions, and all the testcases I'm handling involve *classes*.

Paolo.
diff mbox

Patch

Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 212204)
+++ cp/pt.c	(working copy)
@@ -8905,8 +8911,15 @@  instantiate_class_template_1 (tree type)
   gcc_assert (TREE_CODE (templ) == TEMPLATE_DECL);
 
   /* Determine what specialization of the original template to
-     instantiate.  */
-  t = most_specialized_class (type, tf_warning_or_error);
+     instantiate. Note: protect vs too deep instantiation.  */
+  if (push_tinst_level (type))
+    {
+      t = most_specialized_class (type, tf_warning_or_error);
+      pop_tinst_level ();
+    }
+  else
+    t = error_mark_node;
+
   if (t == error_mark_node)
     {
       TYPE_BEING_DEFINED (type) = 1;
Index: testsuite/g++.dg/cpp0x/template-recurse1.C
===================================================================
--- testsuite/g++.dg/cpp0x/template-recurse1.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/template-recurse1.C	(working copy)
@@ -0,0 +1,25 @@ 
+// PR c++/58059
+// { dg-do compile { target c++11 } }
+
+template<bool, typename T = void> struct enable_if { typedef T type; };
+template<typename T> struct enable_if<false, T> { };
+
+// This code is nonsense; it was produced by minimizing the problem repeatedly.
+constexpr bool test_func(int value) {
+  return true;
+}
+template <int TParm, class Enable=void>
+struct test_class {
+  static constexpr int value = 0;
+};
+template <int TParm>
+struct test_class<
+    TParm,
+    // This line ultimately causes the crash.
+    typename enable_if<test_func(test_class<TParm-1>::value)>::type  // { dg-error "depth exceeds" }
+    > {
+  static constexpr int value = 1;
+};
+
+// This instantiation is required in order to crash.
+template class test_class<2,void>;
Index: testsuite/g++.dg/template/recurse.C
===================================================================
--- testsuite/g++.dg/template/recurse.C	(revision 212204)
+++ testsuite/g++.dg/template/recurse.C	(working copy)
@@ -5,9 +5,7 @@  template <int I> struct F
 {
   int operator()()
     {
-      F<I+1> f;			// { dg-error "incomplete type" "incomplete" }
-				// { dg-bogus "exceeds maximum.*exceeds maximum" "exceeds" { xfail *-*-* } 8 }
-                                // { dg-error "exceeds maximum" "exceeds" { xfail *-*-* } 8 }
+      F<I+1> f;			// { dg-error "depth exceeds|incomplete" }
       return f()*I;             // { dg-message "recursively" "recurse" }
     }
 };
Index: testsuite/g++.dg/template/recurse4.C
===================================================================
--- testsuite/g++.dg/template/recurse4.C	(revision 0)
+++ testsuite/g++.dg/template/recurse4.C	(working copy)
@@ -0,0 +1,5 @@ 
+// PR c++/51488
+
+template<class T,class U=void> struct s;
+template<class T> struct s<T,typename s<T>::a> {};
+s<int> ca;  // { dg-error "depth exceeds|incomplete" }