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