| //===- LeaksContext.h - LeadDetector Implementation ------------*- C++ -*--===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file defines various helper methods and classes used by |
| // LLVMContextImpl for leaks detectors. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "llvm/Value.h" |
| #include "llvm/ADT/SmallPtrSet.h" |
| |
| namespace llvm { |
| |
| template <class T> |
| struct PrinterTrait { |
| static void print(const T* P) { errs() << P; } |
| }; |
| |
| template<> |
| struct PrinterTrait<Value> { |
| static void print(const Value* P) { errs() << *P; } |
| }; |
| |
| template <typename T> |
| struct LeakDetectorImpl { |
| explicit LeakDetectorImpl(const char* const name = "") : |
| Cache(0), Name(name) { } |
| |
| void clear() { |
| Cache = 0; |
| Ts.clear(); |
| } |
| |
| void setName(const char* n) { |
| Name = n; |
| } |
| |
| // Because the most common usage pattern, by far, is to add a |
| // garbage object, then remove it immediately, we optimize this |
| // case. When an object is added, it is not added to the set |
| // immediately, it is added to the CachedValue Value. If it is |
| // immediately removed, no set search need be performed. |
| void addGarbage(const T* o) { |
| assert(Ts.count(o) == 0 && "Object already in set!"); |
| if (Cache) { |
| assert(Cache != o && "Object already in set!"); |
| Ts.insert(Cache); |
| } |
| Cache = o; |
| } |
| |
| void removeGarbage(const T* o) { |
| if (o == Cache) |
| Cache = 0; // Cache hit |
| else |
| Ts.erase(o); |
| } |
| |
| bool hasGarbage(const std::string& Message) { |
| addGarbage(0); // Flush the Cache |
| |
| assert(Cache == 0 && "No value should be cached anymore!"); |
| |
| if (!Ts.empty()) { |
| errs() << "Leaked " << Name << " objects found: " << Message << ":\n"; |
| for (typename SmallPtrSet<const T*, 8>::iterator I = Ts.begin(), |
| E = Ts.end(); I != E; ++I) { |
| errs() << '\t'; |
| PrinterTrait<T>::print(*I); |
| errs() << '\n'; |
| } |
| errs() << '\n'; |
| |
| return true; |
| } |
| |
| return false; |
| } |
| |
| private: |
| SmallPtrSet<const T*, 8> Ts; |
| const T* Cache; |
| const char* Name; |
| }; |
| |
| } |