From 5383f737ca464c54a2e24fcd330a4bab316cbecf Mon Sep 17 00:00:00 2001 From: Dan Katz Date: Fri, 16 May 2025 12:00:24 -0400 Subject: [PATCH] Extraction of arrays as pointers. --- clang/lib/AST/ExprConstantMeta.cpp | 25 ++++++++++++++++--- .../reflection/to-and-from-values.pass.cpp | 10 ++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/clang/lib/AST/ExprConstantMeta.cpp b/clang/lib/AST/ExprConstantMeta.cpp index 99bdf01df5e2..db0f7d029897 100644 --- a/clang/lib/AST/ExprConstantMeta.cpp +++ b/clang/lib/AST/ExprConstantMeta.cpp @@ -3081,10 +3081,29 @@ bool extract(APValue &Result, ASTContext &C, MetaActions &Meta, } Synthesized = DeclRefExpr::Create(C, NNSLocBuilder.getTemporary(), SourceLocation(), Decl, false, - Range.getBegin(), ResultTy, - ReturnsLValue ? VK_LValue : - VK_PRValue, + Range.getBegin(), ResultTy, VK_LValue, Decl, nullptr); + } else if (auto *ArrTy = dyn_cast(Decl->getType())) { + QualType PtrTy = C.getPointerType(ArrTy->getElementType()); + + ReturnsLValue = true; + if (RawResultTy.getCanonicalType().getTypePtr() != + PtrTy.getCanonicalType().getTypePtr()) + return Diagnoser(Range.getBegin(), diag::metafn_extract_type_mismatch) + << 1 << PtrTy << 1 << ResultTy << Range; + + NestedNameSpecifierLocBuilder NNSLocBuilder; + if (auto *ParentClsDecl = dyn_cast_or_null( + Decl->getDeclContext())) { + TypeSourceInfo *TSI = C.CreateTypeSourceInfo( + QualType(ParentClsDecl->getTypeForDecl(), 0), 0); + NNSLocBuilder.Extend(C, Range.getBegin(), TSI->getTypeLoc(), + Range.getBegin()); + } + + APValue::LValuePathEntry Path[1] = {APValue::LValuePathEntry::ArrayIndex(0)}; + return SetAndSucceed(Result, + APValue(Decl, CharUnits::Zero(), Path, false)); } else { // We have a reflection of a (possibly local) non-reference variable. // Synthesize an lvalue by reaching up the call stack. diff --git a/libcxx/test/std/experimental/reflection/to-and-from-values.pass.cpp b/libcxx/test/std/experimental/reflection/to-and-from-values.pass.cpp index 4801546f7788..e0034a08d2d4 100644 --- a/libcxx/test/std/experimental/reflection/to-and-from-values.pass.cpp +++ b/libcxx/test/std/experimental/reflection/to-and-from-values.pass.cpp @@ -205,6 +205,16 @@ namespace extract_ref_semantics { } } // namespace extract_ref_semantics + // ==================== + // extract_array_as_ptr + // ==================== + +namespace extract_array_as_ptr { +constexpr int arr[] = {1, 2, 3}; +static_assert(extract(^^arr)[2] == 3); + +} // namespace extract_array_as_ptr + // ============== // value_of_types // ==============