"git@repo.hca.bsc.es:rferrer/llvm-epi-0.8.git" did not exist on "29e4c9192dd136a1acb25d0f1c33fe60d712e38f"
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"
#include "clang/Analysis/PathSensitive/ValueManager.h"
Ted Kremenek
committed
#include "clang/Analysis/PathSensitive/AnalysisContext.h"
#include "clang/AST/StmtVisitor.h"
Ted Kremenek
committed
using namespace clang;
Ted Kremenek
committed
//===----------------------------------------------------------------------===//
// Object destruction.
Ted Kremenek
committed
//===----------------------------------------------------------------------===//
Ted Kremenek
committed
MemRegion::~MemRegion() {}
MemRegionManager::~MemRegionManager() {
// All regions and their data are BumpPtrAllocated. No need to call
// their destructors.
}
//===----------------------------------------------------------------------===//
// Basic methods.
//===----------------------------------------------------------------------===//
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;
}
MemRegionManager* SubRegion::getMemRegionManager() const {
const SubRegion* r = this;
do {
const MemRegion *superRegion = r->getSuperRegion();
if (const SubRegion *sr = dyn_cast<SubRegion>(superRegion)) {
r = sr;
continue;
}
return superRegion->getMemRegionManager();
} while (1);
}
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,
Ted Kremenek
committed
const Expr* Ex, unsigned cnt,
const MemRegion *) {
ID.AddInteger((unsigned) AllocaRegionKind);
ID.AddPointer(Ex);
ID.AddInteger(cnt);
}
void AllocaRegion::Profile(llvm::FoldingSetNodeID& ID) const {
Ted Kremenek
committed
ProfileRegion(ID, Ex, Cnt, 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 VarRegion::Profile(llvm::FoldingSetNodeID &ID) const {
VarRegion::ProfileRegion(ID, getDecl(), LC, superRegion);
}
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,
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 FunctionTextRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
const FunctionDecl *FD,
const MemRegion*) {
ID.AddInteger(MemRegion::FunctionTextRegionKind);
ID.AddPointer(FD);
void FunctionTextRegion::Profile(llvm::FoldingSetNodeID& ID) const {
FunctionTextRegion::ProfileRegion(ID, FD, superRegion);
}
void BlockTextRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
const BlockDecl *BD, CanQualType,
const MemRegion*) {
ID.AddInteger(MemRegion::BlockTextRegionKind);
ID.AddPointer(BD);
}
void BlockTextRegion::Profile(llvm::FoldingSetNodeID& ID) const {
BlockTextRegion::ProfileRegion(ID, BD, locTy, superRegion);
void BlockDataRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
const BlockTextRegion *BC,
const LocationContext *LC,
const MemRegion *) {
ID.AddInteger(MemRegion::BlockDataRegionKind);
ID.AddPointer(BC);
ID.AddPointer(LC);
}
void BlockDataRegion::Profile(llvm::FoldingSetNodeID& ID) const {
BlockDataRegion::ProfileRegion(ID, BC, LC, NULL);
}
Ted Kremenek
committed
//===----------------------------------------------------------------------===//
// Region pretty-printing.
//===----------------------------------------------------------------------===//
void MemRegion::dump() const {
dumpToStream(llvm::errs());
Ted Kremenek
committed
std::string MemRegion::getString() const {
std::string s;
llvm::raw_string_ostream os(s);
dumpToStream(os);
Ted Kremenek
committed
return os.str();
}
void MemRegion::dumpToStream(llvm::raw_ostream& os) const {
Ted Kremenek
committed
os << "<Unknown Region>";
}
void AllocaRegion::dumpToStream(llvm::raw_ostream& os) const {
os << "alloca{" << (void*) Ex << ',' << Cnt << '}';
}
void FunctionTextRegion::dumpToStream(llvm::raw_ostream& os) const {
os << "code{" << getDecl()->getDeclName().getAsString() << '}';
Ted Kremenek
committed
}
void BlockTextRegion::dumpToStream(llvm::raw_ostream& os) const {
os << "block_code{" << (void*) this << '}';
}
void BlockDataRegion::dumpToStream(llvm::raw_ostream& os) const {
os << "block_data{" << BC << '}';
}
void CompoundLiteralRegion::dumpToStream(llvm::raw_ostream& os) const {
Ted Kremenek
committed
// FIXME: More elaborate pretty-printing.
os << "{ " << (void*) CL << " }";
Ted Kremenek
committed
}
void ElementRegion::dumpToStream(llvm::raw_ostream& os) const {
os << "element{" << superRegion << ','
<< Index << ',' << getElementType().getAsString() << '}';
}
void FieldRegion::dumpToStream(llvm::raw_ostream& os) const {
os << superRegion << "->" << getDecl()->getNameAsString();
void ObjCIvarRegion::dumpToStream(llvm::raw_ostream& os) const {
os << "ivar{" << superRegion << ',' << getDecl()->getNameAsString() << '}';
}
void StringRegion::dumpToStream(llvm::raw_ostream& os) const {
Str->printPretty(os, 0, PrintingPolicy(getContext().getLangOptions()));
void SymbolicRegion::dumpToStream(llvm::raw_ostream& os) const {
Ted Kremenek
committed
os << "SymRegion{" << sym << '}';
Ted Kremenek
committed
}
void VarRegion::dumpToStream(llvm::raw_ostream& os) const {
Ted Kremenek
committed
os << cast<VarDecl>(D)->getNameAsString();
void RegionRawOffset::dump() const {
dumpToStream(llvm::errs());
}
void RegionRawOffset::dumpToStream(llvm::raw_ostream& os) const {
os << "raw_offset{" << getRegion() << ',' << getByteOffset() << '}';
}
Ted Kremenek
committed
//===----------------------------------------------------------------------===//
// MemRegionManager methods.
//===----------------------------------------------------------------------===//
MemSpaceRegion* MemRegionManager::LazyAllocate(MemSpaceRegion*& region) {
if (!region) {
Ted Kremenek
committed
region = (MemSpaceRegion*) A.Allocate<MemSpaceRegion>();
Ted Kremenek
committed
}
Ted Kremenek
committed
return region;
}
MemSpaceRegion* MemRegionManager::getStackRegion() {
return LazyAllocate(stack);
}
Ted Kremenek
committed
MemSpaceRegion* MemRegionManager::getStackArgumentsRegion() {
return LazyAllocate(stackArguments);
}
Ted Kremenek
committed
MemSpaceRegion* MemRegionManager::getGlobalsRegion() {
return LazyAllocate(globals);
}
MemSpaceRegion* MemRegionManager::getHeapRegion() {
return LazyAllocate(heap);
}
MemSpaceRegion* MemRegionManager::getUnknownRegion() {
return LazyAllocate(unknown);
}
MemSpaceRegion* MemRegionManager::getCodeRegion() {
return LazyAllocate(code);
}
Ted Kremenek
committed
//===----------------------------------------------------------------------===//
// Constructing regions.
//===----------------------------------------------------------------------===//
Ted Kremenek
committed
StringRegion* MemRegionManager::getStringRegion(const StringLiteral* Str) {
return getRegion<StringRegion>(Str);
Ted Kremenek
committed
VarRegion* MemRegionManager::getVarRegion(const VarDecl *D,
Ted Kremenek
committed
const LocationContext *LC) {
Ted Kremenek
committed
// FIXME: Once we implement scope handling, we will need to properly lookup
// 'D' to the proper LocationContext. For now, just strip down to the
// StackFrame.
while (!isa<StackFrameContext>(LC))
LC = LC->getParent();
Ted Kremenek
committed
return getRegion<VarRegion>(D, LC);
Ted Kremenek
committed
}
BlockDataRegion *MemRegionManager::getBlockDataRegion(const BlockTextRegion *BC,
const LocationContext *LC)
{
// FIXME: Once we implement scope handling, we will need to properly lookup
// 'D' to the proper LocationContext. For now, just strip down to the
// StackFrame.
while (!isa<StackFrameContext>(LC))
LC = LC->getParent();
return getSubRegion<BlockDataRegion>(BC, LC, getStackRegion());
}
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,
const MemRegion* superRegion,
ASTContext& Ctx){
Zhongxing Xu
committed
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;
}
FunctionTextRegion *
MemRegionManager::getFunctionTextRegion(const FunctionDecl *FD) {
return getRegion<FunctionTextRegion>(FD);
BlockTextRegion *MemRegionManager::getBlockTextRegion(const BlockDecl *BD,
CanQualType locTy) {
return getRegion<BlockTextRegion>(BD, locTy);
}
/// 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 getSubRegion<FieldRegion>(d, superRegion);
Ted Kremenek
committed
}
ObjCIvarRegion*
MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl* d,
const MemRegion* superRegion) {
Ted Kremenek
committed
return getSubRegion<ObjCIvarRegion>(d, superRegion);
Ted Kremenek
committed
}
Ted Kremenek
committed
ObjCObjectRegion*
MemRegionManager::getObjCObjectRegion(const ObjCInterfaceDecl* d,
Ted Kremenek
committed
const MemRegion* superRegion) {
Ted Kremenek
committed
return getSubRegion<ObjCObjectRegion>(d, superRegion);
Ted Kremenek
committed
}
AllocaRegion* MemRegionManager::getAllocaRegion(const Expr* E, unsigned cnt) {
Ted Kremenek
committed
return getRegion<AllocaRegion>(E, cnt);
}
const MemSpaceRegion *MemRegion::getMemorySpace() const {
const MemRegion *R = this;
const SubRegion* SR = dyn_cast<SubRegion>(this);
while (SR) {
R = SR->getSuperRegion();
SR = dyn_cast<SubRegion>(R);
Ted Kremenek
committed
}
Ted Kremenek
committed
}
Ted Kremenek
committed
bool MemRegion::hasStackStorage() const {
Ted Kremenek
committed
if (const MemSpaceRegion *MS = getMemorySpace()) {
MemRegionManager *Mgr = getMemRegionManager();
return MS == Mgr->getStackRegion() || MS == Mgr->getStackArgumentsRegion();
}
bool MemRegion::hasHeapStorage() const {
if (const MemSpaceRegion *MS = getMemorySpace())
return MS == getMemRegionManager()->getHeapRegion();
bool MemRegion::hasHeapOrStackStorage() const {
if (const MemSpaceRegion *MS = getMemorySpace()) {
MemRegionManager *Mgr = getMemRegionManager();
Ted Kremenek
committed
return MS == Mgr->getHeapRegion()
|| MS == Mgr->getStackRegion()
|| MS == Mgr->getStackArgumentsRegion();
Ted Kremenek
committed
}
bool MemRegion::hasGlobalsStorage() const {
if (const MemSpaceRegion *MS = getMemorySpace())
return MS == getMemRegionManager()->getGlobalsRegion();
return false;
}
bool MemRegion::hasParametersStorage() const {
if (const MemSpaceRegion *MS = getMemorySpace())
return MS == getMemRegionManager()->getStackArgumentsRegion();
return false;
}
Ted Kremenek
committed
bool MemRegion::hasGlobalsOrParametersStorage() const {
if (const MemSpaceRegion *MS = getMemorySpace()) {
MemRegionManager *Mgr = getMemRegionManager();
return MS == Mgr->getGlobalsRegion()
|| MS == Mgr->getStackArgumentsRegion();
}
return false;
}
Ted Kremenek
committed
// getBaseRegion strips away all elements and fields, and get the base region
// of them.
const MemRegion *MemRegion::getBaseRegion() const {
const MemRegion *R = this;
while (true) {
if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
R = ER->getSuperRegion();
continue;
}
if (const FieldRegion *FR = dyn_cast<FieldRegion>(R)) {
R = FR->getSuperRegion();
continue;
}
break;
}
return R;
}
Ted Kremenek
committed
//===----------------------------------------------------------------------===//
// View handling.
//===----------------------------------------------------------------------===//
const MemRegion *MemRegion::StripCasts() const {
Ted Kremenek
committed
const MemRegion *R = this;
while (true) {
if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
Ted Kremenek
committed
// FIXME: generalize. Essentially we want to strip away ElementRegions
// that were layered on a symbolic region because of casts. We only
// want to strip away ElementRegions, however, where the index is 0.
SVal index = ER->getIndex();
if (nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&index)) {
if (CI->getValue().getSExtValue() == 0) {
Ted Kremenek
committed
R = ER->getSuperRegion();
continue;
}
}
}
break;
}
return R;
}
// FIXME: Merge with the implementation of the same method in Store.cpp
static bool IsCompleteType(ASTContext &Ctx, QualType Ty) {
if (const RecordType *RT = Ty->getAs<RecordType>()) {
const RecordDecl *D = RT->getDecl();
if (!D->getDefinition(Ctx))
return false;
}
return true;
}
RegionRawOffset ElementRegion::getAsRawOffset() const {
int64_t offset = 0;
const ElementRegion *ER = this;
const MemRegion *superR = NULL;
ASTContext &C = getContext();
// FIXME: Handle multi-dimensional arrays.
while (ER) {
superR = ER->getSuperRegion();
// FIXME: generalize to symbolic offsets.
SVal index = ER->getIndex();
if (nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&index)) {
// Update the offset.
int64_t i = CI->getValue().getSExtValue();
if (i != 0) {
QualType elemType = ER->getElementType();
// If we are pointing to an incomplete type, go no further.
if (!IsCompleteType(C, elemType)) {
superR = ER;
break;
}
int64_t size = (int64_t) (C.getTypeSize(elemType) / 8);
offset += (i * size);
}
// Go to the next ElementRegion (if any).
ER = dyn_cast<ElementRegion>(superR);
continue;
}
return NULL;
}
assert(superR && "super region cannot be NULL");
return RegionRawOffset(superR, offset);
}
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
//===----------------------------------------------------------------------===//
// BlockDataRegion
//===----------------------------------------------------------------------===//
void BlockDataRegion::LazyInitializeReferencedVars() {
if (ReferencedVars)
return;
AnalysisContext *AC = LC->getAnalysisContext();
AnalysisContext::referenced_decls_iterator I, E;
llvm::tie(I, E) = AC->getReferencedBlockVars(BC->getDecl());
if (I == E) {
ReferencedVars = (void*) 0x1;
return;
}
MemRegionManager &MemMgr = *getMemRegionManager();
llvm::BumpPtrAllocator &A = MemMgr.getAllocator();
BumpVectorContext BC(A);
typedef BumpVector<const MemRegion*> VarVec;
VarVec *BV = (VarVec*) A.Allocate<VarVec>();
new (BV) VarVec(BC, (E - I) / sizeof(*I));
for ( ; I != E; ++I)
BV->push_back(MemMgr.getVarRegion(*I, LC), BC);
ReferencedVars = BV;
}
BlockDataRegion::referenced_vars_iterator
BlockDataRegion::referenced_vars_begin() const {
const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars();
BumpVector<const MemRegion*> *Vec =
static_cast<BumpVector<const MemRegion*>*>(ReferencedVars);
return Vec == (void*) 0x1 ? NULL : Vec->begin();
}
BlockDataRegion::referenced_vars_iterator
BlockDataRegion::referenced_vars_end() const {
const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars();
BumpVector<const MemRegion*> *Vec =
static_cast<BumpVector<const MemRegion*>*>(ReferencedVars);
return Vec == (void*) 0x1 ? NULL : Vec->end();
}