Split CodeTextRegion into FunctionTextRegion and BlockTextRegion. This a precursor to having basic static analysis support for blocks.

llvm-svn: 89828
This commit is contained in:
Ted Kremenek 2009-11-25 01:32:22 +00:00
parent 906d871e6c
commit 10a50e7371
8 changed files with 115 additions and 39 deletions

View File

@ -48,7 +48,8 @@ public:
AllocaRegionKind,
// Typed regions.
BEG_TYPED_REGIONS,
CodeTextRegionKind,
FunctionTextRegionKind,
BlockTextRegionKind,
CompoundLiteralRegionKind,
StringRegionKind, ElementRegionKind,
// Decl Regions.
@ -237,43 +238,78 @@ public:
}
};
/// CodeTextRegion - A region that represents code texts of a function. It wraps
/// two kinds of code texts: real function and symbolic function. Real function
/// is a function declared in the program. Symbolic function is a function
/// pointer that we don't know which function it points to.
class CodeTextRegion : public TypedRegion {
const FunctionDecl *FD;
protected:
CodeTextRegion(const MemRegion *sreg, Kind k) : TypedRegion(sreg, k) {}
public:
CodeTextRegion(const FunctionDecl* fd, const MemRegion* sreg)
: TypedRegion(sreg, CodeTextRegionKind), FD(fd) {}
QualType getValueType(ASTContext &C) const {
// Do not get the object type of a CodeTextRegion.
assert(0);
return QualType();
}
bool isBoundable() const { return false; }
static bool classof(const MemRegion* R) {
Kind k = R->getKind();
return k >= FunctionTextRegionKind && k <= BlockTextRegionKind;
}
};
/// FunctionTextRegion - A region that represents code texts of function.
class FunctionTextRegion : public CodeTextRegion {
const FunctionDecl *FD;
public:
FunctionTextRegion(const FunctionDecl* fd, const MemRegion* sreg)
: CodeTextRegion(sreg, FunctionTextRegionKind), FD(fd) {}
QualType getLocationType(ASTContext &C) const {
return C.getPointerType(FD->getType());
}
const FunctionDecl *getDecl() const {
return FD;
}
bool isBoundable() const { return false; }
virtual void dumpToStream(llvm::raw_ostream& os) const;
void Profile(llvm::FoldingSetNodeID& ID) const;
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FunctionDecl *FD,
const MemRegion*);
static bool classof(const MemRegion* R) {
return R->getKind() == CodeTextRegionKind;
return R->getKind() == FunctionTextRegionKind;
}
};
/// BlockTextRegion - A region that represents code texts of blocks (closures).
class BlockTextRegion : public CodeTextRegion {
const BlockDecl *BD;
CanQualType locTy;
public:
BlockTextRegion(const BlockDecl *bd, CanQualType lTy, const MemRegion* sreg)
: CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), locTy(lTy) {}
QualType getLocationType(ASTContext &C) const {
return locTy;
}
const BlockDecl *getDecl() const {
return BD;
}
virtual void dumpToStream(llvm::raw_ostream& os) const;
void Profile(llvm::FoldingSetNodeID& ID) const;
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const BlockDecl *BD,
CanQualType, const MemRegion*);
static bool classof(const MemRegion* R) {
return R->getKind() == BlockTextRegionKind;
}
};
@ -656,7 +692,9 @@ public:
ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl* ivd,
const MemRegion* superRegion);
CodeTextRegion *getCodeTextRegion(const FunctionDecl *FD);
FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD);
BlockTextRegion *getBlockTextRegion(const BlockDecl *BD, CanQualType locTy);
template <typename RegionTy, typename A1>
RegionTy* getRegion(const A1 a1);
@ -801,18 +839,21 @@ template <> struct MemRegionManagerTrait<SymbolicRegion> {
}
};
template<> struct MemRegionManagerTrait<CodeTextRegion> {
template<> struct MemRegionManagerTrait<FunctionTextRegion> {
typedef MemSpaceRegion SuperRegionTy;
static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
const FunctionDecl*) {
return MRMgr.getCodeRegion();
}
};
template<> struct MemRegionManagerTrait<BlockTextRegion> {
typedef MemSpaceRegion SuperRegionTy;
static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
SymbolRef, QualType) {
const BlockDecl*, CanQualType) {
return MRMgr.getCodeRegion();
}
};
} // end clang namespace
//===----------------------------------------------------------------------===//

View File

