[clang] [clang][bytecode] Move Descriptor::{ElemDesc, ElemRecord} into a PointerUnion (PR #217324)

Timm Baeder via cfe-commits cfe-commits at lists.llvm.org
Wed Aug 19 05:23:41 PDT 2026


https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/217324

We only ever need one of them. Also reorder the Descriptor members a bit to reduce the size of `Desciptor` from 72 to 64 bytes.

>From ee2c59e5b6094360d2f3dcf60580309c61336abf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Wed, 19 Aug 2026 10:28:23 +0200
Subject: [PATCH] elemdesc/elemrecord

---
 clang/lib/AST/ByteCode/Compiler.cpp           |  10 +-
 clang/lib/AST/ByteCode/Descriptor.cpp         | 106 +++++++++---------
 clang/lib/AST/ByteCode/Descriptor.h           |  47 +++++---
 clang/lib/AST/ByteCode/Disasm.cpp             |  12 +-
 clang/lib/AST/ByteCode/EvaluationResult.cpp   |  12 +-
 clang/lib/AST/ByteCode/Interp.cpp             |   8 +-
 clang/lib/AST/ByteCode/InterpBuiltin.cpp      |   8 +-
 .../lib/AST/ByteCode/InterpBuiltinBitCast.cpp |   2 +-
 clang/lib/AST/ByteCode/Pointer.cpp            |   2 +-
 clang/lib/AST/ByteCode/Pointer.h              |  12 +-
 clang/lib/AST/ByteCode/Program.cpp            |   2 +-
 11 files changed, 119 insertions(+), 102 deletions(-)

diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index cbfd067bfbdd4..9c6fdc70e9300 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -5087,7 +5087,7 @@ bool Compiler<Emitter>::visitZeroRecordInitializer(const Record *R,
       if (!this->visitZeroArrayInitializer(D->getType(), E))
         return false;
     } else if (D->isRecord()) {
-      if (!this->visitZeroRecordInitializer(D->ElemRecord, E))
+      if (!this->visitZeroRecordInitializer(D->getElemRecord(), E))
         return false;
     } else
       return false;
@@ -8676,7 +8676,7 @@ bool Compiler<Emitter>::emitDestructionPop(const Descriptor *Desc,
 
   // Arrays.
   if (Desc->isArray()) {
-    const Descriptor *ElemDesc = Desc->ElemDesc;
+    const Descriptor *ElemDesc = Desc->getElemDesc();
     assert(ElemDesc);
 
     unsigned N = Desc->getNumElems();
@@ -8699,9 +8699,9 @@ bool Compiler<Emitter>::emitDestructionPop(const Descriptor *Desc,
     return this->emitDestructionPop(ElemDesc, Loc);
   }
 
-  assert(Desc->ElemRecord);
-  assert(!Desc->ElemRecord->hasTrivialDtor());
-  return this->emitRecordDestructionPop(Desc->ElemRecord, Loc);
+  assert(Desc->isRecord());
+  assert(!Desc->getElemRecord()->hasTrivialDtor());
+  return this->emitRecordDestructionPop(Desc->getElemRecord(), Loc);
 }
 
 /// Create a dummy pointer for the given decl (or expr) and
diff --git a/clang/lib/AST/ByteCode/Descriptor.cpp b/clang/lib/AST/ByteCode/Descriptor.cpp
index d0435d4684875..be5d42967059f 100644
--- a/clang/lib/AST/ByteCode/Descriptor.cpp
+++ b/clang/lib/AST/ByteCode/Descriptor.cpp
@@ -83,13 +83,13 @@ static void ctorArrayDesc(Block *B, std::byte *Ptr, bool IsConst,
                           bool InUnion, const Descriptor *D) {
   const unsigned NumElems = D->getNumElems();
   const unsigned ElemSize =
-      D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor);
+      D->getElemDesc()->getAllocSize() + sizeof(InlineDescriptor);
 
   unsigned ElemOffset = 0;
   for (unsigned I = 0; I != NumElems; ++I, ElemOffset += ElemSize) {
     auto *ElemPtr = Ptr + ElemOffset;
     auto *Desc = reinterpret_cast<InlineDescriptor *>(ElemPtr);
-    auto *SD = D->ElemDesc;
+    auto *SD = D->getElemDesc();
 
     Desc->Offset = ElemOffset + sizeof(InlineDescriptor);
     Desc->Desc = SD;
@@ -102,10 +102,10 @@ static void ctorArrayDesc(Block *B, std::byte *Ptr, bool IsConst,
     Desc->IsArrayElement = true;
     Desc->IsVolatile = IsVolatile;
 
-    if (auto Fn = D->ElemDesc->CtorFn) {
+    if (auto Fn = D->getElemDesc()->CtorFn) {
       auto *ElemLoc = reinterpret_cast<std::byte *>(Desc + 1);
       Fn(B, ElemLoc, Desc->IsConst, Desc->IsFieldMutable, IsVolatile, IsActive,
-         Desc->InUnion || SD->isUnion(), D->ElemDesc);
+         Desc->InUnion || SD->isUnion(), D->getElemDesc());
     }
   }
 }
@@ -113,17 +113,17 @@ static void ctorArrayDesc(Block *B, std::byte *Ptr, bool IsConst,
 static void dtorArrayDesc(Block *B, std::byte *Ptr, const Descriptor *D) {
   const unsigned NumElems = D->getNumElems();
   const unsigned ElemSize =
-      D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor);
+      D->getElemDesc()->getAllocSize() + sizeof(InlineDescriptor);
 
   unsigned ElemOffset = 0;
-  auto Dtor = D->ElemDesc->DtorFn;
+  auto Dtor = D->getElemDesc()->DtorFn;
   assert(Dtor &&
          "a composite array without an elem dtor shouldn't have a dtor itself");
   for (unsigned I = 0; I != NumElems; ++I, ElemOffset += ElemSize) {
     auto *ElemPtr = Ptr + ElemOffset;
     auto *Desc = reinterpret_cast<InlineDescriptor *>(ElemPtr);
     auto *ElemLoc = reinterpret_cast<std::byte *>(Desc + 1);
-    Dtor(B, ElemLoc, D->ElemDesc);
+    Dtor(B, ElemLoc, D->getElemDesc());
   }
 }
 
@@ -157,8 +157,8 @@ static void initBase(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
                      const Descriptor *D, unsigned FieldOffset,
                      bool IsVirtualBase) {
   assert(D);
-  assert(D->ElemRecord);
-  assert(!D->ElemRecord->isUnion()); // Unions cannot be base classes.
+  assert(D->getElemRecord());
+  assert(!D->getElemRecord()->isUnion()); // Unions cannot be base classes.
 
   auto *Desc = reinterpret_cast<InlineDescriptor *>(Ptr + FieldOffset) - 1;
   Desc->Offset = FieldOffset;
@@ -172,10 +172,10 @@ static void initBase(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
   Desc->InUnion = InUnion;
   Desc->IsVolatile = false;
 
-  for (const auto &V : D->ElemRecord->bases())
+  for (const auto &V : D->getElemRecord()->bases())
     initBase(B, Ptr + FieldOffset, IsConst, IsMutable, IsVolatile, IsActive,
              InUnion, V.Desc, V.Offset, false);
-  for (const auto &F : D->ElemRecord->fields())
+  for (const auto &F : D->getElemRecord()->fields())
     initField(B, Ptr + FieldOffset, IsConst, IsMutable, IsVolatile, IsActive,
               InUnion, InUnion, F.Desc, F.Offset);
 }
@@ -183,16 +183,16 @@ static void initBase(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
 static void ctorRecord(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
                        bool IsVolatile, bool IsActive, bool InUnion,
                        const Descriptor *D) {
-  for (const auto &V : D->ElemRecord->bases())
+  for (const auto &V : D->getElemRecord()->bases())
     initBase(B, Ptr, IsConst, IsMutable, IsVolatile, IsActive, InUnion, V.Desc,
              V.Offset,
              /*IsVirtualBase=*/false);
-  for (const auto &F : D->ElemRecord->fields()) {
+  for (const auto &F : D->getElemRecord()->fields()) {
     bool IsUnionField = D->isUnion();
     initField(B, Ptr, IsConst, IsMutable, IsVolatile, IsActive, IsUnionField,
               InUnion || IsUnionField, F.Desc, F.Offset);
   }
-  for (const auto &V : D->ElemRecord->virtual_bases())
+  for (const auto &V : D->getElemRecord()->virtual_bases())
     initBase(B, Ptr, IsConst, IsMutable, IsVolatile, IsActive, InUnion, V.Desc,
              V.Offset,
              /*IsVirtualBase=*/true);
@@ -207,20 +207,20 @@ static void destroyField(Block *B, std::byte *Ptr, const Descriptor *D,
 static void destroyBase(Block *B, std::byte *Ptr, const Descriptor *D,
                         unsigned FieldOffset) {
   assert(D);
-  assert(D->ElemRecord);
+  assert(D->getElemRecord());
 
-  for (const auto &V : D->ElemRecord->bases())
+  for (const auto &V : D->getElemRecord()->bases())
     destroyBase(B, Ptr + FieldOffset, V.Desc, V.Offset);
-  for (const auto &F : D->ElemRecord->fields())
+  for (const auto &F : D->getElemRecord()->fields())
     destroyField(B, Ptr + FieldOffset, F.Desc, F.Offset);
 }
 
 static void dtorRecord(Block *B, std::byte *Ptr, const Descriptor *D) {
-  for (const auto &F : D->ElemRecord->bases())
+  for (const auto &F : D->getElemRecord()->bases())
     destroyBase(B, Ptr, F.Desc, F.Offset);
-  for (const auto &F : D->ElemRecord->fields())
+  for (const auto &F : D->getElemRecord()->fields())
     destroyField(B, Ptr, F.Desc, F.Offset);
-  for (const auto &F : D->ElemRecord->virtual_bases())
+  for (const auto &F : D->getElemRecord()->virtual_bases())
     destroyBase(B, Ptr, F.Desc, F.Offset);
 }
 
@@ -282,10 +282,10 @@ static BlockDtorFn getDtorArrayPrim(PrimType Type) {
 Descriptor::Descriptor(DeclOrExpr D, const Type *SourceTy, PrimType Type,
                        bool IsConst, bool IsTemporary, bool IsMutable,
                        bool IsVolatile)
-    : Source(D), SourceType(SourceTy), ElemSize(primSize(Type)), Size(ElemSize),
+    : Source(D), SourceType(SourceTy), CtorFn(getCtorPrim(Type)),
+      DtorFn(getDtorPrim(Type)), ElemSize(primSize(Type)), Size(ElemSize),
       AllocSize(align(ElemSize)), PrimT(Type), IsConst(IsConst),
-      IsMutable(IsMutable), IsTemporary(IsTemporary), IsVolatile(IsVolatile),
-      CtorFn(getCtorPrim(Type)), DtorFn(getDtorPrim(Type)) {
+      IsMutable(IsMutable), IsTemporary(IsTemporary), IsVolatile(IsVolatile) {
   assert(Source && "Missing source");
 }
 
@@ -293,11 +293,11 @@ Descriptor::Descriptor(DeclOrExpr D, const Type *SourceTy, PrimType Type,
 Descriptor::Descriptor(DeclOrExpr D, const Type *SourceTy, PrimType Type,
                        size_t NumElems, bool IsConst, bool IsTemporary,
                        bool IsMutable, bool IsVolatile)
-    : Source(D), SourceType(SourceTy), ElemSize(primSize(Type)),
+    : Source(D), SourceType(SourceTy), CtorFn(getCtorArrayPrim(Type)),
+      DtorFn(getDtorArrayPrim(Type)), ElemSize(primSize(Type)),
       Size(ElemSize * NumElems), AllocSize(align(Size) + sizeof(InitMapPtr)),
       PrimT(Type), IsConst(IsConst), IsMutable(IsMutable),
-      IsTemporary(IsTemporary), IsVolatile(IsVolatile), IsArray(true),
-      CtorFn(getCtorArrayPrim(Type)), DtorFn(getDtorArrayPrim(Type)) {
+      IsTemporary(IsTemporary), IsVolatile(IsVolatile), IsArray(true) {
   assert(Source && "Missing source");
   assert(NumElems <= (MaxArrayElemBytes / ElemSize));
 }
@@ -305,11 +305,11 @@ Descriptor::Descriptor(DeclOrExpr D, const Type *SourceTy, PrimType Type,
 /// Primitive unknown-size arrays.
 Descriptor::Descriptor(DeclOrExpr D, PrimType Type, bool IsConst,
                        bool IsTemporary, UnknownSize)
-    : Source(D), ElemSize(primSize(Type)), Size(UnknownSizeMark),
+    : Source(D), CtorFn(getCtorArrayPrim(Type)), DtorFn(getDtorArrayPrim(Type)),
+      ElemSize(primSize(Type)), Size(UnknownSizeMark),
       AllocSize(sizeof(InitMapPtr) + alignof(void *)), PrimT(Type),
       IsConst(IsConst), IsMutable(false), IsTemporary(IsTemporary),
-      IsArray(true), CtorFn(getCtorArrayPrim(Type)),
-      DtorFn(getDtorArrayPrim(Type)) {
+      IsArray(true) {
   assert(Source && "Missing source");
 }
 
@@ -317,40 +317,41 @@ Descriptor::Descriptor(DeclOrExpr D, PrimType Type, bool IsConst,
 Descriptor::Descriptor(DeclOrExpr D, const Type *SourceTy,
                        const Descriptor *Elem, unsigned NumElems, bool IsConst,
                        bool IsTemporary, bool IsMutable)
-    : Source(D), SourceType(SourceTy),
+    : Source(D), SourceType(SourceTy), ElemDescOrRecord(Elem),
+      CtorFn(ctorArrayDesc), DtorFn(Elem->DtorFn ? dtorArrayDesc : nullptr),
       ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)),
       Size(ElemSize * NumElems),
-      AllocSize(std::max<size_t>(alignof(void *), Size)), ElemDesc(Elem),
-      IsConst(IsConst), IsMutable(IsMutable), IsTemporary(IsTemporary),
-      IsArray(true), CtorFn(ctorArrayDesc),
-      DtorFn(Elem->DtorFn ? dtorArrayDesc : nullptr) {
+      AllocSize(std::max<size_t>(alignof(void *), Size)), IsConst(IsConst),
+      IsMutable(IsMutable), IsTemporary(IsTemporary), IsArray(true) {
   assert(Source && "Missing source");
 }
 
 /// Unknown-size arrays of composite elements.
 Descriptor::Descriptor(DeclOrExpr D, const Descriptor *Elem, bool IsTemporary,
                        UnknownSize)
-    : Source(D), ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)),
-      Size(UnknownSizeMark), AllocSize(alignof(void *)), ElemDesc(Elem),
-      IsConst(true), IsMutable(false), IsTemporary(IsTemporary), IsArray(true),
-      CtorFn(ctorArrayDesc), DtorFn(Elem->DtorFn ? dtorArrayDesc : nullptr) {
+    : Source(D), ElemDescOrRecord(Elem), CtorFn(ctorArrayDesc),
+      DtorFn(Elem->DtorFn ? dtorArrayDesc : nullptr),
+      ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)),
+      Size(UnknownSizeMark), AllocSize(alignof(void *)), IsConst(true),
+      IsMutable(false), IsTemporary(IsTemporary), IsArray(true) {
   assert(Source && "Missing source");
 }
 
 /// Composite records.
 Descriptor::Descriptor(DeclOrExpr D, const Record *R, bool IsConst,
                        bool IsTemporary, bool IsMutable, bool IsVolatile)
-    : Source(D), ElemSize(std::max<size_t>(alignof(void *), R->getFullSize())),
-      Size(ElemSize), AllocSize(Size), ElemRecord(R), IsConst(IsConst),
-      IsMutable(IsMutable), IsTemporary(IsTemporary), IsVolatile(IsVolatile),
-      CtorFn(ctorRecord), DtorFn(needsRecordDtor(R) ? dtorRecord : nullptr) {
+    : Source(D), ElemDescOrRecord(R), CtorFn(ctorRecord),
+      DtorFn(needsRecordDtor(R) ? dtorRecord : nullptr),
+      ElemSize(std::max<size_t>(alignof(void *), R->getFullSize())),
+      Size(ElemSize), AllocSize(Size), IsConst(IsConst), IsMutable(IsMutable),
+      IsTemporary(IsTemporary), IsVolatile(IsVolatile) {
   assert(Source && "Missing source");
 }
 
 /// Dummy.
 Descriptor::Descriptor(DeclOrExpr D)
-    : Source(D), ElemSize(1), Size(1), AllocSize(0), ElemDesc(nullptr),
-      IsConst(true), IsMutable(false), IsTemporary(false) {
+    : Source(D), ElemSize(1), Size(1), AllocSize(0), IsConst(true),
+      IsMutable(false), IsTemporary(false) {
   assert(Source && "Missing source");
 }
 
@@ -364,7 +365,7 @@ QualType Descriptor::getType() const {
   // The Source sometimes has a different type than the once
   // we really save. Try to consult the Record first.
   if (isRecord()) {
-    const RecordDecl *RD = ElemRecord->getDecl();
+    const RecordDecl *RD = getElemRecord()->getDecl();
     QualType T = RD->getASTContext().getTagType(ElaboratedTypeKeyword::None,
                                                 std::nullopt, RD, false);
     if (IsConst)
@@ -399,7 +400,7 @@ QualType Descriptor::getElemQualType() const {
   } else if (const auto *TDecl = dyn_cast_if_present<TypeDecl>(asDecl())) {
     T = TDecl->getASTContext().getTypeDeclType(TDecl);
   } else if (isRecord()) {
-    const RecordDecl *RD = ElemRecord->getDecl();
+    const RecordDecl *RD = getElemRecord()->getDecl();
     T = RD->getASTContext().getTagType(ElaboratedTypeKeyword::None,
                                        std::nullopt, RD, false);
     if (IsConst)
@@ -480,17 +481,18 @@ bool Descriptor::hasTrivialDtor() const {
     return true;
 
   if (isRecord()) {
-    assert(ElemRecord);
-    return ElemRecord->hasTrivialDtor();
+    return getElemRecord()->hasTrivialDtor();
   }
 
-  if (!ElemDesc)
-    return true;
+  if (const Descriptor *ElemDesc = getElemDescOrNull())
+    return ElemDesc->hasTrivialDtor();
   // Composite arrays.
-  return ElemDesc->hasTrivialDtor();
+  return true;
 }
 
-bool Descriptor::isUnion() const { return isRecord() && ElemRecord->isUnion(); }
+bool Descriptor::isUnion() const {
+  return isRecord() && getElemRecord()->isUnion();
+}
 
 unsigned Descriptor::getElemDataSize() const {
   if ((isPrimitive() || isPrimitiveArray()) &&
diff --git a/clang/lib/AST/ByteCode/Descriptor.h b/clang/lib/AST/ByteCode/Descriptor.h
index ee88b8bad3aee..466dddaf5b0bf 100644
--- a/clang/lib/AST/ByteCode/Descriptor.h
+++ b/clang/lib/AST/ByteCode/Descriptor.h
@@ -16,13 +16,14 @@
 #include "DeclOrExpr.h"
 #include "InitMap.h"
 #include "PrimType.h"
+#include "Record.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/Expr.h"
+#include <unistd.h>
 
 namespace clang {
 namespace interp {
 class Block;
-class Record;
 class SourceInfo;
 struct Descriptor;
 enum PrimType : uint8_t;
@@ -124,6 +125,15 @@ struct Descriptor final {
   /// Original declaration, used to emit the error message.
   const DeclOrExpr Source;
   const Type *SourceType = nullptr;
+  const llvm::PointerUnion<const Record *, const Descriptor *>
+      ElemDescOrRecord = nullptr;
+
+public:
+  /// Storage management methods.
+  const BlockCtorFn CtorFn = nullptr;
+  const BlockDtorFn DtorFn = nullptr;
+
+private:
   /// Size of an element, in host bytes.
   const unsigned ElemSize;
   /// Size of the storage, in host bytes.
@@ -142,10 +152,6 @@ struct Descriptor final {
   static constexpr unsigned MaxArrayElemBytes =
       std::numeric_limits<decltype(AllocSize)>::max() - sizeof(InitMapPtr);
 
-  /// Pointer to the record, if block contains records.
-  const Record *const ElemRecord = nullptr;
-  /// Descriptor of the array element.
-  const Descriptor *const ElemDesc = nullptr;
   /// The primitive type this descriptor was created for,
   /// or the primitive element type in case this is
   /// a primitive array.
@@ -161,10 +167,6 @@ struct Descriptor final {
   const bool IsArray = false;
   bool IsConstexprUnknown = false;
 
-  /// Storage management methods.
-  const BlockCtorFn CtorFn = nullptr;
-  const BlockDtorFn DtorFn = nullptr;
-
   /// Allocates a descriptor for a primitive.
   Descriptor(DeclOrExpr D, const Type *SourceTy, PrimType Type, bool IsConst,
              bool IsTemporary, bool IsMutable, bool IsVolatile);
@@ -192,6 +194,19 @@ struct Descriptor final {
   /// Allocates a dummy descriptor.
   Descriptor(DeclOrExpr D);
 
+  const Descriptor *getElemDesc() const {
+    return cast<const Descriptor *>(ElemDescOrRecord);
+  }
+  const Descriptor *getElemDescOrNull() const {
+    return dyn_cast_if_present<const Descriptor *>(ElemDescOrRecord);
+  }
+  const Record *getElemRecord() const {
+    return cast<const Record *>(ElemDescOrRecord);
+  }
+  const Record *getElemRecordOrNull() const {
+    return dyn_cast_if_present<const Record *>(ElemDescOrRecord);
+  }
+
   QualType getType() const;
   QualType getElemQualType() const;
   QualType getDataType(const ASTContext &Ctx) const;
@@ -218,10 +233,6 @@ struct Descriptor final {
     return dyn_cast_if_present<RecordDecl>(asDecl());
   }
 
-  template <typename T> const T *getAs() const {
-    return dyn_cast_if_present<T>(asDecl());
-  }
-
   /// Returns the size of the object without metadata.
   unsigned getSize() const {
     assert(!isUnknownSizeArray() && "Array of unknown size");
@@ -248,21 +259,23 @@ struct Descriptor final {
   }
 
   /// Checks if the descriptor is of an array of primitives.
-  bool isPrimitiveArray() const { return IsArray && !ElemDesc; }
+  bool isPrimitiveArray() const { return IsArray && !getElemDescOrNull(); }
   /// Checks if the descriptor is of an array of composites.
-  bool isCompositeArray() const { return IsArray && ElemDesc; }
+  bool isCompositeArray() const { return IsArray && getElemDescOrNull(); }
   /// Checks if the descriptor is of an array of zero size.
   bool isZeroSizeArray() const { return Size == 0; }
   /// Checks if the descriptor is of an array of unknown size.
   bool isUnknownSizeArray() const { return Size == UnknownSizeMark; }
 
   /// Checks if the descriptor is of a primitive.
-  bool isPrimitive() const { return !IsArray && !ElemRecord && PrimT; }
+  bool isPrimitive() const {
+    return !IsArray && !getElemRecordOrNull() && PrimT;
+  }
 
   /// Checks if the descriptor is of an array.
   bool isArray() const { return IsArray; }
   /// Checks if the descriptor is of a record.
-  bool isRecord() const { return !IsArray && ElemRecord; }
+  bool isRecord() const { return !IsArray && getElemRecordOrNull(); }
   /// Checks if the descriptor is of a union.
   bool isUnion() const;
 
diff --git a/clang/lib/AST/ByteCode/Disasm.cpp b/clang/lib/AST/ByteCode/Disasm.cpp
index 9499d3a246706..f2b466171744d 100644
--- a/clang/lib/AST/ByteCode/Disasm.cpp
+++ b/clang/lib/AST/ByteCode/Disasm.cpp
@@ -453,9 +453,9 @@ LLVM_DUMP_METHOD void Descriptor::dump(llvm::raw_ostream &OS) const {
   else if (isCompositeArray())
     OS << " composite-array " << getNumElems();
   else if (isUnion())
-    OS << " union(" << ElemRecord->getName() << ")";
+    OS << " union(" << getElemRecord()->getName() << ")";
   else if (isRecord())
-    OS << " record(" << ElemRecord->getName() << ")";
+    OS << " record(" << getElemRecord()->getName() << ")";
   else if (isPrimitive())
     OS << " primitive " << primTypeToString(getPrimType());
 
@@ -484,9 +484,9 @@ LLVM_DUMP_METHOD void Descriptor::dumpFull(unsigned Offset,
     for (unsigned I = 0; I != getNumElems(); ++I) {
       FO += sizeof(InlineDescriptor);
       OS.indent(Spaces) << "Element " << I << " offset: " << FO << '\n';
-      ElemDesc->dumpFull(FO, Indent + 1);
+      getElemDesc()->dumpFull(FO, Indent + 1);
 
-      FO += ElemDesc->getAllocSize();
+      FO += getElemDesc()->getAllocSize();
     }
   } else if (isPrimitiveArray()) {
     OS.indent(Spaces) << "Elements: " << getNumElems() << '\n';
@@ -498,9 +498,9 @@ LLVM_DUMP_METHOD void Descriptor::dumpFull(unsigned Offset,
       FO += getElemSize();
     }
   } else if (isRecord()) {
-    ElemRecord->dump(OS, Indent + 1, Offset);
+    getElemRecord()->dump(OS, Indent + 1, Offset);
     unsigned I = 0;
-    for (const Record::Field &F : ElemRecord->fields()) {
+    for (const Record::Field &F : getElemRecord()->fields()) {
       OS.indent(Spaces) << "- Field " << I << ": ";
       {
         ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_RED, true});
diff --git a/clang/lib/AST/ByteCode/EvaluationResult.cpp b/clang/lib/AST/ByteCode/EvaluationResult.cpp
index 19a2744f73f15..d5b65e5a7868e 100644
--- a/clang/lib/AST/ByteCode/EvaluationResult.cpp
+++ b/clang/lib/AST/ByteCode/EvaluationResult.cpp
@@ -47,10 +47,10 @@ static bool CheckArrayInitialized(InterpState &S, SourceLocation Loc,
     DiagnoseUninitializedSubobject(S, Loc, BasePtr.getField());
     return false;
   }
-  const Descriptor *ElemDesc = BaseDesc->ElemDesc;
+  const Descriptor *ElemDesc = BaseDesc->getElemDesc();
 
   if (ElemDesc->isRecord()) {
-    const Record *R = ElemDesc->ElemRecord;
+    const Record *R = ElemDesc->getElemRecord();
     for (size_t I = 0; I != NumElems; ++I) {
       PtrView ElemPtr = BasePtr.atIndex(I).narrow();
       Result &= CheckFieldsInitialized(S, Loc, ElemPtr, R);
@@ -166,8 +166,8 @@ static bool isOrHasPtr(const Descriptor *D) {
   if ((D->isPrimitive() || D->isPrimitiveArray()) && D->getPrimType() == PT_Ptr)
     return true;
 
-  if (D->ElemRecord)
-    return D->ElemRecord->hasPtrField();
+  if (D->isRecord())
+    return D->getElemRecord()->hasPtrField();
   return false;
 }
 
@@ -188,7 +188,7 @@ static void collectBlocks(PtrView Ptr, llvm::SetVector<const Block *> &Blocks,
   if (!Desc)
     return;
 
-  if (const Record *R = Desc->ElemRecord) {
+  if (const Record *R = Desc->getElemRecordOrNull()) {
     if (!R->hasPtrField())
       return;
 
@@ -235,7 +235,7 @@ static void collectBlocks(PtrView Ptr, llvm::SetVector<const Block *> &Blocks,
     return;
   }
 
-  if (Desc->isCompositeArray() && isOrHasPtr(Desc->ElemDesc)) {
+  if (Desc->isCompositeArray() && isOrHasPtr(Desc->getElemDesc())) {
     for (unsigned I = 0; I != Desc->getNumElems(); ++I) {
       PtrView ElemPtr = Ptr.atIndex(I).narrow();
       collectBlocks(ElemPtr, Blocks);
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index 7704550a12d82..2b6758edfc873 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -1351,7 +1351,7 @@ static bool runRecordDestructor(InterpState &S, CodePtr OpPC,
                                 const Pointer &BasePtr,
                                 const Descriptor *Desc) {
   assert(Desc->isRecord());
-  const Record *R = Desc->ElemRecord;
+  const Record *R = Desc->getElemRecord();
   assert(R);
 
   if (!S.Current->isBottomFrame() && S.Current->hasThisPointer() &&
@@ -1390,7 +1390,7 @@ static bool RunDestructors(InterpState &S, CodePtr OpPC, const Block *B) {
     unsigned N = Desc->getNumElems();
     if (N == 0)
       return true;
-    const Descriptor *ElemDesc = Desc->ElemDesc;
+    const Descriptor *ElemDesc = Desc->getElemDesc();
     assert(ElemDesc->isRecord());
 
     Pointer RP(const_cast<Block *>(B));
@@ -1729,13 +1729,13 @@ static bool checkConstructor(InterpState &S, CodePtr OpPC, const Function *Func,
   const Descriptor *D = ThisPtr.getFieldDesc();
   // FIXME: I think this case is not 100% correct. E.g. a pointer into a
   // subobject of a composite array.
-  if (!D->ElemRecord)
+  if (!D->isRecord())
     return true;
 
   if (S.getLangOpts().CPlusPlus26)
     return true;
 
-  if (D->ElemRecord->getNumVirtualBases() == 0)
+  if (D->getElemRecord()->getNumVirtualBases() == 0)
     return true;
 
   S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_virtual_base)
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 54b2b4bb1b16d..f2b9b22ae773d 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -2310,7 +2310,7 @@ static std::optional<unsigned> computeFullDescSize(const ASTContext &ASTCtx,
     // at the decl directly.
     return ASTCtx
         .getTypeSizeInChars(
-            ASTCtx.getCanonicalTagType(Desc->ElemRecord->getDecl()))
+            ASTCtx.getCanonicalTagType(Desc->getElemRecord()->getDecl()))
         .getQuantity();
   }
 
@@ -6902,7 +6902,7 @@ static void zeroAll(PtrView Dest) {
   }
 
   if (Desc->isRecord()) {
-    const Record *R = Desc->ElemRecord;
+    const Record *R = Desc->getElemRecord();
     for (const Record::Field &F : R->fields()) {
       PtrView FieldPtr = Dest.atField(F.Offset);
       zeroAll(FieldPtr);
@@ -6953,8 +6953,8 @@ static bool copyRecord(InterpState &S, CodePtr OpPC, PtrView Src, PtrView Dest,
   };
 
   assert(SrcDesc->isRecord());
-  assert(SrcDesc->ElemRecord == DestDesc->ElemRecord);
-  const Record *R = DestDesc->ElemRecord;
+  assert(SrcDesc->getElemRecord() == DestDesc->getElemRecord());
+  const Record *R = DestDesc->getElemRecord();
   for (const Record::Field &F : R->fields()) {
     PtrView FP = Src.atField(F.Offset);
 
diff --git a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
index 2529bfc6c1cbd..59bb40b22a602 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
@@ -130,7 +130,7 @@ static Result enumerateData(PtrView P, const Context &Ctx, Bits Offset,
 
   // Records.
   if (FieldDesc->isRecord()) {
-    const Record *R = FieldDesc->ElemRecord;
+    const Record *R = FieldDesc->getElemRecord();
     if (R->getDecl()->isInvalidDecl())
       return Result::Failure;
     const ASTRecordLayout &Layout =
diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp
index 46f658f7cef64..46eab1b6ee747 100644
--- a/clang/lib/AST/ByteCode/Pointer.cpp
+++ b/clang/lib/AST/ByteCode/Pointer.cpp
@@ -1216,7 +1216,7 @@ IntPointer IntPointer::baseCast(const interp::Context &Ctx,
   CharUnits BaseLayoutOffset =
       Layout.getBaseClassOffset(cast<CXXRecordDecl>(BaseDesc->asDecl()));
 
-  const RecordDecl *RD = BaseDesc->ElemRecord->getDecl();
+  const RecordDecl *RD = BaseDesc->getElemRecord()->getDecl();
   QualType T = RD->getASTContext().getTagType(ElaboratedTypeKeyword::None,
                                               std::nullopt, RD, false);
   return {T.getTypePtr(), Value + BaseLayoutOffset.getQuantity()};
diff --git a/clang/lib/AST/ByteCode/Pointer.h b/clang/lib/AST/ByteCode/Pointer.h
index 78768929f3487..2cc10dad7aac2 100644
--- a/clang/lib/AST/ByteCode/Pointer.h
+++ b/clang/lib/AST/ByteCode/Pointer.h
@@ -150,10 +150,12 @@ struct PtrView {
     return PtrView{Pointee, Base, Base};
   }
 
-  const Record *getRecord() const { return getFieldDesc()->ElemRecord; }
+  const Record *getRecord() const {
+    return getFieldDesc()->getElemRecordOrNull();
+  }
   const Record *getElemRecord() const {
-    const Descriptor *ElemDesc = getFieldDesc()->ElemDesc;
-    return ElemDesc ? ElemDesc->ElemRecord : nullptr;
+    const Descriptor *ElemDesc = getFieldDesc()->getElemDescOrNull();
+    return ElemDesc ? ElemDesc->getElemRecord() : nullptr;
   }
   const FieldDecl *getField() const { return getFieldDesc()->asFieldDecl(); }
 
@@ -176,7 +178,7 @@ struct PtrView {
 
     unsigned Adjust = 0;
     if (Offset != Base) {
-      if (getFieldDesc()->ElemDesc)
+      if (getFieldDesc()->getElemDescOrNull())
         Adjust = sizeof(InlineDescriptor);
       else
         Adjust = sizeof(InitMapPtr);
@@ -196,7 +198,7 @@ struct PtrView {
 
   PtrView atIndex(unsigned Idx) const {
     unsigned Off = Idx * elemSize();
-    if (getFieldDesc()->ElemDesc)
+    if (getFieldDesc()->getElemDescOrNull())
       Off += sizeof(InlineDescriptor);
     else
       Off += sizeof(InitMapPtr);
diff --git a/clang/lib/AST/ByteCode/Program.cpp b/clang/lib/AST/ByteCode/Program.cpp
index c838729fb599d..2b6aaab021d1e 100644
--- a/clang/lib/AST/ByteCode/Program.cpp
+++ b/clang/lib/AST/ByteCode/Program.cpp
@@ -396,7 +396,7 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
       HasPtrField =
           HasPtrField ||
           (Desc->isPrimitiveArray() && Desc->getPrimType() == PT_Ptr) ||
-          (Desc->ElemRecord && Desc->ElemRecord->hasPtrField());
+          (Desc->isRecord() && Desc->getElemRecord()->hasPtrField());
     } else {
       Desc = allocateDescriptor(FD);
     }



More information about the cfe-commits mailing list