gollvm: relax assertion in IntegrityVisitor::unsetParent
Convert an overly narrow assertion in IntegrityVisitor::unsetParent to
a guard (needed to enable tree sharing repair in certain cases).
Change-Id: I198109e6a5733cefbb37158871a2ab1f1f4f87c8
Reviewed-on: https://go-review.googlesource.com/43953
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/llvm-gofrontend/go-llvm-tree-integrity.cpp b/llvm-gofrontend/go-llvm-tree-integrity.cpp
index 1ab8122..f396c51 100644
--- a/llvm-gofrontend/go-llvm-tree-integrity.cpp
+++ b/llvm-gofrontend/go-llvm-tree-integrity.cpp
@@ -59,6 +59,30 @@
return true;
}
+// This helper routine is invoked in situations where the node
+// builder wants to "reparent" the children of a node, e.g. it has
+// a "foo" node with children X and Y, and it wants to convert it
+// into a "bar" node with the same children. Ex:
+//
+// foo bar
+// . . => . .
+// . . . .
+// X Y X Y
+//
+// In this situation we need to update "nparent_" to reflect the fact
+// that X and Y are no longer parented by foo. A complication can crop
+// up if sharing has already been established at the point where this
+// routine is called. For example, suppose that there is some other
+// node "baz" that has also installed "X" as a child:
+//
+// baz foo
+// . . . .
+// . . . .
+// W X Y
+//
+// If this situation arises, we need to preserve the existing nparent_
+// mapping, so as to be able to repair the sharing later on.
+
void IntegrityVisitor::unsetParent(Bnode *child, Bnode *parent, unsigned slot)
{
if (! shouldBeTracked(child))
@@ -68,9 +92,8 @@
parslot pps = it->second;
Bnode *prevParent = pps.first;
unsigned prevSlot = pps.second;
- assert(prevParent == parent);
- assert(prevSlot == slot);
- nparent_.erase(it);
+ if (prevParent == parent || prevSlot == slot)
+ nparent_.erase(it);
}
void IntegrityVisitor::setParent(Bnode *child, Bnode *parent, unsigned slot)