[pushed] c++: generic lambda and function ptr conv [PR105221]

Message ID 20230330222552.793991-1-jason@redhat.com
State Committed
Commit 85131af0603c0af2aa6b40de6cc929905f22bd50
Headers
Series [pushed] c++: generic lambda and function ptr conv [PR105221] |

Commit Message

Jason Merrill March 30, 2023, 10:25 p.m. UTC
  Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

We weren't properly considering the function pointer conversions in
deduction between FUNCTION_TYPE; we just hardcoded the
UNIFY_ALLOW_MORE_CV_QUAL semantics, which are backwards when deducing for a
template conversion function like the one in a generic lambda.  And when I
started checking the ALLOW flags, I needed to make sure they stay set to
avoid breaking trailing13.C.

	PR c++/105221

gcc/cp/ChangeLog:

	* pt.cc (unify) [FUNCTION_TYPE]: Handle function pointer
	conversions.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp1z/noexcept-type27.C: New test.
---
 gcc/cp/pt.cc                                 | 33 ++++++++++++++++++--
 gcc/testsuite/g++.dg/cpp1z/noexcept-type27.C |  8 +++++
 2 files changed, 38 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1z/noexcept-type27.C


base-commit: 83d2b1ccd17d394d546a38562815ef83daa05e85
  

Patch

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index e514a277872..dd7f0db9658 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -24472,9 +24472,12 @@  unify (tree tparms, tree targs, tree parm, tree arg, int strict,
     return unify_cv_qual_mismatch (explain_p, parm, arg);
 
   if (!(strict & UNIFY_ALLOW_OUTER_LEVEL)
-      && TYPE_P (parm) && !CP_TYPE_CONST_P (parm))
+      && TYPE_P (parm) && !CP_TYPE_CONST_P (parm)
+      && !FUNC_OR_METHOD_TYPE_P (parm))
     strict &= ~UNIFY_ALLOW_MORE_CV_QUAL;
-  strict &= ~UNIFY_ALLOW_OUTER_LEVEL;
+  /* PMFs recurse at the same level, so don't strip this yet.  */
+  if (!TYPE_PTRMEMFUNC_P (parm))
+    strict &= ~UNIFY_ALLOW_OUTER_LEVEL;
   strict &= ~UNIFY_ALLOW_DERIVED;
   strict &= ~UNIFY_ALLOW_OUTER_MORE_CV_QUAL;
   strict &= ~UNIFY_ALLOW_OUTER_LESS_CV_QUAL;
@@ -25022,7 +25025,31 @@  unify (tree tparms, tree targs, tree parm, tree arg, int strict,
 	      RECUR_AND_CHECK_FAILURE (tparms, targs, TREE_PURPOSE (pspec),
 				       TREE_PURPOSE (aspec),
 				       UNIFY_ALLOW_NONE, explain_p);
-	    else if (nothrow_spec_p (pspec) && !nothrow_spec_p (aspec))
+	    else
+	      {
+		bool pn = nothrow_spec_p (pspec);
+		bool an = nothrow_spec_p (aspec);
+		/* Here "less cv-qual" means the deduced arg (i.e. parm) has
+		   /more/ noexcept, since function pointer conversions are the
+		   reverse of qualification conversions.  */
+		if (an == pn
+		    || (an < pn && (strict & UNIFY_ALLOW_LESS_CV_QUAL))
+		    || (an > pn && (strict & UNIFY_ALLOW_MORE_CV_QUAL)))
+		  /* OK.  */;
+		else
+		  return unify_type_mismatch (explain_p, parm, arg);
+	      }
+	  }
+	if (flag_tm)
+	  {
+	    /* As for noexcept.  */
+	    bool pn = tx_safe_fn_type_p (parm);
+	    bool an = tx_safe_fn_type_p (arg);
+	    if (an == pn
+		|| (an < pn && (strict & UNIFY_ALLOW_LESS_CV_QUAL))
+		|| (an > pn && (strict & UNIFY_ALLOW_MORE_CV_QUAL)))
+	      /* OK.  */;
+	    else
 	      return unify_type_mismatch (explain_p, parm, arg);
 	  }
 
diff --git a/gcc/testsuite/g++.dg/cpp1z/noexcept-type27.C b/gcc/testsuite/g++.dg/cpp1z/noexcept-type27.C
new file mode 100644
index 00000000000..a691f695389
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/noexcept-type27.C
@@ -0,0 +1,8 @@ 
+// PR c++/105221
+// { dg-do compile { target c++14 } }
+
+void (*p)(int) = [](auto) noexcept {};
+
+int main() {
+  true ? [](auto) noexcept {} : [](int) {};
+}