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 #ifndef LLVM_IR_LEAKSCONTEXT_H 16 #define LLVM_IR_LEAKSCONTEXT_H 17 18 #include "llvm/ADT/SmallPtrSet.h" 19 #include "llvm/IR/Value.h" 20 #include "llvm/Support/raw_ostream.h" 21 22 namespace llvm { 23 24 template <class T> 25 struct PrinterTrait { printPrinterTrait26 static void print(const T* P) { errs() << P; } 27 }; 28 29 template<> 30 struct PrinterTrait<Value> { 31 static void print(const Value* P) { errs() << *P; } 32 }; 33 34 template <typename T> 35 struct LeakDetectorImpl { 36 explicit LeakDetectorImpl(const char* const name = "") : 37 Cache(nullptr), Name(name) { } 38 39 void clear() { 40 Cache = nullptr; 41 Ts.clear(); 42 } 43 44 void setName(const char* n) { 45 Name = n; 46 } 47 48 // Because the most common usage pattern, by far, is to add a 49 // garbage object, then remove it immediately, we optimize this 50 // case. When an object is added, it is not added to the set 51 // immediately, it is added to the CachedValue Value. If it is 52 // immediately removed, no set search need be performed. 53 void addGarbage(const T* o) { 54 assert(Ts.count(o) == 0 && "Object already in set!"); 55 if (Cache) { 56 assert(Cache != o && "Object already in set!"); 57 Ts.insert(Cache); 58 } 59 Cache = o; 60 } 61 62 void removeGarbage(const T* o) { 63 if (o == Cache) 64 Cache = nullptr; // Cache hit 65 else 66 Ts.erase(o); 67 } 68 69 bool hasGarbage(const std::string& Message) { 70 addGarbage(nullptr); // Flush the Cache 71 72 assert(!Cache && "No value should be cached anymore!"); 73 74 if (!Ts.empty()) { 75 errs() << "Leaked " << Name << " objects found: " << Message << ":\n"; 76 for (typename SmallPtrSet<const T*, 8>::iterator I = Ts.begin(), 77 E = Ts.end(); I != E; ++I) { 78 errs() << '\t'; 79 PrinterTrait<T>::print(*I); 80 errs() << '\n'; 81 } 82 errs() << '\n'; 83 84 return true; 85 } 86 87 return false; 88 } 89 90 private: 91 SmallPtrSet<const T*, 8> Ts; 92 const T* Cache; 93 const char* Name; 94 }; 95 96 } 97 98 #endif // LLVM_IR_LEAKSCONTEXT_H 99