IR: Remove an invalid assertion when replacing resolved operands
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>
Tue, 13 Jan 2015 00:46:34 +0000 (00:46 +0000)
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>
Tue, 13 Jan 2015 00:46:34 +0000 (00:46 +0000)
This adds back the testcase from r225738, and adds to it.  Looks like we
need both sides for now (the assertion was incorrect both ways, and
although it seemed reasonable (when written correctly) it wasn't
particularly important).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225745 91177308-0d34-0410-b5e6-96231b3b80d8

lib/IR/Metadata.cpp
unittests/IR/MetadataTest.cpp

index 13844313925aaf5a78f24b5e5ad9a3ccc01c82fa..852f1dc2041d75c9ab6a0ae9d90f8ae0de8165ca 100644 (file)
@@ -443,9 +443,11 @@ void UniquableMDNode::resolveAfterOperandChange(Metadata *Old, Metadata *New) {
   assert(SubclassData32 != 0 && "Expected unresolved operands");
 
   // Check if an operand was resolved.
-  if (!isOperandUnresolved(Old))
-    assert(isOperandUnresolved(New) && "Operand just became unresolved");
-  else if (!isOperandUnresolved(New))
+  if (!isOperandUnresolved(Old)) {
+    if (isOperandUnresolved(New))
+      // An operand was un-resolved!
+      ++SubclassData32;
+  } else if (!isOperandUnresolved(New))
     decrementUnresolvedOperandCount();
 }
 
index af110742dd7118291ac3ba726e2fdf1f8a5e0448..d85225561b2154310ecf79b9b3247db87b8b8f57 100644 (file)
@@ -7,6 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/IR/Metadata.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/Instructions.h"
@@ -361,6 +362,32 @@ TEST_F(MDNodeTest, handleChangedOperandRecursion) {
   EXPECT_EQ(N4, N6->getOperand(0));
 }
 
+TEST_F(MDNodeTest, replaceResolvedOperand) {
+  // Check code for replacing one resolved operand with another.  If doing this
+  // directly (via replaceOperandWith()) becomes illegal, change the operand to
+  // a global value that gets RAUW'ed.
+  //
+  // Use a temporary node to keep N from being resolved.
+  std::unique_ptr<MDNodeFwdDecl> Temp(MDNodeFwdDecl::get(Context, None));
+  Metadata *Ops[] = {nullptr, Temp.get()};
+
+  MDNode *Empty = MDTuple::get(Context, {});
+  MDNode *N = MDTuple::get(Context, Ops);
+  EXPECT_EQ(nullptr, N->getOperand(0));
+  ASSERT_FALSE(N->isResolved());
+
+  // Check code for replacing resolved nodes.
+  N->replaceOperandWith(0, Empty);
+  EXPECT_EQ(Empty, N->getOperand(0));
+
+  // Check code for adding another unresolved operand.
+  N->replaceOperandWith(0, Temp.get());
+  EXPECT_EQ(Temp.get(), N->getOperand(0));
+
+  // Remove the references to Temp; required for teardown.
+  Temp->replaceAllUsesWith(nullptr);
+}
+
 typedef MetadataTest MetadataAsValueTest;
 
 TEST_F(MetadataAsValueTest, MDNode) {