summaryrefslogtreecommitdiffstats
path: root/include/clang/Analysis
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/Analysis')
-rw-r--r--include/clang/Analysis/CallGraph.h146
-rw-r--r--include/clang/Analysis/PathDiagnostic.h36
-rw-r--r--include/clang/Analysis/PathSensitive/AnalysisContext.h126
-rw-r--r--include/clang/Analysis/PathSensitive/AnalysisManager.h5
-rw-r--r--include/clang/Analysis/PathSensitive/BugType.h1
-rw-r--r--include/clang/Analysis/PathSensitive/Checker.h74
-rw-r--r--include/clang/Analysis/PathSensitive/GRExprEngine.h23
-rw-r--r--include/clang/Analysis/PathSensitive/GRState.h16
-rw-r--r--include/clang/Analysis/PathSensitive/GRTransferFuncs.h3
-rw-r--r--include/clang/Analysis/PathSensitive/MemRegion.h491
-rw-r--r--include/clang/Analysis/PathSensitive/Store.h14
-rw-r--r--include/clang/Analysis/PathSensitive/SymbolManager.h19
-rw-r--r--include/clang/Analysis/ProgramPoint.h7
-rw-r--r--include/clang/Analysis/Support/BumpVector.h2
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)
OpenPOWER on IntegriCloud