public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/marxin/heads/PR93274-make-resolver-static-v2)] c++: Fix ICE with constrained friend (PR93400).
@ 2020-01-27 10:14 Martin Liska
  0 siblings, 0 replies; only message in thread
From: Martin Liska @ 2020-01-27 10:14 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:9c1179c339e050e2ce7c545f648b684d38dec69d

commit 9c1179c339e050e2ce7c545f648b684d38dec69d
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Jan 24 14:58:56 2020 -0500

    c++: Fix ICE with constrained friend (PR93400).
    
    Here, the problem was that tsubst_friend_function was modifying the
    CONSTRAINT_INFO for the friend template to have the constraints for one
    instantiation, which fell down when we went to adjust it for another
    instantiation.  Fixed by deferring substitution of trailing requirements
    until we try to check declaration matching.
    
    	PR c++/93400 - ICE with constrained friend.
    	* constraint.cc (maybe_substitute_reqs_for): New.
    	* decl.c (function_requirements_equivalent_p): Call it.
    	* pt.c (tsubst_friend_function): Only substitute
    	TEMPLATE_PARMS_CONSTRAINTS.
    	(tsubst_template_parms): Copy constraints.

Diff:
---
 gcc/cp/ChangeLog                              |  9 ++++++++
 gcc/cp/constraint.cc                          | 23 ++++++++++++++++++++
 gcc/cp/cp-tree.h                              |  1 +
 gcc/cp/decl.c                                 |  2 ++
 gcc/cp/pt.c                                   | 31 +++++++--------------------
 gcc/testsuite/g++.dg/cpp2a/concepts-friend3.C |  3 +++
 gcc/testsuite/g++.dg/cpp2a/concepts-friend5.C |  8 +++++++
 gcc/testsuite/g++.dg/cpp2a/concepts-pr84140.C |  5 ++---
 8 files changed, 56 insertions(+), 26 deletions(-)

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 764b9cc..ca56766 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,14 @@
 2020-01-24  Jason Merrill  <jason@redhat.com>
 
+	PR c++/93400 - ICE with constrained friend.
+	* constraint.cc (maybe_substitute_reqs_for): New.
+	* decl.c (function_requirements_equivalent_p): Call it.
+	* pt.c (tsubst_friend_function): Only substitute
+	TEMPLATE_PARMS_CONSTRAINTS.
+	(tsubst_template_parms): Copy constraints.
+
+2020-01-24  Jason Merrill  <jason@redhat.com>
+
 	PR c++/93279 - ICE with lambda in member operator.
 	* name-lookup.c (maybe_save_operator_binding): Don't remember
 	class-scope bindings.
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 823604a..cda644e 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -1189,6 +1189,29 @@ remove_constraints (tree t)
     decl_constraints->remove (t);
 }
 
+/* If DECL is a friend, substitute into REQS to produce requirements suitable
+   for declaration matching.  */
+
+tree
+maybe_substitute_reqs_for (tree reqs, const_tree decl_)
+{
+  if (reqs == NULL_TREE)
+    return NULL_TREE;
+  tree decl = CONST_CAST_TREE (decl_);
+  tree result = STRIP_TEMPLATE (decl);
+  if (DECL_FRIEND_P (result))
+    {
+      tree tmpl = decl == result ? DECL_TI_TEMPLATE (result) : decl;
+      tree gargs = generic_targs_for (tmpl);
+      processing_template_decl_sentinel s;
+      if (uses_template_parms (gargs))
+	++processing_template_decl;
+      reqs = tsubst_constraint (reqs, gargs,
+				tf_warning_or_error, NULL_TREE);
+    }
+  return reqs;
+}
+
 /* Returns the template-head requires clause for the template
    declaration T or NULL_TREE if none.  */
 
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 77bcf04..b8035b4 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7832,6 +7832,7 @@ extern void remove_constraints                  (tree);
 extern tree current_template_constraints	(void);
 extern tree associate_classtype_constraints     (tree);
 extern tree build_constraints                   (tree, tree);
+extern tree maybe_substitute_reqs_for		(tree, const_tree);
 extern tree get_template_head_requirements	(tree);
 extern tree get_trailing_function_requirements	(tree);
 extern tree get_shorthand_constraints           (tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 98ed79f..e55de5d 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -942,6 +942,8 @@ function_requirements_equivalent_p (tree newfn, tree oldfn)
   tree reqs2 = get_trailing_function_requirements (oldfn);
   if ((reqs1 != NULL_TREE) != (reqs2 != NULL_TREE))
     return false;
+  reqs1 = maybe_substitute_reqs_for (reqs1, newfn);
+  reqs2 = maybe_substitute_reqs_for (reqs2, oldfn);
   return cp_tree_equal (reqs1, reqs2);
 }
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 2090441..45c204e 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -10834,29 +10834,12 @@ tsubst_friend_function (tree decl, tree args)
       DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (new_friend))
 	= DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (decl));
 
