From: Marek Polacek Date: Thu, 22 Jan 2026 16:31:35 +0000 (-0500) Subject: c++/reflection: fix fnptr extraction [PR123620] X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=745e36a9acc6eb1d814ddd838dbcb5a7b724b3e2;p=thirdparty%2Fgcc.git c++/reflection: fix fnptr extraction [PR123620] When extracting a function pointer, removing noexcept should be allowed (but not the other way round): int fn (int) noexcept; constexpr auto a = extract(^^fn); but currently we reject this code -- I didn't realize that fnptr_conv_p allows things that same_type_p doesn't allow, and in can_extract_* we should check both. And then we need to perform the actual conversion. PR c++/123620 gcc/cp/ChangeLog: * reflect.cc (can_extract_member_or_function_p): Also check fnptr_conv_p. (extract_member_or_function): Call perform_implicit_conversion. gcc/testsuite/ChangeLog: * g++.dg/reflect/extract1.C: Test removing noexcept. * g++.dg/reflect/extract2.C: Adjust static_assert. Reviewed-by: Jason Merrill --- diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc index c1173ced168..2f9aa36c787 100644 --- a/gcc/cp/reflect.cc +++ b/gcc/cp/reflect.cc @@ -7206,7 +7206,7 @@ can_extract_member_or_function_p (tree T, tree r, reflect_kind kind) tree F = TREE_TYPE (r); F = build_pointer_type (F); F = build_ptrmemfunc_type (F); - if (same_type_p (T, F)) + if (same_type_p (T, F) || fnptr_conv_p (T, F)) return true; return false; } @@ -7214,7 +7214,7 @@ can_extract_member_or_function_p (tree T, tree r, reflect_kind kind) { tree F = TREE_TYPE (r); F = build_pointer_type (F); - if (same_type_p (T, F)) + if (same_type_p (T, F) || fnptr_conv_p (T, F)) return true; return false; } @@ -7250,7 +7250,10 @@ extract_member_or_function (location_t loc, const constexpr_ctx *ctx, const tsubst_flags_t complain = complain_flags (ctx); if (POINTER_TYPE_P (T)) - return cp_build_addr_expr (r, complain); + { + r = cp_build_addr_expr (r, complain); + return perform_implicit_conversion (T, r, complain); + } else { if (!mark_used (r, complain)) diff --git a/gcc/testsuite/g++.dg/reflect/extract1.C b/gcc/testsuite/g++.dg/reflect/extract1.C index 6eaf9ffe4b9..4f05fce40a5 100644 --- a/gcc/testsuite/g++.dg/reflect/extract1.C +++ b/gcc/testsuite/g++.dg/reflect/extract1.C @@ -171,13 +171,10 @@ constexpr auto a4 = extract(^^B::fn4); constexpr auto a5 = extract(^^B::fn5); constexpr auto a6 = extract(^^B::fn6); constexpr auto a7 = extract(^^B::fn7); - constexpr auto a8 = extract(^^B::m); constexpr auto a9 = extract(^^B::m); constexpr auto a10 = extract(^^B::p); constexpr auto a11 = extract(^^B::p); constexpr auto a12 = extract(^^B::p); - -// FIXME removing noexcept should be allowed -// constexpr auto a13 = extract(^^B::fn4); -// constexpr auto a14 = extract(^^B::fn2); +constexpr auto a13 = extract(^^B::fn4); +constexpr auto a14 = extract(^^B::fn2); diff --git a/gcc/testsuite/g++.dg/reflect/extract2.C b/gcc/testsuite/g++.dg/reflect/extract2.C index edb5382ce39..9de23d1e931 100644 --- a/gcc/testsuite/g++.dg/reflect/extract2.C +++ b/gcc/testsuite/g++.dg/reflect/extract2.C @@ -130,11 +130,11 @@ struct C { }; static_assert (!can_extract(^^C::fn)); static_assert (!can_extract(^^C::fn)); -static_assert (!can_extract(^^C::fn2)); +static_assert (can_extract(^^C::fn2)); static_assert (!can_extract(^^C::fn3)); static_assert (!can_extract(^^C::fn4)); static_assert (!can_extract(^^C::fn3)); -static_assert (!can_extract(^^C::fn4)); +static_assert (can_extract(^^C::fn4)); static_assert (!can_extract(^^C::fn5)); static_assert (!can_extract(^^C::fn6)); static_assert (!can_extract(^^C::fn7));