1249259Sdim//===- LeaksContext.h - LeadDetector Implementation ------------*- C++ -*--===// 2249259Sdim// 3249259Sdim// The LLVM Compiler Infrastructure 4249259Sdim// 5249259Sdim// This file is distributed under the University of Illinois Open Source 6249259Sdim// License. See LICENSE.TXT for details. 7249259Sdim// 8249259Sdim//===----------------------------------------------------------------------===// 9249259Sdim// 10249259Sdim// This file defines various helper methods and classes used by 11249259Sdim// LLVMContextImpl for leaks detectors. 12249259Sdim// 13249259Sdim//===----------------------------------------------------------------------===// 14249259Sdim 15249259Sdim#include "llvm/ADT/SmallPtrSet.h" 16249259Sdim#include "llvm/IR/Value.h" 17249259Sdim 18249259Sdimnamespace llvm { 19249259Sdim 20249259Sdimtemplate <class T> 21249259Sdimstruct PrinterTrait { 22249259Sdim static void print(const T* P) { errs() << P; } 23249259Sdim}; 24249259Sdim 25249259Sdimtemplate<> 26249259Sdimstruct PrinterTrait<Value> { 27249259Sdim static void print(const Value* P) { errs() << *P; } 28249259Sdim}; 29249259Sdim 30249259Sdimtemplate <typename T> 31249259Sdimstruct LeakDetectorImpl { 32249259Sdim explicit LeakDetectorImpl(const char* const name = "") : 33249259Sdim Cache(0), Name(name) { } 34249259Sdim 35249259Sdim void clear() { 36249259Sdim Cache = 0; 37249259Sdim Ts.clear(); 38249259Sdim } 39249259Sdim 40249259Sdim void setName(const char* n) { 41249259Sdim Name = n; 42249259Sdim } 43249259Sdim 44249259Sdim // Because the most common usage pattern, by far, is to add a 45249259Sdim // garbage object, then remove it immediately, we optimize this 46249259Sdim // case. When an object is added, it is not added to the set 47249259Sdim // immediately, it is added to the CachedValue Value. If it is 48249259Sdim // immediately removed, no set search need be performed. 49249259Sdim void addGarbage(const T* o) { 50249259Sdim assert(Ts.count(o) == 0 && "Object already in set!"); 51249259Sdim if (Cache) { 52249259Sdim assert(Cache != o && "Object already in set!"); 53249259Sdim Ts.insert(Cache); 54249259Sdim } 55249259Sdim Cache = o; 56249259Sdim } 57249259Sdim 58249259Sdim void removeGarbage(const T* o) { 59249259Sdim if (o == Cache) 60249259Sdim Cache = 0; // Cache hit 61249259Sdim else 62249259Sdim Ts.erase(o); 63249259Sdim } 64249259Sdim 65249259Sdim bool hasGarbage(const std::string& Message) { 66249259Sdim addGarbage(0); // Flush the Cache 67249259Sdim 68249259Sdim assert(Cache == 0 && "No value should be cached anymore!"); 69249259Sdim 70249259Sdim if (!Ts.empty()) { 71249259Sdim errs() << "Leaked " << Name << " objects found: " << Message << ":\n"; 72249259Sdim for (typename SmallPtrSet<const T*, 8>::iterator I = Ts.begin(), 73249259Sdim E = Ts.end(); I != E; ++I) { 74249259Sdim errs() << '\t'; 75249259Sdim PrinterTrait<T>::print(*I); 76249259Sdim errs() << '\n'; 77249259Sdim } 78249259Sdim errs() << '\n'; 79249259Sdim 80249259Sdim return true; 81249259Sdim } 82249259Sdim 83249259Sdim return false; 84249259Sdim } 85249259Sdim 86249259Sdimprivate: 87249259Sdim SmallPtrSet<const T*, 8> Ts; 88249259Sdim const T* Cache; 89249259Sdim const char* Name; 90249259Sdim}; 91249259Sdim 92249259Sdim} 93