diff options
author | Timm Baeder <tbaeder@redhat.com> | 2025-04-10 06:12:00 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-04-10 06:12:00 +0200 |
commit | 98ea512f720ec954a6f096dbb39534f06affa196 (patch) | |
tree | cfda7be1c7ad332bf37fd53a91226fd5242c2447 /clang/lib/AST/ByteCode/InterpBuiltin.cpp | |
parent | 2828328611089481d6ebd2e148791d9729117a8a (diff) | |
download | llvm-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.cpp | 44 |
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)) |