From 698be08c841091c73ca7c1c6ead1c3027e9f5169 Mon Sep 17 00:00:00 2001 From: "Duncan P. N. Exon Smith" Date: Tue, 13 Jan 2015 00:46:34 +0000 Subject: [PATCH] IR: Remove an invalid assertion when replacing resolved operands 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 | 8 +++++--- unittests/IR/MetadataTest.cpp | 27 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/lib/IR/Metadata.cpp b/lib/IR/Metadata.cpp index 13844313925..852f1dc2041 100644 --- a/lib/IR/Metadata.cpp +++ b/lib/IR/Metadata.cpp @@ -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(); } diff --git a/unittests/IR/MetadataTest.cpp b/unittests/IR/MetadataTest.cpp index af110742dd7..d85225561b2 100644 --- a/unittests/IR/MetadataTest.cpp +++ b/unittests/IR/MetadataTest.cpp @@ -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 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) {