aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ByteCode/Pointer.cpp
diff options
context:
space:
mode:
authorTimm Baeder <tbaeder@redhat.com>2025-07-06 14:55:29 +0200
committerGitHub <noreply@github.com>2025-07-06 14:55:29 +0200
commitdb4e927f9f02b40a0bc332205b88bc40edc29afc (patch)
tree45e08d0f2666331d86654a069c496137028ce221 /clang/lib/AST/ByteCode/Pointer.cpp
parent6c153e50f8b23dbd422c3f9eedf65344839bbbb1 (diff)
downloadllvm-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.cpp31
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();
}
}