aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ByteCode/InterpBuiltin.cpp
diff options
context:
space:
mode:
authorTimm Baeder <tbaeder@redhat.com>2025-04-10 06:12:00 +0200
committerGitHub <noreply@github.com>2025-04-10 06:12:00 +0200
commit98ea512f720ec954a6f096dbb39534f06affa196 (patch)
treecfda7be1c7ad332bf37fd53a91226fd5242c2447 /clang/lib/AST/ByteCode/InterpBuiltin.cpp
parent2828328611089481d6ebd2e148791d9729117a8a (diff)
downloadllvm-98ea512f720ec954a6f096dbb39534f06affa196.zip
llvm-98ea512f720ec954a6f096dbb39534f06affa196.tar.gz
llvm-98ea512f720ec954a6f096dbb39534f06affa196.tar.bz2
[clang][bytecode] Clear inactive union fields when copying (#134982)
When copying unions, we need to only copy the active field of the source union, which we were already doing. However, we also need to zero out the (now) inactive fields, so we don't end up with dangling pointers in those inactive fields.
Diffstat (limited to 'clang/lib/AST/ByteCode/InterpBuiltin.cpp')
-rw-r--r--clang/lib/AST/ByteCode/InterpBuiltin.cpp44
1 files changed, 43 insertions, 1 deletions
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 3029314..bde416d 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -2723,6 +2723,45 @@ bool SetThreeWayComparisonField(InterpState &S, CodePtr OpPC,
return true;
}
+static void zeroAll(Pointer &Dest) {
+ const Descriptor *Desc = Dest.getFieldDesc();
+
+ if (Desc->isPrimitive()) {
+ TYPE_SWITCH(Desc->getPrimType(), {
+ Dest.deref<T>().~T();
+ new (&Dest.deref<T>()) T();
+ });
+ return;
+ }
+
+ if (Desc->isRecord()) {
+ const Record *R = Desc->ElemRecord;
+ for (const Record::Field &F : R->fields()) {
+ Pointer FieldPtr = Dest.atField(F.Offset);
+ zeroAll(FieldPtr);
+ }
+ return;
+ }
+
+ if (Desc->isPrimitiveArray()) {
+ for (unsigned I = 0, N = Desc->getNumElems(); I != N; ++I) {
+ TYPE_SWITCH(Desc->getPrimType(), {
+ Dest.deref<T>().~T();
+ new (&Dest.deref<T>()) T();
+ });
+ }
+ return;
+ }
+
+ if (Desc->isCompositeArray()) {
+ for (unsigned I = 0, N = Desc->getNumElems(); I != N; ++I) {
+ Pointer ElemPtr = Dest.atIndex(I).narrow();
+ zeroAll(ElemPtr);
+ }
+ return;
+ }
+}
+
static bool copyComposite(InterpState &S, CodePtr OpPC, const Pointer &Src,
Pointer &Dest, bool Activate);
static bool copyRecord(InterpState &S, CodePtr OpPC, const Pointer &Src,
@@ -2751,11 +2790,14 @@ static bool copyRecord(InterpState &S, CodePtr OpPC, const Pointer &Src,
const Record *R = DestDesc->ElemRecord;
for (const Record::Field &F : R->fields()) {
if (R->isUnion()) {
- // For unions, only copy the active field.
+ // For unions, only copy the active field. Zero all others.
const Pointer &SrcField = Src.atField(F.Offset);
if (SrcField.isActive()) {
if (!copyField(F, /*Activate=*/true))
return false;
+ } else {
+ Pointer DestField = Dest.atField(F.Offset);
+ zeroAll(DestField);
}
} else {
if (!copyField(F, Activate))