On 12/2/25 1:51 AM, Marek Polacek wrote:
On Sat, Nov 29, 2025 at 03:18:14PM -0500, Eczbek wrote:
From 21240d2a1d4c99fb85ceb9b39c95eb18f8e61c1d Mon Sep 17 00:00:00 2001
From: Eczbek <[email protected]>
Date: Wed, 26 Nov 2025 21:58:28 -0500
Subject: [PATCH] c++: Make std::meta::operator_of() accept operator function
templates [PR122771]
eval_operator_of() checks if a reflection does not
represent an operator function, but it should also check that
the reflection does not represent an operator function template.
Thanks for the patch, it looks good.
Since Reflection isn't merged yet, we can either wait for that to happen,
or I could include the patch in my devel reflection branch, but I think
we'd need a Signed-off-by.
We can't accept Signed-off-by for an anonymous pseudonym (not a known
identity), so I've advised Eczbek to omit it for small changes like this
that are not significant for copyright. Of course, the testcase changes
are larger than the usual cut-off for that, but they are also pretty
mechanical and seem insignificant for copyright for that reason.
You can apply it to the branch with a Reviewed-by me.
PR c++/122771
Please assign that PR to yourself (if you're able to).
Thanks!
gcc/cp/ChangeLog:
* reflect.cc (eval_operator_of): Add check for operator function
templates and improve error message.
gcc/testsuite/ChangeLog:
* g++.dg/reflect/operator_of1.C: Add tests for operator function
templates.
---
gcc/cp/reflect.cc | 6 +-
gcc/testsuite/g++.dg/reflect/operator_of1.C | 107 +++++++++++++++++++-
2 files changed, 110 insertions(+), 3 deletions(-)
diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc
index 38188920cea..6e84c6c40c1 100644
--- a/gcc/cp/reflect.cc
+++ b/gcc/cp/reflect.cc
@@ -2332,10 +2332,12 @@ eval_operator_of (location_t loc, const
constexpr_ctx *ctx, tree r,
bool *non_constant_p, tree *jump_target, tree ret_type,
tree fun)
{
- if (eval_is_operator_function (r) == boolean_false_node)
+ if (eval_is_operator_function (r) == boolean_false_node
+ && eval_is_operator_function_template (r) == boolean_false_node)
return throw_exception (loc, ctx,
"reflection does not represent an operator "
- "function", fun, non_constant_p, jump_target);
+ "function or operator function template",
+ fun, non_constant_p, jump_target);
r = maybe_get_reflection_fndecl (r);
r = STRIP_TEMPLATE (r);
maybe_init_meta_operators (loc);
diff --git a/gcc/testsuite/g++.dg/reflect/operator_of1.C
b/gcc/testsuite/g++.dg/reflect/operator_of1.C
index 25e73713bb9..e950b1a1b90 100644
--- a/gcc/testsuite/g++.dg/reflect/operator_of1.C
+++ b/gcc/testsuite/g++.dg/reflect/operator_of1.C
@@ -164,11 +164,68 @@ struct S
struct T
{
T &operator ++ (int);
- T &operator -- (int);
+ T &operator -- (int);
T &operator + ();
T &operator - ();
};
+struct U
+{
+ using size_t = decltype (sizeof 0);
+ template<int> void *operator new (size_t, void *);
+ template<int> void *operator new[] (size_t, void *);
+ template<int> void operator delete (void *, U);
+ template<int> void operator delete[] (void *, U);
+ template<int> U &operator () (const U &);
+ template<int> U &operator [] (const U &);
+ template<int> U &operator = (const U &);
+ template<int> U &operator << (int);
+ template<int> U &operator >> (int);
+ template<int> U &operator ++ ();
+ template<int> U &operator -- ();
+ template<int> U &operator ~ ();
+ template<int> U &operator ! ();
+ template<int> U &operator + (const U &);
+ template<int> U &operator - (const U &);
+ template<int> U &operator * (const U &);
+ template<int> U &operator / (const U &);
+ template<int> U &operator % (const U &);
+ template<int> U &operator ^ (const U &);
+ template<int> U &operator & (const U &);
+ template<int> U &operator | (const U &);
+ template<int> U &operator += (const U &);
+ template<int> U &operator -= (const U &);
+ template<int> U &operator *= (const U &);
+ template<int> U &operator /= (const U &);
+ template<int> U &operator %= (const U &);
+ template<int> U &operator ^= (const U &);
+ template<int> U &operator &= (const U &);
+ template<int> U &operator |= (const U &);
+ template<int> U &operator <<= (int);
+ template<int> U &operator >>= (int);
+ template<int> bool operator == (const U &);
+ template<int> bool operator != (const U &);
+ template<int> bool operator < (const U &);
+ template<int> bool operator > (const U &);
+ template<int> bool operator <= (const U &);
+ template<int> bool operator >= (const U &);
+ template<int> int operator <=> (const U &);
+ template<int> bool operator && (const U &);
+ template<int> bool operator || (const U &);
+ template<int> U &operator , (const U &);
+ template<int> U *operator -> ();
+ template<int> U &operator ->* (const U &);
+ template<int> U &operator co_await ();
+};
+
+struct V
+{
+ template<int> V &operator ++ (int);
+ template<int> V &operator -- (int);
+ template<int> V &operator + ();
+ template<int> V &operator - ();
+};
+
static_assert (operator_of (^^S::operator new) == op_new);
static_assert (operator_of (^^S::operator delete) ==
std::meta::op_delete);
static_assert (operator_of (^^S::operator new[]) ==
std::meta::operators::op_array_new);
@@ -217,3 +274,51 @@ static_assert (operator_of (^^T::operator +) ==
op_plus);
static_assert (operator_of (^^T::operator -) == op_minus);
static_assert (operator_of (^^T::operator ++) == op_plus_plus);
static_assert (operator_of (^^T::operator --) == op_minus_minus);
+static_assert (operator_of (^^U::operator new) == op_new);
+static_assert (operator_of (^^U::operator delete) == std::meta::op_delete);
+static_assert (operator_of (^^U::operator new[]) ==
std::meta::operators::op_array_new);
+static_assert (operator_of (^^U::operator delete[]) == op_array_delete);
+static_assert (operator_of (^^U::operator co_await) == op_co_await);
+static_assert (operator_of (^^U::operator ()) == op_parentheses);
+static_assert (operator_of (^^U::operator []) == op_square_brackets);
+static_assert (operator_of (^^U::operator ->) == op_arrow);
+static_assert (operator_of (^^U::operator ->*) == op_arrow_star);
+static_assert (operator_of (^^U::operator ~) == op_tilde);
+static_assert (operator_of (^^U::operator !) == op_exclamation);
+static_assert (operator_of (^^U::operator +) == op_plus);
+static_assert (operator_of (^^U::operator -) == op_minus);
+static_assert (operator_of (^^U::operator *) == op_star);
+static_assert (operator_of (^^U::operator /) == op_slash);
+static_assert (operator_of (^^U::operator %) == op_percent);
+static_assert (operator_of (^^U::operator ^) == op_caret);
+static_assert (operator_of (^^U::operator &) == op_ampersand);
+static_assert (operator_of (template_of (^^U::operator =<0>)) ==
op_equals);
+static_assert (operator_of (^^U::operator |) == op_pipe);
+static_assert (operator_of (^^U::operator +=) == op_plus_equals);
+static_assert (operator_of (^^U::operator -=) == op_minus_equals);
+static_assert (operator_of (^^U::operator *=) == op_star_equals);
+static_assert (operator_of (^^U::operator /=) == op_slash_equals);
+static_assert (operator_of (^^U::operator %=) == op_percent_equals);
+static_assert (operator_of (^^U::operator ^=) == op_caret_equals);
+static_assert (operator_of (^^U::operator &=) == op_ampersand_equals);
+static_assert (operator_of (^^U::operator |=) == op_pipe_equals);
+static_assert (operator_of (^^U::operator ==) == op_equals_equals);
+static_assert (operator_of (^^U::operator !=) == op_exclamation_equals);
+static_assert (operator_of (^^U::operator <) == op_less);
+static_assert (operator_of (^^U::operator >) == op_greater);
+static_assert (operator_of (^^U::operator <=) == op_less_equals);
+static_assert (operator_of (^^U::operator >=) == op_greater_equals);
+static_assert (operator_of (^^U::operator <=>) == op_spaceship);
+static_assert (operator_of (^^U::operator &&) == op_ampersand_ampersand);
+static_assert (operator_of (^^U::operator ||) == op_pipe_pipe);
+static_assert (operator_of (^^U::operator <<) == op_less_less);
+static_assert (operator_of (^^U::operator >>) == op_greater_greater);
+static_assert (operator_of (^^U::operator <<=) == op_less_less_equals);
+static_assert (operator_of (^^U::operator >>=) ==
op_greater_greater_equals);
+static_assert (operator_of (^^U::operator ++) == op_plus_plus);
+static_assert (operator_of (^^U::operator --) == op_minus_minus);
+static_assert (operator_of (^^U::operator ,) == op_comma);
+static_assert (operator_of (^^V::operator +) == op_plus);
+static_assert (operator_of (^^V::operator -) == op_minus);
+static_assert (operator_of (^^V::operator ++) == op_plus_plus);
+static_assert (operator_of (^^V::operator --) == op_minus_minus);
--
2.52.0
Marek