LLVM API Documentation

LeaksContext.h
Go to the documentation of this file.
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