From 8894d4bbca547afe170a3faba03fbfdb2da23bed Mon Sep 17 00:00:00 2001
From: Septicake <septicake056@gmail.com>
Date: Sat, 4 Apr 2026 15:46:40 -0400
Subject: [PATCH] libstdc++: Allow for function parameters in
 annotations_of[_with_type] [P3795R2]

Signed-off-by: Septicake <septicake056@gmail.com>
---
 gcc/cp/reflect.cc                            |  8 +++++---
 gcc/testsuite/g++.dg/reflect/annotations18.C | 14 ++++++++++++++
 gcc/testsuite/g++.dg/reflect/annotations19.C | 20 ++++++++++++++++++++
 gcc/testsuite/g++.dg/reflect/annotations20.C | 19 +++++++++++++++++++
 4 files changed, 58 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/reflect/annotations18.C
 create mode 100644 gcc/testsuite/g++.dg/reflect/annotations19.C
 create mode 100644 gcc/testsuite/g++.dg/reflect/annotations20.C

diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc
index df7f0b54b5b..f9dd331dd82 100644
--- a/gcc/cp/reflect.cc
+++ b/gcc/cp/reflect.cc
@@ -3818,15 +3818,17 @@ eval_annotations_of (location_t loc, const constexpr_ctx *ctx, tree r,
 	|| eval_is_type_alias (r) == boolean_true_node
 	|| eval_is_variable (r, kind) == boolean_true_node
 	|| eval_is_function (r) == boolean_true_node
+	|| eval_is_function_parameter (r, kind) == boolean_true_node
 	|| eval_is_namespace (r) == boolean_true_node
 	|| eval_is_enumerator (r) == boolean_true_node
 	|| eval_is_base (r, kind) == boolean_true_node
 	|| eval_is_nonstatic_data_member (r) == boolean_true_node))
     return throw_exception (loc, ctx,
 			    "reflection does not represent a type,"
-			    " type alias, variable, function, namespace,"
-			    " enumerator, direct base class relationship,"
-			    " or non-static data member",
+			    " type alias, variable, function, function"
+			    " parameter, namespace, enumerator, direct"
+			    " base class relationship, or non-static"
+			    " data member.",
 			    fun, non_constant_p, jump_target);
 
   if (type)
diff --git a/gcc/testsuite/g++.dg/reflect/annotations18.C b/gcc/testsuite/g++.dg/reflect/annotations18.C
new file mode 100644
index 00000000000..8400ee30ac5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/annotations18.C
@@ -0,0 +1,14 @@
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+// Test annotations_of on function parameter reflections
+
+#include <meta>
+
+using namespace std::meta;
+
+void foo([[=2]] int);
+
+void foo([[=1]] int) {}
+
+static_assert (define_static_array(annotations_of(parameters_of(^^foo)[0])).size() == 2);
+static_assert ([: constant_of(annotations_of(parameters_of(^^foo)[0])[0]) :] == 2);
diff --git a/gcc/testsuite/g++.dg/reflect/annotations19.C b/gcc/testsuite/g++.dg/reflect/annotations19.C
new file mode 100644
index 00000000000..2d9b9cc3a16
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/annotations19.C
@@ -0,0 +1,20 @@
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+// Test annotations_of_with_type works as expected
+
+#include <meta>
+#include <ranges>
+#include <vector>
+
+using namespace std::meta;
+
+void foo([[=1, =2.0f, =2.3f]] int) {
+    constexpr auto a_p = define_static_array(annotations_of_with_type(parameters_of(^^foo)[0], ^^float));
+
+    static_assert(a_p.size() == 2);
+    static_assert((annotations_of_with_type(parameters_of(^^foo)[0], ^^float)
+                  | std::views::transform(constant_of)
+                  | std::ranges::to<std::vector>())
+            == std::vector { reflect_constant(2.0f),
+                             reflect_constant(2.3f) });
+}
diff --git a/gcc/testsuite/g++.dg/reflect/annotations20.C b/gcc/testsuite/g++.dg/reflect/annotations20.C
new file mode 100644
index 00000000000..80db4a1bbbf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/annotations20.C
@@ -0,0 +1,19 @@
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+// Test that annotations match between
+// variable and parameter reflections
+
+#include <meta>
+
+using namespace std::meta;
+
+void foo([[=2]] int);
+
+void foo([[=1]] int i) {
+    constexpr info p_r = parameters_of(^^foo)[0];
+    constexpr info i_r = ^^i;
+
+    static_assert(define_static_array(annotations_of(p_r)).size() == 2);
+    static_assert(define_static_array(annotations_of(i_r)).size() == 2);
+    static_assert(annotations_of(p_r) == annotations_of(i_r));
+}
-- 
2.43.0

