From 133a61c0db63f4e216fbdb6744caf43b6d97ce03 Mon Sep 17 00:00:00 2001 From: Dan Katz Date: Wed, 12 Jun 2024 14:36:39 -0400 Subject: [PATCH] Unicode upgrades. Also closes #10. --- clang/include/clang/Lex/Lexer.h | 2 + clang/lib/Lex/Lexer.cpp | 79 ++++++++++ clang/lib/Sema/Metafunctions.cpp | 135 ++++++++---------- clang/lib/Sema/SemaTemplate.cpp | 2 + libcxx/include/experimental/meta | 35 ++++- .../reflection/define-class.pass.cpp | 40 +++++- .../experimental/reflection/names.pass.cpp | 72 +++++----- ...6-ex-parsing-command-line-options-2.sh.cpp | 2 +- ...996-ex-struct-to-struct-of-arrays.pass.cpp | 4 +- 9 files changed, 252 insertions(+), 119 deletions(-) diff --git a/clang/include/clang/Lex/Lexer.h b/clang/include/clang/Lex/Lexer.h index b6ecc7e5ded9e2..916a99c185e09b 100644 --- a/clang/include/clang/Lex/Lexer.h +++ b/clang/include/clang/Lex/Lexer.h @@ -602,6 +602,8 @@ class Lexer : public PreprocessorLexer { /// Check if this is the first time we're lexing the input file. bool isFirstTimeLexingFile() const { return IsFirstTimeLexingFile; } + bool validateAndRewriteIdentifier(std::string &In); + private: //===--------------------------------------------------------------------===// // Internal implementation interfaces. diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp index a41b76f7c71230..278a5db4dc7a2e 100644 --- a/clang/lib/Lex/Lexer.cpp +++ b/clang/lib/Lex/Lexer.cpp @@ -4689,3 +4689,82 @@ bool Lexer::LexDependencyDirectiveTokenWhileSkipping(Token &Result) { convertDependencyDirectiveToken(DDTok, Result); return false; } + +bool Lexer::validateAndRewriteIdentifier(std::string &In) { + SmallVector RewriteUTF32; + + static const llvm::sys::UnicodeCharRange DigitRanges[] = { + {0x0030, 0x0039} + }; + static llvm::sys::UnicodeCharRange NondigitRanges[] = { + {0x0041, 0x005A}, {0x005F, 0x005F}, {0x0061, 0x007A} + }; + static const llvm::sys::UnicodeCharSet DigitChars(DigitRanges); + static const llvm::sys::UnicodeCharSet NondigitChars(NondigitRanges); + static const llvm::sys::UnicodeCharSet XIDStartChars(XIDStartRanges); + static const llvm::sys::UnicodeCharSet XIDContinueChars(XIDContinueRanges); + + if (In.size() == 0) + return false; + + const auto *Cursor = &In[0]; + const auto *End = Cursor + In.size(); + + // Validate leading character. + if (*Cursor == '\\') { + const char *SlashLoc = Cursor++; + std::optional UCN = tryReadUCN(Cursor, SlashLoc, nullptr); + if (!UCN || !XIDStartChars.contains(UCN.value())) + return false; + RewriteUTF32.push_back(UCN.value()); + } else { + llvm::UTF32 CodePoint; + + if (llvm::conversionOK != llvm::convertUTF8Sequence( + reinterpret_cast(&Cursor), + reinterpret_cast(End), &CodePoint, + llvm::ConversionFlags::strictConversion)) + return false; + + if (!NondigitChars.contains(CodePoint) && + !XIDStartChars.contains(CodePoint)) + return false; + RewriteUTF32.push_back(CodePoint); + } + + // Validate remaining characters. + while (Cursor < End) { + if (*Cursor == '\\') { + const char *SlashLoc = Cursor++; + std::optional UCN = tryReadUCN(Cursor, SlashLoc, nullptr); + if (!UCN || !(XIDStartChars.contains(UCN.value()) || + XIDContinueChars.contains(UCN.value()))) + return false; + RewriteUTF32.push_back(UCN.value()); + } else { + llvm::UTF32 CodePoint; + + if (llvm::conversionOK != llvm::convertUTF8Sequence( + reinterpret_cast(&Cursor), + reinterpret_cast(End), &CodePoint, + llvm::ConversionFlags::strictConversion)) + return false; + + if (!DigitChars.contains(CodePoint) && + !NondigitChars.contains(CodePoint) && + !XIDStartChars.contains(CodePoint) && + !XIDContinueChars.contains(CodePoint)) + return false; + RewriteUTF32.push_back(CodePoint); + } + } + assert(Cursor == End); + + std::string Rewrite; + Rewrite.reserve(RewriteUTF32.size() * 4); + if (!llvm::convertUTF32ToUTF8String(RewriteUTF32, Rewrite)) + return true; + In = Rewrite; + + return true; +} diff --git a/clang/lib/Sema/Metafunctions.cpp b/clang/lib/Sema/Metafunctions.cpp index 93206b87811b38..5b1606b9fa0c51 100644 --- a/clang/lib/Sema/Metafunctions.cpp +++ b/clang/lib/Sema/Metafunctions.cpp @@ -20,6 +20,7 @@ #include "clang/AST/RecordLayout.h" #include "clang/AST/Reflection.h" #include "clang/Basic/SourceManager.h" +#include "clang/Lex/Lexer.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Metafunction.h" #include "clang/Sema/ParsedTemplate.h" @@ -392,7 +393,7 @@ static constexpr Metafunction Metafunctions[] = { { Metafunction::MFRK_bool, 1, 1, is_special_member }, { Metafunction::MFRK_metaInfo, 2, 2, reflect_result }, { Metafunction::MFRK_metaInfo, 5, 5, reflect_invoke }, - { Metafunction::MFRK_metaInfo, 9, 9, data_member_spec }, + { Metafunction::MFRK_metaInfo, 10, 10, data_member_spec }, { Metafunction::MFRK_metaInfo, 3, 3, define_class }, { Metafunction::MFRK_sizeT, 1, 1, offset_of }, { Metafunction::MFRK_sizeT, 1, 1, size_of }, @@ -527,6 +528,7 @@ static void getTypeName(std::string &Result, ASTContext &C, QualType QT, bool BasicOnly) { PrintingPolicy PP = C.getPrintingPolicy(); PP.SuppressTagKeyword = true; + PP.SuppressScope = true; encodeName(Result, QT.getAsString(PP), BasicOnly); } @@ -1779,27 +1781,20 @@ bool can_substitute(APValue &Result, Sema &S, EvalFn Evaluator, for (uint64_t k = 0; k < nArgs; ++k) { llvm::APInt Idx(S.Context.getTypeSize(S.Context.getSizeType()), k, false); - Expr *IdxExpr = IntegerLiteral::Create(S.Context, Idx, - S.Context.getSizeType(), - Args[1]->getExprLoc()); - - ArraySubscriptExpr *SubscriptExpr = - new (S.Context) ArraySubscriptExpr(Args[1], IdxExpr, - S.Context.MetaInfoTy, - VK_LValue, OK_Ordinary, - Range.getBegin()); - - ImplicitCastExpr *RVExpr = ImplicitCastExpr::Create(S.Context, - S.Context.MetaInfoTy, - CK_LValueToRValue, - SubscriptExpr, - nullptr, VK_PRValue, - FPOptionsOverride()); - if (RVExpr->isValueDependent() || RVExpr->isTypeDependent()) + Expr *Synthesized = IntegerLiteral::Create(S.Context, Idx, + S.Context.getSizeType(), + Args[1]->getExprLoc()); + + Synthesized = new (S.Context) ArraySubscriptExpr(Args[1], Synthesized, + S.Context.MetaInfoTy, + VK_LValue, OK_Ordinary, + Range.getBegin()); + if (Synthesized->isValueDependent() || Synthesized->isTypeDependent()) return true; APValue Unwrapped; - if (!Evaluator(Unwrapped, RVExpr, true) || !Unwrapped.isReflection() || + if (!Evaluator(Unwrapped, Synthesized, true) || + !Unwrapped.isReflection() || !CanActAsTemplateArg(Unwrapped.getReflection())) return true; @@ -1852,27 +1847,20 @@ bool substitute(APValue &Result, Sema &S, EvalFn Evaluator, QualType ResultTy, for (uint64_t k = 0; k < nArgs; ++k) { llvm::APInt Idx(S.Context.getTypeSize(S.Context.getSizeType()), k, false); - Expr *IdxExpr = IntegerLiteral::Create(S.Context, Idx, - S.Context.getSizeType(), - Args[1]->getExprLoc()); - - ArraySubscriptExpr *SubscriptExpr = - new (S.Context) ArraySubscriptExpr(Args[1], IdxExpr, - S.Context.MetaInfoTy, - VK_LValue, OK_Ordinary, - Range.getBegin()); - - ImplicitCastExpr *RVExpr = ImplicitCastExpr::Create(S.Context, - S.Context.MetaInfoTy, - CK_LValueToRValue, - SubscriptExpr, - nullptr, VK_PRValue, - FPOptionsOverride()); - if (RVExpr->isValueDependent() || RVExpr->isTypeDependent()) + Expr *Synthesized = IntegerLiteral::Create(S.Context, Idx, + S.Context.getSizeType(), + Args[1]->getExprLoc()); + + Synthesized = new (S.Context) ArraySubscriptExpr(Args[1], Synthesized, + S.Context.MetaInfoTy, + VK_LValue, OK_Ordinary, + Range.getBegin()); + if (Synthesized->isValueDependent() || Synthesized->isTypeDependent()) return true; APValue Unwrapped; - if (!Evaluator(Unwrapped, RVExpr, true) || !Unwrapped.isReflection() || + if (!Evaluator(Unwrapped, Synthesized, true) || + !Unwrapped.isReflection() || !CanActAsTemplateArg(Unwrapped.getReflection())) return true; @@ -3363,34 +3351,41 @@ bool data_member_spec(APValue &Result, Sema &S, EvalFn Evaluator, size_t nameLen = Scratch.getInt().getExtValue(); Name.emplace(nameLen, '\0'); + // Evaluate the character type. + if (!Evaluator(Scratch, Args[ArgIdx++], true)) + return true; + QualType CharTy = Scratch.getReflectedType(); + + // Evaluate the data contents. for (uint64_t k = 0; k < nameLen; ++k) { llvm::APInt Idx(S.Context.getTypeSize(S.Context.getSizeType()), k, false); - Expr *IdxExpr = IntegerLiteral::Create(S.Context, Idx, - S.Context.getSizeType(), - Args[ArgIdx]->getExprLoc()); - - ArraySubscriptExpr *SubscriptExpr = - new (S.Context) ArraySubscriptExpr(Args[ArgIdx], IdxExpr, - S.Context.CharTy, - VK_LValue, OK_Ordinary, - Range.getBegin()); - - ImplicitCastExpr *RVExpr = ImplicitCastExpr::Create(S.Context, - S.Context.CharTy, - CK_LValueToRValue, - SubscriptExpr, - nullptr, VK_PRValue, - FPOptionsOverride()); - if (RVExpr->isValueDependent() || RVExpr->isTypeDependent()) + Expr *Synthesized = IntegerLiteral::Create(S.Context, Idx, + S.Context.getSizeType(), + Args[ArgIdx]->getExprLoc()); + + Synthesized = new (S.Context) ArraySubscriptExpr(Args[ArgIdx], + Synthesized, CharTy, + VK_LValue, OK_Ordinary, + Range.getBegin()); + if (Synthesized->isValueDependent() || Synthesized->isTypeDependent()) return true; - if (!Evaluator(Scratch, RVExpr, true)) + if (!Evaluator(Scratch, Synthesized, true)) return true; + (*Name)[k] = static_cast(Scratch.getInt().getExtValue()); } ArgIdx++; } else { - ArgIdx += 2; + ArgIdx += 3; + } + + // Validate the name as an identifier. + if (Name) { + Lexer Lex(Range.getBegin(), S.getLangOpts(), Name->data(), Name->data(), + Name->data() + Name->size(), false); + if (!Lex.validateAndRewriteIdentifier(*Name)) + return true; } // Evaluate whether an alignment was provided. @@ -3581,28 +3576,20 @@ bool define_class(APValue &Result, Sema &S, EvalFn Evaluator, QualType ResultTy, for (size_t k = 0; k < NumMembers; ++k) { // Extract the reflection from the list of member specs. llvm::APInt Idx(S.Context.getTypeSize(S.Context.getSizeType()), k, false); - Expr *IdxExpr = IntegerLiteral::Create(S.Context, Idx, - S.Context.getSizeType(), - Args[2]->getExprLoc()); - - ArraySubscriptExpr *SubscriptExpr = - new (S.Context) ArraySubscriptExpr(Args[2], IdxExpr, - S.Context.MetaInfoTy, - VK_LValue, OK_Ordinary, - Range.getBegin()); - - ImplicitCastExpr *RVExpr = ImplicitCastExpr::Create(S.Context, - S.Context.MetaInfoTy, - CK_LValueToRValue, - SubscriptExpr, - nullptr, VK_PRValue, - FPOptionsOverride()); - if (RVExpr->isValueDependent() || RVExpr->isTypeDependent()) { + Expr *Synthesized = IntegerLiteral::Create(S.Context, Idx, + S.Context.getSizeType(), + Args[2]->getExprLoc()); + + Synthesized = new (S.Context) ArraySubscriptExpr(Args[2], Synthesized, + S.Context.MetaInfoTy, + VK_LValue, OK_Ordinary, + Range.getBegin()); + if (Synthesized->isValueDependent() || Synthesized->isTypeDependent()) { RestoreDC(); return true; } - if (!Evaluator(Scratch, RVExpr, true) || + if (!Evaluator(Scratch, Synthesized, true) || Scratch.getReflection().getKind() != ReflectionValue::RK_data_member_spec) { RestoreDC(); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 8b805c7dd66889..e6767c71d92239 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -8843,6 +8843,8 @@ static ExprResult BuildExpressionFromReflection(Sema &S, const ReflectionValue &R, SourceLocation Loc) { switch (R.getKind()) { + case ReflectionValue::RK_null: + return CXXReflectExpr::Create(S.Context, Loc, Loc); case ReflectionValue::RK_type: return CXXReflectExpr::Create(S.Context, Loc, Loc, R.getAsType()); case ReflectionValue::RK_expr_result: diff --git a/libcxx/include/experimental/meta b/libcxx/include/experimental/meta index bb0d5f2c4dd419..bdc70b63b8033b 100644 --- a/libcxx/include/experimental/meta +++ b/libcxx/include/experimental/meta @@ -158,6 +158,7 @@ consteval auto has_default_argument(info) -> bool; #include #include #include +#include #include #if __has_feature(reflection) @@ -942,7 +943,17 @@ consteval auto reflect_invoke(info target, R1 &&targs, R2 &&args) -> info { // Representation of a data member which may be passed to 'data_member_spec'. struct data_member_options_t { - optional name = nullopt; + struct name_type { + std::variant impl; + + template requires constructible_from + consteval name_type(T &&in) : impl(std::in_place_type, in) {} + + template requires constructible_from + consteval name_type(T &&in) : impl(std::in_place_type, in) {} + }; + + optional name = nullopt; bool is_static = false; optional alignment = nullopt; optional width = nullopt; @@ -952,16 +963,26 @@ struct data_member_options_t { // be used with 'define_class' to define a record type. consteval auto data_member_spec(info member_type, data_member_options_t options = {}) -> info { - string_view name = options.name.value_or(""); + auto name = options.name.value_or(u8"").impl; bool is_static = options.is_static; int alignment = options.alignment.value_or(0); int width = options.width.value_or(0); - return __metafunction(detail::__metafn_data_member_spec, - member_type, is_static, - options.name.has_value(), name.size(), name.data(), - options.alignment.has_value(), alignment, - options.width.has_value(), width); + if (holds_alternative(name)) { + const u8string &s = get(name); + return __metafunction(detail::__metafn_data_member_spec, + member_type, is_static, options.name.has_value(), + s.size(), ^const char8_t *, s.data(), + options.alignment.has_value(), alignment, + options.width.has_value(), width); + } else { + const string &s = get(name); + return __metafunction(detail::__metafn_data_member_spec, + member_type, is_static, options.name.has_value(), + s.size(), ^const char *, s.data(), + options.alignment.has_value(), alignment, + options.width.has_value(), width); + } } // Completes the definition of the record type reflected by 'class_type' with diff --git a/libcxx/test/std/experimental/reflection/define-class.pass.cpp b/libcxx/test/std/experimental/reflection/define-class.pass.cpp index 9fa75ec241a4cc..58485439343804 100644 --- a/libcxx/test/std/experimental/reflection/define-class.pass.cpp +++ b/libcxx/test/std/experimental/reflection/define-class.pass.cpp @@ -239,12 +239,50 @@ union U; static_assert(is_incomplete_type(^S)); static_assert(is_type(define_class(^S, { - data_member_spec(^int,{.name="count", .is_static=true}), + data_member_spec(^int, {.name="count", .is_static=true}), }))); static_assert(!is_incomplete_type(^S)); decltype(S::count) S::count = 14; } // namespace static_data_member + // ======================= + // utf8_name_of_roundtrips + // ======================= + +namespace utf8_name_of_roundtrip { +class Kühl { }; + +class Cls1; +static_assert( + is_type(define_class(^Cls1, {data_member_spec(^int, + {.name=name_of(^Kühl)})}))); +static_assert(name_of(nonstatic_data_members_of(^Cls1)[0]) == u8"Kühl"); + +class Cls2; + +constexpr std::string_view sv = name_of(^Kühl); +static_assert(sv == "K\\u{00FC}hl"); +static_assert(is_type(define_class(^Cls2, + {data_member_spec(^int, {.name=sv})}))); +static_assert(name_of(nonstatic_data_members_of(^Cls2)[0]) == u8"Kühl"); + +} // namespace utf8_name_of_roundtrip + + // ====================== + // member_names_with_ucns + // ====================== + +namespace member_names_with_ucns { +struct S; +constexpr auto U = define_class(^S, { + data_member_spec(^int, {.name="i", .alignment=64}), + data_member_spec(^int, {.name=u8"こんにち", .alignment=64}), + data_member_spec(^int, {.name="v\\N{LATIN SMALL LETTER AE}rs\\u{E5}god"}) +}); +[[maybe_unused]] constexpr [:U:] s{.i=1, .こんにち=2, .værsågod=3}; + +} // namespace member_names_with_ucns + int main() { // RUN: grep "S::count=14" %t.stdout std::print("S::count={}", static_data_member::S::count); diff --git a/libcxx/test/std/experimental/reflection/names.pass.cpp b/libcxx/test/std/experimental/reflection/names.pass.cpp index 06c0dc9d83bf96..900a0dceb82f00 100644 --- a/libcxx/test/std/experimental/reflection/names.pass.cpp +++ b/libcxx/test/std/experimental/reflection/names.pass.cpp @@ -19,11 +19,17 @@ static_assert(name_of(^::) == u8""); +static_assert(name_of(^::) == ""); static_assert(name_of(std::meta::reflect_value(3)) == u8""); +static_assert(name_of(std::meta::reflect_value(3)) == ""); static_assert(name_of(^int) == u8"int"); +static_assert(name_of(^int) == "int"); static_assert(display_name_of(^::) == u8""); +static_assert(display_name_of(^::) == ""); static_assert(display_name_of(std::meta::reflect_value(3)) == u8""); -static_assert(display_name_of(^int) == u8"int"); +static_assert(display_name_of(std::meta::reflect_value(3)) == + ""); +static_assert(display_name_of(^int) == "int"); using Alias = int; @@ -108,11 +114,11 @@ struct Cls : Base { }; static_assert(name_of(^Cls) == u8"Cls"); static_assert(name_of(bases_of(^Cls)[0]) == u8"Base"); -//static_assert(name_of(^Cls::Alias) == u8"Alias"); // TODO(P2996). +static_assert(name_of(^Cls::Alias) == u8"Alias"); static_assert(name_of(^Cls::mem) == u8"mem"); static_assert(name_of(^Cls::memfn) == u8"memfn"); static_assert(name_of(^Cls::sfn) == u8"sfn"); -//static_assert(name_of(^Cls::Inner) == u8"Inner"); // TODO(P2996). +static_assert(name_of(^Cls::Inner) == u8"Inner"); static_assert(name_of(members_of(^Cls, std::meta::is_constructor)[0]) == u8"Cls"); static_assert(name_of(members_of(^Cls, std::meta::is_constructor)[1]) == @@ -122,21 +128,21 @@ static_assert(name_of(members_of(^Cls, std::meta::is_destructor)[0]) == static_assert(name_of(^Cls::operator bool) == u8"operator bool"); static_assert(name_of(members_of(^Cls, std::meta::is_template)[5]) == u8"operator int"); -//static_assert(name_of(^Cls::TInner) == u8"TInner"); // TODO(P2996). -//static_assert(name_of(^Cls::TMemFn) == u8"TMemFn"); // TODO(P2996). -//static_assert(name_of(^Cls::TAlias) == u8"TAlias"); // TODO(P2996). -//static_assert(name_of(^Cls::TSVar) == u8"TSVar"); // TODO(P2996). -//static_assert(name_of(^Cls::Enum) == u8"Enum"); // TODO(P2996). +static_assert(name_of(^Cls::TInner) == u8"TInner"); +static_assert(name_of(^Cls::TMemFn) == u8"TMemFn"); +static_assert(name_of(^Cls::TAlias) == u8"TAlias"); +static_assert(name_of(^Cls::TSVar) == u8"TSVar"); +static_assert(name_of(^Cls::Enum) == u8"Enum"); static_assert(name_of(^Cls::Enum::B) == u8"B"); -//static_assert(name_of(^Cls::EnumCls) == u8"EnumCls"); // TODO(P2996). +static_assert(name_of(^Cls::EnumCls) == u8"EnumCls"); static_assert(name_of(^Cls::EnumCls::B) == u8"B"); static_assert(display_name_of(^Cls) == u8"Cls"); static_assert(display_name_of(bases_of(^Cls)[0]) == u8"Base"); -//static_assert(display_name_of(^Cls::Alias) == u8"Alias"); // TODO(P2996). +static_assert(display_name_of(^Cls::Alias) == u8"Alias"); static_assert(display_name_of(^Cls::mem) == u8"mem"); static_assert(display_name_of(^Cls::memfn) == u8"memfn"); static_assert(display_name_of(^Cls::sfn) == u8"sfn"); -//static_assert(display_name_of(^Cls::Inner) == u8"Inner"); // TODO(P2996). +static_assert(display_name_of(^Cls::Inner) == u8"Inner"); static_assert(display_name_of(members_of(^Cls, std::meta::is_constructor)[0]) == u8"Cls"); static_assert(display_name_of(members_of(^Cls, @@ -146,13 +152,13 @@ static_assert(display_name_of(members_of(^Cls, static_assert(display_name_of(^Cls::operator bool) == u8"operator bool"); static_assert(display_name_of(members_of(^Cls, std::meta::is_template)[5]) == u8"operator int"); -//static_assert(display_name_of(^Cls::TInner) == u8"TInner"); // TODO(P2996). -//static_assert(display_name_of(^Cls::TMemFn) == u8"TMemFn"); // TODO(P2996). -//static_assert(display_name_of(^Cls::TAlias) == u8"TAlias"); // TODO(P2996). -//static_assert(display_name_of(^Cls::TSVar) == u8"TSVar"); // TODO(P2996). -//static_assert(display_name_of(^Cls::Enum) == u8"Enum"); // TODO(P2996). +static_assert(display_name_of(^Cls::TInner) == u8"TInner"); +static_assert(display_name_of(^Cls::TMemFn) == u8"TMemFn"); +static_assert(display_name_of(^Cls::TAlias) == u8"TAlias"); +static_assert(display_name_of(^Cls::TSVar) == u8"TSVar"); +static_assert(display_name_of(^Cls::Enum) == u8"Enum"); static_assert(display_name_of(^Cls::Enum::B) == u8"B"); -//static_assert(display_name_of(^Cls::EnumCls) == u8"EnumCls"); // TODO(P2996). +static_assert(display_name_of(^Cls::EnumCls) == u8"EnumCls"); static_assert(display_name_of(^Cls::EnumCls::B) == u8"B"); @@ -174,28 +180,28 @@ enum class EnumCls { C }; static_assert(name_of(^myns) == u8"myns"); static_assert(name_of(^myns::mem) == u8"mem"); static_assert(name_of(^myns::memfn) == u8"memfn"); -//static_assert(name_of(^myns::Cls) == u8"Cls"); // TODO(P2996). -//static_assert(name_of(^myns::TInner) == u8"TInner"); // TODO(P2996). -//static_assert(name_of(^myns::TFn) == u8"TFn"); // TODO(P2996). -//static_assert(name_of(^myns::TAlias) == u8"TAlias"); // TODO(P2996). -//static_assert(name_of(^myns::TVar) == u8"TVar"); // TODO(P2996). -//static_assert(name_of(^myns::Concept) == u8"Concept"); // TODO(P2996). -//static_assert(name_of(^myns::Enum) == u8"Enum"); // TODO(P2996). +static_assert(name_of(^myns::Cls) == u8"Cls"); +static_assert(name_of(^myns::TInner) == u8"TInner"); +static_assert(name_of(^myns::TFn) == u8"TFn"); +static_assert(name_of(^myns::TAlias) == u8"TAlias"); +static_assert(name_of(^myns::TVar) == u8"TVar"); +static_assert(name_of(^myns::Concept) == u8"Concept"); +static_assert(name_of(^myns::Enum) == u8"Enum"); static_assert(name_of(^myns::Enum::C) == u8"C"); -//static_assert(name_of(^myns::EnumCls) == u8"EnumCls"); // TODO(P2996). +static_assert(name_of(^myns::EnumCls) == u8"EnumCls"); static_assert(name_of(^myns::EnumCls::C) == u8"C"); static_assert(display_name_of(^myns) == u8"myns"); static_assert(display_name_of(^myns::mem) == u8"mem"); static_assert(display_name_of(^myns::memfn) == u8"memfn"); -//static_assert(display_name_of(^myns::Cls) == u8"Cls"); // TODO(P2996). -//static_assert(display_name_of(^myns::TInner) == u8"TInner"); // TODO(P2996). -//static_assert(display_name_of(^myns::TFn) == u8"TFn"); // TODO(P2996). -//static_assert(display_name_of(^myns::TAlias) == u8"TAlias"); // TODO(P2996). -//static_assert(display_name_of(^myns::TVar) == u8"TVar"); // TODO(P2996). -//static_assert(display_name_of(^myns::Concept) == u8"Concept"); // TODO(P2996). -//static_assert(display_name_of(^myns::Enum) == u8"Enum"); // TODO(P2996). +static_assert(display_name_of(^myns::Cls) == u8"Cls"); +static_assert(display_name_of(^myns::TInner) == u8"TInner"); +static_assert(display_name_of(^myns::TFn) == u8"TFn"); +static_assert(display_name_of(^myns::TAlias) == u8"TAlias"); +static_assert(display_name_of(^myns::TVar) == u8"TVar"); +static_assert(display_name_of(^myns::Concept) == u8"Concept"); +static_assert(display_name_of(^myns::Enum) == u8"Enum"); static_assert(display_name_of(^myns::Enum::C) == u8"C"); -//static_assert(display_name_of(^myns::EnumCls) == u8"EnumCls"); // TODO(P2996). +static_assert(display_name_of(^myns::EnumCls) == u8"EnumCls"); static_assert(display_name_of(^myns::EnumCls::C) == u8"C"); class K\u{00FC}hl1 {}; diff --git a/libcxx/test/std/experimental/reflection/p2996-ex-parsing-command-line-options-2.sh.cpp b/libcxx/test/std/experimental/reflection/p2996-ex-parsing-command-line-options-2.sh.cpp index 8ffd6064f533ee..2f002278d66dcb 100644 --- a/libcxx/test/std/experimental/reflection/p2996-ex-parsing-command-line-options-2.sh.cpp +++ b/libcxx/test/std/experimental/reflection/p2996-ex-parsing-command-line-options-2.sh.cpp @@ -73,7 +73,7 @@ consteval auto spec_to_opts(std::meta::info opts, for (auto member : nonstatic_data_members_of(spec)) { auto new_type = template_arguments_of(type_of(member))[0]; new_members.push_back( - data_member_spec(new_type, {.name=name_of(member)})); + data_member_spec(new_type, {.name=name_of(member)})); } return define_class(opts, new_members); } diff --git a/libcxx/test/std/experimental/reflection/p2996-ex-struct-to-struct-of-arrays.pass.cpp b/libcxx/test/std/experimental/reflection/p2996-ex-struct-to-struct-of-arrays.pass.cpp index d9b03cf6f2e8f1..2b7d44e47350f5 100644 --- a/libcxx/test/std/experimental/reflection/p2996-ex-struct-to-struct-of-arrays.pass.cpp +++ b/libcxx/test/std/experimental/reflection/p2996-ex-struct-to-struct-of-arrays.pass.cpp @@ -34,9 +34,7 @@ consteval auto make_struct_of_arrays(std::meta::info type, std::vector new_members = {}; for (std::meta::info member : old_members) { auto array_type = substitute(^std::array, {type_of(member), N }); - auto mem_descr = - data_member_spec(array_type, - {.name = name_of(member)}); + auto mem_descr = data_member_spec(array_type, {.name=name_of(member)}); new_members.push_back(mem_descr); } return std::meta::define_class(substitute(^struct_of_arrays_impl, {type, N}),