LLVM API Documentation

Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

LeakDetector.cpp

Go to the documentation of this file.
00001 //===-- LeakDetector.cpp - Implement LeakDetector interface ---------------===//
00002 // 
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file was developed by the LLVM research group and is distributed under
00006 // the University of Illinois Open Source License. See LICENSE.TXT for details.
00007 // 
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements the LeakDetector class.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "llvm/Support/LeakDetector.h"
00015 #include "llvm/Value.h"
00016 #include <iostream>
00017 #include <set>
00018 using namespace llvm;
00019 
00020 namespace {
00021   template <class T>
00022   struct PrinterTrait {
00023     static void print(const T* P) { std::cerr << P; }
00024   };
00025 
00026   template<>
00027   struct PrinterTrait<Value> {
00028     static void print(const Value* P) { std::cerr << *P; }
00029   };
00030 
00031   template <typename T>
00032   struct LeakDetectorImpl {
00033     LeakDetectorImpl(const char* const name) : Cache(0), Name(name) { }
00034 
00035     // Because the most common usage pattern, by far, is to add a
00036     // garbage object, then remove it immediately, we optimize this
00037     // case.  When an object is added, it is not added to the set
00038     // immediately, it is added to the CachedValue Value.  If it is
00039     // immediately removed, no set search need be performed.
00040     void addGarbage(const T* o) {
00041       if (Cache) {
00042         assert(Ts.count(Cache) == 0 && "Object already in set!");
00043         Ts.insert(Cache);
00044       }
00045       Cache = o;
00046     }
00047 
00048     void removeGarbage(const T* o) {
00049       if (o == Cache)
00050         Cache = 0; // Cache hit
00051       else
00052         Ts.erase(o);
00053     }
00054 
00055     bool hasGarbage(const std::string& Message) {
00056       addGarbage(0); // Flush the Cache
00057 
00058       assert(Cache == 0 && "No value should be cached anymore!");
00059 
00060       if (!Ts.empty()) {
00061         std::cerr
00062             << "Leaked " << Name << " objects found: " << Message << ":\n";
00063         for (typename std::set<const T*>::iterator I = Ts.begin(),
00064                E = Ts.end(); I != E; ++I) {
00065           std::cerr << "\t";
00066           PrinterTrait<T>::print(*I);
00067           std::cerr << "\n";
00068         }
00069         std::cerr << '\n';
00070 
00071         return true;
00072       }
00073       return false;
00074     }
00075 
00076   private:
00077     std::set<const T*> Ts;
00078     const T* Cache;
00079     const char* const Name;
00080   };
00081 
00082   LeakDetectorImpl<void>  *Objects;
00083   LeakDetectorImpl<Value> *LLVMObjects;
00084 
00085   LeakDetectorImpl<void> &getObjects() {
00086     if (Objects == 0)
00087       Objects = new LeakDetectorImpl<void>("GENERIC");
00088     return *Objects;
00089   }
00090 
00091   LeakDetectorImpl<Value> &getLLVMObjects() {
00092     if (LLVMObjects == 0)
00093       LLVMObjects = new LeakDetectorImpl<Value>("LLVM");
00094     return *LLVMObjects;
00095   }
00096 
00097   void clearGarbage() {
00098     delete Objects;
00099     delete LLVMObjects;
00100     Objects = 0;
00101     LLVMObjects = 0;
00102   }
00103 }
00104 
00105 void LeakDetector::addGarbageObjectImpl(void *Object) {
00106   getObjects().addGarbage(Object);
00107 }
00108 
00109 void LeakDetector::addGarbageObjectImpl(const Value *Object) {
00110   getLLVMObjects().addGarbage(Object);
00111 }
00112 
00113 void LeakDetector::removeGarbageObjectImpl(void *Object) {
00114   getObjects().removeGarbage(Object);
00115 }
00116 
00117 void LeakDetector::removeGarbageObjectImpl(const Value *Object) {
00118   getLLVMObjects().removeGarbage(Object);
00119 }
00120 
00121 void LeakDetector::checkForGarbageImpl(const std::string &Message) {
00122   // use non-short-circuit version so that both checks are performed
00123   if (getObjects().hasGarbage(Message) |
00124       getLLVMObjects().hasGarbage(Message))
00125     std::cerr << "\nThis is probably because you removed an object, but didn't "
00126                  "delete it.  Please check your code for memory leaks.\n";
00127 
00128   // Clear out results so we don't get duplicate warnings on
00129   // next call...
00130   clearGarbage();
00131 }