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

Reply via email to