diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h --- a/llvm/include/llvm/IR/Module.h +++ b/llvm/include/llvm/IR/Module.h @@ -581,6 +581,17 @@ // Use ifunc_size() to get the number of functions in IFuncList. // Use ifuncs() to get the range of all IFuncs. + /// Detach \p MDNode from the list but don't delete it. + void removeNamedMDNode(NamedMDNode *MDNode) { NamedMDList.remove(MDNode); } + /// Remove \p MDNode from the list and delete it. + void eraseNamedMDNode(NamedMDNode *MDNode) { NamedMDList.erase(MDNode); } + /// Insert \p MDNode at the end of the alias list and take ownership. + void insertNamedMDNode(NamedMDNode *MDNode) { + NamedMDList.push_back(MDNode); + } + // Use named_metadata_size() to get the size of the named meatadata list. + // Use named_metadata() to get the range of all named metadata. + private: // Please use functions like insertAlias(), removeAlias() etc. /// Get the Module's list of aliases (constant). const AliasListType &getAliasList() const { return AliasList; } @@ -602,7 +613,6 @@ } friend class llvm::SymbolTableListTraits; -public: /// Get the Module's list of named metadata (constant). const NamedMDListType &getNamedMDList() const { return NamedMDList; } /// Get the Module's list of named metadata. @@ -612,6 +622,7 @@ return &Module::NamedMDList; } +public: /// Get the symbol table of global variable and function identifiers const ValueSymbolTable &getValueSymbolTable() const { return *ValSymTab; } /// Get the Module's symbol table of global variable and function identifiers. diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp --- a/llvm/lib/IR/DebugInfo.cpp +++ b/llvm/lib/IR/DebugInfo.cpp @@ -870,7 +870,7 @@ // Create a new llvm.dbg.cu, which is equivalent to the one // -gline-tables-only would have created. - for (auto &NMD : M.getNamedMDList()) { + for (auto &NMD : M.named_metadata()) { SmallVector Ops; for (MDNode *Op : NMD.operands()) Ops.push_back(remap(Op)); diff --git a/llvm/lib/IR/Module.cpp b/llvm/lib/IR/Module.cpp --- a/llvm/lib/IR/Module.cpp +++ b/llvm/lib/IR/Module.cpp @@ -262,7 +262,7 @@ if (!NMD) { NMD = new NamedMDNode(Name); NMD->setParent(this); - NamedMDList.push_back(NMD); + insertNamedMDNode(NMD); } return NMD; } @@ -271,7 +271,7 @@ /// delete it. void Module::eraseNamedMetadata(NamedMDNode *NMD) { NamedMDSymTab.erase(NMD->getName()); - NamedMDList.erase(NMD->getIterator()); + eraseNamedMDNode(NMD); } bool Module::isValidModFlagBehavior(Metadata *MD, ModFlagBehavior &MFB) { diff --git a/llvm/unittests/IR/ModuleTest.cpp b/llvm/unittests/IR/ModuleTest.cpp --- a/llvm/unittests/IR/ModuleTest.cpp +++ b/llvm/unittests/IR/ModuleTest.cpp @@ -239,4 +239,38 @@ EXPECT_EQ(M->ifunc_size(), 1u); } +TEST(ModuleTest, NamedMDList) { + // This tests all Module's functions that interact with Module::NamedMDList. + LLVMContext C; + SMDiagnostic Err; + LLVMContext Context; + auto M = std::make_unique("M", C); + NamedMDNode *MDN1 = M->getOrInsertNamedMetadata("MDN1"); + EXPECT_EQ(M->named_metadata_size(), 1u); + NamedMDNode *MDN2 = M->getOrInsertNamedMetadata("MDN2"); + EXPECT_EQ(M->named_metadata_size(), 2u); + auto *NewMDN = M->getOrInsertNamedMetadata("NewMDN"); + EXPECT_EQ(M->named_metadata_size(), 3u); + + M->removeNamedMDNode(NewMDN); + EXPECT_EQ(M->named_metadata_size(), 2u); + + M->insertNamedMDNode(NewMDN); + EXPECT_EQ(&*std::prev(M->named_metadata().end()), NewMDN); + + M->removeNamedMDNode(NewMDN); + M->insertNamedMDNode(NewMDN); + EXPECT_EQ(M->named_metadata_size(), 3u); + EXPECT_EQ(&*std::prev(M->named_metadata().end()), NewMDN); + + auto Range = M->named_metadata(); + EXPECT_EQ(&*Range.begin(), MDN1); + EXPECT_EQ(&*std::next(Range.begin(), 1), MDN2); + EXPECT_EQ(&*std::next(Range.begin(), 2), NewMDN); + EXPECT_EQ(std::next(Range.begin(), 3), Range.end()); + + M->eraseNamedMDNode(NewMDN); + EXPECT_EQ(M->named_metadata_size(), 2u); +} + } // end namespace