* [PATCH] c++: Fix reference NTTP binding to noexcept fn [PR97420]
@ 2021-05-21 20:35 Patrick Palka
2021-05-24 21:03 ` Jason Merrill
0 siblings, 1 reply; 2+ messages in thread
From: Patrick Palka @ 2021-05-21 20:35 UTC (permalink / raw)
To: gcc-patches
Here, in C++17 mode, convert_nontype_argument_function is rejecting
binding a non-noexcept function reference template parameter to a
noexcept function (encoded as the template argument '*(int (&) (int)) &f').
The first roadblock to making this work is that the argument is wrapped
an an implicit INDIRECT_REF, so we need to unwrap it before calling
strip_fnptr_conv.
The second roadblock is that the NOP_EXPR cast converts from a function
pointer type to a reference type while simultaneously removing the
noexcept qualification, and fnptr_conv_p doesn't consider this cast to
be a function pointer conversion. This patch fixes this by making
fnptr_conv_p treat REFERENCE_TYPEs and POINTER_TYPEs interchangeably.
Finally, in passing, this patch also simplifies noexcept_conv_p by
removing a bunch of redundant checks already performed by its only
caller fnptr_conv_p.
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?
gcc/cp/ChangeLog:
PR c++/97420
* cvt.c (noexcept_conv_p): Remove redundant checks and simplify.
(fnptr_conv_p): Don't call non_reference. Use INDIRECT_TYPE_P
instead of TYPE_PTR_P.
* pt.c (convert_nontype_argument_function): Look through
implicit INDIRECT_REFs before calling strip_fnptr_conv.
gcc/testsuite/ChangeLog:
PR c++/97420
* g++.dg/cpp0x/noexcept68.C: New test.
---
gcc/cp/cvt.c | 33 +++++++------------------
gcc/cp/pt.c | 5 +++-
gcc/testsuite/g++.dg/cpp0x/noexcept68.C | 8 ++++++
3 files changed, 21 insertions(+), 25 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept68.C
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 7fa6e8df52b..582d03f61f5 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -2089,30 +2089,15 @@ noexcept_conv_p (tree to, tree from)
if (!flag_noexcept_type)
return false;
- tree t = non_reference (to);
- tree f = from;
- if (TYPE_PTRMEMFUNC_P (t)
- && TYPE_PTRMEMFUNC_P (f))
- {
- t = TYPE_PTRMEMFUNC_FN_TYPE (t);
- f = TYPE_PTRMEMFUNC_FN_TYPE (f);
- }
- if (TYPE_PTR_P (t)
- && TYPE_PTR_P (f))
- {
- t = TREE_TYPE (t);
- f = TREE_TYPE (f);
- }
- tree_code code = TREE_CODE (f);
- if (TREE_CODE (t) != code)
+ if (TREE_CODE (to) != TREE_CODE (from))
return false;
- if (code != FUNCTION_TYPE && code != METHOD_TYPE)
+ if (!FUNC_OR_METHOD_TYPE_P (from))
return false;
- if (!type_throw_all_p (t)
- || type_throw_all_p (f))
+ if (!type_throw_all_p (to)
+ || type_throw_all_p (from))
return false;
- tree v = build_exception_variant (f, NULL_TREE);
- return same_type_p (t, v);
+ tree v = build_exception_variant (from, NULL_TREE);
+ return same_type_p (to, v);
}
/* Return true iff FROM can convert to TO by a function pointer conversion. */
@@ -2120,7 +2105,7 @@ noexcept_conv_p (tree to, tree from)
bool
fnptr_conv_p (tree to, tree from)
{
- tree t = non_reference (to);
+ tree t = to;
tree f = from;
if (TYPE_PTRMEMFUNC_P (t)
&& TYPE_PTRMEMFUNC_P (f))
@@ -2128,8 +2113,8 @@ fnptr_conv_p (tree to, tree from)
t = TYPE_PTRMEMFUNC_FN_TYPE (t);
f = TYPE_PTRMEMFUNC_FN_TYPE (f);
}
- if (TYPE_PTR_P (t)
- && TYPE_PTR_P (f))
+ if (INDIRECT_TYPE_P (t)
+ && INDIRECT_TYPE_P (f))
{
t = TREE_TYPE (t);
f = TREE_TYPE (f);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 99a9ee5ade2..f3fa9c192ad 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -6622,7 +6622,10 @@ convert_nontype_argument_function (tree type, tree expr,
if (value_dependent_expression_p (fn))
goto accept;
- fn_no_ptr = strip_fnptr_conv (fn);
+ fn_no_ptr = fn;
+ if (REFERENCE_REF_P (fn_no_ptr))
+ fn_no_ptr = TREE_OPERAND (fn_no_ptr, 0);
+ fn_no_ptr = strip_fnptr_conv (fn_no_ptr);
if (TREE_CODE (fn_no_ptr) == ADDR_EXPR)
fn_no_ptr = TREE_OPERAND (fn_no_ptr, 0);
if (BASELINK_P (fn_no_ptr))
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept68.C b/gcc/testsuite/g++.dg/cpp0x/noexcept68.C
new file mode 100644
index 00000000000..086899a4a19
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept68.C
@@ -0,0 +1,8 @@
+// PR c++/97420
+// { dg-do compile { target c++11 } }
+
+int f(int) noexcept;
+template<int (&)(int)> void A();
+int main() {
+ A<f>();
+}
--
2.32.0.rc0
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] c++: Fix reference NTTP binding to noexcept fn [PR97420]
2021-05-21 20:35 [PATCH] c++: Fix reference NTTP binding to noexcept fn [PR97420] Patrick Palka
@ 2021-05-24 21:03 ` Jason Merrill
0 siblings, 0 replies; 2+ messages in thread
From: Jason Merrill @ 2021-05-24 21:03 UTC (permalink / raw)
To: Patrick Palka, gcc-patches
On 5/21/21 4:35 PM, Patrick Palka wrote:
> Here, in C++17 mode, convert_nontype_argument_function is rejecting
> binding a non-noexcept function reference template parameter to a
> noexcept function (encoded as the template argument '*(int (&) (int)) &f').
>
> The first roadblock to making this work is that the argument is wrapped
> an an implicit INDIRECT_REF, so we need to unwrap it before calling
> strip_fnptr_conv.
>
> The second roadblock is that the NOP_EXPR cast converts from a function
> pointer type to a reference type while simultaneously removing the
> noexcept qualification, and fnptr_conv_p doesn't consider this cast to
> be a function pointer conversion. This patch fixes this by making
> fnptr_conv_p treat REFERENCE_TYPEs and POINTER_TYPEs interchangeably.
>
> Finally, in passing, this patch also simplifies noexcept_conv_p by
> removing a bunch of redundant checks already performed by its only
> caller fnptr_conv_p.
>
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> trunk?
> gcc/cp/ChangeLog:
>
> PR c++/97420
> * cvt.c (noexcept_conv_p): Remove redundant checks and simplify.
This is fine, but please also add a note to its comment that it's just a
subroutine of fnptr_conv_p.
OK with that change.
> (fnptr_conv_p): Don't call non_reference. Use INDIRECT_TYPE_P
> instead of TYPE_PTR_P.
> * pt.c (convert_nontype_argument_function): Look through
> implicit INDIRECT_REFs before calling strip_fnptr_conv.
>
> gcc/testsuite/ChangeLog:
>
> PR c++/97420
> * g++.dg/cpp0x/noexcept68.C: New test.
> ---
> gcc/cp/cvt.c | 33 +++++++------------------
> gcc/cp/pt.c | 5 +++-
> gcc/testsuite/g++.dg/cpp0x/noexcept68.C | 8 ++++++
> 3 files changed, 21 insertions(+), 25 deletions(-)
> create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept68.C
>
> diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
> index 7fa6e8df52b..582d03f61f5 100644
> --- a/gcc/cp/cvt.c
> +++ b/gcc/cp/cvt.c
> @@ -2089,30 +2089,15 @@ noexcept_conv_p (tree to, tree from)
> if (!flag_noexcept_type)
> return false;
>
> - tree t = non_reference (to);
> - tree f = from;
> - if (TYPE_PTRMEMFUNC_P (t)
> - && TYPE_PTRMEMFUNC_P (f))
> - {
> - t = TYPE_PTRMEMFUNC_FN_TYPE (t);
> - f = TYPE_PTRMEMFUNC_FN_TYPE (f);
> - }
> - if (TYPE_PTR_P (t)
> - && TYPE_PTR_P (f))
> - {
> - t = TREE_TYPE (t);
> - f = TREE_TYPE (f);
> - }
> - tree_code code = TREE_CODE (f);
> - if (TREE_CODE (t) != code)
> + if (TREE_CODE (to) != TREE_CODE (from))
> return false;
> - if (code != FUNCTION_TYPE && code != METHOD_TYPE)
> + if (!FUNC_OR_METHOD_TYPE_P (from))
> return false;
> - if (!type_throw_all_p (t)
> - || type_throw_all_p (f))
> + if (!type_throw_all_p (to)
> + || type_throw_all_p (from))
> return false;
> - tree v = build_exception_variant (f, NULL_TREE);
> - return same_type_p (t, v);
> + tree v = build_exception_variant (from, NULL_TREE);
> + return same_type_p (to, v);
> }
>
> /* Return true iff FROM can convert to TO by a function pointer conversion. */
> @@ -2120,7 +2105,7 @@ noexcept_conv_p (tree to, tree from)
> bool
> fnptr_conv_p (tree to, tree from)
> {
> - tree t = non_reference (to);
> + tree t = to;
> tree f = from;
> if (TYPE_PTRMEMFUNC_P (t)
> && TYPE_PTRMEMFUNC_P (f))
> @@ -2128,8 +2113,8 @@ fnptr_conv_p (tree to, tree from)
> t = TYPE_PTRMEMFUNC_FN_TYPE (t);
> f = TYPE_PTRMEMFUNC_FN_TYPE (f);
> }
> - if (TYPE_PTR_P (t)
> - && TYPE_PTR_P (f))
> + if (INDIRECT_TYPE_P (t)
> + && INDIRECT_TYPE_P (f))
> {
> t = TREE_TYPE (t);
> f = TREE_TYPE (f);
> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> index 99a9ee5ade2..f3fa9c192ad 100644
> --- a/gcc/cp/pt.c
> +++ b/gcc/cp/pt.c
> @@ -6622,7 +6622,10 @@ convert_nontype_argument_function (tree type, tree expr,
> if (value_dependent_expression_p (fn))
> goto accept;
>
> - fn_no_ptr = strip_fnptr_conv (fn);
> + fn_no_ptr = fn;
> + if (REFERENCE_REF_P (fn_no_ptr))
> + fn_no_ptr = TREE_OPERAND (fn_no_ptr, 0);
> + fn_no_ptr = strip_fnptr_conv (fn_no_ptr);
> if (TREE_CODE (fn_no_ptr) == ADDR_EXPR)
> fn_no_ptr = TREE_OPERAND (fn_no_ptr, 0);
> if (BASELINK_P (fn_no_ptr))
> diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept68.C b/gcc/testsuite/g++.dg/cpp0x/noexcept68.C
> new file mode 100644
> index 00000000000..086899a4a19
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept68.C
> @@ -0,0 +1,8 @@
> +// PR c++/97420
> +// { dg-do compile { target c++11 } }
> +
> +int f(int) noexcept;
> +template<int (&)(int)> void A();
> +int main() {
> + A<f>();
> +}
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2021-05-24 21:03 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-21 20:35 [PATCH] c++: Fix reference NTTP binding to noexcept fn [PR97420] Patrick Palka
2021-05-24 21:03 ` Jason Merrill
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).