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.
PR c++/122771
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