From 85131af0603c0af2aa6b40de6cc929905f22bd50 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 30 Mar 2023 11:07:17 -0400 Subject: [PATCH] c++: generic lambda and function ptr conv [PR105221] 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 diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index e514a27..dd7f0db 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 0000000..a691f69 --- /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) {}; +} -- 2.7.4