//===-- LeakDetector.cpp - Implement LeakDetector interface ---------------===// // // This file implements the LeakDetector class. // //===----------------------------------------------------------------------===// #include "Support/LeakDetector.h" #include "llvm/Value.h" #include // Lazily allocate set so that release build doesn't have to do anything. static std::set *Objects = 0; static std::set *LLVMObjects = 0; // Because the most common usage pattern, by far, is to add a garbage object, // then remove it immediately, we optimize this case. When an object is added, // it is not added to the set immediately, it is added to the CachedValue Value. // If it is immediately removed, no set search need be performed. // static const Value *CachedValue; void LeakDetector::addGarbageObjectImpl(void *Object) { if (Objects == 0) Objects = new std::set(); assert(Objects->count(Object) == 0 && "Object already in set!"); Objects->insert(Object); } void LeakDetector::removeGarbageObjectImpl(void *Object) { if (Objects) Objects->erase(Object); } void LeakDetector::addGarbageObjectImpl(const Value *Object) { if (CachedValue) { if (LLVMObjects == 0) LLVMObjects = new std::set(); assert(LLVMObjects->count(CachedValue) == 0 && "Object already in set!"); LLVMObjects->insert(CachedValue); } CachedValue = Object; } void LeakDetector::removeGarbageObjectImpl(const Value *Object) { if (Object == CachedValue) CachedValue = 0; // Cache hit! else if (LLVMObjects) LLVMObjects->erase(Object); } void LeakDetector::checkForGarbageImpl(const std::string &Message) { if (CachedValue) // Flush the cache to the set... addGarbageObjectImpl((Value*)0); assert(CachedValue == 0 && "No value should be cached anymore!"); if ((Objects && !Objects->empty()) || (LLVMObjects && !LLVMObjects->empty())){ std::cerr << "Leaked objects found: " << Message << "\n"; if (Objects && !Objects->empty()) { std::cerr << " Non-Value objects leaked:"; for (std::set::iterator I = Objects->begin(), E = Objects->end(); I != E; ++I) std::cerr << " " << *I; } if (LLVMObjects && !LLVMObjects->empty()) { std::cerr << " LLVM Value subclasses leaked:"; for (std::set::iterator I = LLVMObjects->begin(), E = LLVMObjects->end(); I != E; ++I) std::cerr << **I << "\n"; } std::cerr << "This is probably because you removed an LLVM value " << "(Instruction, BasicBlock, \netc), 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... delete Objects; delete LLVMObjects; Objects = 0; LLVMObjects = 0; } }