mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-01 00:11:00 +00:00
b663d76f86
implementation class. This makes the code simpler and allows for more types to be added easily. It also implements caching for generic objects (it was only available for llvm objects). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@11452 91177308-0d34-0410-b5e6-96231b3b80d8
108 lines
3.0 KiB
C++
108 lines
3.0 KiB
C++
//===-- LeakDetector.cpp - Implement LeakDetector interface ---------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file was developed by the LLVM research group and is distributed under
|
|
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements the LeakDetector class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "Support/LeakDetector.h"
|
|
#include "llvm/Value.h"
|
|
#include <set>
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
|
|
template <typename T>
|
|
struct LeakDetectorImpl {
|
|
LeakDetectorImpl(const char* const name) : Cache(0), Name(name) { }
|
|
|
|
// 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) {
|
|
if (Cache) {
|
|
assert(Ts.count(Cache) == 0 && "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()) {
|
|
std::cerr
|
|
<< "Leaked " << Name << " objects found: " << Message << ":\n\t";
|
|
std::copy(Ts.begin(), Ts.end(),
|
|
std::ostream_iterator<const T*>(std::cerr, " "));
|
|
std::cerr << '\n';
|
|
|
|
// Clear out results so we don't get duplicate warnings on
|
|
// next call...
|
|
Ts.clear();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private:
|
|
std::set<const T*> Ts;
|
|
const T* Cache;
|
|
const char* const Name;
|
|
};
|
|
|
|
typedef LeakDetectorImpl<void> Objects;
|
|
typedef LeakDetectorImpl<Value> LLVMObjects;
|
|
|
|
Objects& getObjects() {
|
|
static Objects o("GENERIC");
|
|
return o;
|
|
}
|
|
|
|
LLVMObjects& getLLVMObjects() {
|
|
static LLVMObjects o("LLVM");
|
|
return o;
|
|
}
|
|
}
|
|
|
|
void LeakDetector::addGarbageObjectImpl(void *Object) {
|
|
getObjects().addGarbage(Object);
|
|
}
|
|
|
|
void LeakDetector::addGarbageObjectImpl(const Value *Object) {
|
|
getLLVMObjects().addGarbage(Object);
|
|
}
|
|
|
|
void LeakDetector::removeGarbageObjectImpl(void *Object) {
|
|
getObjects().removeGarbage(Object);
|
|
}
|
|
|
|
void LeakDetector::removeGarbageObjectImpl(const Value *Object) {
|
|
getLLVMObjects().removeGarbage(Object);
|
|
}
|
|
|
|
void LeakDetector::checkForGarbageImpl(const std::string &Message) {
|
|
// use non-short-circuit version so that both checks are performed
|
|
if (getObjects().hasGarbage(Message) |
|
|
getLLVMObjects().hasGarbage(Message))
|
|
std::cerr << "\nThis is probably because you removed an object, but didn't "
|
|
"delete it. Please check your code for memory leaks.\n";
|
|
}
|