-      /* Attach the template requirements to the new declaration
-         for declaration matching. We need to rebuild the requirements
-         so that parameter levels match.  */
-      if (tree ci = get_constraints (decl))
-	{
-	  tree parms = DECL_TEMPLATE_PARMS (new_friend);
-	  tree args = generic_targs_for (new_friend);
-	  tree treqs = tsubst_constraint (CI_TEMPLATE_REQS (ci), args,
-					  tf_warning_or_error, NULL_TREE);
-	  tree freqs = tsubst_constraint (CI_DECLARATOR_REQS (ci), args,
-					  tf_warning_or_error, NULL_TREE);
-
-	  /* Update the constraints -- these won't really be valid for
-	     checking, but that's not what we need them for. These ensure
-	     that the declared function can find the friend during
-	     declaration matching.  */
-	  tree new_ci = get_constraints (new_friend);
-	  CI_TEMPLATE_REQS (new_ci) = treqs;
-	  CI_DECLARATOR_REQS (new_ci) = freqs;
-
-	  /* Also update the template parameter list.  */
-	  TEMPLATE_PARMS_CONSTRAINTS (parms) = treqs;
-	}
+      /* Substitute TEMPLATE_PARMS_CONSTRAINTS so that parameter levels will
+	 match in decls_match.  */
+      tree parms = DECL_TEMPLATE_PARMS (new_friend);
+      tree treqs = TEMPLATE_PARMS_CONSTRAINTS (parms);
+      treqs = maybe_substitute_reqs_for (treqs, new_friend);
+      TEMPLATE_PARMS_CONSTRAINTS (parms) = treqs;
     }
 
   /* The mangled name for the NEW_FRIEND is incorrect.  The function
@@ -13225,6 +13208,8 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
 	tree_cons (size_int (TMPL_PARMS_DEPTH (parms)
 			     - TMPL_ARGS_DEPTH (args)),
 		   new_vec, NULL_TREE);
+      TEMPLATE_PARMS_CONSTRAINTS (*new_parms)
+	= TEMPLATE_PARMS_CONSTRAINTS (parms);
     }
 
   --processing_template_decl;
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-friend3.C b/gcc/testsuite/g++.dg/cpp2a/concepts-friend3.C
index 4f49358..4278278 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-friend3.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-friend3.C
@@ -4,6 +4,7 @@ template <class T> concept True = true;
 
 template <True U> struct B { int i = ++U::x; };
 template <True U> void f() { ++U::x; }
+template <class U> void g() requires True<U> { ++U::x; }
 
 template <class V> class C
 {
@@ -11,10 +12,12 @@ template <class V> class C
 
   template <True U> friend struct B;
   template <True U> friend void f();
+  template <class U> friend void g() requires True<U>;
 };
 
 int main()
 {
   f<C<int>>();
+  g<C<int>>();
   B<C<int>>();
 }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-friend5.C b/gcc/testsuite/g++.dg/cpp2a/concepts-friend5.C
new file mode 100644
index 0000000..394f141
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-friend5.C
@@ -0,0 +1,8 @@
+// PR c++/93400
+// { dg-do compile { target concepts } }
+
+template <typename> bool a = true;
+template <typename i> concept b = a<i>;
+template <int> struct f { template <b c> friend auto g(c, f); };
+auto d = f<1>{};
+auto e = f<0>{};
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr84140.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr84140.C
index d901ab2..83a9083 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-pr84140.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr84140.C
@@ -1,14 +1,13 @@
 // { dg-do run { target c++2a } }
-// { dg-additional-options "-fconcepts-ts" }
 
 template<class, class> constexpr bool is_same_v = false;
 template<class T> constexpr bool is_same_v<T, T> = true;
 
 template<class T, class U>
-concept bool Same = is_same_v<T, U>;
+concept Same = is_same_v<T, U>;
 
 template<class T, class U>
-concept bool Diff = requires(T& t, U& u) { u - t; };
+concept Diff = requires(T& t, U& u) { u - t; };
 
 template<class I, class S>
 int distance(I, S) { return 0; }


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2020-01-27 10:14 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-27 10:14 [gcc(refs/users/marxin/heads/PR93274-make-resolver-static-v2)] c++: Fix ICE with constrained friend (PR93400) Martin Liska

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).