@ -114,6 +114,8 @@ public:
const TypedRegion *R);
DefinedSVal getFunctionPointer(const FunctionDecl *FD);
DefinedSVal getBlockPointer(const BlockDecl *BD, CanQualType locTy);
NonLoc makeCompoundVal(QualType T, llvm::ImmutableList<SVal> Vals) {
return nonloc::CompoundVal(BasicVals.getCompoundValData(T, Vals));

View File

@ -126,15 +126,26 @@ void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const {
ElementRegion::ProfileRegion(ID, ElementType, Index, superRegion);
}
void CodeTextRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
const FunctionDecl *FD,
const MemRegion*) {
ID.AddInteger(MemRegion::CodeTextRegionKind);
void FunctionTextRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
const FunctionDecl *FD,
const MemRegion*) {
ID.AddInteger(MemRegion::FunctionTextRegionKind);
ID.AddPointer(FD);
}
void CodeTextRegion::Profile(llvm::FoldingSetNodeID& ID) const {
CodeTextRegion::ProfileRegion(ID, FD, superRegion);
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);
}
//===----------------------------------------------------------------------===//
@ -160,10 +171,14 @@ void AllocaRegion::dumpToStream(llvm::raw_ostream& os) const {
os << "alloca{" << (void*) Ex << ',' << Cnt << '}';
}
void CodeTextRegion::dumpToStream(llvm::raw_ostream& os) const {
void FunctionTextRegion::dumpToStream(llvm::raw_ostream& os) const {
os << "code{" << getDecl()->getDeclName().getAsString() << '}';
}
void BlockTextRegion::dumpToStream(llvm::raw_ostream& os) const {
os << "block{" << (void*) this << '}';
}
void CompoundLiteralRegion::dumpToStream(llvm::raw_ostream& os) const {
// FIXME: More elaborate pretty-printing.
os << "{ " << (void*) CL << " }";
@ -287,10 +302,17 @@ MemRegionManager::getElementRegion(QualType elementType, SVal Idx,
return R;
}
CodeTextRegion *MemRegionManager::getCodeTextRegion(const FunctionDecl *FD) {
return getRegion<CodeTextRegion>(FD);
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.
SymbolicRegion* MemRegionManager::getSymbolicRegion(SymbolRef sym) {
return getRegion<SymbolicRegion>(sym);

View File

@ -59,8 +59,8 @@ void PthreadLockChecker::PostVisitCallExpr(CheckerContext &C,
const CallExpr *CE) {
const GRState *state = C.getState();
const Expr *Callee = CE->getCallee();
const CodeTextRegion *R =
dyn_cast_or_null<CodeTextRegion>(state->getSVal(Callee).getAsRegion());
const FunctionTextRegion *R =
dyn_cast_or_null<FunctionTextRegion>(state->getSVal(Callee).getAsRegion());
if (!R)
return;

View File

@ -712,7 +712,8 @@ DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state,
assert(0 && "Cannot index into a MemSpace");
return UnknownVal();
case MemRegion::CodeTextRegionKind:
case MemRegion::FunctionTextRegionKind:
case MemRegion::BlockTextRegionKind:
// Technically this can happen if people do funny things with casts.
return UnknownVal();
@ -857,7 +858,8 @@ SVal RegionStoreManager::EvalBinOp(const GRState *state,
case MemRegion::ObjCIvarRegionKind:
return UnknownVal();
case MemRegion::CodeTextRegionKind:
case MemRegion::FunctionTextRegionKind:
case MemRegion::BlockTextRegionKind:
// Technically this can happen if people do funny things with casts.
return UnknownVal();

View File

@ -51,7 +51,7 @@ bool SVal::hasConjuredSymbol() const {
const FunctionDecl *SVal::getAsFunctionDecl() const {
if (const loc::MemRegionVal* X = dyn_cast<loc::MemRegionVal>(this)) {
const MemRegion* R = X->getRegion();
if (const CodeTextRegion *CTR = R->getAs<CodeTextRegion>())
if (const FunctionTextRegion *CTR = R->getAs<FunctionTextRegion>())
return CTR->getDecl();
}

View File

@ -85,7 +85,9 @@ const MemRegion *StoreManager::CastRegion(const MemRegion *R, QualType CastToTy)
assert(0 && "Invalid region cast");
break;
}
case MemRegion::CodeTextRegionKind: {
case MemRegion::FunctionTextRegionKind:
case MemRegion::BlockTextRegionKind: {
// CodeTextRegion should be cast to only a function or block pointer type,
// although they can in practice be casted to anything, e.g, void*, char*,
// etc.

View File

@ -138,6 +138,13 @@ ValueManager::getDerivedRegionValueSymbolVal(SymbolRef parentSymbol,
}
DefinedSVal ValueManager::getFunctionPointer(const FunctionDecl* FD) {
CodeTextRegion *R = MemMgr.getCodeTextRegion(FD);
CodeTextRegion *R = MemMgr.getFunctionTextRegion(FD);
return loc::MemRegionVal(R);
}
DefinedSVal ValueManager::getBlockPointer(const BlockDecl *BD,
CanQualType locTy) {
CodeTextRegion *R = MemMgr.getBlockTextRegion(BD, locTy);
return loc::MemRegionVal(R);
}