On Wed, 10 Jun 2026, Marek Polacek wrote:
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/16?
OK
>
> -- >8 --
> Here we ICE because S::S(int) lost its DECL_ARGUMENTS, and so the
> skip_artificial_parms_for in FUNCTION_FIRST_USER_PARM in write_reflection
> crashes on a null tree. We've thrown away the body of S::S(int) in
> cgraph_node::release_body along with its DECL_ARGUMENTS:
>
> if (!keep_arguments)
> DECL_ARGUMENTS (decl) = NULL;
>
> This happens in finalize_compilation_unit -> analyze_functions because
> there are no cgraph_node::callers (so referred_to_p() is false I think),
> and .force_output is false.
>
> We then call mangle_decl from finalize_compilation_unit ->
> dwarf2out_early_finish.
>
> Instead of FUNCTION_FIRST_USER_PARM we can use DECL_PARM_INDEX, thus
> avoiding the need to either keep the body around or at least set
> keep_arguments.
>
> PR c++/125498
>
> gcc/cp/ChangeLog:
>
> * mangle.cc (write_reflection): Use DECL_PARM_INDEX for
> computing the parameter index.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/reflect/mangle7.C: New test.
> * g++.dg/reflect/parameters_of9.C: New test.
> ---
> gcc/cp/mangle.cc | 9 +--
> gcc/testsuite/g++.dg/reflect/mangle7.C | 65 +++++++++++++++++++
> gcc/testsuite/g++.dg/reflect/parameters_of9.C | 45 +++++++++++++
> 3 files changed, 112 insertions(+), 7 deletions(-)
> create mode 100644 gcc/testsuite/g++.dg/reflect/mangle7.C
> create mode 100644 gcc/testsuite/g++.dg/reflect/parameters_of9.C
>
> diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
> index 982864ebf0c..a287cded8ae 100644
> --- a/gcc/cp/mangle.cc
> +++ b/gcc/cp/mangle.cc
> @@ -4220,13 +4220,8 @@ write_reflection (tree refl)
> else if (strcmp (prefix, "pa") == 0)
> {
> tree fn = DECL_CONTEXT (arg);
> - tree args = FUNCTION_FIRST_USER_PARM (fn);
> - int idx = 0;
> - while (arg != args)
> - {
> - args = DECL_CHAIN (args);
> - ++idx;
> - }
> + /* DECL_PARM_INDEX is 1-based but here we want a 0-based index. */
> + const int idx = DECL_PARM_INDEX (arg) - 1;
> write_compact_number (idx);
> write_encoding (fn);
> }
> diff --git a/gcc/testsuite/g++.dg/reflect/mangle7.C
> b/gcc/testsuite/g++.dg/reflect/mangle7.C
> new file mode 100644
> index 00000000000..f6d9e347204
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/reflect/mangle7.C
> @@ -0,0 +1,65 @@
> +// PR c++/125498
> +// { dg-do compile { target c++26 } }
> +// { dg-additional-options "-freflection" }
> +
> +#include <meta>
> +
> +using namespace std::meta;
> +
> +template<info>
> +void
> +xyzzy ()
> +{
> +}
> +
> +struct S {
> + void fn1 (const S &)
> + {
> + xyzzy<parameters_of (^^S::fn1)[0]> ();
> + }
> + void fn2 (this S)
> + {
> + xyzzy<parameters_of (^^S::fn2)[0]> ();
> + }
> + static void fn3 (int)
> + {
> + xyzzy<parameters_of (^^S::fn3)[0]> ();
> + }
> +};
> +
> +struct V : virtual S {
> + void fn1 (const V &)
> + {
> + xyzzy<parameters_of (^^V::fn1)[0]> ();
> + }
> + void fn2 (this V)
> + {
> + xyzzy<parameters_of (^^V::fn2)[0]> ();
> + }
> + static void fn3 (int)
> + {
> + xyzzy<parameters_of (^^V::fn3)[0]> ();
> + }
> +};
> +
> +void
> +g (int)
> +{
> + xyzzy<parameters_of (^^g)[0]> ();
> + S s;
> + s.fn1 (s);
> + s.fn2 ();
> + S::fn3 (42);
> + V v;
> + v.fn1 (v);
> + v.fn2 ();
> + V::fn3 (42);
> +}
> +
> +// { dg-final { scan-assembler "_Z5xyzzyILDmpa_N1S3fn1ERKS0_EEvv" } }
> +// { dg-final { scan-assembler "_Z5xyzzyILDmpa_NH1S3fn2ES0_EEvv" } }
> +// { dg-final { scan-assembler "_Z5xyzzyILDmpa_N1S3fn3EiEEvv" } }
> +// { dg-final { scan-assembler "_Z5xyzzyILDmpa_N1V3fn1ERKS0_EEvv" } }
> +// { dg-final { scan-assembler "_Z5xyzzyILDmpa_NH1V3fn2ES0_EEvv" } }
> +// { dg-final { scan-assembler "_Z5xyzzyILDmpa_N1V3fn3EiEEvv" } }
> +// { dg-final { scan-assembler "_Z5xyzzyILDmpa_1giEEvv" } }
> diff --git a/gcc/testsuite/g++.dg/reflect/parameters_of9.C
> b/gcc/testsuite/g++.dg/reflect/parameters_of9.C
> new file mode 100644
> index 00000000000..ef7059a111a
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/reflect/parameters_of9.C
> @@ -0,0 +1,45 @@
> +// PR c++/125498
> +// { dg-do compile { target c++26 } }
> +// { dg-additional-options "-freflection -g" }
> +
> +#include <meta>
> +
> +struct tag {};
> +
> +struct S {
> + S(int) {}
> +};
> +
> +struct B { };
> +struct A : virtual B { A(int); };
> +
> +template <auto Param> struct GetAnnotations {
> + static constexpr auto value = std::define_static_array(
> + std::meta::annotations_of_with_type(Param, ^^tag));
> +};
> +
> +consteval bool test() {
> + template for (constexpr auto member :
> + std::define_static_array(std::meta::members_of(
> + ^^S, std::meta::access_context::unchecked()))) {
> + if constexpr (std::meta::is_constructor(member)) {
> + constexpr auto parameters =
> + std::define_static_array(std::meta::parameters_of(member));
> + constexpr auto annotations = GetAnnotations<parameters[0]>::value;
> + return annotations.empty();
> + }
> + }
> +}
> +
> +consteval bool test2() {
> + template for (constexpr auto member :
> + std::define_static_array(std::meta::members_of(
> + ^^A, std::meta::access_context::unchecked()))) {
> + if constexpr (std::meta::is_constructor(member)) {
> + constexpr auto parameters =
> + std::define_static_array(std::meta::parameters_of(member));
> + constexpr auto annotations = GetAnnotations<parameters[0]>::value;
> + return annotations.empty();
> + }
> + }
> +}
>
> base-commit: de7756c90f3bebdf02492842ec355d7e18745e7b
> --
> 2.54.0
>
>