From 8d4f8401a4e58a8363b125a30d423f92c5e3c1c6 Mon Sep 17 00:00:00 2001
From: Andrew Sutton <asutton@lock3software.com>
Date: Mon, 18 Nov 2019 10:08:46 -0500
Subject: [PATCH 1/1] Prevent recursive satisfaction (PR c++/88395).

gcc/cp/
        * constraint.cc (satisfy_declaration_constraints): Push tinst levels
        around satisfaction.

gcc/testsuite/
	* g++.dg/cpp2a/concepts-pr88395.C: New.
	* g++.dg/cpp2a/concepts-recursive-sat1.C: New.
	* g++.dg/cpp2a/concepts-recursive-sat2.C: New.
	* g++.dg/cpp2a/concepts-recursive-sat3.C: New.
---
 gcc/cp/ChangeLog                              |  6 +++++
 gcc/cp/constraint.cc                          |  7 +++++-
 gcc/testsuite/ChangeLog                       |  8 +++++++
 gcc/testsuite/g++.dg/cpp2a/concepts-pr88395.C | 23 +++++++++++++++++++
 .../g++.dg/cpp2a/concepts-recursive-sat1.C    | 18 +++++++++++++++
 .../g++.dg/cpp2a/concepts-recursive-sat2.C    | 15 ++++++++++++
 .../g++.dg/cpp2a/concepts-recursive-sat3.C    | 12 ++++++++++
 7 files changed, 88 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-pr88395.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat1.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat2.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat3.C

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index dea4042272f..f1e343f1074 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2019-11-18  Andrew Sutton  <asutton@lock3software.com>
+
+	PR c++/88395
+	* constraint.cc (satisfy_declaration_constraints): Push tinst levels
+	around satisfaction.
+
 2019-11-12  Andrew Sutton  <asutton@lock3software.com>
 
 	Diagnose certain constraint errors as hard errors, but otherwise treat
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index b227e877856..0e5c4d448ea 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -2629,10 +2629,11 @@ satisfy_declaration_constraints (tree t, subst_info info)
 
   /* Get the normalized constraints.  */
   tree norm = NULL_TREE;
+  tree tmpl = NULL_TREE;
   tree args = NULL_TREE;
   if (tree ti = DECL_TEMPLATE_INFO (t))
     {
-      tree tmpl = TI_TEMPLATE (ti);
+      tmpl = TI_TEMPLATE (ti);
       norm = normalize_template_requirements (tmpl, info.noisy ());
 
       /* The initial parameter mapping is the complete set of
@@ -2648,9 +2649,13 @@ satisfy_declaration_constraints (tree t, subst_info info)
   tree result = boolean_true_node;
   if (norm)
     {
+      if (tmpl)
+	push_tinst_level (tmpl);
       push_access_scope (t);
       result = satisfy_associated_constraints (norm, args, info);
       pop_access_scope (t);
+      if (tmpl)
+	pop_tinst_level ();
     }
 
   if (info.quiet ())
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7595a16f81b..b1d1b04797c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2019-11-18  Andrew Sutton  <asutton@lock3software.com>
+
+	PR c++/88395
+	* g++.dg/cpp2a/concepts-pr88395.C: New.
+	* g++.dg/cpp2a/concepts-recursive-sat1.C: New.
+	* g++.dg/cpp2a/concepts-recursive-sat2.C: New.
+	* g++.dg/cpp2a/concepts-recursive-sat3.C: New.
+
 2019-11-12  Andrew Sutton  <asutton@lock3software.com>
 
 	Emit hard errors for certain satisfaction errors.
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr88395.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr88395.C
new file mode 100644
index 00000000000..ad24da9cb47
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr88395.C
@@ -0,0 +1,23 @@
+// { dg-do compile { target c++2a } }
+
+template <class T, class U>
+concept Concept2 = requires (T t, U u)
+{
+    t += u; // { dg-error "template instantiation depth" }
+};
+
+template <class T>
+concept Concept = Concept2 <T, T>;
+
+struct S
+{
+    template <Concept T>
+    constexpr S& operator += (T o);
+};
+
+constexpr S operator * (S a, S b)
+{
+    return a += b;
+}
+
+// { dg-prune-output "compilation terminated" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat1.C b/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat1.C
new file mode 100644
index 00000000000..ee83d560cf6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat1.C
@@ -0,0 +1,18 @@
+// { dg-do compile { target c++2a } }
+
+template<int N, typename T>
+concept Foo = requires(T t) { foo<N + 1>(t); }; // { dg-error "template instantiation depth" }
+
+template<int N = 1, typename T = int>
+  requires Foo<N, T>
+int foo(T t)
+{
+  return foo<N + 1>(t);
+}
+
+int main(int, char**)
+{
+  return foo<1>(1);
+}
+
+// { dg-prune-output "compilation terminated" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat2.C b/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat2.C
new file mode 100644
index 00000000000..d76f12eb209
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat2.C
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++2a } }
+
+template<typename T>
+concept Fooable = requires(T t) { foo(t); }; // { dg-error "template instantiation depth" }
+
+template<Fooable T>
+void foo(T t) { }
+
+void test()
+{
+  struct S {} s;
+  foo(s);
+}
+
+// { dg-prune-output "compilation terminated" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat3.C b/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat3.C
new file mode 100644
index 00000000000..b8ca9164792
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat3.C
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++2a } }
+
+template<typename T>
+concept Fooable = requires(T t) { foo(t); };
+
+template<Fooable T>
+void foo(T t) { }
+
+void test()
+{
+  foo(0); // { dg-error "unsatisfied constraints" }
+}
-- 
2.18.0

