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