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 "clang/Checker/PathSensitive/MemRegion.h"
#include "clang/Checker/PathSensitive/ValueManager.h"
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/Support/BumpVector.h"
#include "clang/AST/CharUnits.h"
#include "llvm/Support/raw_ostream.h"
Ted Kremenek
committed
using namespace clang;
Ted Kremenek
committed
//===----------------------------------------------------------------------===//
// MemRegion Construction.
//===----------------------------------------------------------------------===//
template<typename RegionTy> struct MemRegionManagerTrait;
template <typename RegionTy, typename A1>
RegionTy* MemRegionManager::getRegion(const A1 a1) {
Ted Kremenek
committed
Ted Kremenek
committed
const typename MemRegionManagerTrait<RegionTy>::SuperRegionTy *superRegion =
MemRegionManagerTrait<RegionTy>::getSuperRegion(*this, a1);
Ted Kremenek
committed
Ted Kremenek
committed
llvm::FoldingSetNodeID ID;
RegionTy::ProfileRegion(ID, a1, superRegion);
void* InsertPos;
RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
InsertPos));
Ted Kremenek
committed
Ted Kremenek
committed
if (!R) {
R = (RegionTy*) A.Allocate<RegionTy>();
new (R) RegionTy(a1, superRegion);
Regions.InsertNode(R, InsertPos);
}
Ted Kremenek
committed
Ted Kremenek
committed
return R;
}
template <typename RegionTy, typename A1>
RegionTy* MemRegionManager::getSubRegion(const A1 a1,
const MemRegion *superRegion) {
llvm::FoldingSetNodeID ID;
RegionTy::ProfileRegion(ID, a1, superRegion);
void* InsertPos;
RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
InsertPos));
Ted Kremenek
committed
Ted Kremenek
committed
if (!R) {
R = (RegionTy*) A.Allocate<RegionTy>();
new (R) RegionTy(a1, superRegion);
Regions.InsertNode(R, InsertPos);
}
Ted Kremenek
committed
Ted Kremenek
committed
return R;
}
template <typename RegionTy, typename A1, typename A2>
RegionTy* MemRegionManager::getRegion(const A1 a1, const A2 a2) {
Ted Kremenek
committed
Ted Kremenek
committed
const typename MemRegionManagerTrait<RegionTy>::SuperRegionTy *superRegion =
MemRegionManagerTrait<RegionTy>::getSuperRegion(*this, a1, a2);
Ted Kremenek
committed
Ted Kremenek
committed
llvm::FoldingSetNodeID ID;
RegionTy::ProfileRegion(ID, a1, a2, superRegion);
void* InsertPos;
RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
InsertPos));
Ted Kremenek
committed
Ted Kremenek
committed
if (!R) {
R = (RegionTy*) A.Allocate<RegionTy>();
new (R) RegionTy(a1, a2, superRegion);
Regions.InsertNode(R, InsertPos);
}
Ted Kremenek
committed
Ted Kremenek
committed
return R;
}
template <typename RegionTy, typename A1, typename A2>
RegionTy* MemRegionManager::getSubRegion(const A1 a1, const A2 a2,
const MemRegion *superRegion) {
Ted Kremenek
committed
Ted Kremenek
committed
llvm::FoldingSetNodeID ID;
RegionTy::ProfileRegion(ID, a1, a2, superRegion);
void* InsertPos;
RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
InsertPos));
Ted Kremenek
committed
Ted Kremenek
committed
if (!R) {
R = (RegionTy*) A.Allocate<RegionTy>();
new (R) RegionTy(a1, a2, superRegion);
Regions.InsertNode(R, InsertPos);
}
Ted Kremenek
committed
Ted Kremenek
committed
return R;
}
template <typename RegionTy, typename A1, typename A2, typename A3>
RegionTy* MemRegionManager::getSubRegion(const A1 a1, const A2 a2, const A3 a3,
const MemRegion *superRegion) {
Ted Kremenek
committed
llvm::FoldingSetNodeID ID;
RegionTy::ProfileRegion(ID, a1, a2, a3, superRegion);
void* InsertPos;
RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
InsertPos));
Ted Kremenek
committed
if (!R) {
R = (RegionTy*) A.Allocate<RegionTy>();
new (R) RegionTy(a1, a2, a3, superRegion);
Regions.InsertNode(R, InsertPos);
Ted Kremenek
committed
}
Ted Kremenek
committed
return R;
}
Ted Kremenek
committed
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);
}
const StackFrameContext *VarRegion::getStackFrame() const {
const StackSpaceRegion *SSR = dyn_cast<StackSpaceRegion>(getMemorySpace());
return SSR ? SSR->getStackFrame() : NULL;
}
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
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
216
217
218
219
//===----------------------------------------------------------------------===//
// Region extents.
//===----------------------------------------------------------------------===//
DefinedOrUnknownSVal DeclRegion::getExtent(ValueManager& ValMgr) const {
ASTContext& Ctx = ValMgr.getContext();
QualType T = getDesugaredValueType(Ctx);
// FIXME: Handle variable-length arrays.
if (isa<VariableArrayType>(T) || isa<IncompleteArrayType>(T))
return UnknownVal();
CharUnits Size = Ctx.getTypeSizeInChars(T);
QualType SizeTy = Ctx.getSizeType();
return ValMgr.makeIntVal(Size.getQuantity(), SizeTy);
}
DefinedOrUnknownSVal FieldRegion::getExtent(ValueManager& ValMgr) const {
DefinedOrUnknownSVal Extent = DeclRegion::getExtent(ValMgr);
// A zero-length array at the end of a struct often stands for dynamically-
// allocated extra memory.
if (Extent.isZeroConstant()) {
ASTContext& Ctx = ValMgr.getContext();
QualType T = getDesugaredValueType(Ctx);
if (isa<ConstantArrayType>(T))
return UnknownVal();
}
return Extent;
}
DefinedOrUnknownSVal AllocaRegion::getExtent(ValueManager& ValMgr) const {
return nonloc::SymbolVal(ValMgr.getSymbolManager().getExtentSymbol(this));
}
DefinedOrUnknownSVal SymbolicRegion::getExtent(ValueManager& ValMgr) const {
return nonloc::SymbolVal(ValMgr.getSymbolManager().getExtentSymbol(this));
}
DefinedOrUnknownSVal StringRegion::getExtent(ValueManager& ValMgr) const {
QualType SizeTy = ValMgr.getContext().getSizeType();
return ValMgr.makeIntVal(getStringLiteral()->getByteLength()+1, SizeTy);
}
//===----------------------------------------------------------------------===//
// FoldingSet profiling.
//===----------------------------------------------------------------------===//
Ted Kremenek
committed
void MemSpaceRegion::Profile(llvm::FoldingSetNodeID& ID) const {
ID.AddInteger((unsigned)getKind());
}
void StackSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const {
ID.AddInteger((unsigned)getKind());
ID.AddPointer(getStackFrame());
}
Ted Kremenek
committed
void StaticGlobalSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const {
ID.AddInteger((unsigned)getKind());
ID.AddPointer(getCodeRegion());
}
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 CXXThisRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
const PointerType *PT,
const MemRegion *sRegion) {
ID.AddInteger((unsigned) CXXThisRegionKind);
ID.AddPointer(PT);
ID.AddPointer(sRegion);
}
void CXXThisRegion::Profile(llvm::FoldingSetNodeID &ID) const {
CXXThisRegion::ProfileRegion(ID, ThisPointerTy, superRegion);
}
Ted Kremenek
committed
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(), superRegion);
Ted Kremenek
committed
}
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 AnalysisContext *AC,
const MemRegion*) {
ID.AddInteger(MemRegion::BlockTextRegionKind);
ID.AddPointer(BD);
}
void BlockTextRegion::Profile(llvm::FoldingSetNodeID& ID) const {
BlockTextRegion::ProfileRegion(ID, BD, locTy, AC, superRegion);
void BlockDataRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
const BlockTextRegion *BC,
const LocationContext *LC,
const MemRegion *sReg) {
ID.AddInteger(MemRegion::BlockDataRegionKind);
ID.AddPointer(BC);
ID.AddPointer(LC);
ID.AddPointer(sReg);
}
void BlockDataRegion::Profile(llvm::FoldingSetNodeID& ID) const {
BlockDataRegion::ProfileRegion(ID, BC, LC, getSuperRegion());
void CXXObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
Expr const *Ex,
const MemRegion *sReg) {
ID.AddPointer(Ex);
ID.AddPointer(sReg);
}
void CXXObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const {
ProfileRegion(ID, Ex, getSuperRegion());
}
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
}
Ted Kremenek
committed
void CXXThisRegion::dumpToStream(llvm::raw_ostream &os) const {
os << "this";
}
void ElementRegion::dumpToStream(llvm::raw_ostream& os) const {
os << "element{" << superRegion << ','
<< Index << ',' << getElementType().getAsString() << '}';
}
void FieldRegion::dumpToStream(llvm::raw_ostream& os) const {
Benjamin Kramer
committed
os << superRegion << "->" << getDecl();
void ObjCIvarRegion::dumpToStream(llvm::raw_ostream& os) const {
Benjamin Kramer
committed
os << "ivar{" << superRegion << ',' << getDecl() << '}';
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 {
Benjamin Kramer
committed
os << cast<VarDecl>(D);
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.
//===----------------------------------------------------------------------===//
template <typename REG>
const REG *MemRegionManager::LazyAllocate(REG*& region) {
region = (REG*) A.Allocate<REG>();
new (region) REG(this);
Ted Kremenek
committed
}
Ted Kremenek
committed
return region;
}
template <typename REG, typename ARG>
const REG *MemRegionManager::LazyAllocate(REG*& region, ARG a) {
if (!region) {
region = (REG*) A.Allocate<REG>();
new (region) REG(this, a);
}
Ted Kremenek
committed
return region;
}
const StackLocalsSpaceRegion*
Ted Kremenek
committed
MemRegionManager::getStackLocalsRegion(const StackFrameContext *STC) {
assert(STC);
Zhongxing Xu
committed
StackLocalsSpaceRegion *&R = StackLocalsSpaceRegions[STC];
if (R)
return R;
R = A.Allocate<StackLocalsSpaceRegion>();
new (R) StackLocalsSpaceRegion(this, STC);
return R;
Ted Kremenek
committed
}
const StackArgumentsSpaceRegion *
MemRegionManager::getStackArgumentsRegion(const StackFrameContext *STC) {
Ted Kremenek
committed
assert(STC);
Zhongxing Xu
committed
StackArgumentsSpaceRegion *&R = StackArgumentsSpaceRegions[STC];
if (R)
return R;
R = A.Allocate<StackArgumentsSpaceRegion>();
new (R) StackArgumentsSpaceRegion(this, STC);
return R;
Ted Kremenek
committed
}
Ted Kremenek
committed
const GlobalsSpaceRegion
*MemRegionManager::getGlobalsRegion(const CodeTextRegion *CR) {
if (!CR)
return LazyAllocate(globals);
StaticGlobalSpaceRegion *&R = StaticsGlobalSpaceRegions[CR];
if (R)
return R;
R = A.Allocate<StaticGlobalSpaceRegion>();
new (R) StaticGlobalSpaceRegion(this, CR);
return R;
Ted Kremenek
committed
}
const HeapSpaceRegion *MemRegionManager::getHeapRegion() {
Ted Kremenek
committed
return LazyAllocate(heap);
}
const MemSpaceRegion *MemRegionManager::getUnknownRegion() {
return LazyAllocate(unknown);
}
const MemSpaceRegion *MemRegionManager::getCodeRegion() {
Ted Kremenek
committed
//===----------------------------------------------------------------------===//
// Constructing regions.
//===----------------------------------------------------------------------===//
Ted Kremenek
committed
const StringRegion* MemRegionManager::getStringRegion(const StringLiteral* Str){
return getSubRegion<StringRegion>(Str, getGlobalsRegion());
const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D,
const LocationContext *LC) {
const MemRegion *sReg = 0;
Ted Kremenek
committed
if (D->hasGlobalStorage() && !D->isStaticLocal())
sReg = getGlobalsRegion();
else {
// FIXME: Once we implement scope handling, we will need to properly lookup
// 'D' to the proper LocationContext.
Ted Kremenek
committed
const DeclContext *DC = D->getDeclContext();
const StackFrameContext *STC = LC->getStackFrameForDeclContext(DC);
if (!STC)
sReg = getUnknownRegion();
else {
Ted Kremenek
committed
if (D->hasLocalStorage()) {
sReg = isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)
? static_cast<const MemRegion*>(getStackArgumentsRegion(STC))
: static_cast<const MemRegion*>(getStackLocalsRegion(STC));
}
else {
assert(D->isStaticLocal());
const Decl *D = STC->getDecl();
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
sReg = getGlobalsRegion(getFunctionTextRegion(FD));
else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
const BlockTextRegion *BTR =
getBlockTextRegion(BD,
C.getCanonicalType(BD->getSignatureAsWritten()->getType()),
STC->getAnalysisContext());
sReg = getGlobalsRegion(BTR);
}
else {
// FIXME: For ObjC-methods, we need a new CodeTextRegion. For now
// just use the main global memspace.
sReg = getGlobalsRegion();
}
}
Ted Kremenek
committed
}
Ted Kremenek
committed
return getSubRegion<VarRegion>(D, sReg);
}
const VarRegion *MemRegionManager::getVarRegion(const VarDecl *D,
const MemRegion *superR) {
return getSubRegion<VarRegion>(D, superR);
Ted Kremenek
committed
}
const BlockDataRegion *
MemRegionManager::getBlockDataRegion(const BlockTextRegion *BC,
const LocationContext *LC) {
const MemRegion *sReg = 0;
Ted Kremenek
committed
if (LC) {
// FIXME: Once we implement scope handling, we want the parent region
Ted Kremenek
committed
// to be the scope.
const StackFrameContext *STC = LC->getCurrentStackFrame();
assert(STC);
sReg = getStackLocalsRegion(STC);
}
else {
// We allow 'LC' to be NULL for cases where want BlockDataRegions
// without context-sensitivity.
sReg = getUnknownRegion();
}
return getSubRegion<BlockDataRegion>(BC, LC, sReg);
const CompoundLiteralRegion*
MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr* CL,
const LocationContext *LC) {
Ted Kremenek
committed
const MemRegion *sReg = 0;
Ted Kremenek
committed
if (CL->isFileScope())
sReg = getGlobalsRegion();
else {
const StackFrameContext *STC = LC->getCurrentStackFrame();
assert(STC);
sReg = getStackLocalsRegion(STC);
}
Ted Kremenek
committed
return getSubRegion<CompoundLiteralRegion>(CL, sReg);
Ted Kremenek
committed
}
const ElementRegion*
MemRegionManager::getElementRegion(QualType elementType, SVal Idx,
const MemRegion* superRegion,
ASTContext& Ctx){
Zhongxing Xu
committed
Ted Kremenek
committed
QualType T = Ctx.getCanonicalType(elementType).getUnqualifiedType();
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;
}
const FunctionTextRegion *
MemRegionManager::getFunctionTextRegion(const FunctionDecl *FD) {
return getSubRegion<FunctionTextRegion>(FD, getCodeRegion());
const BlockTextRegion *
MemRegionManager::getBlockTextRegion(const BlockDecl *BD, CanQualType locTy,
AnalysisContext *AC) {
return getSubRegion<BlockTextRegion>(BD, locTy, AC, getCodeRegion());
}
/// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
const SymbolicRegion *MemRegionManager::getSymbolicRegion(SymbolRef sym) {
return getSubRegion<SymbolicRegion>(sym, getUnknownRegion());
}
Ted Kremenek
committed
const FieldRegion*
MemRegionManager::getFieldRegion(const FieldDecl* d,
const MemRegion* superRegion){
Ted Kremenek
committed
return getSubRegion<FieldRegion>(d, superRegion);
Ted Kremenek
committed
}
const ObjCIvarRegion*
MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl* d,
const MemRegion* superRegion) {
Ted Kremenek
committed
return getSubRegion<ObjCIvarRegion>(d, superRegion);
Ted Kremenek
committed
}
Ted Kremenek
committed
const CXXObjectRegion*
MemRegionManager::getCXXObjectRegion(Expr const *E,
LocationContext const *LC) {
const StackFrameContext *SFC = LC->getCurrentStackFrame();
assert(SFC);
return getSubRegion<CXXObjectRegion>(E, getStackLocalsRegion(SFC));
}
Ted Kremenek
committed
const CXXThisRegion*
MemRegionManager::getCXXThisRegion(QualType thisPointerTy,
const LocationContext *LC) {
const StackFrameContext *STC = LC->getCurrentStackFrame();
assert(STC);
const PointerType *PT = thisPointerTy->getAs<PointerType>();
assert(PT);
return getSubRegion<CXXThisRegion>(PT, getStackArgumentsRegion(STC));
}
const AllocaRegion*
MemRegionManager::getAllocaRegion(const Expr* E, unsigned cnt,
const LocationContext *LC) {
const StackFrameContext *STC = LC->getCurrentStackFrame();
assert(STC);
return getSubRegion<AllocaRegion>(E, cnt, getStackLocalsRegion(STC));
}
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 {
return isa<StackSpaceRegion>(getMemorySpace());
Ted Kremenek
committed
bool MemRegion::hasStackNonParametersStorage() const {
return isa<StackLocalsSpaceRegion>(getMemorySpace());
Ted Kremenek
committed
}
Ted Kremenek
committed
bool MemRegion::hasStackParametersStorage() const {
return isa<StackArgumentsSpaceRegion>(getMemorySpace());
}
Ted Kremenek
committed
bool MemRegion::hasGlobalsOrParametersStorage() const {
const MemSpaceRegion *MS = getMemorySpace();
return isa<StackArgumentsSpaceRegion>(MS) ||
isa<GlobalsSpaceRegion>(MS);
Ted Kremenek
committed
}
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) {
switch (R->getKind()) {
case MemRegion::ElementRegionKind:
case MemRegion::FieldRegionKind:
case MemRegion::ObjCIvarRegionKind:
R = cast<SubRegion>(R)->getSuperRegion();
continue;
default:
break;
}
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())
return false;
}
return true;
}
RegionRawOffset ElementRegion::getAsRawOffset() const {
CharUnits offset = CharUnits::Zero();
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;
}
CharUnits size = C.getTypeSizeInChars(elemType);
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.getQuantity());
}
//===----------------------------------------------------------------------===//
// BlockDataRegion
//===----------------------------------------------------------------------===//
void BlockDataRegion::LazyInitializeReferencedVars() {
if (ReferencedVars)
return;
AnalysisContext *AC = getCodeRegion()->getAnalysisContext();
AnalysisContext::referenced_decls_iterator I, E;
llvm::tie(I, E) = AC->getReferencedBlockVars(BC->getDecl());
Ted Kremenek
committed
if (I == E) {
ReferencedVars = (void*) 0x1;
return;
}
Ted Kremenek
committed
MemRegionManager &MemMgr = *getMemRegionManager();
llvm::BumpPtrAllocator &A = MemMgr.getAllocator();
BumpVectorContext BC(A);
Ted Kremenek
committed
typedef BumpVector<const MemRegion*> VarVec;
VarVec *BV = (VarVec*) A.Allocate<VarVec>();
new (BV) VarVec(BC, E - I);
Ted Kremenek
committed
for ( ; I != E; ++I) {
const VarDecl *VD = *I;
const VarRegion *VR = 0;
Ted Kremenek
committed
Ted Kremenek
committed
if (!VD->getAttr<BlocksAttr>() && VD->hasLocalStorage())
VR = MemMgr.getVarRegion(VD, this);
else {
if (LC)
VR = MemMgr.getVarRegion(VD, LC);
else {
VR = MemMgr.getVarRegion(VD, MemMgr.getUnknownRegion());
}
}
Ted Kremenek
committed
assert(VR);
BV->push_back(VR, BC);
}
Ted Kremenek
committed
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);
Ted Kremenek
committed
Ted Kremenek
committed
return BlockDataRegion::referenced_vars_iterator(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);
Ted Kremenek
committed
Ted Kremenek
committed
return BlockDataRegion::referenced_vars_iterator(Vec == (void*) 0x1 ?
NULL : Vec->end());