LLVM API Documentation
00001 //===- LeaksContext.h - LeadDetector Implementation ------------*- C++ -*--===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines various helper methods and classes used by 00011 // LLVMContextImpl for leaks detectors. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #ifndef LLVM_LIB_IR_LEAKSCONTEXT_H 00016 #define LLVM_LIB_IR_LEAKSCONTEXT_H 00017 00018 #include "llvm/ADT/SmallPtrSet.h" 00019 #include "llvm/IR/Value.h" 00020 #include "llvm/Support/raw_ostream.h" 00021 00022 namespace llvm { 00023 00024 template <class T> 00025 struct PrinterTrait { 00026 static void print(const T* P) { errs() << P; } 00027 }; 00028 00029 template<> 00030 struct PrinterTrait<Value> { 00031 static void print(const Value* P) { errs() << *P; } 00032 }; 00033 00034 template <typename T> 00035 struct LeakDetectorImpl { 00036 explicit LeakDetectorImpl(const char* const name = "") : 00037 Cache(nullptr), Name(name) { } 00038 00039 void clear() { 00040 Cache = nullptr; 00041 Ts.clear(); 00042 } 00043 00044 void setName(const char* n) { 00045 Name = n; 00046 } 00047 00048 // Because the most common usage pattern, by far, is to add a 00049 // garbage object, then remove it immediately, we optimize this 00050 // case. When an object is added, it is not added to the set 00051 // immediately, it is added to the CachedValue Value. If it is 00052 // immediately removed, no set search need be performed. 00053 void addGarbage(const T* o) { 00054 assert(Ts.count(o) == 0 && "Object already in set!"); 00055 if (Cache) { 00056 assert(Cache != o && "Object already in set!"); 00057 Ts.insert(Cache); 00058 } 00059 Cache = o; 00060 } 00061 00062 void removeGarbage(const T* o) { 00063 if (o == Cache) 00064 Cache = nullptr; // Cache hit 00065 else 00066 Ts.erase(o); 00067 } 00068 00069 bool hasGarbage(const std::string& Message) { 00070 addGarbage(nullptr); // Flush the Cache 00071 00072 assert(!Cache && "No value should be cached anymore!"); 00073 00074 if (!Ts.empty()) { 00075 errs() << "Leaked " << Name << " objects found: " << Message << ":\n"; 00076 for (typename SmallPtrSet<const T*, 8>::iterator I = Ts.begin(), 00077 E = Ts.end(); I != E; ++I) { 00078 errs() << '\t'; 00079 PrinterTrait<T>::print(*I); 00080 errs() << '\n'; 00081 } 00082 errs() << '\n'; 00083 00084 return true; 00085 } 00086 00087 return false; 00088 } 00089 00090 private: 00091 SmallPtrSet<const T*, 8> Ts; 00092 const T* Cache; 00093 const char* Name; 00094 }; 00095 00096 } 00097 00098 #endif