diff options
Diffstat (limited to 'include/clang/Analysis')
-rw-r--r-- | include/clang/Analysis/CallGraph.h | 146 | ||||
-rw-r--r-- | include/clang/Analysis/PathDiagnostic.h | 36 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/AnalysisContext.h | 126 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/AnalysisManager.h | 5 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/BugType.h | 1 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/Checker.h | 74 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/GRExprEngine.h | 23 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/GRState.h | 16 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/GRTransferFuncs.h | 3 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/MemRegion.h | 491 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/Store.h | 14 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/SymbolManager.h | 19 | ||||
-rw-r--r-- | include/clang/Analysis/ProgramPoint.h | 7 | ||||
-rw-r--r-- | include/clang/Analysis/Support/BumpVector.h | 2 |
14 files changed, 465 insertions, 498 deletions
diff --git a/include/clang/Analysis/CallGraph.h b/include/clang/Analysis/CallGraph.h deleted file mode 100644 index 5edfe6f..0000000 --- a/include/clang/Analysis/CallGraph.h +++ /dev/null @@ -1,146 +0,0 @@ -//== CallGraph.cpp - Call graph building ------------------------*- C++ -*--==// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defined the CallGraph and CallGraphNode classes. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_ANALYSIS_CALLGRAPH -#define LLVM_CLANG_ANALYSIS_CALLGRAPH - -#include "clang/Index/ASTLocation.h" -#include "clang/Index/Entity.h" -#include "clang/Index/Program.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/STLExtras.h" -#include <vector> -#include <map> - -namespace clang { - -class CallGraphNode { - idx::Entity F; - typedef std::pair<idx::ASTLocation, CallGraphNode*> CallRecord; - std::vector<CallRecord> CalledFunctions; - -public: - CallGraphNode(idx::Entity f) : F(f) {} - - typedef std::vector<CallRecord>::iterator iterator; - typedef std::vector<CallRecord>::const_iterator const_iterator; - - iterator begin() { return CalledFunctions.begin(); } - iterator end() { return CalledFunctions.end(); } - const_iterator begin() const { return CalledFunctions.begin(); } - const_iterator end() const { return CalledFunctions.end(); } - - void addCallee(idx::ASTLocation L, CallGraphNode *Node) { - CalledFunctions.push_back(std::make_pair(L, Node)); - } - - bool hasCallee() const { return begin() != end(); } - - std::string getName() const { return F.getPrintableName(); } - - Decl *getDecl(ASTContext &Ctx) const { return F.getDecl(Ctx); } -}; - -class CallGraph { - /// Program manages all Entities. - idx::Program Prog; - - typedef std::map<idx::Entity, CallGraphNode *> FunctionMapTy; - - /// FunctionMap owns all CallGraphNodes. - FunctionMapTy FunctionMap; - - /// CallerCtx maps a caller to its ASTContext. - llvm::DenseMap<CallGraphNode *, ASTContext *> CallerCtx; - - /// Root node is the 'main' function or 0. - CallGraphNode *Root; - - /// ExternalCallingNode has edges to all external functions. - CallGraphNode *ExternalCallingNode; - -public: - CallGraph(); - ~CallGraph(); - - typedef FunctionMapTy::iterator iterator; - typedef FunctionMapTy::const_iterator const_iterator; - - iterator begin() { return FunctionMap.begin(); } - iterator end() { return FunctionMap.end(); } - const_iterator begin() const { return FunctionMap.begin(); } - const_iterator end() const { return FunctionMap.end(); } - - CallGraphNode *getRoot() { return Root; } - - CallGraphNode *getExternalCallingNode() { return ExternalCallingNode; } - - void addTU(ASTContext &AST); - - idx::Program &getProgram() { return Prog; } - - CallGraphNode *getOrInsertFunction(idx::Entity F); - - Decl *getDecl(CallGraphNode *Node); - - void print(llvm::raw_ostream &os); - void dump(); - - void ViewCallGraph() const; -}; - -} // end clang namespace - -namespace llvm { - -template <> struct GraphTraits<clang::CallGraph> { - typedef clang::CallGraph GraphType; - typedef clang::CallGraphNode NodeType; - - typedef std::pair<clang::idx::ASTLocation, NodeType*> CGNPairTy; - typedef std::pointer_to_unary_function<CGNPairTy, NodeType*> CGNDerefFun; - - typedef mapped_iterator<NodeType::iterator, CGNDerefFun> ChildIteratorType; - - static NodeType *getEntryNode(GraphType *CG) { - return CG->getExternalCallingNode(); - } - - static ChildIteratorType child_begin(NodeType *N) { - return map_iterator(N->begin(), CGNDerefFun(CGNDeref)); - } - static ChildIteratorType child_end(NodeType *N) { - return map_iterator(N->end(), CGNDerefFun(CGNDeref)); - } - - typedef std::pair<clang::idx::Entity, NodeType*> PairTy; - typedef std::pointer_to_unary_function<PairTy, NodeType*> DerefFun; - - typedef mapped_iterator<GraphType::const_iterator, DerefFun> nodes_iterator; - - static nodes_iterator nodes_begin(const GraphType &CG) { - return map_iterator(CG.begin(), DerefFun(CGDeref)); - } - static nodes_iterator nodes_end(const GraphType &CG) { - return map_iterator(CG.end(), DerefFun(CGDeref)); - } - - static NodeType *CGNDeref(CGNPairTy P) { return P.second; } - - static NodeType *CGDeref(PairTy P) { return P.second; } -}; - -} // end llvm namespace - -#endif diff --git a/include/clang/Analysis/PathDiagnostic.h b/include/clang/Analysis/PathDiagnostic.h index cad702c..970b523 100644 --- a/include/clang/Analysis/PathDiagnostic.h +++ b/include/clang/Analysis/PathDiagnostic.h @@ -179,9 +179,7 @@ private: PathDiagnosticPiece& operator=(const PathDiagnosticPiece &P); protected: - PathDiagnosticPiece(const std::string& s, Kind k, DisplayHint hint = Below); - - PathDiagnosticPiece(const char* s, Kind k, DisplayHint hint = Below); + PathDiagnosticPiece(llvm::StringRef s, Kind k, DisplayHint hint = Below); PathDiagnosticPiece(Kind k, DisplayHint hint = Below); @@ -242,7 +240,7 @@ private: PathDiagnosticLocation Pos; public: PathDiagnosticSpotPiece(const PathDiagnosticLocation &pos, - const std::string& s, + llvm::StringRef s, PathDiagnosticPiece::Kind k, bool addPosRange = true) : PathDiagnosticPiece(s, k), Pos(pos) { @@ -261,11 +259,7 @@ class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece { public: PathDiagnosticEventPiece(const PathDiagnosticLocation &pos, - const std::string& s, bool addPosRange = true) - : PathDiagnosticSpotPiece(pos, s, Event, addPosRange) {} - - PathDiagnosticEventPiece(const PathDiagnosticLocation &pos, const char* s, - bool addPosRange = true) + llvm::StringRef s, bool addPosRange = true) : PathDiagnosticSpotPiece(pos, s, Event, addPosRange) {} ~PathDiagnosticEventPiece(); @@ -280,14 +274,7 @@ class PathDiagnosticControlFlowPiece : public PathDiagnosticPiece { public: PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos, const PathDiagnosticLocation &endPos, - const std::string& s) - : PathDiagnosticPiece(s, ControlFlow) { - LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos)); - } - - PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos, - const PathDiagnosticLocation &endPos, - const char* s) + llvm::StringRef s) : PathDiagnosticPiece(s, ControlFlow) { LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos)); } @@ -384,22 +371,19 @@ class PathDiagnostic : public llvm::FoldingSetNode { public: PathDiagnostic(); - PathDiagnostic(const char* bugtype, const char* desc, const char* category); - - PathDiagnostic(const std::string& bugtype, const std::string& desc, - const std::string& category); + PathDiagnostic(llvm::StringRef bugtype, llvm::StringRef desc, + llvm::StringRef category); ~PathDiagnostic(); - const std::string& getDescription() const { return Desc; } - const std::string& getBugType() const { return BugType; } - const std::string& getCategory() const { return Category; } + llvm::StringRef getDescription() const { return Desc; } + llvm::StringRef getBugType() const { return BugType; } + llvm::StringRef getCategory() const { return Category; } typedef std::deque<std::string>::const_iterator meta_iterator; meta_iterator meta_begin() const { return OtherDesc.begin(); } meta_iterator meta_end() const { return OtherDesc.end(); } - void addMeta(const std::string& s) { OtherDesc.push_back(s); } - void addMeta(const char* s) { OtherDesc.push_back(s); } + void addMeta(llvm::StringRef s) { OtherDesc.push_back(s); } PathDiagnosticLocation getLocation() const { assert(Size > 0 && "getLocation() requires a non-empty PathDiagnostic."); diff --git a/include/clang/Analysis/PathSensitive/AnalysisContext.h b/include/clang/Analysis/PathSensitive/AnalysisContext.h index 8b1a329..abc33b7 100644 --- a/include/clang/Analysis/PathSensitive/AnalysisContext.h +++ b/include/clang/Analysis/PathSensitive/AnalysisContext.h @@ -15,9 +15,10 @@ #ifndef LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H #define LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H -#include "clang/AST/Stmt.h" +#include "clang/AST/Decl.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Support/Allocator.h" @@ -29,7 +30,10 @@ class CFG; class LiveVariables; class ParentMap; class ImplicitParamDecl; - +class LocationContextManager; +class BlockDataRegion; +class StackFrameContext; + /// AnalysisContext contains the context data for the function or method under /// analysis. class AnalysisContext { @@ -78,7 +82,7 @@ public: class LocationContext : public llvm::FoldingSetNode { public: - enum ContextKind { StackFrame, Scope }; + enum ContextKind { StackFrame, Scope, Block }; private: ContextKind Kind; @@ -91,7 +95,7 @@ protected: : Kind(k), Ctx(ctx), Parent(parent) {} public: - virtual ~LocationContext() {} + virtual ~LocationContext(); ContextKind getKind() const { return Kind; } @@ -114,36 +118,42 @@ public: const ImplicitParamDecl *getSelfDecl() const { return Ctx->getSelfDecl(); } + + const StackFrameContext *getCurrentStackFrame() const; + const StackFrameContext * + getStackFrameForDeclContext(const DeclContext *DC) const; - virtual void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, Kind, Ctx, Parent); - } - - static void Profile(llvm::FoldingSetNodeID &ID, ContextKind k, - AnalysisContext *ctx, const LocationContext *parent); + virtual void Profile(llvm::FoldingSetNodeID &ID) = 0; static bool classof(const LocationContext*) { return true; } + +public: + static void ProfileCommon(llvm::FoldingSetNodeID &ID, + ContextKind ck, + AnalysisContext *ctx, + const LocationContext *parent, + const void* data); }; class StackFrameContext : public LocationContext { const Stmt *CallSite; -public: + friend class LocationContextManager; StackFrameContext(AnalysisContext *ctx, const LocationContext *parent, const Stmt *s) : LocationContext(StackFrame, ctx, parent), CallSite(s) {} - - virtual ~StackFrameContext() {} +public: + ~StackFrameContext() {} - Stmt const *getCallSite() const { return CallSite; } - - virtual void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getAnalysisContext(), getParent(), CallSite); - } + const Stmt *getCallSite() const { return CallSite; } + void Profile(llvm::FoldingSetNodeID &ID); + static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, - const LocationContext *parent, const Stmt *s); + const LocationContext *parent, const Stmt *s) { + ProfileCommon(ID, StackFrame, ctx, parent, s); + } static bool classof(const LocationContext* Ctx) { return Ctx->getKind() == StackFrame; @@ -152,41 +162,91 @@ public: class ScopeContext : public LocationContext { const Stmt *Enter; - -public: + + friend class LocationContextManager; ScopeContext(AnalysisContext *ctx, const LocationContext *parent, const Stmt *s) : LocationContext(Scope, ctx, parent), Enter(s) {} - - virtual ~ScopeContext() {} - virtual void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getAnalysisContext(), getParent(), Enter); - } +public: + ~ScopeContext() {} + + void Profile(llvm::FoldingSetNodeID &ID); static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, - const LocationContext *parent, const Stmt *s); + const LocationContext *parent, const Stmt *s) { + ProfileCommon(ID, Scope, ctx, parent, s); + } static bool classof(const LocationContext* Ctx) { return Ctx->getKind() == Scope; } }; +class BlockInvocationContext : public LocationContext { + llvm::PointerUnion<const BlockDataRegion *, const BlockDecl *> Data; + + friend class LocationContextManager; + + BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent, + const BlockDataRegion *br) + : LocationContext(Block, ctx, parent), Data(br) {} + + BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent, + const BlockDecl *bd) + : LocationContext(Block, ctx, parent), Data(bd) {} + +public: + ~BlockInvocationContext() {} + + const BlockDataRegion *getBlockRegion() const { + return Data.is<const BlockDataRegion*>() ? + Data.get<const BlockDataRegion*>() : 0; + } + + const BlockDecl *getBlockDecl() const; + + void Profile(llvm::FoldingSetNodeID &ID); + + static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, + const LocationContext *parent, const BlockDataRegion *br){ + ProfileCommon(ID, Block, ctx, parent, br); + } + + static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, + const LocationContext *parent, const BlockDecl *bd) { + ProfileCommon(ID, Block, ctx, parent, bd); + } + + static bool classof(const LocationContext* Ctx) { + return Ctx->getKind() == Block; + } +}; + class LocationContextManager { llvm::FoldingSet<LocationContext> Contexts; - public: ~LocationContextManager(); - StackFrameContext *getStackFrame(AnalysisContext *ctx, - const LocationContext *parent, - const Stmt *s); + const StackFrameContext *getStackFrame(AnalysisContext *ctx, + const LocationContext *parent, + const Stmt *s); - ScopeContext *getScope(AnalysisContext *ctx, const LocationContext *parent, - const Stmt *s); + const ScopeContext *getScope(AnalysisContext *ctx, + const LocationContext *parent, + const Stmt *s); + + const BlockInvocationContext * + getBlockInvocation(AnalysisContext *ctx, const LocationContext *parent, + const BlockDataRegion *BR); /// Discard all previously created LocationContext objects. void clear(); +private: + template <typename LOC, typename DATA> + const LOC *getLocationContext(AnalysisContext *ctx, + const LocationContext *parent, + const DATA *d); }; } // end clang namespace diff --git a/include/clang/Analysis/PathSensitive/AnalysisManager.h b/include/clang/Analysis/PathSensitive/AnalysisManager.h index 18eae9a..9ef5cce 100644 --- a/include/clang/Analysis/PathSensitive/AnalysisManager.h +++ b/include/clang/Analysis/PathSensitive/AnalysisManager.h @@ -56,8 +56,7 @@ public: const LangOptions &lang, PathDiagnosticClient *pd, StoreManagerCreator storemgr, ConstraintManagerCreator constraintmgr, - bool displayProgress, bool vizdot, bool vizubi, - bool purge, bool eager, bool trim) + bool vizdot, bool vizubi, bool purge, bool eager, bool trim) : Ctx(ctx), Diags(diags), LangInfo(lang), PD(pd), CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr), @@ -132,7 +131,7 @@ public: } // Get the top level stack frame. - StackFrameContext *getStackFrame(Decl const *D) { + const StackFrameContext *getStackFrame(Decl const *D) { return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), 0, 0); } diff --git a/include/clang/Analysis/PathSensitive/BugType.h b/include/clang/Analysis/PathSensitive/BugType.h index 4f1523a..b75a818 100644 --- a/include/clang/Analysis/PathSensitive/BugType.h +++ b/include/clang/Analysis/PathSensitive/BugType.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_ANALYSIS_BUGTYPE #define LLVM_CLANG_ANALYSIS_BUGTYPE +#include "clang/Analysis/PathSensitive/BugReporter.h" #include <llvm/ADT/FoldingSet.h> #include <string> diff --git a/include/clang/Analysis/PathSensitive/Checker.h b/include/clang/Analysis/PathSensitive/Checker.h index 91a4b6d..a625a7a 100644 --- a/include/clang/Analysis/PathSensitive/Checker.h +++ b/include/clang/Analysis/PathSensitive/Checker.h @@ -39,7 +39,7 @@ class CheckerContext { SaveAndRestore<const void*> OldTag; SaveAndRestore<ProgramPoint::Kind> OldPointKind; SaveOr OldHasGen; - const GRState *state; + const GRState *ST; const Stmt *statement; const unsigned size; bool DoneEvaluating; // FIXME: This is not a permanent API change. @@ -53,22 +53,14 @@ public: OldTag(B.Tag, tag), OldPointKind(B.PointKind, K), OldHasGen(B.HasGeneratedNode), - state(st), statement(stmt), size(Dst.size()), - DoneEvaluating(false) {} + ST(st), statement(stmt), size(Dst.size()) {} ~CheckerContext(); - - // FIXME: This were added to support CallAndMessageChecker to indicating - // to GRExprEngine to "stop evaluating" a message expression under certain - // cases. This is *not* meant to be a permanent API change, and was added - // to aid in the transition of removing logic for checks from GRExprEngine. - void setDoneEvaluating() { - DoneEvaluating = true; - } - bool isDoneEvaluating() const { - return DoneEvaluating; + + GRExprEngine &getEngine() { + return Eng; } - + ConstraintManager &getConstraintManager() { return Eng.getConstraintManager(); } @@ -80,7 +72,7 @@ public: ExplodedNodeSet &getNodeSet() { return Dst; } GRStmtNodeBuilder &getNodeBuilder() { return B; } ExplodedNode *&getPredecessor() { return Pred; } - const GRState *getState() { return state ? state : B.GetState(Pred); } + const GRState *getState() { return ST ? ST : B.GetState(Pred); } ASTContext &getASTContext() { return Eng.getContext(); @@ -98,6 +90,10 @@ public: return Eng.getValueManager(); } + SValuator &getSValuator() { + return Eng.getSValuator(); + } + ExplodedNode *GenerateNode(bool autoTransition = true) { assert(statement && "Only transitions with statements currently supported"); ExplodedNode *N = GenerateNodeImpl(statement, getState(), false); @@ -115,6 +111,15 @@ public: return N; } + ExplodedNode *GenerateNode(const GRState *state, ExplodedNode *pred, + bool autoTransition = true) { + assert(statement && "Only transitions with statements currently supported"); + ExplodedNode *N = GenerateNodeImpl(statement, state, pred, false); + if (N && autoTransition) + addTransition(N); + return N; + } + ExplodedNode *GenerateNode(const GRState *state, bool autoTransition = true) { assert(statement && "Only transitions with statements currently supported"); ExplodedNode *N = GenerateNodeImpl(statement, state, false); @@ -138,8 +143,7 @@ public: void addTransition(const GRState *state) { assert(state); - if (state != getState() || - (state && state != B.GetState(Pred))) + if (state != getState() || (ST && ST != B.GetState(Pred))) GenerateNode(state, true); else Dst.Add(Pred); @@ -157,7 +161,14 @@ private: node->markAsSink(); return node; } - + + ExplodedNode *GenerateNodeImpl(const Stmt* stmt, const GRState *state, + ExplodedNode *pred, bool markAsSink) { + ExplodedNode *node = B.generateNode(stmt, state, pred); + if (markAsSink && node) + node->markAsSink(); + return node; + } }; class Checker { @@ -165,7 +176,7 @@ private: friend class GRExprEngine; // FIXME: Remove the 'tag' option. - bool GR_Visit(ExplodedNodeSet &Dst, + void GR_Visit(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder, GRExprEngine &Eng, const Stmt *S, @@ -177,7 +188,22 @@ private: _PreVisit(C, S); else _PostVisit(C, S); - return C.isDoneEvaluating(); + } + + bool GR_EvalNilReceiver(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder, + GRExprEngine &Eng, const ObjCMessageExpr *ME, + ExplodedNode *Pred, const GRState *state, void *tag) { + CheckerContext C(Dst, Builder, Eng, Pred, tag, ProgramPoint::PostStmtKind, + ME, state); + return EvalNilReceiver(C, ME); + } + + bool GR_EvalCallExpr(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder, + GRExprEngine &Eng, const CallExpr *CE, + ExplodedNode *Pred, void *tag) { + CheckerContext C(Dst, Builder, Eng, Pred, tag, ProgramPoint::PostStmtKind, + CE); + return EvalCallExpr(C, CE); } // FIXME: Remove the 'tag' option. @@ -231,6 +257,14 @@ public: virtual void VisitBranchCondition(GRBranchNodeBuilder &Builder, GRExprEngine &Eng, Stmt *Condition, void *tag) {} + + virtual bool EvalNilReceiver(CheckerContext &C, const ObjCMessageExpr *ME) { + return false; + } + + virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE) { + return false; + } }; } // end clang namespace diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index a7302c0..8b20a82 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -209,8 +209,17 @@ public: protected: /// CheckerVisit - Dispatcher for performing checker-specific logic /// at specific statements. - bool CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src, + void CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src, bool isPrevisit); + + bool CheckerEvalCall(const CallExpr *CE, + ExplodedNodeSet &Dst, + ExplodedNode *Pred); + + void CheckerEvalNilReceiver(const ObjCMessageExpr *ME, + ExplodedNodeSet &Dst, + const GRState *state, + ExplodedNode *Pred); void CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE, ExplodedNodeSet &Dst, ExplodedNodeSet &Src, @@ -272,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); @@ -358,9 +374,10 @@ public: } protected: - void EvalObjCMessageExpr(ExplodedNodeSet& Dst, ObjCMessageExpr* ME, ExplodedNode* Pred) { + void EvalObjCMessageExpr(ExplodedNodeSet& Dst, ObjCMessageExpr* ME, + ExplodedNode* Pred, const GRState *state) { assert (Builder && "GRStmtNodeBuilder must be defined."); - getTF().EvalObjCMessageExpr(Dst, *this, *Builder, ME, Pred); + getTF().EvalObjCMessageExpr(Dst, *this, *Builder, ME, Pred, state); } const GRState* MarkBranch(const GRState* St, Stmt* Terminator, diff --git a/include/clang/Analysis/PathSensitive/GRState.h b/include/clang/Analysis/PathSensitive/GRState.h index d8bc241..421ebbf 100644 --- a/include/clang/Analysis/PathSensitive/GRState.h +++ b/include/clang/Analysis/PathSensitive/GRState.h @@ -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 { diff --git a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h index 40c1ed3..2594618 100644 --- a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h +++ b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h @@ -47,7 +47,8 @@ public: GRExprEngine& Engine, GRStmtNodeBuilder& Builder, ObjCMessageExpr* ME, - ExplodedNode* Pred) {} + ExplodedNode* Pred, + const GRState *state) {} // Stores. diff --git a/include/clang/Analysis/PathSensitive/MemRegion.h b/include/clang/Analysis/PathSensitive/MemRegion.h index ed96497..2fe5ea0 100644 --- a/include/clang/Analysis/PathSensitive/MemRegion.h +++ b/include/clang/Analysis/PathSensitive/MemRegion.h @@ -35,6 +35,7 @@ namespace clang { class MemRegionManager; class MemSpaceRegion; class LocationContext; +class StackFrameContext; class VarRegion; //===----------------------------------------------------------------------===// @@ -45,22 +46,37 @@ 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, + UnknownSpaceRegionKind, + 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 +127,102 @@ 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) {} + MemSpaceRegion(MemRegionManager *mgr, Kind k = GenericMemSpaceRegionKind) + : MemRegion(k), Mgr(mgr) { + assert(classof(this)); + } + + MemRegionManager* getMemRegionManager() const { return Mgr; } + +public: + bool isBoundable() const { return false; } + + void Profile(llvm::FoldingSetNodeID &ID) const; - MemRegionManager* getMemRegionManager() const { - return Mgr; + 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: - void Profile(llvm::FoldingSetNodeID& ID) const; + 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 UnknownSpaceRegion : public MemSpaceRegion { + friend class MemRegionManager; + UnknownSpaceRegion(MemRegionManager *mgr) + : MemSpaceRegion(mgr, UnknownSpaceRegionKind) {} +public: + static bool classof(const MemRegion *R) { + return R->getKind() == UnknownSpaceRegionKind; + } +}; + +class StackSpaceRegion : public MemSpaceRegion { +private: + const StackFrameContext *SFC; - bool isBoundable() const { return false; } +protected: + StackSpaceRegion(MemRegionManager *mgr, Kind k, const StackFrameContext *sfc) + : MemSpaceRegion(mgr, k), SFC(sfc) { + assert(classof(this)); + } - static bool classof(const MemRegion* R) { - return R->getKind() == MemSpaceRegionKind; +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 +242,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 +330,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 +388,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 +406,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,18 +430,45 @@ 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; } - typedef const MemRegion * const * referenced_vars_iterator; + const BlockDecl *getDecl() const { return BC->getDecl(); } + + class referenced_vars_iterator { + const MemRegion * const *R; + public: + explicit referenced_vars_iterator(const MemRegion * const *r) : R(r) {} + + operator const MemRegion * const *() const { + return R; + } + + const VarRegion* operator*() const { + return cast<VarRegion>(*R); + } + + bool operator==(const referenced_vars_iterator &I) const { + return I.R == R; + } + bool operator!=(const referenced_vars_iterator &I) const { + return I.R != R; + } + referenced_vars_iterator& operator++() { + ++R; + return *this; + } + }; + referenced_vars_iterator referenced_vars_begin() const; referenced_vars_iterator referenced_vars_end() const; @@ -348,9 +476,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; @@ -473,25 +600,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; @@ -499,8 +621,8 @@ class VarRegion : public DeclRegion { public: const VarDecl *getDecl() const { return cast<VarDecl>(D); } - const LocationContext *getLocationContext() const { return LC; } - + const StackFrameContext *getStackFrame() const; + QualType getValueType(ASTContext& C) const { // FIXME: We can cache this if needed. return C.getCanonicalType(getDecl()->getType()); @@ -647,17 +769,24 @@ class MemRegionManager { llvm::BumpPtrAllocator& A; llvm::FoldingSet<MemRegion> Regions; - MemSpaceRegion *globals; - MemSpaceRegion *stack; - MemSpaceRegion *stackArguments; - MemSpaceRegion *heap; - MemSpaceRegion *unknown; + GlobalsSpaceRegion *globals; + + const StackFrameContext *cachedStackLocalsFrame; + StackLocalsSpaceRegion *cachedStackLocalsRegion; + + const StackFrameContext *cachedStackArgumentsFrame; + StackArgumentsSpaceRegion *cachedStackArgumentsRegion; + + HeapSpaceRegion *heap; + UnknownSpaceRegion *unknown; MemSpaceRegion *code; public: MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator& a) - : C(c), A(a), globals(0), stack(0), stackArguments(0), heap(0), - unknown(0), code(0) {} + : C(c), A(a), globals(0), + cachedStackLocalsFrame(0), cachedStackLocalsRegion(0), + cachedStackArgumentsFrame(0), cachedStackArgumentsRegion(0), + heap(0), unknown(0), code(0) {} ~MemRegionManager(); @@ -665,52 +794,60 @@ public: llvm::BumpPtrAllocator &getAllocator() { return A; } - /// getStackRegion - Retrieve the memory region associated with the - /// current stack frame. - 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. - 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. - MemSpaceRegion *getGlobalsRegion(); + const GlobalsSpaceRegion *getGlobalsRegion(); /// getHeapRegion - Retrieve the memory region associated with the /// generic "heap". - MemSpaceRegion *getHeapRegion(); + const HeapSpaceRegion *getHeapRegion(); /// getUnknownRegion - Retrieve the memory region associated with unknown /// memory space. - MemSpaceRegion *getUnknownRegion(); + const MemSpaceRegion *getUnknownRegion(); - MemSpaceRegion *getCodeRegion(); + const MemSpaceRegion *getCodeRegion(); /// getAllocaRegion - Retrieve a region associated with a call to alloca(). - 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. - CompoundLiteralRegion* - getCompoundLiteralRegion(const CompoundLiteralExpr* CL); + const CompoundLiteralRegion* + getCompoundLiteralRegion(const CompoundLiteralExpr* CL, + const LocationContext *LC); /// getSymbolicRegion - Retrieve or create a "symbolic" memory region. - SymbolicRegion* getSymbolicRegion(SymbolRef sym); + const SymbolicRegion* getSymbolicRegion(SymbolRef sym); - StringRegion* getStringRegion(const StringLiteral* Str); + const StringRegion* getStringRegion(const StringLiteral* Str); /// getVarRegion - Retrieve or create the memory region associated with /// a specified VarDecl and LocationContext. - VarRegion* getVarRegion(const VarDecl *D, const LocationContext *LC); + 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. - ElementRegion *getElementRegion(QualType elementType, SVal Idx, + const ElementRegion *getElementRegion(QualType elementType, SVal Idx, const MemRegion *superRegion, ASTContext &Ctx); - ElementRegion *getElementRegionWithSuper(const ElementRegion *ER, + const ElementRegion *getElementRegionWithSuper(const ElementRegion *ER, const MemRegion *superRegion) { return getElementRegion(ER->getElementType(), ER->getIndex(), superRegion, ER->getContext()); @@ -720,31 +857,44 @@ public: /// a specified FieldDecl. 'superRegion' corresponds to the containing /// memory region (which typically represents the memory representing /// a structure or class). - FieldRegion *getFieldRegion(const FieldDecl* fd, - const MemRegion* superRegion); + const FieldRegion *getFieldRegion(const FieldDecl* fd, + const MemRegion* superRegion); - FieldRegion *getFieldRegionWithSuper(const FieldRegion *FR, - const MemRegion *superRegion) { + const FieldRegion *getFieldRegionWithSuper(const FieldRegion *FR, + const MemRegion *superRegion) { return getFieldRegion(FR->getDecl(), superRegion); } /// getObjCObjectRegion - Retrieve or create the memory region associated with /// the instance of a specified Objective-C class. - ObjCObjectRegion* getObjCObjectRegion(const ObjCInterfaceDecl* ID, - const MemRegion* superRegion); + const ObjCObjectRegion* getObjCObjectRegion(const ObjCInterfaceDecl* ID, + const MemRegion* superRegion); /// getObjCIvarRegion - Retrieve or create the memory region associated with /// a specified Objective-c instance variable. 'superRegion' corresponds /// to the containing region (which typically represents the Objective-C /// object). - ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl* ivd, - const MemRegion* superRegion); + const ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl* ivd, + const MemRegion* superRegion); - FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD); - BlockTextRegion *getBlockTextRegion(const BlockDecl *BD, CanQualType locTy); - BlockDataRegion *getBlockDataRegion(const BlockTextRegion *bc, - const LocationContext *lc); + const FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD); + const BlockTextRegion *getBlockTextRegion(const BlockDecl *BD, + 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 = NULL); + bool isGlobalsRegion(const MemRegion* R) { + assert(R); + return R == globals; + } + +private: template <typename RegionTy, typename A1> RegionTy* getRegion(const A1 a1); @@ -758,13 +908,15 @@ public: RegionTy* getSubRegion(const A1 a1, const A2 a2, const MemRegion* superRegion); - bool isGlobalsRegion(const MemRegion* R) { - assert(R); - return R == globals; - } - -private: - 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); }; //===----------------------------------------------------------------------===// @@ -774,157 +926,6 @@ private: inline ASTContext& MemRegion::getContext() const { return getMemRegionManager()->getContext(); } - -template<typename RegionTy> struct MemRegionManagerTrait; - -template <typename RegionTy, typename A1> -RegionTy* MemRegionManager::getRegion(const A1 a1) { - - const typename MemRegionManagerTrait<RegionTy>::SuperRegionTy *superRegion = - MemRegionManagerTrait<RegionTy>::getSuperRegion(*this, a1); - - llvm::FoldingSetNodeID ID; - RegionTy::ProfileRegion(ID, a1, superRegion); - void* InsertPos; - RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, - InsertPos)); - - if (!R) { - R = (RegionTy*) A.Allocate<RegionTy>(); - new (R) RegionTy(a1, superRegion); - Regions.InsertNode(R, InsertPos); - } - - 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)); - - if (!R) { - R = (RegionTy*) A.Allocate<RegionTy>(); - new (R) RegionTy(a1, superRegion); - Regions.InsertNode(R, InsertPos); - } - - return R; -} - -template <typename RegionTy, typename A1, typename A2> -RegionTy* MemRegionManager::getRegion(const A1 a1, const A2 a2) { - - const typename MemRegionManagerTrait<RegionTy>::SuperRegionTy *superRegion = - MemRegionManagerTrait<RegionTy>::getSuperRegion(*this, a1, a2); - - llvm::FoldingSetNodeID ID; - RegionTy::ProfileRegion(ID, a1, a2, 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, superRegion); - Regions.InsertNode(R, InsertPos); - } - - return R; -} - -template <typename RegionTy, typename A1, typename A2> -RegionTy* MemRegionManager::getSubRegion(const A1 a1, const A2 a2, - const MemRegion *superRegion) { - - llvm::FoldingSetNodeID ID; - RegionTy::ProfileRegion(ID, a1, a2, 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, superRegion); - Regions.InsertNode(R, InsertPos); - } - - 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 <> 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(); - } -}; } // end clang namespace diff --git a/include/clang/Analysis/PathSensitive/Store.h b/include/clang/Analysis/PathSensitive/Store.h index 55fa83d..648710f 100644 --- a/include/clang/Analysis/PathSensitive/Store.h +++ b/include/clang/Analysis/PathSensitive/Store.h @@ -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; @@ -147,6 +149,12 @@ public: const MemRegion *R, const Expr *E, unsigned Count, InvalidatedSymbols *IS) = 0; + + virtual const GRState *InvalidateRegions(const GRState *state, + const MemRegion * const *Begin, + const MemRegion * const *End, + const Expr *E, unsigned Count, + InvalidatedSymbols *IS); // FIXME: Make out-of-line. virtual const GRState *setExtent(const GRState *state, diff --git a/include/clang/Analysis/PathSensitive/SymbolManager.h b/include/clang/Analysis/PathSensitive/SymbolManager.h index 167a102..8eb3196 100644 --- a/include/clang/Analysis/PathSensitive/SymbolManager.h +++ b/include/clang/Analysis/PathSensitive/SymbolManager.h @@ -28,10 +28,12 @@ namespace llvm { } namespace clang { - class MemRegion; - class TypedRegion; class ASTContext; class BasicValueFactory; + class MemRegion; + class TypedRegion; + class VarRegion; + class StackFrameContext; } namespace clang { @@ -332,10 +334,13 @@ class SymbolReaper { SetTy TheDead; LiveVariables& Liveness; SymbolManager& SymMgr; + const StackFrameContext *CurrentStackFrame; public: - SymbolReaper(LiveVariables& liveness, SymbolManager& symmgr) - : Liveness(liveness), SymMgr(symmgr) {} + SymbolReaper(LiveVariables& liveness, SymbolManager& symmgr, + const StackFrameContext *currentStackFrame) + : Liveness(liveness), SymMgr(symmgr), CurrentStackFrame(currentStackFrame) + {} ~SymbolReaper() {} @@ -345,10 +350,8 @@ public: return Liveness.isLive(Loc, ExprVal); } - bool isLive(const Stmt* Loc, const VarDecl* VD) const { - return Liveness.isLive(Loc, VD); - } - + bool isLive(const Stmt* Loc, const VarRegion *VR) const; + void markLive(SymbolRef sym); bool maybeDead(SymbolRef sym); diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h index 78827df..5abe1ab 100644 --- a/include/clang/Analysis/ProgramPoint.h +++ b/include/clang/Analysis/ProgramPoint.h @@ -333,10 +333,11 @@ static bool isEqual(const clang::ProgramPoint& L, return L == R; } -static bool isPod() { - return true; -} }; + +template <> +struct isPodLike<clang::ProgramPoint> { static const bool value = true; }; + } // end namespace llvm #endif diff --git a/include/clang/Analysis/Support/BumpVector.h b/include/clang/Analysis/Support/BumpVector.h index b23a80e..48851d0 100644 --- a/include/clang/Analysis/Support/BumpVector.h +++ b/include/clang/Analysis/Support/BumpVector.h @@ -166,7 +166,7 @@ public: private: /// grow - double the size of the allocated memory, guaranteeing space for at /// least one more element or MinSize if specified. - void grow(BumpVectorContext &C, size_type MinSize = 0); + void grow(BumpVectorContext &C, size_type MinSize = 1); void construct_range(T *S, T *E, const T &Elt) { for (; S != E; ++S) |