diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h index ffdd7002cea..573e49fbb06 100644 --- a/include/llvm/IR/Metadata.h +++ b/include/llvm/IR/Metadata.h @@ -49,6 +49,7 @@ class Metadata { protected: /// \brief Storage flag for non-uniqued, otherwise unowned, metadata. bool IsDistinctInContext : 1; + bool InRAUW : 1; // TODO: expose remaining bits to subclasses. unsigned short SubclassData16; @@ -65,8 +66,8 @@ public: protected: Metadata(unsigned ID) - : SubclassID(ID), IsDistinctInContext(false), SubclassData16(0), - SubclassData32(0) {} + : SubclassID(ID), IsDistinctInContext(false), InRAUW(false), + SubclassData16(0), SubclassData32(0) {} ~Metadata() {} /// \brief Store this in a big non-uniqued untyped bucket. diff --git a/lib/IR/Metadata.cpp b/lib/IR/Metadata.cpp index 805b7377bce..7a354c42c4c 100644 --- a/lib/IR/Metadata.cpp +++ b/lib/IR/Metadata.cpp @@ -495,6 +495,14 @@ void GenericMDNode::handleChangedOperand(void *Ref, Metadata *New) { setOperand(Op, New); return; } + if (InRAUW) { + // We just hit a recursion due to RAUW. Set the operand and move on, since + // we're about to be deleted. + // + // FIXME: Can this cycle really happen? + setOperand(Op, New); + return; + } auto &Store = getContext().pImpl->MDNodeSet; Store.erase(this); @@ -550,6 +558,7 @@ void GenericMDNode::handleChangedOperand(void *Ref, Metadata *New) { // Collision. if (!isResolved()) { // Still unresolved, so RAUW. + InRAUW = true; ReplaceableUses->replaceAllUsesWith(*I); delete this; return;