diff options
Diffstat (limited to 'include/clang/Checker')
-rw-r--r-- | include/clang/Checker/PathSensitive/Checker.h | 10 | ||||
-rw-r--r-- | include/clang/Checker/PathSensitive/GRCoreEngine.h | 75 | ||||
-rw-r--r-- | include/clang/Checker/PathSensitive/GRExprEngine.h | 8 | ||||
-rw-r--r-- | include/clang/Checker/PathSensitive/GRState.h | 24 | ||||
-rw-r--r-- | include/clang/Checker/PathSensitive/GRSubEngine.h | 8 | ||||
-rw-r--r-- | include/clang/Checker/PathSensitive/MemRegion.h | 15 | ||||
-rw-r--r-- | include/clang/Checker/PathSensitive/SymbolManager.h | 25 | ||||
-rw-r--r-- | include/clang/Checker/PathSensitive/ValueManager.h | 3 |
8 files changed, 123 insertions, 45 deletions
diff --git a/include/clang/Checker/PathSensitive/Checker.h b/include/clang/Checker/PathSensitive/Checker.h index d498044..2401a72 100644 --- a/include/clang/Checker/PathSensitive/Checker.h +++ b/include/clang/Checker/PathSensitive/Checker.h @@ -147,12 +147,22 @@ public: void addTransition(const GRState *state) { assert(state); + // If the 'state' is not new, we need to check if the cached state 'ST' + // is new. if (state != getState() || (ST && ST != B.GetState(Pred))) GenerateNode(state, true); else Dst.Add(Pred); } + // Generate a node with a new program point different from the one that will + // be created by the GRStmtNodeBuilder. + void addTransition(const GRState *state, ProgramPoint Loc) { + ExplodedNode *N = B.generateNode(Loc, state, Pred); + if (N) + addTransition(N); + } + void EmitReport(BugReport *R) { Eng.getBugReporter().EmitReport(R); } diff --git a/include/clang/Checker/PathSensitive/GRCoreEngine.h b/include/clang/Checker/PathSensitive/GRCoreEngine.h index 6da4581..c5bf513 100644 --- a/include/clang/Checker/PathSensitive/GRCoreEngine.h +++ b/include/clang/Checker/PathSensitive/GRCoreEngine.h @@ -40,6 +40,8 @@ class GRCoreEngine { friend class GRIndirectGotoNodeBuilder; friend class GRSwitchNodeBuilder; friend class GREndPathNodeBuilder; + friend class GRCallEnterNodeBuilder; + friend class GRCallExitNodeBuilder; GRSubEngine& SubEngine; @@ -67,6 +69,9 @@ class GRCoreEngine { void HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock* B, ExplodedNode* Pred); + void HandleCallEnter(const CallEnter &L, const CFGBlock *Block, + unsigned Index, ExplodedNode *Pred); + void HandleCallExit(const CallExit &L, ExplodedNode *Pred); /// Get the initial state from the subengine. const GRState* getInitialState(const LocationContext *InitLoc) { @@ -90,6 +95,9 @@ class GRCoreEngine { void ProcessSwitch(GRSwitchNodeBuilder& Builder); + void ProcessCallEnter(GRCallEnterNodeBuilder &Builder); + void ProcessCallExit(GRCallExitNodeBuilder &Builder); + private: GRCoreEngine(const GRCoreEngine&); // Do not implement. GRCoreEngine& operator=(const GRCoreEngine&); @@ -130,7 +138,6 @@ class GRStmtNodeBuilder { CFGBlock& B; const unsigned Idx; ExplodedNode* Pred; - ExplodedNode* LastNode; GRStateManager& Mgr; GRAuditor* Auditor; @@ -157,10 +164,6 @@ public: ExplodedNode* getBasePredecessor() const { return Pred; } - ExplodedNode* getLastNode() const { - return LastNode ? (LastNode->isSink() ? NULL : LastNode) : NULL; - } - // FIXME: This should not be exposed. GRWorkList *getWorkList() { return Eng.WList; } @@ -194,6 +197,12 @@ public: return generateNode(S, St, Pred, PointKind); } + ExplodedNode *generateNode(const ProgramPoint &PP, const GRState* State, + ExplodedNode* Pred) { + HasGeneratedNode = true; + return generateNodeInternal(PP, State, Pred); + } + ExplodedNode* generateNodeInternal(const ProgramPoint &PP, const GRState* State, ExplodedNode* Pred); @@ -431,6 +440,8 @@ public: ExplodedNode* generateNode(const GRState* State, const void *tag = 0, ExplodedNode *P = 0); + void GenerateCallExitNode(const GRState *state); + CFGBlock* getBlock() const { return &B; } const GRState* getState() const { @@ -438,6 +449,60 @@ public: } }; +class GRCallEnterNodeBuilder { + GRCoreEngine &Eng; + + const ExplodedNode *Pred; + + // The call site. + const Stmt *CE; + + // The definition of callee. + const FunctionDecl *FD; + + // The parent block of the CallExpr. + const CFGBlock *Block; + + // The CFGBlock index of the CallExpr. + unsigned Index; + +public: + GRCallEnterNodeBuilder(GRCoreEngine &eng, const ExplodedNode *pred, + const Stmt *s, const FunctionDecl *fd, + const CFGBlock *blk, unsigned idx) + : Eng(eng), Pred(pred), CE(s), FD(fd), Block(blk), Index(idx) {} + + const GRState *getState() const { return Pred->getState(); } + + const LocationContext *getLocationContext() const { + return Pred->getLocationContext(); + } + + const Stmt *getCallExpr() const { return CE; } + + const FunctionDecl *getCallee() const { return FD; } + + const CFGBlock *getBlock() const { return Block; } + + unsigned getIndex() const { return Index; } + + void GenerateNode(const GRState *state, const LocationContext *LocCtx); +}; + +class GRCallExitNodeBuilder { + GRCoreEngine &Eng; + const ExplodedNode *Pred; + +public: + GRCallExitNodeBuilder(GRCoreEngine &eng, const ExplodedNode *pred) + : Eng(eng), Pred(pred) {} + + const ExplodedNode *getPredecessor() const { return Pred; } + + const GRState *getState() const { return Pred->getState(); } + + void GenerateNode(const GRState *state); +}; } // end clang namespace #endif diff --git a/include/clang/Checker/PathSensitive/GRExprEngine.h b/include/clang/Checker/PathSensitive/GRExprEngine.h index 90a2cd5..763bbcc 100644 --- a/include/clang/Checker/PathSensitive/GRExprEngine.h +++ b/include/clang/Checker/PathSensitive/GRExprEngine.h @@ -171,7 +171,13 @@ public: /// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path /// nodes when the control reaches the end of a function. void ProcessEndPath(GREndPathNodeBuilder& builder); - + + // Generate the entry node of the callee. + void ProcessCallEnter(GRCallEnterNodeBuilder &builder); + + // Generate the first post callsite node. + void ProcessCallExit(GRCallExitNodeBuilder &builder); + /// EvalAssume - Callback function invoked by the ConstraintManager when /// making assumptions about state values. const GRState *ProcessAssume(const GRState *state, SVal cond, bool assumption); diff --git a/include/clang/Checker/PathSensitive/GRState.h b/include/clang/Checker/PathSensitive/GRState.h index 4e44697..9194ee8 100644 --- a/include/clang/Checker/PathSensitive/GRState.h +++ b/include/clang/Checker/PathSensitive/GRState.h @@ -16,25 +16,24 @@ // FIXME: Reduce the number of includes. +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/Expr.h" +#include "clang/Analysis/Analyses/LiveVariables.h" +#include "clang/Checker/PathSensitive/ConstraintManager.h" #include "clang/Checker/PathSensitive/Environment.h" +#include "clang/Checker/PathSensitive/GRCoreEngine.h" #include "clang/Checker/PathSensitive/Store.h" -#include "clang/Checker/PathSensitive/ConstraintManager.h" #include "clang/Checker/PathSensitive/ValueManager.h" -#include "clang/Checker/PathSensitive/GRCoreEngine.h" -#include "clang/AST/Expr.h" -#include "clang/AST/Decl.h" -#include "clang/AST/ASTContext.h" -#include "clang/Analysis/Analyses/LiveVariables.h" -#include "llvm/Support/Casting.h" -#include "llvm/System/DataTypes.h" #include "llvm/ADT/APSInt.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ImmutableMap.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/DenseSet.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/raw_ostream.h" - +#include "llvm/System/DataTypes.h" #include <functional> namespace clang { @@ -77,16 +76,13 @@ public: typedef llvm::ImmutableMap<void*, void*> GenericDataMap; private: - void operator=(const GRState& R) const; + void operator=(const GRState& R) const; // Do not implement. friend class GRStateManager; GRStateManager *StateMgr; Environment Env; Store St; - - // FIXME: Make these private. -public: GenericDataMap GDM; public: diff --git a/include/clang/Checker/PathSensitive/GRSubEngine.h b/include/clang/Checker/PathSensitive/GRSubEngine.h index ce57c2c..f2cd048 100644 --- a/include/clang/Checker/PathSensitive/GRSubEngine.h +++ b/include/clang/Checker/PathSensitive/GRSubEngine.h @@ -28,6 +28,8 @@ class GRBranchNodeBuilder; class GRIndirectGotoNodeBuilder; class GRSwitchNodeBuilder; class GREndPathNodeBuilder; +class GRCallEnterNodeBuilder; +class GRCallExitNodeBuilder; class LocationContext; class GRSubEngine { @@ -64,6 +66,12 @@ public: /// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path /// nodes when the control reaches the end of a function. virtual void ProcessEndPath(GREndPathNodeBuilder& builder) = 0; + + // Generate the entry node of the callee. + virtual void ProcessCallEnter(GRCallEnterNodeBuilder &builder) = 0; + + // Generate the first post callsite node. + virtual void ProcessCallExit(GRCallExitNodeBuilder &builder) = 0; /// EvalAssume - Called by ConstraintManager. Used to call checker-specific /// logic for handling assumptions on symbolic values. diff --git a/include/clang/Checker/PathSensitive/MemRegion.h b/include/clang/Checker/PathSensitive/MemRegion.h index 12bc0b7..be89d2a 100644 --- a/include/clang/Checker/PathSensitive/MemRegion.h +++ b/include/clang/Checker/PathSensitive/MemRegion.h @@ -428,7 +428,6 @@ public: /// which correspond to "code+data". The distinction is important, because /// like a closure a block captures the values of externally referenced /// variables. -/// BlockDataRegion - A region that represents code texts of blocks (closures). class BlockDataRegion : public SubRegion { friend class MemRegionManager; const BlockTextRegion *BC; @@ -798,11 +797,10 @@ class MemRegionManager { GlobalsSpaceRegion *globals; - const StackFrameContext *cachedStackLocalsFrame; - StackLocalsSpaceRegion *cachedStackLocalsRegion; - - const StackFrameContext *cachedStackArgumentsFrame; - StackArgumentsSpaceRegion *cachedStackArgumentsRegion; + llvm::DenseMap<const StackFrameContext *, StackLocalsSpaceRegion *> + StackLocalsSpaceRegions; + llvm::DenseMap<const StackFrameContext *, StackArgumentsSpaceRegion *> + StackArgumentsSpaceRegions; HeapSpaceRegion *heap; UnknownSpaceRegion *unknown; @@ -810,10 +808,7 @@ class MemRegionManager { public: MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator& a) - : C(c), A(a), globals(0), - cachedStackLocalsFrame(0), cachedStackLocalsRegion(0), - cachedStackArgumentsFrame(0), cachedStackArgumentsRegion(0), - heap(0), unknown(0), code(0) {} + : C(c), A(a), globals(0), heap(0), unknown(0), code(0) {} ~MemRegionManager(); diff --git a/include/clang/Checker/PathSensitive/SymbolManager.h b/include/clang/Checker/PathSensitive/SymbolManager.h index 8eb3196..d49f5e8 100644 --- a/include/clang/Checker/PathSensitive/SymbolManager.h +++ b/include/clang/Checker/PathSensitive/SymbolManager.h @@ -89,27 +89,23 @@ public: typedef const SymbolData* SymbolRef; +// A symbol representing the value of a MemRegion. class SymbolRegionValue : public SymbolData { - const MemRegion *R; - // We may cast the region to another type, so the expected type of the symbol - // may be different from the region's original type. - QualType T; + const TypedRegion *R; public: - SymbolRegionValue(SymbolID sym, const MemRegion *r, QualType t = QualType()) - : SymbolData(RegionValueKind, sym), R(r), T(t) {} + SymbolRegionValue(SymbolID sym, const TypedRegion *r) + : SymbolData(RegionValueKind, sym), R(r) {} - const MemRegion* getRegion() const { return R; } + const TypedRegion* getRegion() const { return R; } - static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion* R, - QualType T) { + static void Profile(llvm::FoldingSetNodeID& profile, const TypedRegion* R) { profile.AddInteger((unsigned) RegionValueKind); profile.AddPointer(R); - T.Profile(profile); } virtual void Profile(llvm::FoldingSetNodeID& profile) { - Profile(profile, R, T); + Profile(profile, R); } void dumpToStream(llvm::raw_ostream &os) const; @@ -122,6 +118,7 @@ public: } }; +// A symbol representing the result of an expression. class SymbolConjured : public SymbolData { const Stmt* S; QualType T; @@ -161,6 +158,8 @@ public: } }; +// A symbol representing the value of a MemRegion whose parent region has +// symbolic value. class SymbolDerived : public SymbolData { SymbolRef parentSymbol; const TypedRegion *R; @@ -294,8 +293,8 @@ public: static bool canSymbolicate(QualType T); /// Make a unique symbol for MemRegion R according to its kind. - const SymbolRegionValue* getRegionValueSymbol(const MemRegion* R, - QualType T = QualType()); + const SymbolRegionValue* getRegionValueSymbol(const TypedRegion* R); + const SymbolConjured* getConjuredSymbol(const Stmt* E, QualType T, unsigned VisitCount, const void* SymbolTag = 0); diff --git a/include/clang/Checker/PathSensitive/ValueManager.h b/include/clang/Checker/PathSensitive/ValueManager.h index ea3af57..f80ad42 100644 --- a/include/clang/Checker/PathSensitive/ValueManager.h +++ b/include/clang/Checker/PathSensitive/ValueManager.h @@ -94,8 +94,7 @@ public: DefinedOrUnknownSVal makeZeroVal(QualType T); /// getRegionValueSymbolVal - make a unique symbol for value of R. - DefinedOrUnknownSVal getRegionValueSymbolVal(const MemRegion *R, - QualType T = QualType()); + DefinedOrUnknownSVal getRegionValueSymbolVal(const TypedRegion *R); DefinedOrUnknownSVal getConjuredSymbolVal(const void *SymbolTag, const Expr *E, unsigned Count); |