aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ByteCode/Pointer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/ByteCode/Pointer.cpp')
-rw-r--r--clang/lib/AST/ByteCode/Pointer.cpp42
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);
+ }
+ }
}
}