Newer
Older
Ted Kremenek
committed
//== MemRegion.cpp - Abstract memory regions for static analysis --*- 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 MemRegion and its subclasses. MemRegion defines a
// partially-typed abstraction of memory useful for path-sensitive dataflow
// analyses.
//
//===----------------------------------------------------------------------===//
#include "llvm/Support/raw_ostream.h"
#include "clang/Analysis/PathSensitive/MemRegion.h"
using namespace clang;
Ted Kremenek
committed
//===----------------------------------------------------------------------===//
// Basic methods.
//===----------------------------------------------------------------------===//
Ted Kremenek
committed
MemRegion::~MemRegion() {}
bool SubRegion::isSubRegionOf(const MemRegion* R) const {
const MemRegion* r = getSuperRegion();
while (r != 0) {
if (r == R)
return true;
if (const SubRegion* sr = dyn_cast<SubRegion>(r))
r = sr->getSuperRegion();
else
break;
}
return false;
}
Ted Kremenek
committed
void MemSpaceRegion::Profile(llvm::FoldingSetNodeID& ID) const {
ID.AddInteger((unsigned)getKind());
}
void StringRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
const StringLiteral* Str,
const MemRegion* superRegion) {
ID.AddInteger((unsigned) StringRegionKind);
ID.AddPointer(Str);
ID.AddPointer(superRegion);
}
void AllocaRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
const Expr* Ex, unsigned cnt) {
ID.AddInteger((unsigned) AllocaRegionKind);
ID.AddPointer(Ex);
ID.AddInteger(cnt);
}
void AllocaRegion::Profile(llvm::FoldingSetNodeID& ID) const {
ProfileRegion(ID, Ex, Cnt);
}
void TypedViewRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, QualType T,
const MemRegion* superRegion) {
ID.AddInteger((unsigned) TypedViewRegionKind);
ID.Add(T);
ID.AddPointer(superRegion);
}
Ted Kremenek
committed
void CompoundLiteralRegion::Profile(llvm::FoldingSetNodeID& ID) const {
CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion);
}
void CompoundLiteralRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
const CompoundLiteralExpr* CL,
const MemRegion* superRegion) {
ID.AddInteger((unsigned) CompoundLiteralRegionKind);
ID.AddPointer(CL);
ID.AddPointer(superRegion);
}
Ted Kremenek
committed
void DeclRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl* D,
const MemRegion* superRegion, Kind k) {
ID.AddInteger((unsigned) k);
ID.AddPointer(D);
ID.AddPointer(superRegion);
}
void DeclRegion::Profile(llvm::FoldingSetNodeID& ID) const {
DeclRegion::ProfileRegion(ID, D, superRegion, getKind());
}
Ted Kremenek
committed
void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym,
const MemRegion *sreg) {
ID.AddInteger((unsigned) MemRegion::SymbolicRegionKind);
Ted Kremenek
committed
ID.Add(sym);
Ted Kremenek
committed
ID.AddPointer(sreg);
}
void SymbolicRegion::Profile(llvm::FoldingSetNodeID& ID) const {
Ted Kremenek
committed
SymbolicRegion::ProfileRegion(ID, sym, getSuperRegion());
}
void ElementRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
QualType ElementType, SVal Idx,
const MemRegion* superRegion) {
ID.AddInteger(MemRegion::ElementRegionKind);
ID.Add(ElementType);
ID.AddPointer(superRegion);
Idx.Profile(ID);
}
void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const {
ElementRegion::ProfileRegion(ID, ElementType, Index, superRegion);
Zhongxing Xu
committed
void CodeTextRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const void* data,
QualType t) {
ID.AddInteger(MemRegion::CodeTextRegionKind);
ID.AddPointer(data);
ID.Add(t);
}
void CodeTextRegion::Profile(llvm::FoldingSetNodeID& ID) const {
CodeTextRegion::ProfileRegion(ID, Data, LocationType);
}
Ted Kremenek
committed
//===----------------------------------------------------------------------===//
// Region pretty-printing.
//===----------------------------------------------------------------------===//
std::string MemRegion::getString() const {
std::string s;
llvm::raw_string_ostream os(s);
print(os);
return os.str();
}
void MemRegion::print(llvm::raw_ostream& os) const {
os << "<Unknown Region>";
}
void AllocaRegion::print(llvm::raw_ostream& os) const {
os << "alloca{" << (void*) Ex << ',' << Cnt << '}';
}
Ted Kremenek
committed
void CodeTextRegion::print(llvm::raw_ostream& os) const {
os << "code{";
if (isDeclared())
Ted Kremenek
committed
os << getDecl()->getDeclName().getAsString();
Ted Kremenek
committed
else
os << '$' << getSymbol();
os << '}';
}
Ted Kremenek
committed
void CompoundLiteralRegion::print(llvm::raw_ostream& os) const {
// FIXME: More elaborate pretty-printing.
os << "{ " << (void*) CL << " }";
Ted Kremenek
committed
}
Ted Kremenek
committed
void ElementRegion::print(llvm::raw_ostream& os) const {
superRegion->print(os);
os << '['; Index.print(os); os << ']';
}
void FieldRegion::print(llvm::raw_ostream& os) const {
superRegion->print(os);
os << "->" << getDecl()->getNameAsString();
Ted Kremenek
committed
void StringRegion::print(llvm::raw_ostream& os) const {
Str->printPretty(os);
Ted Kremenek
committed
void SymbolicRegion::print(llvm::raw_ostream& os) const {
os << "SymRegion-" << sym;
Ted Kremenek
committed
}
Ted Kremenek
committed
void TypedViewRegion::print(llvm::raw_ostream& os) const {
os << "typed_view{" << LValueType.getAsString() << ',';
getSuperRegion()->print(os);
os << '}';
}
void VarRegion::print(llvm::raw_ostream& os) const {
os << cast<VarDecl>(D)->getNameAsString();
Ted Kremenek
committed
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
//===----------------------------------------------------------------------===//
// MemRegionManager methods.
//===----------------------------------------------------------------------===//
MemSpaceRegion* MemRegionManager::LazyAllocate(MemSpaceRegion*& region) {
if (!region) {
region = (MemSpaceRegion*) A.Allocate<MemSpaceRegion>();
new (region) MemSpaceRegion();
}
return region;
}
MemSpaceRegion* MemRegionManager::getStackRegion() {
return LazyAllocate(stack);
}
MemSpaceRegion* MemRegionManager::getGlobalsRegion() {
return LazyAllocate(globals);
}
MemSpaceRegion* MemRegionManager::getHeapRegion() {
return LazyAllocate(heap);
}
MemSpaceRegion* MemRegionManager::getUnknownRegion() {
return LazyAllocate(unknown);
}
MemSpaceRegion* MemRegionManager::getCodeRegion() {
return LazyAllocate(code);
}
bool MemRegionManager::onStack(const MemRegion* R) {
while (const SubRegion* SR = dyn_cast<SubRegion>(R))
R = SR->getSuperRegion();
return (R != 0) && (R == stack);
}
bool MemRegionManager::onHeap(const MemRegion* R) {
while (const SubRegion* SR = dyn_cast<SubRegion>(R))
R = SR->getSuperRegion();
return (R != 0) && (R == heap);
}
Ted Kremenek
committed
//===----------------------------------------------------------------------===//
// Constructing regions.
//===----------------------------------------------------------------------===//
Ted Kremenek
committed
StringRegion* MemRegionManager::getStringRegion(const StringLiteral* Str) {
return getRegion<StringRegion>(Str);
VarRegion* MemRegionManager::getVarRegion(const VarDecl* d) {
Ted Kremenek
committed
return getRegion<VarRegion>(d);
Ted Kremenek
committed
}
Ted Kremenek
committed
CompoundLiteralRegion*
MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr* CL) {
Ted Kremenek
committed
return getRegion<CompoundLiteralRegion>(CL);
Ted Kremenek
committed
}
ElementRegion*
MemRegionManager::getElementRegion(QualType elementType, SVal Idx,
Zhongxing Xu
committed
const MemRegion* superRegion, ASTContext& Ctx){
QualType T = Ctx.getCanonicalType(elementType);
llvm::FoldingSetNodeID ID;
Zhongxing Xu
committed
ElementRegion::ProfileRegion(ID, T, Idx, superRegion);
void* InsertPos;
MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
ElementRegion* R = cast_or_null<ElementRegion>(data);
if (!R) {
R = (ElementRegion*) A.Allocate<ElementRegion>();
Zhongxing Xu
committed
new (R) ElementRegion(T, Idx, superRegion);
Regions.InsertNode(R, InsertPos);
}
return R;
}
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
CodeTextRegion* MemRegionManager::getCodeTextRegion(const FunctionDecl* fd,
QualType t) {
llvm::FoldingSetNodeID ID;
CodeTextRegion::ProfileRegion(ID, fd, t);
void* InsertPos;
MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
CodeTextRegion* R = cast_or_null<CodeTextRegion>(data);
if (!R) {
R = (CodeTextRegion*) A.Allocate<CodeTextRegion>();
new (R) CodeTextRegion(fd, t, getCodeRegion());
Regions.InsertNode(R, InsertPos);
}
return R;
}
CodeTextRegion* MemRegionManager::getCodeTextRegion(SymbolRef sym, QualType t) {
llvm::FoldingSetNodeID ID;
CodeTextRegion::ProfileRegion(ID, sym, t);
void* InsertPos;
MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
CodeTextRegion* R = cast_or_null<CodeTextRegion>(data);
if (!R) {
R = (CodeTextRegion*) A.Allocate<CodeTextRegion>();
new (R) CodeTextRegion(sym, t, getCodeRegion());
Regions.InsertNode(R, InsertPos);
}
return R;
}
/// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
Ted Kremenek
committed
SymbolicRegion* MemRegionManager::getSymbolicRegion(SymbolRef sym) {
Ted Kremenek
committed
return getRegion<SymbolicRegion>(sym);
}
Ted Kremenek
committed
FieldRegion* MemRegionManager::getFieldRegion(const FieldDecl* d,
const MemRegion* superRegion) {
Ted Kremenek
committed
return getRegion<FieldRegion>(d, superRegion);
Ted Kremenek
committed
}
ObjCIvarRegion*
MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl* d,
const MemRegion* superRegion) {
Ted Kremenek
committed
return getRegion<ObjCIvarRegion>(d, superRegion);
Ted Kremenek
committed
}
Ted Kremenek
committed
ObjCObjectRegion*
MemRegionManager::getObjCObjectRegion(const ObjCInterfaceDecl* d,
const MemRegion* superRegion) {
llvm::FoldingSetNodeID ID;
DeclRegion::ProfileRegion(ID, d, superRegion,
MemRegion::ObjCObjectRegionKind);
void* InsertPos;
MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
ObjCObjectRegion* R = cast_or_null<ObjCObjectRegion>(data);
if (!R) {
R = (ObjCObjectRegion*) A.Allocate<ObjCObjectRegion>();
new (R) ObjCObjectRegion(d, superRegion);
Regions.InsertNode(R, InsertPos);
}
return R;
}
TypedViewRegion*
MemRegionManager::getTypedViewRegion(QualType t, const MemRegion* superRegion) {
llvm::FoldingSetNodeID ID;
TypedViewRegion::ProfileRegion(ID, t, superRegion);
void* InsertPos;
MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
TypedViewRegion* R = cast_or_null<TypedViewRegion>(data);
if (!R) {
R = (TypedViewRegion*) A.Allocate<TypedViewRegion>();
new (R) TypedViewRegion(t, superRegion);
Regions.InsertNode(R, InsertPos);
}
return R;
}
Ted Kremenek
committed
AllocaRegion* MemRegionManager::getAllocaRegion(const Expr* E, unsigned cnt) {
llvm::FoldingSetNodeID ID;
AllocaRegion::ProfileRegion(ID, E, cnt);
void* InsertPos;
MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
AllocaRegion* R = cast_or_null<AllocaRegion>(data);
if (!R) {
R = (AllocaRegion*) A.Allocate<AllocaRegion>();
new (R) AllocaRegion(E, cnt, getStackRegion());
Regions.InsertNode(R, InsertPos);
}
return R;
}
Ted Kremenek
committed
bool MemRegionManager::hasStackStorage(const MemRegion* R) {
// Only subregions can have stack storage.
const SubRegion* SR = dyn_cast<SubRegion>(R);
if (!SR)
return false;
Ted Kremenek
committed
MemSpaceRegion* S = getStackRegion();
while (SR) {
R = SR->getSuperRegion();
if (R == S)
return true;
SR = dyn_cast<SubRegion>(R);
Ted Kremenek
committed
}
Ted Kremenek
committed
Ted Kremenek
committed
return false;
}
Ted Kremenek
committed
//===----------------------------------------------------------------------===//
// View handling.
//===----------------------------------------------------------------------===//
const MemRegion *TypedViewRegion::removeViews() const {
const SubRegion *SR = this;
const MemRegion *R = SR;
while (SR && isa<TypedViewRegion>(SR)) {
R = SR->getSuperRegion();
SR = dyn_cast<SubRegion>(R);
}
return R;
}