Implement 'is_enumerable_type'.
This commit is contained in:
@@ -377,6 +377,12 @@ static bool has_complete_definition(APValue &Result, ASTContext &C,
|
||||
ArrayRef<Expr *> Args,
|
||||
Decl *ContainingDecl);
|
||||
|
||||
static bool is_enumerable_type(APValue &Result, ASTContext &C,
|
||||
MetaActions &Meta, EvalFn Evaluator,
|
||||
DiagFn Diagnoser, bool AllowInjection,
|
||||
QualType ResultTy, SourceRange Range,
|
||||
ArrayRef<Expr *> Args, Decl *ContainingDecl);
|
||||
|
||||
static bool is_template(APValue &Result, ASTContext &C, MetaActions &Meta,
|
||||
EvalFn Evaluator, DiagFn Diagnoser, bool AllowInjection,
|
||||
QualType ResultTy, SourceRange Range,
|
||||
@@ -772,6 +778,7 @@ static constexpr Metafunction Metafunctions[] = {
|
||||
{ Metafunction::MFRK_bool, 1, 1, is_alias },
|
||||
{ Metafunction::MFRK_bool, 1, 1, is_complete_type },
|
||||
{ Metafunction::MFRK_bool, 1, 1, has_complete_definition },
|
||||
{ Metafunction::MFRK_bool, 1, 1, is_enumerable_type },
|
||||
{ Metafunction::MFRK_bool, 1, 1, is_template },
|
||||
{ Metafunction::MFRK_bool, 1, 1, is_function_template },
|
||||
{ Metafunction::MFRK_bool, 1, 1, is_variable_template },
|
||||
@@ -2252,22 +2259,12 @@ bool type_of(APValue &Result, ASTContext &C, MetaActions &Meta,
|
||||
|
||||
switch (RV.getReflectionKind()) {
|
||||
case ReflectionKind::Null:
|
||||
case ReflectionKind::Type: {
|
||||
QualType QT = desugarType(RV.getTypeOfReflectedResult(C),
|
||||
/*UnwrapAliases=*/ true, /*DropCV=*/false,
|
||||
/*DropRefs=*/false);
|
||||
return SetAndSucceed(Result, makeReflection(QT));
|
||||
}
|
||||
case ReflectionKind::Type:
|
||||
case ReflectionKind::Template:
|
||||
case ReflectionKind::Namespace:
|
||||
return Diagnoser(Range.getBegin(), diag::metafn_no_associated_property)
|
||||
<< DescriptionOf(RV) << 0 << Range;
|
||||
case ReflectionKind::Object: {
|
||||
QualType QT = desugarType(RV.getTypeOfReflectedResult(C),
|
||||
/*UnwrapAliases=*/ true, /*DropCV=*/false,
|
||||
/*DropRefs=*/false);
|
||||
return SetAndSucceed(Result, makeReflection(QT));
|
||||
}
|
||||
case ReflectionKind::Object:
|
||||
case ReflectionKind::Value: {
|
||||
QualType QT = desugarType(RV.getTypeOfReflectedResult(C),
|
||||
/*UnwrapAliases=*/true, /*DropCV=*/false,
|
||||
@@ -3970,6 +3967,41 @@ bool has_complete_definition(APValue &Result, ASTContext &C, MetaActions &Meta,
|
||||
return SetAndSucceed(Result, makeBool(C, result));
|
||||
}
|
||||
|
||||
bool is_enumerable_type(APValue &Result, ASTContext &C, MetaActions &Meta,
|
||||
EvalFn Evaluator, DiagFn Diagnoser, bool AllowInjection,
|
||||
QualType ResultTy, SourceRange Range,
|
||||
ArrayRef<Expr *> Args, Decl *ContainingDecl) {
|
||||
assert(Args[0]->getType()->isReflectionType());
|
||||
assert(ResultTy == C.BoolTy);
|
||||
|
||||
APValue RV;
|
||||
if (!Evaluator(RV, Args[0], true))
|
||||
return true;
|
||||
|
||||
bool result = false;
|
||||
switch (RV.getReflectionKind()) {
|
||||
case ReflectionKind::Type:
|
||||
if (Decl *typeDecl = findTypeDecl(RV.getReflectedType())) {
|
||||
if (auto *TD = dyn_cast<TagDecl>(typeDecl))
|
||||
result = (TD->getDefinition() != nullptr &&
|
||||
!TD->getDefinition()->isBeingDefined());
|
||||
}
|
||||
break;
|
||||
case ReflectionKind::Null:
|
||||
case ReflectionKind::Object:
|
||||
case ReflectionKind::Value:
|
||||
case ReflectionKind::Declaration:
|
||||
case ReflectionKind::Template:
|
||||
case ReflectionKind::Namespace:
|
||||
case ReflectionKind::BaseSpecifier:
|
||||
case ReflectionKind::DataMemberSpec:
|
||||
case ReflectionKind::Annotation:
|
||||
break;
|
||||
}
|
||||
|
||||
return SetAndSucceed(Result, makeBool(C, result));
|
||||
}
|
||||
|
||||
bool is_template(APValue &Result, ASTContext &C, MetaActions &Meta,
|
||||
EvalFn Evaluator, DiagFn Diagnoser, bool AllowInjection,
|
||||
QualType ResultTy, SourceRange Range,
|
||||
|
||||
@@ -128,7 +128,7 @@ consteval auto is_type(info) -> bool;
|
||||
consteval auto is_type_alias(info) -> bool;
|
||||
consteval auto is_namespace_alias(info) -> bool;
|
||||
consteval auto is_complete_type(info) -> bool;
|
||||
consteval auto has_complete_definition(info) -> bool;
|
||||
consteval auto is_enumerable_type(info) -> bool;
|
||||
consteval auto is_template(info) -> bool;
|
||||
consteval auto is_function_template(info) -> bool;
|
||||
consteval auto is_variable_template(info) -> bool;
|
||||
@@ -483,6 +483,7 @@ enum : unsigned {
|
||||
__metafn_is_alias,
|
||||
__metafn_is_complete_type,
|
||||
__metafn_has_complete_definition,
|
||||
__metafn_is_enumerable_type,
|
||||
__metafn_is_template,
|
||||
__metafn_is_function_template,
|
||||
__metafn_is_variable_template,
|
||||
@@ -1076,13 +1077,13 @@ consteval auto nonstatic_data_members_of(info r) -> vector<info> {
|
||||
ranges::to<vector>();
|
||||
}
|
||||
|
||||
// Returns true if the reflected entity has a complete definition.
|
||||
consteval auto has_complete_definition(info r) -> bool {
|
||||
return __metafunction(detail::__metafn_has_complete_definition, r);
|
||||
// Returns true if the reflected entity is an enumerable type.
|
||||
consteval auto is_enumerable_type(info r) -> bool {
|
||||
return __metafunction(detail::__metafn_is_enumerable_type, r);
|
||||
}
|
||||
|
||||
consteval auto enumerators_of(info r) -> vector<info> {
|
||||
if (!has_complete_definition(r))
|
||||
if (!is_enumerable_type(r))
|
||||
throw "Reflection must represent an enumeration with a definition";
|
||||
|
||||
using iterator =
|
||||
@@ -2375,6 +2376,11 @@ consteval auto nonstatic_data_members_of(info r) -> vector<info> {
|
||||
return nonstatic_data_members_of(r, access_context::unchecked());
|
||||
}
|
||||
|
||||
[[deprecated("replaced with 'is_enumerable_type' in P2996R11")]]
|
||||
consteval auto has_complete_definition(info r) -> bool {
|
||||
return __metafunction(detail::__metafn_has_complete_definition, r);
|
||||
}
|
||||
|
||||
#endif // __has_feature(access_contexts)
|
||||
|
||||
|
||||
|
||||
@@ -363,62 +363,62 @@ static_assert(is_public(bases_of(^^D2<B1, B3>,
|
||||
|
||||
namespace enumerators {
|
||||
enum class EnumCls;
|
||||
static_assert(!has_complete_definition(^^EnumCls));
|
||||
static_assert(!is_enumerable_type(^^EnumCls));
|
||||
|
||||
enum class EnumCls {
|
||||
A,
|
||||
B = has_complete_definition(^^EnumCls) ? 1 : 0,
|
||||
B = is_enumerable_type(^^EnumCls) ? 1 : 0,
|
||||
C,
|
||||
};
|
||||
static_assert(int(EnumCls::B) == 0);
|
||||
static_assert(has_complete_definition(^^EnumCls));
|
||||
static_assert(is_enumerable_type(^^EnumCls));
|
||||
static_assert(enumerators_of(^^EnumCls) ==
|
||||
std::vector{^^EnumCls::A, ^^EnumCls::B, ^^EnumCls::C});
|
||||
|
||||
struct Cls { enum Enum { A, B, C }; };
|
||||
static_assert(!has_complete_definition(^^::));
|
||||
static_assert(has_complete_definition(^^Cls::Enum));
|
||||
static_assert(!is_enumerable_type(^^::));
|
||||
static_assert(is_enumerable_type(^^Cls::Enum));
|
||||
static_assert(enumerators_of(^^Cls::Enum) ==
|
||||
std::vector{^^Cls::A, ^^Cls::B, ^^Cls::C});
|
||||
|
||||
} // namespace enumerators
|
||||
|
||||
// ====================
|
||||
// complete_definitions
|
||||
// ====================
|
||||
// ================
|
||||
// enumerable_types
|
||||
// ================
|
||||
|
||||
namespace complete_definitions {
|
||||
namespace enumerable_types {
|
||||
enum E : int;
|
||||
static_assert(!has_complete_definition(^^E));
|
||||
static_assert(!is_enumerable_type(^^E));
|
||||
|
||||
enum E : int { A = has_complete_definition(^^E) ? 1 : 0 };
|
||||
enum E : int { A = is_enumerable_type(^^E) ? 1 : 0 };
|
||||
static_assert(E::A == 0);
|
||||
static_assert(has_complete_definition(^^E));
|
||||
static_assert(is_enumerable_type(^^E));
|
||||
|
||||
struct S;
|
||||
static_assert(!has_complete_definition(^^S));
|
||||
static_assert(!is_enumerable_type(^^S));
|
||||
|
||||
struct S {
|
||||
void fn() {
|
||||
static_assert(has_complete_definition(^^S));
|
||||
static_assert(is_enumerable_type(^^S));
|
||||
}
|
||||
static_assert(!has_complete_definition(^^S));
|
||||
static_assert(!is_enumerable_type(^^S));
|
||||
};
|
||||
static_assert(has_complete_definition(^^S));
|
||||
static_assert(is_enumerable_type(^^S));
|
||||
|
||||
void fn();
|
||||
static_assert(!has_complete_definition(^^fn));
|
||||
static_assert(!is_enumerable_type(^^fn));
|
||||
|
||||
void fn() {
|
||||
static_assert(!has_complete_definition(^^fn));
|
||||
static_assert(!is_enumerable_type(^^fn));
|
||||
}
|
||||
static_assert(has_complete_definition(^^fn));
|
||||
static_assert(!is_enumerable_type(^^fn));
|
||||
|
||||
static_assert(!has_complete_definition(^^::));
|
||||
static_assert(!has_complete_definition(^^int));
|
||||
static_assert(!has_complete_definition(^^std::vector));
|
||||
static_assert(!is_enumerable_type(^^::));
|
||||
static_assert(!is_enumerable_type(^^int));
|
||||
static_assert(!is_enumerable_type(^^std::vector));
|
||||
|
||||
} // namespace complete_definitions
|
||||
} // namespace enumrable_types
|
||||
|
||||
// ====================
|
||||
// deduced_return_types
|
||||
|
||||
Reference in New Issue
Block a user