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

Reply via email to