Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/16?

-- >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

Reply via email to