Add analysis support for blocks. This includes a few key changes:

- Refactor the MemRegion hierarchy to distinguish between different StackSpaceRegions for locals and parameters.
- VarRegions for "captured" variables now have the BlockDataRegion as their super region (except those passed by reference)
- Add transfer function support to GRExprEngine for BlockDeclRefExprs.

This change also supports analyzing blocks as an analysis entry point
(top-of-the-stack), which required pushing more context-sensitivity
around in the MemRegion hierarchy via the use of LocationContext
objects.  Functionally almost everything is the same, except we track
LocationContexts in a few more areas and StackSpaceRegions now refer
to a StackFrameContext object.  In the future we will need to modify
MemRegionManager to allow multiple StackSpaceRegions in flight at once
(for the analysis of multiple stack frames).


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90809 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Ted Kremenek 2009-12-07 22:05:27 +00:00
Родитель 3cdff236e2
Коммит 67d1287035
13 изменённых файлов: 437 добавлений и 262 удалений

Просмотреть файл

@ -32,7 +32,8 @@ class ParentMap;
class ImplicitParamDecl;
class LocationContextManager;
class BlockDataRegion;
class StackFrameContext;
/// AnalysisContext contains the context data for the function or method under
/// analysis.
class AnalysisContext {
@ -117,6 +118,8 @@ public:
const ImplicitParamDecl *getSelfDecl() const {
return Ctx->getSelfDecl();
}
const StackFrameContext *getCurrentStackFrame() const;
virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;

Просмотреть файл

@ -281,6 +281,13 @@ protected:
void VisitDeclRefExpr(DeclRefExpr* DR, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
/// VisitBlockDeclRefExpr - Transfer function logic for BlockDeclRefExprs.
void VisitBlockDeclRefExpr(BlockDeclRefExpr* DR, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
void VisitCommonDeclRefExpr(Expr* DR, const NamedDecl *D,ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
/// VisitDeclStmt - Transfer function logic for DeclStmts.
void VisitDeclStmt(DeclStmt* DS, ExplodedNode* Pred, ExplodedNodeSet& Dst);

Просмотреть файл

@ -217,6 +217,7 @@ public:
/// for the compound literal and 'BegInit' and 'EndInit' represent an
/// array of initializer values.
const GRState* bindCompoundLiteral(const CompoundLiteralExpr* CL,
const LocationContext *LC,
SVal V) const;
const GRState *BindExpr(const Stmt *S, SVal V, bool Invalidate = true) const;
@ -237,7 +238,8 @@ public:
/// Get the lvalue for a StringLiteral.
SVal getLValue(const StringLiteral *literal) const;
SVal getLValue(const CompoundLiteralExpr *literal) const;
SVal getLValue(const CompoundLiteralExpr *literal,
const LocationContext *LC) const;
/// Get the lvalue for an ivar reference.
SVal getLValue(const ObjCIvarDecl *decl, SVal base) const;
@ -609,9 +611,10 @@ inline const GRState *GRState::AssumeInBound(DefinedOrUnknownSVal Idx,
cast<DefinedSVal>(UpperBound), Assumption);
}
inline const GRState *GRState::bindCompoundLiteral(const CompoundLiteralExpr* CL,
SVal V) const {
return getStateManager().StoreMgr->BindCompoundLiteral(this, CL, V);
inline const GRState *
GRState::bindCompoundLiteral(const CompoundLiteralExpr* CL,
const LocationContext *LC, SVal V) const {
return getStateManager().StoreMgr->BindCompoundLiteral(this, CL, LC, V);
}
inline const GRState *GRState::bindDecl(const VarRegion* VR, SVal IVal) const {
@ -639,8 +642,9 @@ inline SVal GRState::getLValue(const StringLiteral *literal) const {
return getStateManager().StoreMgr->getLValueString(literal);
}
inline SVal GRState::getLValue(const CompoundLiteralExpr *literal) const {
return getStateManager().StoreMgr->getLValueCompoundLiteral(literal);
inline SVal GRState::getLValue(const CompoundLiteralExpr *literal,
const LocationContext *LC) const {
return getStateManager().StoreMgr->getLValueCompoundLiteral(literal, LC);
}
inline SVal GRState::getLValue(const ObjCIvarDecl *D, SVal Base) const {

Просмотреть файл

@ -35,6 +35,7 @@ namespace clang {
class MemRegionManager;
class MemSpaceRegion;
class LocationContext;
class StackFrameContext;
class VarRegion;
//===----------------------------------------------------------------------===//
@ -45,22 +46,36 @@ class VarRegion;
class MemRegion : public llvm::FoldingSetNode {
friend class MemRegionManager;
public:
enum Kind { MemSpaceRegionKind,
SymbolicRegionKind,
AllocaRegionKind,
// Typed regions.
BEG_TYPED_REGIONS,
FunctionTextRegionKind,
BlockTextRegionKind,
BlockDataRegionKind,
CompoundLiteralRegionKind,
StringRegionKind, ElementRegionKind,
// Decl Regions.
BEG_DECL_REGIONS,
VarRegionKind, FieldRegionKind,
ObjCIvarRegionKind, ObjCObjectRegionKind,
END_DECL_REGIONS,
END_TYPED_REGIONS };
enum Kind {
// Memory spaces.
BEG_MEMSPACES,
GenericMemSpaceRegionKind = BEG_MEMSPACES,
StackLocalsSpaceRegionKind,
StackArgumentsSpaceRegionKind,
HeapSpaceRegionKind,
GlobalsSpaceRegionKind,
END_MEMSPACES = GlobalsSpaceRegionKind,
// Untyped regions.
SymbolicRegionKind,
AllocaRegionKind,
// Typed regions.
BEG_TYPED_REGIONS,
FunctionTextRegionKind = BEG_TYPED_REGIONS,
BlockTextRegionKind,
BlockDataRegionKind,
CompoundLiteralRegionKind,
StringRegionKind,
ElementRegionKind,
// Decl Regions.
BEG_DECL_REGIONS,
VarRegionKind = BEG_DECL_REGIONS,
FieldRegionKind,
ObjCIvarRegionKind,
ObjCObjectRegionKind,
END_DECL_REGIONS = ObjCObjectRegionKind,
END_TYPED_REGIONS = END_DECL_REGIONS
};
private:
const Kind kind;
@ -111,25 +126,92 @@ public:
/// MemSpaceRegion - A memory region that represents and "memory space";
/// for example, the set of global variables, the stack frame, etc.
class MemSpaceRegion : public MemRegion {
friend class MemRegionManager;
protected:
friend class MemRegionManager;
MemRegionManager *Mgr;
MemSpaceRegion(MemRegionManager *mgr) : MemRegion(MemSpaceRegionKind),
Mgr(mgr) {}
MemRegionManager* getMemRegionManager() const {
return Mgr;
MemSpaceRegion(MemRegionManager *mgr, Kind k = GenericMemSpaceRegionKind)
: MemRegion(k), Mgr(mgr) {
assert(classof(this));
}
MemRegionManager* getMemRegionManager() const { return Mgr; }
public:
void Profile(llvm::FoldingSetNodeID& ID) const;
bool isBoundable() const { return false; }
void Profile(llvm::FoldingSetNodeID &ID) const;
static bool classof(const MemRegion* R) {
return R->getKind() == MemSpaceRegionKind;
static bool classof(const MemRegion *R) {
Kind k = R->getKind();
return k >= BEG_MEMSPACES && k <= END_MEMSPACES;
}
};
class GlobalsSpaceRegion : public MemSpaceRegion {
friend class MemRegionManager;
GlobalsSpaceRegion(MemRegionManager *mgr)
: MemSpaceRegion(mgr, GlobalsSpaceRegionKind) {}
public:
static bool classof(const MemRegion *R) {
return R->getKind() == GlobalsSpaceRegionKind;
}
};
class HeapSpaceRegion : public MemSpaceRegion {
friend class MemRegionManager;
HeapSpaceRegion(MemRegionManager *mgr)
: MemSpaceRegion(mgr, HeapSpaceRegionKind) {}
public:
static bool classof(const MemRegion *R) {
return R->getKind() == HeapSpaceRegionKind;
}
};
class StackSpaceRegion : public MemSpaceRegion {
private:
const StackFrameContext *SFC;
protected:
StackSpaceRegion(MemRegionManager *mgr, Kind k, const StackFrameContext *sfc)
: MemSpaceRegion(mgr, k), SFC(sfc) {
assert(classof(this));
}
public:
const StackFrameContext *getStackFrame() const { return SFC; }
void Profile(llvm::FoldingSetNodeID &ID) const;
static bool classof(const MemRegion *R) {
Kind k = R->getKind();
return k >= StackLocalsSpaceRegionKind &&
k <= StackArgumentsSpaceRegionKind;
}
};
class StackLocalsSpaceRegion : public StackSpaceRegion {
private:
friend class MemRegionManager;
StackLocalsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc)
: StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {}
public:
static bool classof(const MemRegion *R) {
return R->getKind() == StackLocalsSpaceRegionKind;
}
};
class StackArgumentsSpaceRegion : public StackSpaceRegion {
private:
friend class MemRegionManager;
StackArgumentsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc)
: StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {}
public:
static bool classof(const MemRegion *R) {
return R->getKind() == StackArgumentsSpaceRegionKind;
}
};
@ -149,7 +231,7 @@ public:
bool isSubRegionOf(const MemRegion* R) const;
static bool classof(const MemRegion* R) {
return R->getKind() > MemSpaceRegionKind;
return R->getKind() > END_MEMSPACES;
}
};
@ -237,7 +319,7 @@ public:
static bool classof(const MemRegion* R) {
unsigned k = R->getKind();
return k > BEG_TYPED_REGIONS && k < END_TYPED_REGIONS;
return k >= BEG_TYPED_REGIONS && k <= END_TYPED_REGIONS;
}
};
@ -295,12 +377,17 @@ public:
/// like a closure a block captures the values of externally referenced
/// variables.
class BlockTextRegion : public CodeTextRegion {
friend class MemRegionManager;
const BlockDecl *BD;
AnalysisContext *AC;
CanQualType locTy;
public:
BlockTextRegion(const BlockDecl *bd, CanQualType lTy, const MemRegion* sreg)
: CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), locTy(lTy) {}
BlockTextRegion(const BlockDecl *bd, CanQualType lTy,
AnalysisContext *ac, const MemRegion* sreg)
: CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), AC(ac), locTy(lTy) {}
public:
QualType getLocationType(ASTContext &C) const {
return locTy;
}
@ -308,13 +395,16 @@ public:
const BlockDecl *getDecl() const {
return BD;
}
AnalysisContext *getAnalysisContext() const { return AC; }
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*);
CanQualType, const AnalysisContext*,
const MemRegion*);
static bool classof(const MemRegion* R) {
return R->getKind() == BlockTextRegionKind;
@ -329,15 +419,16 @@ public:
/// variables.
/// BlockDataRegion - A region that represents code texts of blocks (closures).
class BlockDataRegion : public SubRegion {
friend class MemRegionManager;
const BlockTextRegion *BC;
const LocationContext *LC;
const LocationContext *LC; // Can be null */
void *ReferencedVars;
public:
BlockDataRegion(const BlockTextRegion *bc,
const LocationContext *lc,
BlockDataRegion(const BlockTextRegion *bc, const LocationContext *lc,
const MemRegion *sreg)
: SubRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), ReferencedVars(0) {}
public:
const BlockTextRegion *getCodeRegion() const { return BC; }
const BlockDecl *getDecl() const { return BC->getDecl(); }
@ -374,9 +465,8 @@ public:
void Profile(llvm::FoldingSetNodeID& ID) const;
static void ProfileRegion(llvm::FoldingSetNodeID& ID,
const BlockTextRegion *BC,
const LocationContext *LC, const MemRegion *);
static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockTextRegion *,
const LocationContext *, const MemRegion *);
static bool classof(const MemRegion* R) {
return R->getKind() == BlockDataRegionKind;
@ -499,25 +589,20 @@ public:
static bool classof(const MemRegion* R) {
unsigned k = R->getKind();
return k > BEG_DECL_REGIONS && k < END_DECL_REGIONS;
return k >= BEG_DECL_REGIONS && k <= END_DECL_REGIONS;
}
};
class VarRegion : public DeclRegion {
friend class MemRegionManager;
// Data.
const LocationContext *LC;
// Constructors and private methods.
VarRegion(const VarDecl* vd, const LocationContext *lC, const MemRegion* sReg)
: DeclRegion(vd, sReg, VarRegionKind), LC(lC) {}
VarRegion(const VarDecl* vd, const MemRegion* sReg)
: DeclRegion(vd, sReg, VarRegionKind) {}
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const VarDecl* VD,
const LocationContext *LC,
const MemRegion *superRegion) {
DeclRegion::ProfileRegion(ID, VD, superRegion, VarRegionKind);
ID.AddPointer(LC);
}
void Profile(llvm::FoldingSetNodeID& ID) const;
@ -525,8 +610,6 @@ class VarRegion : public DeclRegion {
public:
const VarDecl *getDecl() const { return cast<VarDecl>(D); }
const LocationContext *getLocationContext() const { return LC; }
QualType getValueType(ASTContext& C) const {
// FIXME: We can cache this if needed.
return C.getCanonicalType(getDecl()->getType());
@ -673,16 +756,16 @@ class MemRegionManager {
llvm::BumpPtrAllocator& A;
llvm::FoldingSet<MemRegion> Regions;
MemSpaceRegion *globals;
MemSpaceRegion *stack;
MemSpaceRegion *stackArguments;
MemSpaceRegion *heap;
GlobalsSpaceRegion *globals;
StackLocalsSpaceRegion *stackLocals;
StackArgumentsSpaceRegion *stackArguments;
HeapSpaceRegion *heap;
MemSpaceRegion *unknown;
MemSpaceRegion *code;
public:
MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator& a)
: C(c), A(a), globals(0), stack(0), stackArguments(0), heap(0),
: C(c), A(a), globals(0), stackLocals(0), stackArguments(0), heap(0),
unknown(0), code(0) {}
~MemRegionManager();
@ -691,21 +774,23 @@ public:
llvm::BumpPtrAllocator &getAllocator() { return A; }
/// getStackRegion - Retrieve the memory region associated with the
/// current stack frame.
const MemSpaceRegion *getStackRegion();
/// getStackLocalsRegion - Retrieve the memory region associated with the
/// specified stack frame.
const StackLocalsSpaceRegion *
getStackLocalsRegion(const StackFrameContext *STC);
/// getStackArgumentsRegion - Retrieve the memory region associated with
/// function/method arguments of the current stack frame.
const MemSpaceRegion *getStackArgumentsRegion();
/// function/method arguments of the specified stack frame.
const StackArgumentsSpaceRegion *
getStackArgumentsRegion(const StackFrameContext *STC);
/// getGlobalsRegion - Retrieve the memory region associated with
/// all global variables.
const MemSpaceRegion *getGlobalsRegion();
const GlobalsSpaceRegion *getGlobalsRegion();
/// getHeapRegion - Retrieve the memory region associated with the
/// generic "heap".
const MemSpaceRegion *getHeapRegion();
const HeapSpaceRegion *getHeapRegion();
/// getUnknownRegion - Retrieve the memory region associated with unknown
/// memory space.
@ -714,12 +799,14 @@ public:
const MemSpaceRegion *getCodeRegion();
/// getAllocaRegion - Retrieve a region associated with a call to alloca().
const AllocaRegion *getAllocaRegion(const Expr* Ex, unsigned Cnt);
const AllocaRegion *getAllocaRegion(const Expr* Ex, unsigned Cnt,
const LocationContext *LC);
/// getCompoundLiteralRegion - Retrieve the region associated with a
/// given CompoundLiteral.
const CompoundLiteralRegion*
getCompoundLiteralRegion(const CompoundLiteralExpr* CL);
getCompoundLiteralRegion(const CompoundLiteralExpr* CL,
const LocationContext *LC);
/// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
const SymbolicRegion* getSymbolicRegion(SymbolRef sym);
@ -730,6 +817,10 @@ public:
/// a specified VarDecl and LocationContext.
const VarRegion* getVarRegion(const VarDecl *D, const LocationContext *LC);
/// getVarRegion - Retrieve or create the memory region associated with
/// a specified VarDecl and super region.
const VarRegion* getVarRegion(const VarDecl *D, const MemRegion *superR);
/// getElementRegion - Retrieve the memory region associated with the
/// associated element type, index, and super region.
const ElementRegion *getElementRegion(QualType elementType, SVal Idx,
@ -768,9 +859,15 @@ public:
const FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD);
const BlockTextRegion *getBlockTextRegion(const BlockDecl *BD,
CanQualType locTy);
CanQualType locTy,
AnalysisContext *AC);
/// getBlockDataRegion - Get the memory region associated with an instance
/// of a block. Unlike many other MemRegions, the LocationContext*
/// argument is allowed to be NULL for cases where we have no known
/// context.
const BlockDataRegion *getBlockDataRegion(const BlockTextRegion *bc,
const LocationContext *lc);
const LocationContext *lc = NULL);
bool isGlobalsRegion(const MemRegion* R) {
assert(R);
@ -791,7 +888,15 @@ private:
RegionTy* getSubRegion(const A1 a1, const A2 a2,
const MemRegion* superRegion);
const MemSpaceRegion* LazyAllocate(MemSpaceRegion*& region);
template <typename RegionTy, typename A1, typename A2, typename A3>
RegionTy* getSubRegion(const A1 a1, const A2 a2, const A3 a3,
const MemRegion* superRegion);
template <typename REG>
const REG* LazyAllocate(REG*& region);
template <typename REG, typename ARG>
const REG* LazyAllocate(REG*& region, ARG a);
};
//===----------------------------------------------------------------------===//

Просмотреть файл

@ -73,8 +73,9 @@ public:
/// for the compound literal and 'BegInit' and 'EndInit' represent an
/// array of initializer values.
virtual const GRState *BindCompoundLiteral(const GRState *state,
const CompoundLiteralExpr* cl,
SVal v) = 0;
const CompoundLiteralExpr* cl,
const LocationContext *LC,
SVal v) = 0;
/// getInitialStore - Returns the initial "empty" store representing the
/// value bindings upon entry to an analyzed function.
@ -93,7 +94,8 @@ public:
virtual SVal getLValueString(const StringLiteral* sl) = 0;
virtual SVal getLValueCompoundLiteral(const CompoundLiteralExpr* cl) = 0;
SVal getLValueCompoundLiteral(const CompoundLiteralExpr* cl,
const LocationContext *LC);
virtual SVal getLValueIvar(const ObjCIvarDecl* decl, SVal base) = 0;

Просмотреть файл

@ -165,6 +165,20 @@ LocationContextManager::getBlockInvocation(AnalysisContext *ctx,
BR);
}
//===----------------------------------------------------------------------===//
// LocationContext methods.
//===----------------------------------------------------------------------===//
const StackFrameContext *LocationContext::getCurrentStackFrame() const {
const LocationContext *LC = this;
while (LC) {
if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LC))
return SFC;
LC = LC->getParent();
}
return NULL;
}
//===----------------------------------------------------------------------===//
// Lazily generated map to query the external variables referenced by a Block.
//===----------------------------------------------------------------------===//

Просмотреть файл

@ -68,14 +68,14 @@ public:
}
const GRState *BindCompoundLiteral(const GRState *state,
const CompoundLiteralExpr* cl,
const CompoundLiteralExpr*,
const LocationContext*,
SVal val) {
return state;
}
SVal getLValueVar(const VarDecl *VD, const LocationContext *LC);
SVal getLValueString(const StringLiteral *S);
SVal getLValueCompoundLiteral(const CompoundLiteralExpr *CL);
SVal getLValueIvar(const ObjCIvarDecl* D, SVal Base);
SVal getLValueField(const FieldDecl *D, SVal Base);
SVal getLValueElement(QualType elementType, SVal Offset, SVal Base);
@ -130,10 +130,6 @@ SVal BasicStoreManager::getLValueString(const StringLiteral* S) {
return ValMgr.makeLoc(MRMgr.getStringRegion(S));
}
SVal BasicStoreManager::getLValueCompoundLiteral(const CompoundLiteralExpr* CL){
return ValMgr.makeLoc(MRMgr.getCompoundLiteralRegion(CL));
}
SVal BasicStoreManager::getLValueIvar(const ObjCIvarDecl* D, SVal Base) {
if (Base.isUnknownOrUndef())

Просмотреть файл

@ -3681,7 +3681,24 @@ void RetainReleaseChecker::PostVisitBlockExpr(CheckerContext &C,
if (I == E)
return;
state = state->scanReachableSymbols<StopTrackingCallback>(I, E).getState();
// FIXME: For now we invalidate the tracking of all symbols passed to blocks
// via captured variables, even though captured variables result in a copy
// and in implicit increment/decrement of a retain count.
llvm::SmallVector<const MemRegion*, 10> Regions;
const LocationContext *LC = C.getPredecessor()->getLocationContext();
MemRegionManager &MemMgr = C.getValueManager().getRegionManager();
for ( ; I != E; ++I) {
const VarRegion *VR = *I;
if (VR->getSuperRegion() == R) {
VR = MemMgr.getVarRegion(VR->getDecl(), LC);
}
Regions.push_back(VR);
}
state =
state->scanReachableSymbols<StopTrackingCallback>(Regions.data(),
Regions.data() + Regions.size()).getState();
C.addTransition(state);
}

Просмотреть файл

@ -473,6 +473,10 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
case Stmt::AsmStmtClass:
VisitAsmStmt(cast<AsmStmt>(S), Pred, Dst);
break;
case Stmt::BlockDeclRefExprClass:
VisitBlockDeclRefExpr(cast<BlockDeclRefExpr>(S), Pred, Dst, false);
break;
case Stmt::BlockExprClass:
VisitBlockExpr(cast<BlockExpr>(S), Pred, Dst);
@ -644,6 +648,10 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
VisitArraySubscriptExpr(cast<ArraySubscriptExpr>(Ex), Pred, Dst, true);
return;
case Stmt::BlockDeclRefExprClass:
VisitBlockDeclRefExpr(cast<BlockDeclRefExpr>(Ex), Pred, Dst, true);
return;
case Stmt::DeclRefExprClass:
VisitDeclRefExpr(cast<DeclRefExpr>(Ex), Pred, Dst, true);
return;
@ -1135,9 +1143,20 @@ void GRExprEngine::VisitBlockExpr(BlockExpr *BE, ExplodedNode *Pred,
void GRExprEngine::VisitDeclRefExpr(DeclRefExpr *Ex, ExplodedNode *Pred,
ExplodedNodeSet &Dst, bool asLValue) {
VisitCommonDeclRefExpr(Ex, Ex->getDecl(), Pred, Dst, asLValue);
}
void GRExprEngine::VisitBlockDeclRefExpr(BlockDeclRefExpr *Ex,
ExplodedNode *Pred,
ExplodedNodeSet &Dst, bool asLValue) {
VisitCommonDeclRefExpr(Ex, Ex->getDecl(), Pred, Dst, asLValue);
}
void GRExprEngine::VisitCommonDeclRefExpr(Expr *Ex, const NamedDecl *D,
ExplodedNode *Pred,
ExplodedNodeSet &Dst, bool asLValue) {
const GRState *state = GetState(Pred);
const NamedDecl *D = Ex->getDecl();
if (const VarDecl* VD = dyn_cast<VarDecl>(D)) {
@ -1566,7 +1585,8 @@ bool GRExprEngine::EvalBuiltinFunction(const FunctionDecl *FD, CallExpr *CE,
// FIXME: Refactor into StoreManager itself?
MemRegionManager& RM = getStateManager().getRegionManager();
const MemRegion* R =
RM.getAllocaRegion(CE, Builder->getCurrentBlockCount());
RM.getAllocaRegion(CE, Builder->getCurrentBlockCount(),
Pred->getLocationContext());
// Set the extent of the region in bytes. This enables us to use the
// SVal of the argument directly. If we save the extent in bits, we
@ -2064,10 +2084,12 @@ void GRExprEngine::VisitCompoundLiteralExpr(CompoundLiteralExpr* CL,
for (ExplodedNodeSet::iterator I = Tmp.begin(), EI = Tmp.end(); I!=EI; ++I) {
const GRState* state = GetState(*I);
SVal ILV = state->getSVal(ILE);
state = state->bindCompoundLiteral(CL, ILV);
const LocationContext *LC = (*I)->getLocationContext();
state = state->bindCompoundLiteral(CL, LC, ILV);
if (asLValue)
MakeNode(Dst, CL, *I, state->BindExpr(CL, state->getLValue(CL)));
if (asLValue) {
MakeNode(Dst, CL, *I, state->BindExpr(CL, state->getLValue(CL, LC)));
}
else
MakeNode(Dst, CL, *I, state->BindExpr(CL, ILV));
}

Просмотреть файл

@ -106,75 +106,24 @@ RegionTy* MemRegionManager::getSubRegion(const A1 a1, const A2 a2,
return R;
}
//===----------------------------------------------------------------------===//
// Traits for constructing regions.
//===----------------------------------------------------------------------===//
template <> struct MemRegionManagerTrait<AllocaRegion> {
typedef MemRegion SuperRegionTy;
static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
const Expr *, unsigned) {
return MRMgr.getStackRegion();
template <typename RegionTy, typename A1, typename A2, typename A3>
RegionTy* MemRegionManager::getSubRegion(const A1 a1, const A2 a2, const A3 a3,
const MemRegion *superRegion) {
llvm::FoldingSetNodeID ID;
RegionTy::ProfileRegion(ID, a1, a2, a3, superRegion);
void* InsertPos;
RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
InsertPos));
if (!R) {
R = (RegionTy*) A.Allocate<RegionTy>();
new (R) RegionTy(a1, a2, a3, superRegion);
Regions.InsertNode(R, InsertPos);
}
};
template <> struct MemRegionManagerTrait<CompoundLiteralRegion> {
typedef MemRegion SuperRegionTy;
static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
const CompoundLiteralExpr *CL) {
return CL->isFileScope() ? MRMgr.getGlobalsRegion()
: MRMgr.getStackRegion();
}
};
template <> struct MemRegionManagerTrait<StringRegion> {
typedef MemSpaceRegion SuperRegionTy;
static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
const StringLiteral*) {
return MRMgr.getGlobalsRegion();
}
};
template <> struct MemRegionManagerTrait<VarRegion> {
typedef MemRegion SuperRegionTy;
static const SuperRegionTy* getSuperRegion(MemRegionManager &MRMgr,
const VarDecl *D,
const LocationContext *LC) {
// FIXME: Make stack regions have a location context?
if (D->hasLocalStorage()) {
return isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)
? MRMgr.getStackArgumentsRegion() : MRMgr.getStackRegion();
}
return MRMgr.getGlobalsRegion();
}
};
template <> struct MemRegionManagerTrait<SymbolicRegion> {
typedef MemRegion SuperRegionTy;
static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
SymbolRef) {
return MRMgr.getUnknownRegion();
}
};
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,
const BlockDecl*, CanQualType) {
return MRMgr.getCodeRegion();
}
};
return R;
}
//===----------------------------------------------------------------------===//
// Object destruction.
@ -220,6 +169,11 @@ 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());
}
void StringRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
const StringLiteral* Str,
const MemRegion* superRegion) {
@ -264,7 +218,7 @@ void DeclRegion::Profile(llvm::FoldingSetNodeID& ID) const {
}
void VarRegion::Profile(llvm::FoldingSetNodeID &ID) const {
VarRegion::ProfileRegion(ID, getDecl(), LC, superRegion);
VarRegion::ProfileRegion(ID, getDecl(), superRegion);
}
void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym,
@ -303,27 +257,29 @@ void FunctionTextRegion::Profile(llvm::FoldingSetNodeID& ID) const {
}
void BlockTextRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
const BlockDecl *BD, CanQualType,
const MemRegion*) {
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, superRegion);
BlockTextRegion::ProfileRegion(ID, BD, locTy, AC, superRegion);
}
void BlockDataRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
const BlockTextRegion *BC,
const LocationContext *LC,
const MemRegion *) {
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, NULL);
BlockDataRegion::ProfileRegion(ID, BC, LC, getSuperRegion());
}
//===----------------------------------------------------------------------===//
@ -404,28 +360,41 @@ void RegionRawOffset::dumpToStream(llvm::raw_ostream& os) const {
// MemRegionManager methods.
//===----------------------------------------------------------------------===//
const MemSpaceRegion *MemRegionManager::LazyAllocate(MemSpaceRegion*& region) {
template <typename REG>
const REG *MemRegionManager::LazyAllocate(REG*& region) {
if (!region) {
region = (MemSpaceRegion*) A.Allocate<MemSpaceRegion>();
new (region) MemSpaceRegion(this);
region = (REG*) A.Allocate<REG>();
new (region) REG(this);
}
return region;
}
const MemSpaceRegion *MemRegionManager::getStackRegion() {
return LazyAllocate(stack);
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);
}
return region;
}
const MemSpaceRegion *MemRegionManager::getStackArgumentsRegion() {
return LazyAllocate(stackArguments);
const StackLocalsSpaceRegion*
MemRegionManager::getStackLocalsRegion(const StackFrameContext *STC) {
return LazyAllocate(stackLocals, STC);
}
const MemSpaceRegion *MemRegionManager::getGlobalsRegion() {
const StackArgumentsSpaceRegion *
MemRegionManager::getStackArgumentsRegion(const StackFrameContext *STC) {
return LazyAllocate(stackArguments, STC);
}
const GlobalsSpaceRegion *MemRegionManager::getGlobalsRegion() {
return LazyAllocate(globals);
}
const MemSpaceRegion *MemRegionManager::getHeapRegion() {
const HeapSpaceRegion *MemRegionManager::getHeapRegion() {
return LazyAllocate(heap);
}
@ -442,36 +411,71 @@ const MemSpaceRegion *MemRegionManager::getCodeRegion() {
//===----------------------------------------------------------------------===//
const StringRegion* MemRegionManager::getStringRegion(const StringLiteral* Str) {
return getRegion<StringRegion>(Str);
return getSubRegion<StringRegion>(Str, getGlobalsRegion());
}
const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D,
const LocationContext *LC) {
const MemRegion *sReg = 0;
// 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();
if (D->hasLocalStorage()) {
// FIXME: Once we implement scope handling, we will need to properly lookup
// 'D' to the proper LocationContext.
const StackFrameContext *STC = LC->getCurrentStackFrame();
return getRegion<VarRegion>(D, LC);
assert(STC);
sReg = isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)
? static_cast<const MemRegion*>(getStackArgumentsRegion(STC))
: static_cast<const MemRegion*>(getStackLocalsRegion(STC));
}
else {
sReg = getGlobalsRegion();
}
return getSubRegion<VarRegion>(D, sReg);
}
const VarRegion *MemRegionManager::getVarRegion(const VarDecl *D,
const MemRegion *superR) {
return getSubRegion<VarRegion>(D, superR);
}
const 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();
const MemRegion *sReg = 0;
return getSubRegion<BlockDataRegion>(BC, LC, getStackRegion());
if (LC) {
// FIXME: Once we implement scope handling, we want the parent region
// 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) {
return getRegion<CompoundLiteralRegion>(CL);
MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr* CL,
const LocationContext *LC) {
const MemRegion *sReg = 0;
if (CL->isFileScope())
sReg = getGlobalsRegion();
else {
const StackFrameContext *STC = LC->getCurrentStackFrame();
assert(STC);
sReg = getStackLocalsRegion(STC);
}
return getSubRegion<CompoundLiteralRegion>(CL, sReg);
}
const ElementRegion*
@ -499,18 +503,19 @@ MemRegionManager::getElementRegion(QualType elementType, SVal Idx,
const FunctionTextRegion *
MemRegionManager::getFunctionTextRegion(const FunctionDecl *FD) {
return getRegion<FunctionTextRegion>(FD);
return getSubRegion<FunctionTextRegion>(FD, getCodeRegion());
}
const BlockTextRegion *
MemRegionManager::getBlockTextRegion(const BlockDecl *BD, CanQualType locTy) {
return getRegion<BlockTextRegion>(BD, locTy);
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 getRegion<SymbolicRegion>(sym);
return getSubRegion<SymbolicRegion>(sym, getUnknownRegion());
}
const FieldRegion *
@ -532,8 +537,11 @@ MemRegionManager::getObjCObjectRegion(const ObjCInterfaceDecl* d,
}
const AllocaRegion*
MemRegionManager::getAllocaRegion(const Expr* E, unsigned cnt) {
return getRegion<AllocaRegion>(E, cnt);
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 {
@ -549,52 +557,30 @@ const MemSpaceRegion *MemRegion::getMemorySpace() const {
}
bool MemRegion::hasStackStorage() const {
if (const MemSpaceRegion *MS = getMemorySpace()) {
MemRegionManager *Mgr = getMemRegionManager();
return MS == Mgr->getStackRegion() || MS == Mgr->getStackArgumentsRegion();
}
return false;
return isa<StackSpaceRegion>(getMemorySpace());
}
bool MemRegion::hasHeapStorage() const {
if (const MemSpaceRegion *MS = getMemorySpace())
return MS == getMemRegionManager()->getHeapRegion();
return false;
return isa<HeapSpaceRegion>(getMemorySpace());
}
bool MemRegion::hasHeapOrStackStorage() const {
if (const MemSpaceRegion *MS = getMemorySpace()) {
MemRegionManager *Mgr = getMemRegionManager();
return MS == Mgr->getHeapRegion()
|| MS == Mgr->getStackRegion()
|| MS == Mgr->getStackArgumentsRegion();
}
return false;
const MemSpaceRegion *MS = getMemorySpace();
return isa<StackSpaceRegion>(MS) || isa<HeapSpaceRegion>(MS);
}
bool MemRegion::hasGlobalsStorage() const {
if (const MemSpaceRegion *MS = getMemorySpace())
return MS == getMemRegionManager()->getGlobalsRegion();
return false;
return isa<GlobalsSpaceRegion>(getMemorySpace());
}
bool MemRegion::hasParametersStorage() const {
if (const MemSpaceRegion *MS = getMemorySpace())
return MS == getMemRegionManager()->getStackArgumentsRegion();
return false;
return isa<StackArgumentsSpaceRegion>(getMemorySpace());
}
bool MemRegion::hasGlobalsOrParametersStorage() const {
if (const MemSpaceRegion *MS = getMemorySpace()) {
MemRegionManager *Mgr = getMemRegionManager();
return MS == Mgr->getGlobalsRegion()
|| MS == Mgr->getStackArgumentsRegion();
}
return false;
const MemSpaceRegion *MS = getMemorySpace();
return isa<StackArgumentsSpaceRegion>(MS) ||
isa<GlobalsSpaceRegion>(MS);
}
// getBaseRegion strips away all elements and fields, and get the base region
@ -700,7 +686,7 @@ void BlockDataRegion::LazyInitializeReferencedVars() {
if (ReferencedVars)
return;
AnalysisContext *AC = LC->getAnalysisContext();
AnalysisContext *AC = getCodeRegion()->getAnalysisContext();
AnalysisContext::referenced_decls_iterator I, E;
llvm::tie(I, E) = AC->getReferencedBlockVars(BC->getDecl());
@ -717,8 +703,23 @@ void BlockDataRegion::LazyInitializeReferencedVars() {
VarVec *BV = (VarVec*) A.Allocate<VarVec>();
new (BV) VarVec(BC, E - I);
for ( ; I != E; ++I)
BV->push_back(MemMgr.getVarRegion(*I, LC), BC);
for ( ; I != E; ++I) {
const VarDecl *VD = *I;
const VarRegion *VR = 0;
if (!VD->getAttr<BlocksAttr>())
VR = MemMgr.getVarRegion(VD, this);
else {
if (LC)
VR = MemMgr.getVarRegion(VD, LC);
else {
VR = MemMgr.getVarRegion(VD, MemMgr.getUnknownRegion());
}
}
assert(VR);
BV->push_back(VR, BC);
}
ReferencedVars = BV;
}

Просмотреть файл

@ -287,7 +287,9 @@ public:
const GRState *Bind(const GRState *state, Loc LV, SVal V);
const GRState *BindCompoundLiteral(const GRState *state,
const CompoundLiteralExpr* CL, SVal V);
const CompoundLiteralExpr* CL,
const LocationContext *LC,
SVal V);
const GRState *BindDecl(const GRState *ST, const VarRegion *VR,
SVal InitVal);
@ -615,15 +617,6 @@ SVal RegionStoreManager::getLValueVar(const VarDecl *VD,
return loc::MemRegionVal(MRMgr.getVarRegion(VD, LC));
}
/// getLValueCompoundLiteral - Returns an SVal representing the lvalue
/// of a compound literal. Within RegionStore a compound literal
/// has an associated region, and the lvalue of the compound literal
/// is the lvalue of that region.
SVal
RegionStoreManager::getLValueCompoundLiteral(const CompoundLiteralExpr* CL) {
return loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL));
}
SVal RegionStoreManager::getLValueIvar(const ObjCIvarDecl* D, SVal Base) {
return getLValueFieldOrIvar(D, Base);
}
@ -730,7 +723,11 @@ DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state,
const MemRegion *R) {
switch (R->getKind()) {
case MemRegion::MemSpaceRegionKind:
case MemRegion::GenericMemSpaceRegionKind:
case MemRegion::StackLocalsSpaceRegionKind:
case MemRegion::StackArgumentsSpaceRegionKind:
case MemRegion::HeapSpaceRegionKind:
case MemRegion::GlobalsSpaceRegionKind:
assert(0 && "Cannot index into a MemSpace");
return UnknownVal();
@ -775,13 +772,6 @@ DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state,
// essentially are arrays of size 1.
return ValMgr.makeIntVal(1, false);
}
case MemRegion::BEG_DECL_REGIONS:
case MemRegion::END_DECL_REGIONS:
case MemRegion::BEG_TYPED_REGIONS:
case MemRegion::END_TYPED_REGIONS:
assert(0 && "Infeasible region");
return UnknownVal();
}
assert(0 && "Unreachable");
@ -886,16 +876,13 @@ SVal RegionStoreManager::EvalBinOp(const GRState *state,
// Technically this can happen if people do funny things with casts.
return UnknownVal();
case MemRegion::MemSpaceRegionKind:
case MemRegion::GenericMemSpaceRegionKind:
case MemRegion::StackLocalsSpaceRegionKind:
case MemRegion::StackArgumentsSpaceRegionKind:
case MemRegion::HeapSpaceRegionKind:
case MemRegion::GlobalsSpaceRegionKind:
assert(0 && "Cannot perform pointer arithmetic on a MemSpace");
return UnknownVal();
case MemRegion::BEG_DECL_REGIONS:
case MemRegion::END_DECL_REGIONS:
case MemRegion::BEG_TYPED_REGIONS:
case MemRegion::END_TYPED_REGIONS:
assert(0 && "Infeasible region");
return UnknownVal();
}
SVal Idx = ER->getIndex();
@ -1462,9 +1449,11 @@ const GRState *RegionStoreManager::BindDecl(const GRState *ST,
// FIXME: this method should be merged into Bind().
const GRState *
RegionStoreManager::BindCompoundLiteral(const GRState *state,
const CompoundLiteralExpr* CL,
const CompoundLiteralExpr *CL,
const LocationContext *LC,
SVal V) {
return Bind(state, loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL)), V);
return Bind(state, loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL, LC)),
V);
}
const GRState *RegionStoreManager::setImplicitDefaultValue(const GRState *state,

Просмотреть файл

@ -77,11 +77,11 @@ const MemRegion *StoreManager::CastRegion(const MemRegion *R, QualType CastToTy)
// Process region cast according to the kind of the region being cast.
switch (R->getKind()) {
case MemRegion::BEG_TYPED_REGIONS:
case MemRegion::MemSpaceRegionKind:
case MemRegion::BEG_DECL_REGIONS:
case MemRegion::END_DECL_REGIONS:
case MemRegion::END_TYPED_REGIONS: {
case MemRegion::GenericMemSpaceRegionKind:
case MemRegion::StackLocalsSpaceRegionKind:
case MemRegion::StackArgumentsSpaceRegionKind:
case MemRegion::HeapSpaceRegionKind:
case MemRegion::GlobalsSpaceRegionKind: {
assert(0 && "Invalid region cast");
break;
}
@ -216,3 +216,16 @@ const GRState *StoreManager::InvalidateRegions(const GRState *state,
return state;
}
//===----------------------------------------------------------------------===//
// Common getLValueXXX methods.
//===----------------------------------------------------------------------===//
/// getLValueCompoundLiteral - Returns an SVal representing the lvalue
/// of a compound literal. Within RegionStore a compound literal
/// has an associated region, and the lvalue of the compound literal
/// is the lvalue of that region.
SVal StoreManager::getLValueCompoundLiteral(const CompoundLiteralExpr* CL,
const LocationContext *LC) {
return loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL, LC));
}

Просмотреть файл

@ -14,6 +14,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Analysis/PathSensitive/ValueManager.h"
#include "clang/Analysis/PathSensitive/AnalysisContext.h"
using namespace clang;
using namespace llvm;
@ -144,7 +145,8 @@ DefinedSVal ValueManager::getFunctionPointer(const FunctionDecl* FD) {
DefinedSVal ValueManager::getBlockPointer(const BlockDecl *D,
CanQualType locTy,
const LocationContext *LC) {
const BlockTextRegion *BC = MemMgr.getBlockTextRegion(D, locTy);
const BlockTextRegion *BC =
MemMgr.getBlockTextRegion(D, locTy, LC->getAnalysisContext());
const BlockDataRegion *BD = MemMgr.getBlockDataRegion(BC, LC);
return loc::MemRegionVal(BD);
}