diff --git a/clang/lib/AST/ExprConstantMeta.cpp b/clang/lib/AST/ExprConstantMeta.cpp index baa8c9fe61908e..734194bbf06c70 100644 --- a/clang/lib/AST/ExprConstantMeta.cpp +++ b/clang/lib/AST/ExprConstantMeta.cpp @@ -505,16 +505,6 @@ static bool alignment_of(APValue &Result, ASTContext &C, MetaActions &Meta, EvalFn Evaluator, DiagFn Diagnoser, QualType ResultTy, SourceRange Range, ArrayRef Args); -static bool define_static_string(APValue &Result, ASTContext &C, - MetaActions &Meta, EvalFn Evaluator, - DiagFn Diagnoser, QualType ResultTy, - SourceRange Range, ArrayRef Args); - -static bool define_static_array(APValue &Result, ASTContext &C, - MetaActions &Meta, EvalFn Evaluator, - DiagFn Diagnoser, QualType ResultTy, - SourceRange Range, ArrayRef Args); - // ----------------------------------------------------------------------------- // P3096 Metafunction declarations // ----------------------------------------------------------------------------- @@ -682,8 +672,6 @@ static constexpr Metafunction Metafunctions[] = { { Metafunction::MFRK_sizeT, 1, 1, bit_offset_of }, { Metafunction::MFRK_sizeT, 1, 1, bit_size_of }, { Metafunction::MFRK_sizeT, 1, 1, alignment_of }, - { Metafunction::MFRK_spliceFromArg, 5, 5, define_static_string }, - { Metafunction::MFRK_spliceFromArg, 4, 4, define_static_array }, // P3096 metafunction extensions { Metafunction::MFRK_metaInfo, 3, 3, get_ith_parameter_of }, @@ -5417,137 +5405,6 @@ bool alignment_of(APValue &Result, ASTContext &C, MetaActions &Meta, llvm_unreachable("unknown reflection kind"); } -bool define_static_string(APValue &Result, ASTContext &C, MetaActions &Meta, - EvalFn Evaluator, DiagFn Diagnoser, QualType ResultTy, - SourceRange Range, ArrayRef Args) { - assert(Args[0]->getType()->isReflectionType()); - assert(Args[1]->getType()->isReflectionType()); - - APValue Scratch; - - // Evaluate the character type. - if (!Evaluator(Scratch, Args[1], true)) - return true; - QualType CharTy = Scratch.getReflectedType(); - - // Evaluate the length of the string provided. - std::string Contents; - if (!Evaluator(Scratch, Args[2], true)) - return true; - size_t Length = Scratch.getInt().getExtValue(); - Contents.resize(Length); - - // Evaluate the given name. Miserably inefficient, but gets the job done. - for (uint64_t k = 0; k < Length; ++k) { - llvm::APInt Idx(C.getTypeSize(C.getSizeType()), k, false); - Expr *Synthesized = IntegerLiteral::Create(C, Idx, C.getSizeType(), - Args[3]->getExprLoc()); - - Synthesized = new (C) ArraySubscriptExpr(Args[3], Synthesized, CharTy, - VK_LValue, OK_Ordinary, - Range.getBegin()); - if (Synthesized->isValueDependent() || Synthesized->isTypeDependent()) - return true; - - if (!Evaluator(Scratch, Synthesized, true)) - return true; - - Contents[k] = static_cast(Scratch.getInt().getExtValue()); - } - - if (!Evaluator(Scratch, Args[4], true)) - return true; - bool IsUtf8 = Scratch.getInt().getBoolValue(); - - VarDecl *AnonArr = C.getGeneratedCharArray(Contents, IsUtf8); - if (!AnonArr->hasInit()) { - Expr *StrLit = makeStrLiteral(Contents, C, IsUtf8); - - AnonArr->setConstexpr(true); - Meta.AttachInitializer(AnonArr, StrLit); - - Meta.BroadcastInjectedDecl(AnonArr); - } - assert(AnonArr->getFormalLinkage() == Linkage::Internal); - - APValue::LValuePathEntry Path[1] = {APValue::LValuePathEntry::ArrayIndex(0)}; - return SetAndSucceed(Result, - APValue(AnonArr, CharUnits::Zero(), Path, false)); -} - -bool define_static_array(APValue &Result, ASTContext &C, MetaActions &Meta, - EvalFn Evaluator, DiagFn Diagnoser, QualType ResultTy, - SourceRange Range, ArrayRef Args) { - assert(Args[0]->getType()->isReflectionType()); - assert(Args[1]->getType()->isReflectionType()); - - APValue Scratch; - - // Evaluate the value type. - if (!Evaluator(Scratch, Args[1], true)) - return true; - QualType ValueTy = Scratch.getReflectedType(); - - // Evaluate the number of elements provided. - SmallVector Elems; - if (!Evaluator(Scratch, Args[2], true)) - return true; - size_t Length = Scratch.getInt().getExtValue(); - Elems.resize(Length); - - for (uint64_t k = 0; k < Length; ++k) { - llvm::APInt Idx(C.getTypeSize(C.getSizeType()), k, false); - Expr *Synthesized = IntegerLiteral::Create(C, Idx, C.getSizeType(), - Args[3]->getExprLoc()); - - Synthesized = new (C) ArraySubscriptExpr(Args[3], Synthesized, ValueTy, - VK_LValue, OK_Ordinary, - Range.getBegin()); - if (Synthesized->isValueDependent() || Synthesized->isTypeDependent()) - return true; - - APValue Val; - if (!Evaluator(Val, Synthesized, true)) - return true; - - Synthesized = new (C) OpaqueValueExpr(Range.getBegin(), ValueTy, - VK_PRValue); - Synthesized = ConstantExpr::Create(C, Synthesized, Val); - - Elems[k] = Synthesized; - } - - std::string Name; - { - static int gen_id = 0; - llvm::raw_string_ostream NameOut(Name); - NameOut << "__gen_array_" << (gen_id++); - } - - QualType ArrTy = C.getConstantArrayType(ValueTy, llvm::APSInt::get(Length), - Args[2], ArraySizeModifier::Normal, - /*IndexTypeQuals=*/0); - VarDecl *AnonArr = VarDecl::Create(C, C.getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &C.Idents.get(Name), ArrTy, nullptr, - SC_Static); - { - Expr *ILE = Meta.CreateInitList(Elems, Range); - if (!ILE) - return true; - AnonArr->setConstexpr(true); - Meta.AttachInitializer(AnonArr, ILE); - - Meta.BroadcastInjectedDecl(AnonArr); - } - assert(AnonArr->getFormalLinkage() == Linkage::Internal); - - APValue::LValuePathEntry Path[1] = {APValue::LValuePathEntry::ArrayIndex(0)}; - return SetAndSucceed(Result, - APValue(AnonArr, CharUnits::Zero(), Path, false)); -} - - bool get_ith_parameter_of(APValue &Result, ASTContext &C, MetaActions &Meta, EvalFn Evaluator, DiagFn Diagnoser, QualType ResultTy, SourceRange Range, ArrayRef Args) { diff --git a/libcxx/include/experimental/meta b/libcxx/include/experimental/meta index 54527ca14bbbc3..cf8f815eafaa75 100644 --- a/libcxx/include/experimental/meta +++ b/libcxx/include/experimental/meta @@ -539,8 +539,6 @@ enum : unsigned { __metafn_bit_offset_of, __metafn_bit_size_of, __metafn_alignment_of, - __metafn_define_static_string, - __metafn_define_static_array, // P3096 metafunctions __metafn_get_ith_parameter_of, @@ -1438,7 +1436,7 @@ consteval auto reflect_value(T r) -> info { constexpr info Ty = type_of(LIFT(r)); return __metafunction(detail::__metafn_reflect_result, Ty, - static_cast(r)); + static_cast(r)); } // Returns a reflection of the object designated by the provided argument. @@ -1625,31 +1623,52 @@ consteval auto bit_size_of(info r) -> size_t { return __metafunction(detail::__metafn_bit_size_of, r); } -// Returns a static string having the provided contents. -consteval auto define_static_string(string_view in) -> const char * { - return __metafunction(detail::__metafn_define_static_string, - LIFT(const char *), LIFT(char), in.size(), in.data(), - /*IsUtf8=*/false); -} +namespace __define_static { -consteval auto define_static_string(u8string_view in) -> const char8_t * { - return __metafunction(detail::__metafn_define_static_string, - LIFT(const char8_t *), LIFT(char8_t), - in.size(), in.data(), /*IsUtf8=*/true); +template +inline constexpr ValTy FixedArray[sizeof...(Vals)] = {Vals...}; + +template +inline constexpr span StaticSpan(S, size(S)); + +template +consteval span impl(const span &in) { + if (in.size() == 0) + return {}; + + vector Args = {^^ValTy}; + for (const auto &V : in) + Args.push_back(reflect_value(V)); + + return extract>( + substitute(^^StaticSpan, { substitute(^^FixedArray, Args) })); } +} // namespace __define_static template requires (is_constructible_v, ranges::range_reference_t>) consteval auto define_static_array(R &&elems) -> span> { - vector vec(from_range, elems); + using ValTy = ranges::range_value_t; + using ImplTy = span(*)(const span &); + auto impl = extract(substitute(^^__define_static::impl, {^^ValTy})); - using value_t = ranges::range_value_t; - const value_t *arr = __metafunction(detail::__metafn_define_static_array, - LIFT(const value_t *), LIFT(value_t), - vec.size(), vec.data()); - return span>(arr, vec.size()); + vector vals(from_range, elems); + return impl(vals); +} + +// Returns a static string having the provided contents. +consteval auto define_static_string(string_view in) -> const char * { + const char nullterm[1] = {0}; + vector> v = {in, nullterm}; + return define_static_array(views::join(v)).data(); +} + +consteval auto define_static_string(u8string_view in) -> const char8_t * { + const char8_t nullterm[1] = {0}; + vector> v = {in, nullterm}; + return define_static_array(views::join(v)).data(); } @@ -2149,7 +2168,7 @@ consteval auto type_tuple_size(info type) -> size_t { consteval auto type_tuple_element(size_t index, info type) -> info { return dealias(substitute(LIFT(tuple_element_t), - {std::meta::reflect_value(index), type})); + {reflect_value(index), type})); } consteval auto type_variant_size(info type) -> size_t { @@ -2158,7 +2177,7 @@ consteval auto type_variant_size(info type) -> size_t { consteval auto type_variant_alternative(size_t index, info type) -> info { return dealias(substitute(LIFT(variant_alternative_t), - {std::meta::reflect_value(index), type})); + {reflect_value(index), type})); } @@ -2241,7 +2260,7 @@ consteval auto annotations_of(info r, info ty) -> vector { template consteval optional annotation_of_type(info r) { - auto v = annotations_of(r, ^^T); + auto v = annotations_of(r, LIFT(T)); optional result{}; for (info a: v) { if (result.has_value()) { @@ -2325,13 +2344,13 @@ struct pretty_printer { using string_t = basic_string; - static consteval const CharT *string_constant(std::string_view contents) { + static consteval const CharT *string_constant(string_view contents) { if constexpr (IsUtf8) { - std::u8string result(contents.size(), 0); + u8string result(contents.size(), 0); for (size_t idx = 0; char c : contents) result[idx++] = char8_t(c); - return std::meta::define_static_string(result); + return define_static_string(result); } else { return contents.data(); } @@ -2626,15 +2645,15 @@ consteval auto pretty_printer::tprint_impl::render() -> string_t { if constexpr (is_constructor_template(R)) return render(); else if (is_operator_function_template(R)) { - std::meta::operators op = operator_of(R); + operators op = operator_of(R); string_t result = "operator"; switch (op) { - case std::meta::operators::op_new: - case std::meta::operators::op_delete: - case std::meta::operators::op_array_new: - case std::meta::operators::op_array_delete: - case std::meta::operators::op_co_await: + case operators::op_new: + case operators::op_delete: + case operators::op_array_new: + case operators::op_array_delete: + case operators::op_co_await: result += " "; [[fallthrough]]; default: @@ -2675,15 +2694,15 @@ consteval auto pretty_printer::tprint_impl::render() -> string_t { } else if constexpr (is_constructor(R)) { return render(); } else if constexpr (is_operator_function(R)) { - std::meta::operators op = operator_of(R); + operators op = operator_of(R); result = "operator"; switch (op) { - case std::meta::operators::op_new: - case std::meta::operators::op_delete: - case std::meta::operators::op_array_new: - case std::meta::operators::op_array_delete: - case std::meta::operators::op_co_await: + case operators::op_new: + case operators::op_delete: + case operators::op_array_new: + case operators::op_array_delete: + case operators::op_co_await: result += " "; [[fallthrough]]; default: diff --git a/libcxx/test/std/experimental/reflection/static-arrays.pass.cpp b/libcxx/test/std/experimental/reflection/static-arrays.pass.cpp index 01f7f039d4a92b..abea7c0a3fbecb 100644 --- a/libcxx/test/std/experimental/reflection/static-arrays.pass.cpp +++ b/libcxx/test/std/experimental/reflection/static-arrays.pass.cpp @@ -40,7 +40,7 @@ struct Cls { }; constexpr auto objs = std::meta::define_static_array(std::vector{1, 3, 5}); static_assert(objs.size() == 3); -static_assert(objs[0].k == 3 && objs[1].k == 5 && objs[2].k == 7); +static_assert(objs[0].k == 5 && objs[1].k == 7 && objs[2].k == 9); constexpr auto infos = std::meta::define_static_array( nonstatic_data_members_of(^^Cls));