Adding reflect_constant_array (#140)

* Attempting to add reflect_constant_array

* Fixing extract from array

* Fixing test

* Adding bounded test case
This commit is contained in:
Barry Revzin
2025-05-19 18:14:13 -05:00
committed by GitHub
parent 38da66472f
commit e8b93df07e
4 changed files with 35 additions and 36 deletions

View File

@@ -3098,13 +3098,17 @@ bool extract(APValue &Result, ASTContext &C, MetaActions &Meta,
Range.getBegin(), ResultTy, VK_LValue,
Decl, nullptr);
} else if (auto *ArrTy = dyn_cast<ArrayType>(Decl->getType())) {
QualType PtrTy = C.getPointerType(ArrTy->getElementType());
QualType Elt = ArrTy->getElementType();
if (auto *VD = dyn_cast<VarDecl>(Decl)) {
if (VD->isConstexpr()) {
Elt.addConst();
}
}
ReturnsLValue = true;
if (RawResultTy.getCanonicalType().getTypePtr() !=
PtrTy.getCanonicalType().getTypePtr())
if (!RawResultTy->isPointerType() || !RawResultTy->getPointeeType().isAtLeastAsQualifiedAs(Elt, C))
return Diagnoser(Range.getBegin(), diag::metafn_extract_type_mismatch)
<< 1 << PtrTy << 1 << ResultTy << Range;
<< 1 << C.getPointerType(Elt) << 1 << ResultTy << Range;
NestedNameSpecifierLocBuilder NNSLocBuilder;
if (auto *ParentClsDecl = dyn_cast_or_null<CXXRecordDecl>(

View File

@@ -1010,7 +1010,7 @@ public:
consteval auto is_accessible(info r, access_context ctx) -> bool {
// Note: The accessibility of an enumerator may be looked up in a class
// for which it's not a member, since that enumerator could be
// for which it's not a member, since that enumerator could be
if (!is_class_member(r) && !is_base(r) && !is_enumerator(r))
return true;
@@ -1402,8 +1402,8 @@ consteval auto is_user_declared(info r) -> bool {
}
// Returns a reflection of the value held by the provided argument.
template <typename T>
requires (!is_reference_v<T> &&
template <typename T>
requires (!is_reference_v<T> &&
__metafunction(detail::__metafn_is_structural_type, ^^T))
consteval auto reflect_constant(const T &r) -> info {
return __metafunction(detail::__metafn_reflect_result, ^^T,
@@ -2320,44 +2320,36 @@ consteval auto has_complete_definition(info r) -> bool {
return __metafunction(detail::__metafn_has_complete_definition, r);
}
_LIBCPP_END_NAMESPACE_REFLECTION_V2
_LIBCPP_BEGIN_NAMESPACE_STD
namespace __define_static {
template <typename ValTy, ValTy... Vals>
inline constexpr ValTy FixedArray[sizeof...(Vals)] = {Vals...};
template <auto &S>
inline constexpr span StaticSpan(S, size(S));
template <typename ValTy>
consteval span<const ValTy> impl(const span<const ValTy> &in) {
if (in.size() == 0)
return {};
vector Args = {^^ValTy};
for (const auto &V : in)
Args.push_back(meta::reflect_constant(V));
return meta::extract<span<const ValTy>>(
meta::substitute(^^StaticSpan, { meta::substitute(^^FixedArray, Args) }));
}
} // namespace __define_static
template <ranges::input_range R>
requires (is_constructible_v<ranges::range_value_t<R>,
ranges::range_reference_t<R>>)
consteval auto reflect_constant_array(R &&elems) -> info {
using ValTy = ranges::range_value_t<R>;
vector Args = {^^ValTy};
for (const auto &V : elems)
Args.push_back(reflect_constant(V));
return substitute(^^__define_static::FixedArray, Args);
}
_LIBCPP_END_NAMESPACE_REFLECTION_V2
_LIBCPP_BEGIN_NAMESPACE_STD
template <ranges::input_range R>
requires (is_constructible_v<ranges::range_value_t<R>,
ranges::range_reference_t<R>>)
consteval auto define_static_array(R &&elems)
-> span<const ranges::range_value_t<R>> {
using ValTy = ranges::range_value_t<R>;
using ImplTy = span<const ValTy>(*)(const span<const ValTy> &);
auto impl = meta::extract<ImplTy>(meta::substitute(^^__define_static::impl,
{^^ValTy}));
vector<ValTy> vals(from_range, elems);
return impl(vals);
meta::info array = meta::reflect_constant_array(elems);
return span<const ValTy>(extract<const ValTy*>(array), meta::extent(type_of(array)));
}
// Returns a static string having the provided contents.

View File

@@ -41,7 +41,7 @@ struct Cls {
};
constexpr auto objs = std::define_static_array(std::vector<Cls>{1, 3, 5});
static_assert(objs.size() == 3);
static_assert(objs[0].k == 5 && objs[1].k == 7 && objs[2].k == 9);
static_assert(objs[0].k == 4 && objs[1].k == 6 && objs[2].k == 8);
constexpr auto infos = std::define_static_array(
nonstatic_data_members_of(^^Cls,

View File

@@ -211,8 +211,11 @@ namespace extract_ref_semantics {
// ====================
namespace extract_array_as_ptr {
constexpr int arr[] = {1, 2, 3};
static_assert(extract<const int *>(^^arr)[2] == 3);
constexpr int a[] = {1, 2, 3};
static_assert(extract<const int *>(^^a)[2] == 3);
constexpr int b[3] = {1, 2, 3};
static_assert(extract<const int *>(^^b)[2] == 3);
} // namespace extract_array_as_ptr
@@ -331,7 +334,7 @@ static_assert([:rvfirst:].first == 1);
namespace reflect_constant_callable {
template<typename T>
constexpr auto reflectValueCallable =
constexpr auto reflectValueCallable =
requires { std::meta::reflect_constant<T>(std::declval<T>()); };
enum class E {};