From: Rafael Espindola Date: Mon, 22 Dec 2014 13:00:36 +0000 (+0000) Subject: The leak detector is dead, long live asan and valgrind. X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=ada5f24b5fd5fd1c9be505ffca21035b54b8d538 The leak detector is dead, long live asan and valgrind. In resent times asan and valgrind have found way more memory management bugs in llvm than the special purpose leak detector. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@224703 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/IR/LeakDetector.h b/include/llvm/IR/LeakDetector.h deleted file mode 100644 index b014fe081f0..00000000000 --- a/include/llvm/IR/LeakDetector.h +++ /dev/null @@ -1,95 +0,0 @@ -//===- LeakDetector.h - Provide leak detection ------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines a class that can be used to provide very simple memory leak -// checks for an API. Basically LLVM uses this to make sure that Instructions, -// for example, are deleted when they are supposed to be, and not leaked away. -// -// When compiling with NDEBUG (Release build), this class does nothing, thus -// adding no checking overhead to release builds. Note that this class is -// implemented in a very simple way, requiring completely manual manipulation -// and checking for garbage, but this is intentional: users should not be using -// this API, only other APIs should. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_LEAKDETECTOR_H -#define LLVM_IR_LEAKDETECTOR_H - -#include - -namespace llvm { - -class LLVMContext; -class Value; -class MDNode; - -struct LeakDetector { - /// addGarbageObject - Add a pointer to the internal set of "garbage" object - /// pointers. This should be called when objects are created, or if they are - /// taken out of an owning collection. - /// - template static void addGarbageObject(T *Object) { -#ifndef NDEBUG - addGarbageObjectImpl(Object); -#endif - } - - /// removeGarbageObject - Remove a pointer from our internal representation of - /// our "garbage" objects. This should be called when an object is added to - /// an "owning" collection. - /// - template static void removeGarbageObject(T *Object) { -#ifndef NDEBUG - removeGarbageObjectImpl(Object); -#endif - } - - /// checkForGarbage - Traverse the internal representation of garbage - /// pointers. If there are any pointers that have been add'ed, but not - /// remove'd, big obnoxious warnings about memory leaks are issued. - /// - /// The specified message will be printed indicating when the check was - /// performed. - /// - static void checkForGarbage(LLVMContext &C, const std::string &Message) { -#ifndef NDEBUG - checkForGarbageImpl(C, Message); -#endif - } - -private: - /// Overload the normal methods to work better with Value* because they are - /// by far the most common in LLVM. - /// - /// Besides making the warning messages nicer, this hides errors by storing - /// Value* in a different leak-detection container than other classes. - static void addGarbageObjectImpl(const Value *Object); - static void removeGarbageObjectImpl(const Value *Object); - - /// Overload the normal methods to work better with MDNode* to improve error - /// messages. - /// - /// For better or worse, this hides errors when other types are added as - /// garbage, deleted without being removed, and an MDNode is allocated in the - /// same spot. - /// - /// \note Only handle \a MDNode for now, since we can't always get access to - /// an \a LLVMContext for other \a Metadata types. - static void addGarbageObjectImpl(const MDNode *Object); - static void removeGarbageObjectImpl(const MDNode *Object); - - static void addGarbageObjectImpl(void *Object); - static void removeGarbageObjectImpl(void *Object); - static void checkForGarbageImpl(LLVMContext &C, const std::string &Message); -}; - -} // End llvm namespace - -#endif diff --git a/lib/CodeGen/MachineBasicBlock.cpp b/lib/CodeGen/MachineBasicBlock.cpp index a7dc1b328c1..3c7390527e5 100644 --- a/lib/CodeGen/MachineBasicBlock.cpp +++ b/lib/CodeGen/MachineBasicBlock.cpp @@ -24,7 +24,6 @@ #include "llvm/CodeGen/SlotIndexes.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/DataLayout.h" -#include "llvm/IR/LeakDetector.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/Support/Debug.h" @@ -45,7 +44,6 @@ MachineBasicBlock::MachineBasicBlock(MachineFunction &mf, const BasicBlock *bb) } MachineBasicBlock::~MachineBasicBlock() { - LeakDetector::removeGarbageObject(this); } /// getSymbol - Return the MCSymbol for this basic block. @@ -85,14 +83,11 @@ void ilist_traits::addNodeToList(MachineBasicBlock *N) { for (MachineBasicBlock::instr_iterator I = N->instr_begin(), E = N->instr_end(); I != E; ++I) I->AddRegOperandsToUseLists(RegInfo); - - LeakDetector::removeGarbageObject(N); } void ilist_traits::removeNodeFromList(MachineBasicBlock *N) { N->getParent()->removeFromMBBNumbering(N->Number); N->Number = -1; - LeakDetector::addGarbageObject(N); } diff --git a/lib/IR/BasicBlock.cpp b/lib/IR/BasicBlock.cpp index 5ed9bed1baf..98a30621ff4 100644 --- a/lib/IR/BasicBlock.cpp +++ b/lib/IR/BasicBlock.cpp @@ -19,7 +19,6 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LLVMContext.h" -#include "llvm/IR/LeakDetector.h" #include "llvm/IR/Type.h" #include using namespace llvm; @@ -47,9 +46,6 @@ BasicBlock::BasicBlock(LLVMContext &C, const Twine &Name, Function *NewParent, BasicBlock *InsertBefore) : Value(Type::getLabelTy(C), Value::BasicBlockVal), Parent(nullptr) { - // Make sure that we get added to a function - LeakDetector::addGarbageObject(this); - if (NewParent) insertInto(NewParent, InsertBefore); else @@ -94,14 +90,8 @@ BasicBlock::~BasicBlock() { } void BasicBlock::setParent(Function *parent) { - if (getParent()) - LeakDetector::addGarbageObject(this); - // Set Parent=parent, updating instruction symtab entries as appropriate. InstList.setSymTabObject(&Parent, parent); - - if (getParent()) - LeakDetector::removeGarbageObject(this); } void BasicBlock::removeFromParent() { diff --git a/lib/IR/CMakeLists.txt b/lib/IR/CMakeLists.txt index 3b149e8690a..1a210e05827 100644 --- a/lib/IR/CMakeLists.txt +++ b/lib/IR/CMakeLists.txt @@ -27,7 +27,6 @@ add_llvm_library(LLVMCore IntrinsicInst.cpp LLVMContext.cpp LLVMContextImpl.cpp - LeakDetector.cpp LegacyPassManager.cpp MDBuilder.cpp Mangler.cpp diff --git a/lib/IR/Function.cpp b/lib/IR/Function.cpp index ba6e4ce79a1..f462ec0890d 100644 --- a/lib/IR/Function.cpp +++ b/lib/IR/Function.cpp @@ -23,7 +23,6 @@ #include "llvm/IR/InstIterator.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LLVMContext.h" -#include "llvm/IR/LeakDetector.h" #include "llvm/IR/Module.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/RWMutex.h" @@ -46,20 +45,13 @@ Argument::Argument(Type *Ty, const Twine &Name, Function *Par) : Value(Ty, Value::ArgumentVal) { Parent = nullptr; - // Make sure that we get added to a function - LeakDetector::addGarbageObject(this); - if (Par) Par->getArgumentList().push_back(this); setName(Name); } void Argument::setParent(Function *parent) { - if (getParent()) - LeakDetector::addGarbageObject(this); Parent = parent; - if (getParent()) - LeakDetector::removeGarbageObject(this); } /// getArgNo - Return the index of this formal argument in its containing @@ -260,9 +252,6 @@ Function::Function(FunctionType *Ty, LinkageTypes Linkage, const Twine &name, if (Ty->getNumParams()) setValueSubclassData(1); // Set the "has lazy arguments" bit. - // Make sure that we get added to a function - LeakDetector::addGarbageObject(this); - if (ParentModule) ParentModule->getFunctionList().push_back(this); @@ -309,11 +298,7 @@ bool Function::arg_empty() const { } void Function::setParent(Module *parent) { - if (getParent()) - LeakDetector::addGarbageObject(this); Parent = parent; - if (getParent()) - LeakDetector::removeGarbageObject(this); } // dropAllReferences() - This function causes all the subinstructions to "let diff --git a/lib/IR/Globals.cpp b/lib/IR/Globals.cpp index e181d623b85..54197d96763 100644 --- a/lib/IR/Globals.cpp +++ b/lib/IR/Globals.cpp @@ -18,7 +18,6 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/GlobalVariable.h" -#include "llvm/IR/LeakDetector.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" #include "llvm/Support/ErrorHandling.h" @@ -159,8 +158,6 @@ GlobalVariable::GlobalVariable(Type *Ty, bool constant, LinkageTypes Link, "Initializer should be the same type as the GlobalVariable!"); Op<0>() = InitVal; } - - LeakDetector::addGarbageObject(this); } GlobalVariable::GlobalVariable(Module &M, Type *Ty, bool constant, @@ -180,8 +177,6 @@ GlobalVariable::GlobalVariable(Module &M, Type *Ty, bool constant, Op<0>() = InitVal; } - LeakDetector::addGarbageObject(this); - if (Before) Before->getParent()->getGlobalList().insert(Before, this); else @@ -189,11 +184,7 @@ GlobalVariable::GlobalVariable(Module &M, Type *Ty, bool constant, } void GlobalVariable::setParent(Module *parent) { - if (getParent()) - LeakDetector::addGarbageObject(this); Parent = parent; - if (getParent()) - LeakDetector::removeGarbageObject(this); } void GlobalVariable::removeFromParent() { @@ -259,7 +250,6 @@ GlobalAlias::GlobalAlias(Type *Ty, unsigned AddressSpace, LinkageTypes Link, Module *ParentModule) : GlobalValue(PointerType::get(Ty, AddressSpace), Value::GlobalAliasVal, &Op<0>(), 1, Link, Name) { - LeakDetector::addGarbageObject(this); Op<0>() = Aliasee; if (ParentModule) @@ -296,11 +286,7 @@ GlobalAlias *GlobalAlias::create(const Twine &Name, GlobalValue *Aliasee) { } void GlobalAlias::setParent(Module *parent) { - if (getParent()) - LeakDetector::addGarbageObject(this); Parent = parent; - if (getParent()) - LeakDetector::removeGarbageObject(this); } void GlobalAlias::removeFromParent() { diff --git a/lib/IR/Instruction.cpp b/lib/IR/Instruction.cpp index 3ee66f56981..92c6e9f3ded 100644 --- a/lib/IR/Instruction.cpp +++ b/lib/IR/Instruction.cpp @@ -15,7 +15,6 @@ #include "llvm/IR/CallSite.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Instructions.h" -#include "llvm/IR/LeakDetector.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" #include "llvm/IR/Type.h" @@ -24,8 +23,6 @@ using namespace llvm; Instruction::Instruction(Type *ty, unsigned it, Use *Ops, unsigned NumOps, Instruction *InsertBefore) : User(ty, Value::InstructionVal + it, Ops, NumOps), Parent(nullptr) { - // Make sure that we get added to a basicblock - LeakDetector::addGarbageObject(this); // If requested, insert this instruction into a basic block... if (InsertBefore) { @@ -42,8 +39,6 @@ const DataLayout *Instruction::getDataLayout() const { Instruction::Instruction(Type *ty, unsigned it, Use *Ops, unsigned NumOps, BasicBlock *InsertAtEnd) : User(ty, Value::InstructionVal + it, Ops, NumOps), Parent(nullptr) { - // Make sure that we get added to a basicblock - LeakDetector::addGarbageObject(this); // append this instruction into the basic block assert(InsertAtEnd && "Basic block to append to may not be NULL!"); @@ -60,12 +55,6 @@ Instruction::~Instruction() { void Instruction::setParent(BasicBlock *P) { - if (getParent()) { - if (!P) LeakDetector::addGarbageObject(this); - } else { - if (P) LeakDetector::removeGarbageObject(this); - } - Parent = P; } diff --git a/lib/IR/LeakDetector.cpp b/lib/IR/LeakDetector.cpp deleted file mode 100644 index be07a481883..00000000000 --- a/lib/IR/LeakDetector.cpp +++ /dev/null @@ -1,82 +0,0 @@ -//===-- LeakDetector.cpp - Implement LeakDetector interface ---------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the LeakDetector class. -// -//===----------------------------------------------------------------------===// - -#include "llvm/IR/LeakDetector.h" -#include "LLVMContextImpl.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/IR/Metadata.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/Mutex.h" -#include "llvm/Support/Threading.h" -using namespace llvm; - -static ManagedStatic > ObjectsLock; -static ManagedStatic > Objects; - -static void clearGarbage(LLVMContext &Context) { - Objects->clear(); - Context.pImpl->LLVMObjects.clear(); -} - -void LeakDetector::addGarbageObjectImpl(void *Object) { - sys::SmartScopedLock Lock(*ObjectsLock); - Objects->addGarbage(Object); -} - -void LeakDetector::addGarbageObjectImpl(const Value *Object) { - LLVMContextImpl *pImpl = Object->getContext().pImpl; - pImpl->LLVMObjects.addGarbage(Object); -} - -void LeakDetector::addGarbageObjectImpl(const MDNode *Object) { - LLVMContextImpl *pImpl = Object->getContext().pImpl; - pImpl->LLVMMDObjects.addGarbage(Object); -} - -void LeakDetector::removeGarbageObjectImpl(void *Object) { - sys::SmartScopedLock Lock(*ObjectsLock); - Objects->removeGarbage(Object); -} - -void LeakDetector::removeGarbageObjectImpl(const Value *Object) { - LLVMContextImpl *pImpl = Object->getContext().pImpl; - pImpl->LLVMObjects.removeGarbage(Object); -} - -void LeakDetector::removeGarbageObjectImpl(const MDNode *Object) { - LLVMContextImpl *pImpl = Object->getContext().pImpl; - pImpl->LLVMMDObjects.removeGarbage(Object); -} - -void LeakDetector::checkForGarbageImpl(LLVMContext &Context, - const std::string &Message) { - LLVMContextImpl *pImpl = Context.pImpl; - sys::SmartScopedLock Lock(*ObjectsLock); - - Objects->setName("GENERIC"); - pImpl->LLVMObjects.setName("LLVM"); - pImpl->LLVMMDObjects.setName("LLVM-MD"); - - // use non-short-circuit version so that both checks are performed - if (Objects->hasGarbage(Message) | - pImpl->LLVMObjects.hasGarbage(Message) | - pImpl->LLVMMDObjects.hasGarbage(Message)) - errs() << "\nThis is probably because you removed an object, but didn't " - << "delete it. Please check your code for memory leaks.\n"; - - // Clear out results so we don't get duplicate warnings on - // next call... - clearGarbage(Context); -} diff --git a/lib/IR/Metadata.cpp b/lib/IR/Metadata.cpp index 936c129662d..4b099ec255f 100644 --- a/lib/IR/Metadata.cpp +++ b/lib/IR/Metadata.cpp @@ -22,7 +22,6 @@ #include "llvm/IR/ConstantRange.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/LLVMContext.h" -#include "llvm/IR/LeakDetector.h" #include "llvm/IR/Module.h" #include "llvm/IR/ValueHandle.h" @@ -596,13 +595,11 @@ MDNode *MDNode::getMDNode(LLVMContext &Context, ArrayRef MDs, MDNodeFwdDecl *MDNode::getTemporary(LLVMContext &Context, ArrayRef MDs) { MDNodeFwdDecl *N = new (MDs.size()) MDNodeFwdDecl(Context, MDs); - LeakDetector::addGarbageObject(N); return N; } void MDNode::deleteTemporary(MDNode *N) { assert(isa(N) && "Expected forward declaration"); - LeakDetector::removeGarbageObject(N); delete cast(N); } diff --git a/lib/IR/Module.cpp b/lib/IR/Module.cpp index 71640bfb9f3..d32ffcdac33 100644 --- a/lib/IR/Module.cpp +++ b/lib/IR/Module.cpp @@ -22,7 +22,6 @@ #include "llvm/IR/GVMaterializer.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/LLVMContext.h" -#include "llvm/IR/LeakDetector.h" #include "llvm/IR/TypeFinder.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/Path.h" diff --git a/lib/IR/Value.cpp b/lib/IR/Value.cpp index d790f9e1089..a9e6a72f0ac 100644 --- a/lib/IR/Value.cpp +++ b/lib/IR/Value.cpp @@ -23,7 +23,6 @@ #include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instructions.h" -#include "llvm/IR/LeakDetector.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" #include "llvm/IR/ValueHandle.h" @@ -84,9 +83,6 @@ Value::~Value() { // If this value is named, destroy the name. This should not be in a symtab // at this point. destroyValueName(); - - // There should be no uses of this object anymore, remove it. - LeakDetector::removeGarbageObject(this); } void Value::destroyValueName() { diff --git a/unittests/IR/CMakeLists.txt b/unittests/IR/CMakeLists.txt index a0462091a31..0c2979632e1 100644 --- a/unittests/IR/CMakeLists.txt +++ b/unittests/IR/CMakeLists.txt @@ -14,7 +14,6 @@ set(IRSources DominatorTreeTest.cpp IRBuilderTest.cpp InstructionsTest.cpp - LeakDetectorTest.cpp LegacyPassManagerTest.cpp MDBuilderTest.cpp MetadataTest.cpp diff --git a/unittests/IR/LeakDetectorTest.cpp b/unittests/IR/LeakDetectorTest.cpp deleted file mode 100644 index 94eed4c1432..00000000000 --- a/unittests/IR/LeakDetectorTest.cpp +++ /dev/null @@ -1,31 +0,0 @@ -//===- LeakDetectorTest.cpp -----------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/IR/LeakDetector.h" -#include "gtest/gtest.h" - -using namespace llvm; - -namespace { - -#ifdef GTEST_HAS_DEATH_TEST -#ifndef NDEBUG -TEST(LeakDetector, Death1) { - LeakDetector::addGarbageObject((void*) 1); - LeakDetector::addGarbageObject((void*) 2); - - EXPECT_DEATH(LeakDetector::addGarbageObject((void*) 1), - ".*Ts.count\\(o\\) == 0 && \"Object already in set!\""); - EXPECT_DEATH(LeakDetector::addGarbageObject((void*) 2), - "Cache != o && \"Object already in set!\""); -} -#endif -#endif - -}