Implement std::meta::is_{{conversion,operator}_function,literal_operator,constructor}_template.

Still no idea how to test is_conversion_function_template and
is_constructor_template.

Also, unsure if is_constructor is not incorrect (i.e. whether it
should only return true for FUNCTION_DECLs and not TEMPLATE_DECLs).
This commit is contained in:
Jakub Jelinek
2025-10-10 20:37:44 +02:00
committed by Marek Polacek
parent c80c5aba39
commit ab12ae0594
5 changed files with 185 additions and 12 deletions

View File

@@ -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"))

View File

@@ -22,7 +22,7 @@ struct S {
struct T {
template <typename T>
operator T();
operator T ();
};
bool operator&&(const S&, const S&);
@@ -35,9 +35,8 @@ int operator""_a(const char *);
template<char...>
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

View File

@@ -0,0 +1,55 @@
// { dg-do compile { target c++26 } }
// { dg-additional-options "-freflection" }
// Test std::meta::is_literal_operator_template.
#include <meta>
using namespace std::meta;
constexpr info null_reflection;
void foo ();
struct S {
S &operator+(const S&);
template <typename T>
S &operator-(const S&);
operator int();
void fn();
};
struct T {
template <typename T>
operator T();
};
bool operator&&(const S&, const S&);
template <typename T>
bool operator||(const S&, const T&);
int operator""_a(const char *);
template<char...>
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||<int>));
static_assert (!is_literal_operator_template (^^S::operator-));
static_assert (!is_literal_operator_template (^^S::operator-<int>));
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));

View File

@@ -0,0 +1,56 @@
// { dg-do compile { target c++26 } }
// { dg-additional-options "-freflection" }
// Test std::meta::is_operator_function_template.
#include <meta>
using namespace std::meta;
constexpr info null_reflection;
void foo ();
struct S {
S &operator+(const S&);
template <typename T>
S &operator-(const S&);
operator int();
void fn();
};
struct T {
template <typename T>
operator T ();
};
bool operator&&(const S&, const S&);
template <typename T>
bool operator||(const S&, const T&);
int operator""_a(const char *);
template<char...>
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||<int>));
static_assert (is_operator_function_template (^^S::operator-));
static_assert (!is_operator_function_template (^^S::operator-<int>));
static_assert (is_operator_function_template (template_of (^^S::operator-<int>)));
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));

View File

@@ -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);