<div dir="ltr">Hi Duncan,<div><br></div><div>ASan bootstrap detects memory leak in the test: <a href="http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/603/steps/check-llvm%20asan/logs/stdio">http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/603/steps/check-llvm%20asan/logs/stdio</a></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Jan 12, 2015 at 11:22 AM, Duncan P. N. Exon Smith <span dir="ltr"><<a href="mailto:dexonsmith@apple.com" target="_blank">dexonsmith@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: dexonsmith<br>
Date: Mon Jan 12 13:22:04 2015<br>
New Revision: 225657<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=225657&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=225657&view=rev</a><br>
Log:<br>
IR: Add test for handleChangedOperand() recursion<br>
<br>
Turns out this can happen.  Remove the `FIXME` and add a testcase that<br>
crashes without the extra logic.<br>
<br>
Modified:<br>
    llvm/trunk/lib/IR/Metadata.cpp<br>
    llvm/trunk/unittests/IR/MetadataTest.cpp<br>
<br>
Modified: llvm/trunk/lib/IR/Metadata.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Metadata.cpp?rev=225657&r1=225656&r2=225657&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Metadata.cpp?rev=225657&r1=225656&r2=225657&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/IR/Metadata.cpp (original)<br>
+++ llvm/trunk/lib/IR/Metadata.cpp Mon Jan 12 13:22:04 2015<br>
@@ -537,8 +537,6 @@ void GenericMDNode::handleChangedOperand<br>
   if (InRAUW) {<br>
     // We just hit a recursion due to RAUW.  Set the operand and move on, since<br>
     // we're about to be deleted.<br>
-    //<br>
-    // FIXME: Can this cycle really happen?<br>
     setOperand(Op, New);<br>
     return;<br>
   }<br>
<br>
Modified: llvm/trunk/unittests/IR/MetadataTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/MetadataTest.cpp?rev=225657&r1=225656&r2=225657&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/MetadataTest.cpp?rev=225657&r1=225656&r2=225657&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/unittests/IR/MetadataTest.cpp (original)<br>
+++ llvm/trunk/unittests/IR/MetadataTest.cpp Mon Jan 12 13:22:04 2015<br>
@@ -293,6 +293,69 @@ TEST_F(MDNodeTest, getDistinctWithUnreso<br>
   EXPECT_EQ(Empty, Distinct->getOperand(0));<br>
 }<br>
<br>
+TEST_F(MDNodeTest, handleChangedOperandRecursion) {<br>
+  // !0 = !{}<br>
+  MDNode *N0 = MDNode::get(Context, None);<br>
+<br>
+  // !1 = !{!3, null}<br>
+  MDNodeFwdDecl *Temp3 = MDNode::getTemporary(Context, None);<br>
+  Metadata *Ops1[] = {Temp3, nullptr};<br>
+  MDNode *N1 = MDNode::get(Context, Ops1);<br>
+<br>
+  // !2 = !{!3, !0}<br>
+  Metadata *Ops2[] = {Temp3, N0};<br>
+  MDNode *N2 = MDNode::get(Context, Ops2);<br>
+<br>
+  // !3 = !{!2}<br>
+  Metadata *Ops3[] = {N2};<br>
+  MDNode *N3 = MDNode::get(Context, Ops3);<br>
+  Temp3->replaceAllUsesWith(N3);<br></blockquote><div><br></div><div>^^</div><div>Can/should you delete Temp3 now?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
+  // !4 = !{!1}<br>
+  Metadata *Ops4[] = {N1};<br>
+  MDNode *N4 = MDNode::get(Context, Ops4);<br>
+<br>
+  // Confirm that the cycle prevented RAUW from getting dropped.<br>
+  EXPECT_TRUE(N0->isResolved());<br>
+  EXPECT_FALSE(N1->isResolved());<br>
+  EXPECT_FALSE(N2->isResolved());<br>
+  EXPECT_FALSE(N3->isResolved());<br>
+  EXPECT_FALSE(N4->isResolved());<br>
+<br>
+  // Create a couple of distinct nodes to observe what's going on.<br>
+  //<br>
+  // !5 = distinct !{!2}<br>
+  // !6 = distinct !{!3}<br>
+  Metadata *Ops5[] = {N2};<br>
+  MDNode *N5 = MDNode::getDistinct(Context, Ops5);<br>
+  Metadata *Ops6[] = {N3};<br>
+  MDNode *N6 = MDNode::getDistinct(Context, Ops6);<br>
+<br>
+  // Mutate !2 to look like !1, causing a uniquing collision (and an RAUW).<br>
+  // This will ripple up, with !3 colliding with !4, and RAUWing.  Since !2<br>
+  // references !3, this can cause a re-entry of handleChangedOperand() when !3<br>
+  // is not ready for it.<br>
+  //<br>
+  // !2->replaceOperandWith(1, nullptr)<br>
+  // !2: !{!3, !0} => !{!3, null}<br>
+  // !2->replaceAllUsesWith(!1)<br>
+  // !3: !{!2] => !{!1}<br>
+  // !3->replaceAllUsesWith(!4)<br>
+  N2->replaceOperandWith(1, nullptr);<br>
+<br>
+  // If all has gone well, N2 and N3 will have been RAUW'ed and deleted from<br>
+  // under us.  Just check that the other nodes are sane.<br>
+  //<br>
+  // !1 = !{!4, null}<br>
+  // !4 = !{!1}<br>
+  // !5 = distinct !{!1}<br>
+  // !6 = distinct !{!4}<br>
+  EXPECT_EQ(N4, N1->getOperand(0));<br>
+  EXPECT_EQ(N1, N4->getOperand(0));<br>
+  EXPECT_EQ(N1, N5->getOperand(0));<br>
+  EXPECT_EQ(N4, N6->getOperand(0));<br>
+}<br>
+<br>
 typedef MetadataTest MetadataAsValueTest;<br>
<br>
 TEST_F(MetadataAsValueTest, MDNode) {<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature"><div dir="ltr">Alexey Samsonov<br><a href="mailto:vonosmas@gmail.com" target="_blank">vonosmas@gmail.com</a></div></div>
</div></div>