//===- LeaksContext.h - LeadDetector Implementation ------------*- 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 various helper methods and classes used by // LLVMContextImpl for leaks detectors. // //===----------------------------------------------------------------------===// #include "llvm/ADT/SmallPtrSet.h" #include "llvm/IR/Value.h" namespace llvm { template struct PrinterTrait { static void print(const T* P) { errs() << P; } }; template<> struct PrinterTrait { static void print(const Value* P) { errs() << *P; } }; template struct LeakDetectorImpl { explicit LeakDetectorImpl(const char* const name = "") : Cache(0), Name(name) { } void clear() { Cache = 0; Ts.clear(); } void setName(const char* n) { Name = n; } // 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. void addGarbage(const T* o) { assert(Ts.count(o) == 0 && "Object already in set!"); if (Cache) { assert(Cache != o && "Object already in set!"); Ts.insert(Cache); } Cache = o; } void removeGarbage(const T* o) { if (o == Cache) Cache = 0; // Cache hit else Ts.erase(o); } bool hasGarbage(const std::string& Message) { addGarbage(0); // Flush the Cache assert(Cache == 0 && "No value should be cached anymore!"); if (!Ts.empty()) { errs() << "Leaked " << Name << " objects found: " << Message << ":\n"; for (typename SmallPtrSet::iterator I = Ts.begin(), E = Ts.end(); I != E; ++I) { errs() << '\t'; PrinterTrait::print(*I); errs() << '\n'; } errs() << '\n'; return true; } return false; } private: SmallPtrSet Ts; const T* Cache; const char* Name; }; }