diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc index 0febbbb5e57..3d966b259bb 100644 --- a/gcc/cp/reflect.cc +++ b/gcc/cp/reflect.cc @@ -1684,10 +1684,68 @@ eval_is_destructor (tree r) Otherwise, false. */ static tree -eval_is_conversion_function_template (const_tree) +eval_is_conversion_function_template (tree r) { - // Need members_of to test this. - gcc_assert (!"TODO"); + r = MAYBE_BASELINK_FUNCTIONS (r); + r = OVL_FIRST (r); + + if (DECL_FUNCTION_TEMPLATE_P (r) && DECL_CONV_FN_P (r)) + return boolean_true_node; + else + return boolean_false_node; +} + +/* Process std::meta::is_operator_function_template. + Returns: true if r represents an operator function template. + Otherwise, false. */ + +static tree +eval_is_operator_function_template (tree r) +{ + r = MAYBE_BASELINK_FUNCTIONS (r); + r = OVL_FIRST (r); + + if (DECL_FUNCTION_TEMPLATE_P (r)) + { + r = STRIP_TEMPLATE (r); + if (DECL_OVERLOADED_OPERATOR_P (r) && !DECL_CONV_FN_P (r)) + return boolean_true_node; + } + + return boolean_false_node; +} + +/* Process std::meta::is_literal_operator_template. + Returns: true if r represents a literal operator template. + Otherwise, false. */ + +static tree +eval_is_literal_operator_template (tree r) +{ + /* No MAYBE_BASELINK_FUNCTIONS here because a literal operator + template must be a non-member function template. */ + r = OVL_FIRST (r); + + if (DECL_FUNCTION_TEMPLATE_P (r) && UDLIT_OPER_P (DECL_NAME (r))) + return boolean_true_node; + else + return boolean_false_node; +} + +/* Process std::meta::is_constructor_template. + Returns: true if r represents a function that is an operator function + template. Otherwise, false. */ + +static tree +eval_is_constructor_template (tree r) +{ + r = MAYBE_BASELINK_FUNCTIONS (r); + r = OVL_FIRST (r); + + if (DECL_FUNCTION_TEMPLATE_P (r) && DECL_CONSTRUCTOR_P (r)) + return boolean_true_node; + else + return boolean_false_node; } /* Process std::meta::operator_of. @@ -2403,14 +2461,11 @@ eval_has_identifier (tree r, reflect_kind kind) } if (eval_is_template (r) == boolean_true_node) { -#if 0 - // TODO: Implement these first if (eval_is_constructor_template (r) == boolean_true_node || eval_is_operator_function_template (r) == boolean_true_node || eval_is_conversion_function_template (r) == boolean_true_node) return boolean_false_node; else -#endif return boolean_true_node; } if (eval_is_function_parameter (r, kind) == boolean_true_node) @@ -4300,6 +4355,12 @@ process_metafunction (const constexpr_ctx *ctx, tree call, return eval_is_destructor (h); if (!strcmp (ident, "conversion_function_template")) return eval_is_conversion_function_template (h); + if (!strcmp (ident, "operator_function_template")) + return eval_is_operator_function_template (h); + if (!strcmp (ident, "literal_operator_template")) + return eval_is_literal_operator_template (h); + if (!strcmp (ident, "constructor_template")) + return eval_is_constructor_template (h); if (!strcmp (ident, "function_type")) return eval_is_function_type (loc, ctx, h, jump_target); if (!strcmp (ident, "void_type")) diff --git a/gcc/testsuite/g++.dg/reflect/is_conversion_function_template1.C b/gcc/testsuite/g++.dg/reflect/is_conversion_function_template1.C index 6e0b174e63e..696790d871f 100644 --- a/gcc/testsuite/g++.dg/reflect/is_conversion_function_template1.C +++ b/gcc/testsuite/g++.dg/reflect/is_conversion_function_template1.C @@ -22,7 +22,7 @@ struct S { struct T { template - operator T(); + operator T (); }; bool operator&&(const S&, const S&); @@ -35,9 +35,8 @@ int operator""_a(const char *); template int operator""_b(); -#if 0 -constexpr auto conversion_template = - (members_of(^^T, ctx) | std::views::filter(std::meta::is_template)).front(); +//constexpr auto conversion_template = +// (members_of(^^T, ctx) | std::views::filter(std::meta::is_template)).front(); static_assert (!is_conversion_function_template (null_reflection)); static_assert (!is_conversion_function_template (^^int)); @@ -48,8 +47,7 @@ static_assert (!is_conversion_function_template (^^operator&&)); static_assert (!is_conversion_function_template (^^operator||)); static_assert (!is_conversion_function_template (^^S::operator-)); static_assert (!is_conversion_function_template (^^S::operator int)); -static_assert (is_conversion_function_template (conversion_template)); +//static_assert (is_conversion_function_template (conversion_template)); static_assert (!is_conversion_function_template (^^S::fn)); static_assert (!is_conversion_function_template (^^operator""_a)); static_assert (!is_conversion_function_template (^^operator""_b)); -#endif diff --git a/gcc/testsuite/g++.dg/reflect/is_literal_operator_template1.C b/gcc/testsuite/g++.dg/reflect/is_literal_operator_template1.C new file mode 100644 index 00000000000..8dd554ecdd9 --- /dev/null +++ b/gcc/testsuite/g++.dg/reflect/is_literal_operator_template1.C @@ -0,0 +1,55 @@ +// { dg-do compile { target c++26 } } +// { dg-additional-options "-freflection" } +// Test std::meta::is_literal_operator_template. + +#include + +using namespace std::meta; + +constexpr info null_reflection; +void foo (); + +struct S { + S &operator+(const S&); + + template + S &operator-(const S&); + + operator int(); + + void fn(); +}; + +struct T { + template + operator T(); +}; + +bool operator&&(const S&, const S&); + +template +bool operator||(const S&, const T&); + +int operator""_a(const char *); + +template +int operator""_b(); + +//constexpr auto conversion_template = +// (members_of(^^T, ctx) | std::views::filter(std::meta::is_template)).front(); + +static_assert (!is_literal_operator_template (null_reflection)); +static_assert (!is_literal_operator_template (^^int)); +static_assert (!is_literal_operator_template (^^::)); +static_assert (!is_literal_operator_template (^^foo)); +static_assert (!is_literal_operator_template (^^S::operator+)); +static_assert (!is_literal_operator_template (^^operator&&)); +static_assert (!is_literal_operator_template (^^operator||)); +static_assert (!is_literal_operator_template (^^operator||)); +static_assert (!is_literal_operator_template (^^S::operator-)); +static_assert (!is_literal_operator_template (^^S::operator-)); +static_assert (!is_literal_operator_template (^^S::operator int)); +//static_assert (!is_literal_operator_template (conversion_template)); +static_assert (!is_literal_operator_template (^^S::fn)); +static_assert (!is_literal_operator_template (^^operator""_a)); +static_assert (is_literal_operator_template (^^operator""_b)); diff --git a/gcc/testsuite/g++.dg/reflect/is_operator_function_template1.C b/gcc/testsuite/g++.dg/reflect/is_operator_function_template1.C new file mode 100644 index 00000000000..1f2c165783a --- /dev/null +++ b/gcc/testsuite/g++.dg/reflect/is_operator_function_template1.C @@ -0,0 +1,56 @@ +// { dg-do compile { target c++26 } } +// { dg-additional-options "-freflection" } +// Test std::meta::is_operator_function_template. + +#include + +using namespace std::meta; + +constexpr info null_reflection; +void foo (); + +struct S { + S &operator+(const S&); + + template + S &operator-(const S&); + + operator int(); + + void fn(); +}; + +struct T { + template + operator T (); +}; + +bool operator&&(const S&, const S&); + +template +bool operator||(const S&, const T&); + +int operator""_a(const char *); + +template +int operator""_b(); + +//constexpr auto conversion_template = +// (members_of(^^T, ctx) | std::views::filter(std::meta::is_template)).front(); + +static_assert (!is_operator_function_template (null_reflection)); +static_assert (!is_operator_function_template (^^int)); +static_assert (!is_operator_function_template (^^::)); +static_assert (!is_operator_function_template (^^foo)); +static_assert (!is_operator_function_template (^^S::operator+)); +static_assert (!is_operator_function_template (^^operator&&)); +static_assert (is_operator_function_template (^^operator||)); +static_assert (!is_operator_function_template (^^operator||)); +static_assert (is_operator_function_template (^^S::operator-)); +static_assert (!is_operator_function_template (^^S::operator-)); +static_assert (is_operator_function_template (template_of (^^S::operator-))); +static_assert (!is_operator_function_template (^^S::operator int)); +//static_assert (!is_operator_function_template (conversion_template)); +static_assert (!is_operator_function_template (^^S::fn)); +static_assert (!is_operator_function_template (^^operator""_a)); +static_assert (!is_operator_function_template (^^operator""_b)); diff --git a/libstdc++-v3/include/std/meta b/libstdc++-v3/include/std/meta index 9a31b1561c8..991a01e19a6 100644 --- a/libstdc++-v3/include/std/meta +++ b/libstdc++-v3/include/std/meta @@ -228,6 +228,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION consteval bool is_class_template(info); consteval bool is_alias_template(info); consteval bool is_conversion_function_template(info); + consteval bool is_operator_function_template(info); + consteval bool is_literal_operator_template(info); + consteval bool is_constructor_template(info); consteval bool is_concept(info); consteval bool is_object(info);