Author: Timm Baeder Date: 2026-08-30T12:10:40+02:00 New Revision: e22a4a5f169feb30bd8bc7c54be4ef08af549562
URL: https://github.com/llvm/llvm-project/commit/e22a4a5f169feb30bd8bc7c54be4ef08af549562 DIFF: https://github.com/llvm/llvm-project/commit/e22a4a5f169feb30bd8bc7c54be4ef08af549562.diff LOG: [clang][bytecode] Use a regular static function in `Pointer::toRValue()` (#219772) Instead of the previous std::function, which was awkward due to recursing. Added: Modified: clang/lib/AST/ByteCode/Pointer.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp index 01968cfe6c9a1..0e16c34fcbdc8 100644 --- a/clang/lib/AST/ByteCode/Pointer.cpp +++ b/clang/lib/AST/ByteCode/Pointer.cpp @@ -980,177 +980,176 @@ Pointer::computeSplitPoint(const Pointer &A, const Pointer &B) { llvm_unreachable("The loop above should've returned."); } -std::optional<APValue> Pointer::toRValue(const Context &Ctx, - QualType ResultType) const { +/// Convert a pointer to a composite value to an rvalue. +static bool toRValue(const Context &Ctx, QualType Ty, PtrView Ptr, APValue &R) { const ASTContext &ASTCtx = Ctx.getASTContext(); - assert(!ResultType.isNull()); - // Method to recursively traverse composites. - std::function<bool(QualType, PtrView, APValue &)> Composite; - Composite = [&Composite, &Ctx, &ASTCtx](QualType Ty, PtrView Ptr, - APValue &R) { - if (const auto *AT = Ty->getAs<AtomicType>()) - Ty = AT->getValueType(); - - // Invalid pointers. - if (Ptr.isDummy() || !Ptr.isLive() || Ptr.isPastEnd()) - return false; + if (const auto *AT = Ty->getAs<AtomicType>()) + Ty = AT->getValueType(); - // Primitives should never end up here. - assert(!Ctx.canClassify(Ty)); - const Descriptor *FieldDesc = Ptr.getFieldDesc(); - assert(FieldDesc); - - if (const auto *RT = Ty->getAsCanonical<RecordType>()) { - if (!FieldDesc->isRecord()) - return false; - const auto *Record = Ptr.getRecord(); - assert(Record && "Missing record descriptor"); - - bool Ok = true; - if (RT->getDecl()->isUnion()) { - const FieldDecl *ActiveField = nullptr; - APValue Value; - for (const auto &F : Record->fields()) { - PtrView FP = Ptr.atField(F.Offset); - if (FP.isActive()) { - const Descriptor *Desc = F.Desc; - if (Desc->isPrimitive()) { - TYPE_SWITCH(Desc->getPrimType(), - Value = FP.deref<T>().toAPValue(ASTCtx)); - } else { - QualType FieldTy = F.Decl->getType(); - Ok &= Composite(FieldTy, FP, Value); - } - ActiveField = FP.getFieldDesc()->asFieldDecl(); - break; - } - } - R = APValue(ActiveField, Value); - } else { - unsigned NF = Record->getNumFields(); - unsigned NB = Record->getNumBases(); - unsigned NV = Ptr.isBaseClass() ? 0 : Record->getNumVirtualBases(); + // Invalid pointers. + if (Ptr.isDummy() || !Ptr.isLive() || Ptr.isPastEnd()) + return false; - R = APValue(APValue::UninitStruct(), NB, NF, NV); + // Primitives should never end up here. + assert(!Ctx.canClassify(Ty)); + const Descriptor *FieldDesc = Ptr.getFieldDesc(); + assert(FieldDesc); - for (unsigned I = 0; I != NF; ++I) { - const Record::Field *FD = Record->getField(I); - const Descriptor *Desc = FD->Desc; - PtrView FP = Ptr.atField(FD->Offset); - APValue &Value = R.getStructField(I); + if (const auto *RT = Ty->getAsCanonical<RecordType>()) { + if (!FieldDesc->isRecord()) + return false; + const auto *Record = Ptr.getRecord(); + assert(Record && "Missing record descriptor"); + + bool Ok = true; + if (RT->getDecl()->isUnion()) { + const FieldDecl *ActiveField = nullptr; + APValue Value; + for (const auto &F : Record->fields()) { + PtrView FP = Ptr.atField(F.Offset); + if (FP.isActive()) { + const Descriptor *Desc = F.Desc; if (Desc->isPrimitive()) { TYPE_SWITCH(Desc->getPrimType(), Value = FP.deref<T>().toAPValue(ASTCtx)); } else { - QualType FieldTy = FD->Decl->getType(); - Ok &= Composite(FieldTy, FP, Value); + QualType FieldTy = F.Decl->getType(); + Ok &= toRValue(Ctx, FieldTy, FP, Value); } + ActiveField = FP.getFieldDesc()->asFieldDecl(); + break; } - - for (unsigned I = 0; I != NB; ++I) { - const Record::Base *BD = Record->getBase(I); - QualType BaseTy = Ctx.getASTContext().getCanonicalTagType(BD->Decl); - PtrView BP = Ptr.atField(BD->Offset); - Ok &= Composite(BaseTy, BP, R.getStructBase(I)); + } + R = APValue(ActiveField, Value); + } else { + unsigned NF = Record->getNumFields(); + unsigned NB = Record->getNumBases(); + unsigned NV = Ptr.isBaseClass() ? 0 : Record->getNumVirtualBases(); + + R = APValue(APValue::UninitStruct(), NB, NF, NV); + + for (unsigned I = 0; I != NF; ++I) { + const Record::Field *FD = Record->getField(I); + const Descriptor *Desc = FD->Desc; + PtrView FP = Ptr.atField(FD->Offset); + APValue &Value = R.getStructField(I); + if (Desc->isPrimitive()) { + TYPE_SWITCH(Desc->getPrimType(), + Value = FP.deref<T>().toAPValue(ASTCtx)); + } else { + QualType FieldTy = FD->Decl->getType(); + Ok &= toRValue(Ctx, FieldTy, FP, Value); } + } - for (unsigned I = 0; I != NV; ++I) { - const Record::Base *VD = Record->getVirtualBase(I); - assert(VD); - QualType VirtBaseTy = - Ctx.getASTContext().getCanonicalTagType(VD->Decl); - PtrView VP = Ptr.atField(VD->Offset); - Ok &= Composite(VirtBaseTy, VP, R.getStructVirtualBase(I)); - } + for (unsigned I = 0; I != NB; ++I) { + const Record::Base *BD = Record->getBase(I); + QualType BaseTy = Ctx.getASTContext().getCanonicalTagType(BD->Decl); + PtrView BP = Ptr.atField(BD->Offset); + Ok &= toRValue(Ctx, BaseTy, BP, R.getStructBase(I)); } - return Ok; - } - if (Ty->isIncompleteArrayType()) { - R = APValue(APValue::UninitArray(), 0, 0); - return true; + for (unsigned I = 0; I != NV; ++I) { + const Record::Base *VD = Record->getVirtualBase(I); + assert(VD); + QualType VirtBaseTy = Ctx.getASTContext().getCanonicalTagType(VD->Decl); + PtrView VP = Ptr.atField(VD->Offset); + Ok &= toRValue(Ctx, VirtBaseTy, VP, R.getStructVirtualBase(I)); + } } + return Ok; + } - if (const auto *AT = Ty->getAsArrayTypeUnsafe()) { - if (!FieldDesc->isArray()) - return false; - const size_t NumElems = Ptr.getNumElems(); - QualType ElemTy = AT->getElementType(); - R = APValue(APValue::UninitArray{}, NumElems, NumElems); - - bool Ok = true; - OptPrimType ElemT = Ctx.classify(ElemTy); - for (unsigned I = 0; I != NumElems; ++I) { - APValue &Slot = R.getArrayInitializedElt(I); - if (ElemT) { - TYPE_SWITCH(*ElemT, Slot = Ptr.elem<T>(I).toAPValue(ASTCtx)); - } else { - Ok &= Composite(ElemTy, Ptr.atIndex(I).narrow(), Slot); - } + if (Ty->isIncompleteArrayType()) { + R = APValue(APValue::UninitArray(), 0, 0); + return true; + } + + if (const auto *AT = Ty->getAsArrayTypeUnsafe()) { + if (!FieldDesc->isArray()) + return false; + const size_t NumElems = Ptr.getNumElems(); + QualType ElemTy = AT->getElementType(); + R = APValue(APValue::UninitArray{}, NumElems, NumElems); + + bool Ok = true; + OptPrimType ElemT = Ctx.classify(ElemTy); + for (unsigned I = 0; I != NumElems; ++I) { + APValue &Slot = R.getArrayInitializedElt(I); + if (ElemT) { + TYPE_SWITCH(*ElemT, Slot = Ptr.elem<T>(I).toAPValue(ASTCtx)); + } else { + Ok &= toRValue(Ctx, ElemTy, Ptr.atIndex(I).narrow(), Slot); } - return Ok; } + return Ok; + } - // Complex types. - if (Ty->isAnyComplexType()) { - // Can happen via C casts. - if (!FieldDesc->getType()->isAnyComplexType()) - return false; - - PrimType ElemT = FieldDesc->getPrimType(); - if (isIntegerOrBoolType(ElemT)) { - INT_TYPE_SWITCH(ElemT, { - auto V1 = Ptr.elem<T>(0); - auto V2 = Ptr.elem<T>(1); - R = APValue(V1.toAPSInt(), V2.toAPSInt()); - return true; - }); - } else if (ElemT == PT_Float) { - R = APValue(Ptr.elem<Floating>(0).getAPFloat(), - Ptr.elem<Floating>(1).getAPFloat()); - return true; - } + // Complex types. + if (Ty->isAnyComplexType()) { + // Can happen via C casts. + if (!FieldDesc->getType()->isAnyComplexType()) return false; + + PrimType ElemT = FieldDesc->getPrimType(); + if (isIntegerOrBoolType(ElemT)) { + INT_TYPE_SWITCH(ElemT, { + auto V1 = Ptr.elem<T>(0); + auto V2 = Ptr.elem<T>(1); + R = APValue(V1.toAPSInt(), V2.toAPSInt()); + return true; + }); + } else if (ElemT == PT_Float) { + R = APValue(Ptr.elem<Floating>(0).getAPFloat(), + Ptr.elem<Floating>(1).getAPFloat()); + return true; } + return false; + } - // Vector types. - if (const auto *VT = Ty->getAs<VectorType>()) { - if (!FieldDesc->isPrimitiveArray()) - return false; - - PrimType ElemT = FieldDesc->getPrimType(); - SmallVector<APValue> Values; - Values.reserve(VT->getNumElements()); - for (unsigned I = 0; I != VT->getNumElements(); ++I) { - TYPE_SWITCH(ElemT, - { Values.push_back(Ptr.elem<T>(I).toAPValue(ASTCtx)); }); - } + // Vector types. + if (const auto *VT = Ty->getAs<VectorType>()) { + if (!FieldDesc->isPrimitiveArray()) + return false; - assert(Values.size() == VT->getNumElements()); - R = APValue(Values.data(), Values.size()); - return true; + PrimType ElemT = FieldDesc->getPrimType(); + SmallVector<APValue> Values; + Values.reserve(VT->getNumElements()); + for (unsigned I = 0; I != VT->getNumElements(); ++I) { + TYPE_SWITCH(ElemT, + { Values.push_back(Ptr.elem<T>(I).toAPValue(ASTCtx)); }); } - // Constant Matrix types. - if (const auto *MT = Ty->getAs<ConstantMatrixType>()) { - if (!FieldDesc->isPrimitiveArray()) - return false; - PrimType ElemT = FieldDesc->getPrimType(); - unsigned NumElems = MT->getNumElementsFlattened(); - - SmallVector<APValue> Values; - Values.reserve(NumElems); - for (unsigned I = 0; I != NumElems; ++I) { - TYPE_SWITCH(ElemT, - { Values.push_back(Ptr.elem<T>(I).toAPValue(ASTCtx)); }); - } + assert(Values.size() == VT->getNumElements()); + R = APValue(Values.data(), Values.size()); + return true; + } - R = APValue(Values.data(), MT->getNumRows(), MT->getNumColumns()); - return true; + // Constant Matrix types. + if (const auto *MT = Ty->getAs<ConstantMatrixType>()) { + if (!FieldDesc->isPrimitiveArray()) + return false; + PrimType ElemT = FieldDesc->getPrimType(); + unsigned NumElems = MT->getNumElementsFlattened(); + + SmallVector<APValue> Values; + Values.reserve(NumElems); + for (unsigned I = 0; I != NumElems; ++I) { + TYPE_SWITCH(ElemT, + { Values.push_back(Ptr.elem<T>(I).toAPValue(ASTCtx)); }); } - llvm_unreachable("invalid value to return"); - }; + R = APValue(Values.data(), MT->getNumRows(), MT->getNumColumns()); + return true; + } + + llvm_unreachable("invalid value to return"); +} + +std::optional<APValue> Pointer::toRValue(const Context &Ctx, + QualType ResultType) const { + const ASTContext &ASTCtx = Ctx.getASTContext(); + assert(!ResultType.isNull()); // Can't return functions as rvalues. if (ResultType->isFunctionType()) @@ -1177,7 +1176,7 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx, // Return the composite type. APValue Result; - if (!Composite(ResultType, view(), Result)) + if (!::toRValue(Ctx, ResultType, view(), Result)) return std::nullopt; return Result; } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
