diff options
author | Timm Baeder <tbaeder@redhat.com> | 2025-07-06 14:55:29 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-07-06 14:55:29 +0200 |
commit | db4e927f9f02b40a0bc332205b88bc40edc29afc (patch) | |
tree | 45e08d0f2666331d86654a069c496137028ce221 /clang/lib/AST/ByteCode/Pointer.cpp | |
parent | 6c153e50f8b23dbd422c3f9eedf65344839bbbb1 (diff) | |
download | llvm-db4e927f9f02b40a0bc332205b88bc40edc29afc.zip llvm-db4e927f9f02b40a0bc332205b88bc40edc29afc.tar.gz llvm-db4e927f9f02b40a0bc332205b88bc40edc29afc.tar.bz2 |
[clang][bytecode] Misc union fixes (#146824)
First, don't forget to also activate fields which are bitfields on
assignment.
Second, when deactivating fields, recurse into records.
Diffstat (limited to 'clang/lib/AST/ByteCode/Pointer.cpp')
-rw-r--r-- | clang/lib/AST/ByteCode/Pointer.cpp | 31 |
1 files changed, 26 insertions, 5 deletions
diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp index f049f1f..298aac3 100644 --- a/clang/lib/AST/ByteCode/Pointer.cpp +++ b/clang/lib/AST/ByteCode/Pointer.cpp @@ -505,8 +505,19 @@ void Pointer::activate() const { auto activate = [](Pointer &P) -> void { P.getInlineDesc()->IsActive = true; }; - auto deactivate = [](Pointer &P) -> void { + + std::function<void(Pointer &)> deactivate; + deactivate = [&deactivate](Pointer &P) -> void { P.getInlineDesc()->IsActive = false; + + if (const Record *R = P.getRecord()) { + for (const Record::Field &F : R->fields()) { + Pointer FieldPtr = P.atField(F.Offset); + if (FieldPtr.getInlineDesc()->IsActive) + deactivate(FieldPtr); + } + // FIXME: Bases? + } }; // Unions might be nested etc., so find the topmost Pointer that's @@ -516,21 +527,31 @@ void Pointer::activate() const { 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 == *this) { + if (FieldPtr == ChildPtr) { + // No need to deactivate, will be activated in the next loop. } else { deactivate(FieldPtr); - // FIXME: Recurse. } } Pointer B = *this; while (B != UnionPtr) { activate(B); - // FIXME: Need to de-activate other fields of parent records. B = B.getBase(); } } |