libstdc++: Allow for function parameters in annotations_of[_with_type] [P3795R2]

Message ID CANeSxVxSyDXvVgw6-F508k5YYvjsdZEoo+Ur=YPvEJ1OKs4=gw@mail.gmail.com
State New
Headers
Series libstdc++: Allow for function parameters in annotations_of[_with_type] [P3795R2] |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Test passed
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 success Test passed

Commit Message

Septicake April 4, 2026, 9:38 p.m. UTC
  This patch adds function parameters as an allowed reflection info that can
be passed to eval_annotations_of, and therefore the annotations_of and
annotations_of_with_type metafunctions, following the update from P3795R2.
The error message when an invalid reflection info has been passed in has
also been updated to reflect this change.

Tested and bootstrapped on x86_64-pc-linux-gnu.

gcc/

* cp/reflect.cc (eval_annotations_of): Allow function parameters and update
error message
accordingly

gcc/testsuite/

* g++.dg/reflect/annotations18.C: New test
* g++.dg/reflect/annotations19.C: Likewise
* g++.dg/reflect/annotations20.C: Likewise
  

Comments

Jason Merrill April 6, 2026, 5:10 p.m. UTC | #1
On 4/4/26 5:38 PM, Septicake wrote:
> This patch adds function parameters as an allowed reflection info that 
> can be passed to eval_annotations_of, and therefore the annotations_of 
> and annotations_of_with_type metafunctions, following the update from 
> P3795R2. The error message when an invalid reflection info has been 
> passed in has also been updated to reflect this change.

Thanks for the contribution!

There's already a patch in review for this, that should be committed soon:

https://inbox.sourceware.org/gcc-patches/acUfPDbhcQHP9ywS@tucnak/

Jason
  
Septicake April 6, 2026, 5:47 p.m. UTC | #2
> There's already a patch in review for this, that should be committed soon:
>
> https://inbox.sourceware.org/gcc-patches/acUfPDbhcQHP9ywS@tucnak/

Ah, fair enough, it seems to handle it better anyway. Thanks for
pointing it out to me!
  

Patch

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