1//===- LeaksContext.h - LeadDetector Implementation ------------*- C++ -*--===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file defines various helper methods and classes used by 11// LLVMContextImpl for leaks detectors. 12// 13//===----------------------------------------------------------------------===// 14 15#include "llvm/Value.h" 16#include "llvm/ADT/SmallPtrSet.h" 17 18namespace llvm { 19 20template <class T> 21struct PrinterTrait { 22 static void print(const T* P) { errs() << P; } 23}; 24 25template<> 26struct PrinterTrait<Value> { 27 static void print(const Value* P) { errs() << *P; } 28}; 29 30template <typename T> 31struct LeakDetectorImpl { 32 explicit LeakDetectorImpl(const char* const name = "") : 33 Cache(0), Name(name) { } 34 35 void clear() { 36 Cache = 0; 37 Ts.clear(); 38 } 39 40 void setName(const char* n) { 41 Name = n; 42 } 43 44 // Because the most common usage pattern, by far, is to add a 45 // garbage object, then remove it immediately, we optimize this 46 // case. When an object is added, it is not added to the set 47 // immediately, it is added to the CachedValue Value. If it is 48 // immediately removed, no set search need be performed. 49 void addGarbage(const T* o) { 50 assert(Ts.count(o) == 0 && "Object already in set!"); 51 if (Cache) { 52 assert(Cache != o && "Object already in set!"); 53 Ts.insert(Cache); 54 } 55 Cache = o; 56 } 57 58 void removeGarbage(const T* o) { 59 if (o == Cache) 60 Cache = 0; // Cache hit 61 else 62 Ts.erase(o); 63 } 64 65 bool hasGarbage(const std::string& Message) { 66 addGarbage(0); // Flush the Cache 67 68 assert(Cache == 0 && "No value should be cached anymore!"); 69 70 if (!Ts.empty()) { 71 errs() << "Leaked " << Name << " objects found: " << Message << ":\n"; 72 for (typename SmallPtrSet<const T*, 8>::iterator I = Ts.begin(), 73 E = Ts.end(); I != E; ++I) { 74 errs() << '\t'; 75 PrinterTrait<T>::print(*I); 76 errs() << '\n'; 77 } 78 errs() << '\n'; 79 80 return true; 81 } 82 83 return false; 84 } 85 86private: 87 SmallPtrSet<const T*, 8> Ts; 88 const T* Cache; 89 const char* Name; 90}; 91 92} 93