diff options
author | Timm Baeder <tbaeder@redhat.com> | 2025-07-08 07:45:17 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-07-08 07:45:17 +0200 |
commit | 36dd61f12a14414c0fe1428faa0ce110c0c48f86 (patch) | |
tree | 3d0b1c8d07651d02ea3d0b369a8903a4eaacc99b /clang/lib/AST/ByteCode/Pointer.cpp | |
parent | 49683eefb2de2e4f8b883e445930afa63289d9a4 (diff) | |
download | llvm-36dd61f12a14414c0fe1428faa0ce110c0c48f86.zip llvm-36dd61f12a14414c0fe1428faa0ce110c0c48f86.tar.gz llvm-36dd61f12a14414c0fe1428faa0ce110c0c48f86.tar.bz2 |
[clang][bytecode] Fix activating nested unions (#147338)
When activating the new pointer, we need to de-activate pointers of all
parent unions, not just the topmost one.
Diffstat (limited to 'clang/lib/AST/ByteCode/Pointer.cpp')
-rw-r--r-- | clang/lib/AST/ByteCode/Pointer.cpp | 42 |
1 files changed, 12 insertions, 30 deletions
diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp index e915316..6769e51 100644 --- a/clang/lib/AST/ByteCode/Pointer.cpp +++ b/clang/lib/AST/ByteCode/Pointer.cpp @@ -520,39 +520,21 @@ void Pointer::activate() const { } }; - // Unions might be nested etc., so find the topmost Pointer that's - // not in a union anymore. - Pointer UnionPtr = getBase(); - while (!UnionPtr.isRoot() && UnionPtr.inUnion()) - UnionPtr = UnionPtr.getBase(); - - assert(UnionPtr.getFieldDesc()->isUnion()); - const Record *UnionRecord = UnionPtr.getRecord(); - - // The direct child pointer of the union that's on the path from - // this pointer to the union. - Pointer ChildPtr = *this; - assert(ChildPtr != UnionPtr); - while (true) { - if (ChildPtr.getBase() == UnionPtr) - break; - ChildPtr = ChildPtr.getBase(); - } - assert(ChildPtr.getBase() == UnionPtr); - - for (const Record::Field &F : UnionRecord->fields()) { - Pointer FieldPtr = UnionPtr.atField(F.Offset); - if (FieldPtr == ChildPtr) { - // No need to deactivate, will be activated in the next loop. - } else { - deactivate(FieldPtr); - } - } - Pointer B = *this; - while (B != UnionPtr) { + while (!B.isRoot() && B.inUnion()) { activate(B); + + // When walking up the pointer chain, deactivate + // all union child pointers that aren't on our path. + Pointer Cur = B; B = B.getBase(); + if (const Record *BR = B.getRecord(); BR && BR->isUnion()) { + for (const Record::Field &F : BR->fields()) { + Pointer FieldPtr = B.atField(F.Offset); + if (FieldPtr != Cur) + deactivate(FieldPtr); + } + } } } |