summaryrefslogtreecommitdiffstats
path: root/include/clang/Analysis/PathSensitive
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/Analysis/PathSensitive')
-rw-r--r--include/clang/Analysis/PathSensitive/AnalysisContext.h14
-rw-r--r--include/clang/Analysis/PathSensitive/BugReporter.h21
-rw-r--r--include/clang/Analysis/PathSensitive/BugType.h30
-rw-r--r--include/clang/Analysis/PathSensitive/Checker.h101
-rw-r--r--include/clang/Analysis/PathSensitive/CheckerVisitor.def18
-rw-r--r--include/clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h33
-rw-r--r--include/clang/Analysis/PathSensitive/ExplodedGraph.h14
-rw-r--r--include/clang/Analysis/PathSensitive/GRCoreEngine.h4
-rw-r--r--include/clang/Analysis/PathSensitive/GRExprEngine.h131
-rw-r--r--include/clang/Analysis/PathSensitive/GRState.h28
-rw-r--r--include/clang/Analysis/PathSensitive/MemRegion.h161
-rw-r--r--include/clang/Analysis/PathSensitive/ValueManager.h3
12 files changed, 319 insertions, 239 deletions
diff --git a/include/clang/Analysis/PathSensitive/AnalysisContext.h b/include/clang/Analysis/PathSensitive/AnalysisContext.h
index 9b58f74..8b1a329 100644
--- a/include/clang/Analysis/PathSensitive/AnalysisContext.h
+++ b/include/clang/Analysis/PathSensitive/AnalysisContext.h
@@ -19,6 +19,7 @@
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/Allocator.h"
namespace clang {
@@ -38,17 +39,26 @@ class AnalysisContext {
CFG *cfg;
LiveVariables *liveness;
ParentMap *PM;
-
+ llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
+ llvm::BumpPtrAllocator A;
public:
- AnalysisContext(const Decl *d) : D(d), cfg(0), liveness(0), PM(0) {}
+ AnalysisContext(const Decl *d) : D(d), cfg(0), liveness(0), PM(0),
+ ReferencedBlockVars(0) {}
+
~AnalysisContext();
+ ASTContext &getASTContext() { return D->getASTContext(); }
const Decl *getDecl() { return D; }
Stmt *getBody();
CFG *getCFG();
ParentMap &getParentMap();
LiveVariables *getLiveVariables();
+ typedef const VarDecl * const * referenced_decls_iterator;
+
+ std::pair<referenced_decls_iterator, referenced_decls_iterator>
+ getReferencedBlockVars(const BlockDecl *BD);
+
/// Return the ImplicitParamDecl* associated with 'self' if this
/// AnalysisContext wraps an ObjCMethodDecl. Returns NULL otherwise.
const ImplicitParamDecl *getSelfDecl() const;
diff --git a/include/clang/Analysis/PathSensitive/BugReporter.h b/include/clang/Analysis/PathSensitive/BugReporter.h
index f429735..58c8018 100644
--- a/include/clang/Analysis/PathSensitive/BugReporter.h
+++ b/include/clang/Analysis/PathSensitive/BugReporter.h
@@ -309,32 +309,33 @@ public:
void EmitReport(BugReport *R);
- void EmitBasicReport(const char* BugName, const char* BugStr,
+ void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef BugStr,
SourceLocation Loc,
SourceRange* RangeBeg, unsigned NumRanges);
- void EmitBasicReport(const char* BugName, const char* BugCategory,
- const char* BugStr, SourceLocation Loc,
+ void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef BugCategory,
+ llvm::StringRef BugStr, SourceLocation Loc,
SourceRange* RangeBeg, unsigned NumRanges);
- void EmitBasicReport(const char* BugName, const char* BugStr,
+ void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef BugStr,
SourceLocation Loc) {
EmitBasicReport(BugName, BugStr, Loc, 0, 0);
}
- void EmitBasicReport(const char* BugName, const char* BugCategory,
- const char* BugStr, SourceLocation Loc) {
+ void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef BugCategory,
+ llvm::StringRef BugStr, SourceLocation Loc) {
EmitBasicReport(BugName, BugCategory, BugStr, Loc, 0, 0);
}
- void EmitBasicReport(const char* BugName, const char* BugStr,
+ void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef BugStr,
SourceLocation Loc, SourceRange R) {
EmitBasicReport(BugName, BugStr, Loc, &R, 1);
}
- void EmitBasicReport(const char* BugName, const char* Category,
- const char* BugStr, SourceLocation Loc, SourceRange R) {
+ void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef Category,
+ llvm::StringRef BugStr, SourceLocation Loc,
+ SourceRange R) {
EmitBasicReport(BugName, Category, BugStr, Loc, &R, 1);
}
@@ -432,7 +433,7 @@ class DiagBugReport : public RangedBugReport {
std::list<std::string> Strs;
FullSourceLoc L;
public:
- DiagBugReport(BugType& D, const char* desc, FullSourceLoc l) :
+ DiagBugReport(BugType& D, llvm::StringRef desc, FullSourceLoc l) :
RangedBugReport(D, desc, 0), L(l) {}
virtual ~DiagBugReport() {}
diff --git a/include/clang/Analysis/PathSensitive/BugType.h b/include/clang/Analysis/PathSensitive/BugType.h
index 8303dee..4f1523a 100644
--- a/include/clang/Analysis/PathSensitive/BugType.h
+++ b/include/clang/Analysis/PathSensitive/BugType.h
@@ -34,13 +34,13 @@ private:
friend class BugReporter;
bool SuppressonSink;
public:
- BugType(const char *name, const char* cat)
+ BugType(llvm::StringRef name, llvm::StringRef cat)
: Name(name), Category(cat), SuppressonSink(false) {}
virtual ~BugType();
// FIXME: Should these be made strings as well?
- const std::string& getName() const { return Name; }
- const std::string& getCategory() const { return Category; }
+ llvm::StringRef getName() const { return Name; }
+ llvm::StringRef getCategory() const { return Category; }
/// isSuppressOnSink - Returns true if bug reports associated with this bug
/// type should be suppressed if the end node of the report is post-dominated
@@ -60,33 +60,15 @@ public:
};
class BuiltinBug : public BugType {
- GRExprEngine *Eng;
-protected:
const std::string desc;
public:
BuiltinBug(const char *name, const char *description)
- : BugType(name, "Logic error"), Eng(0), desc(description) {}
+ : BugType(name, "Logic error"), desc(description) {}
BuiltinBug(const char *name)
- : BugType(name, "Logic error"), Eng(0), desc(name) {}
+ : BugType(name, "Logic error"), desc(name) {}
- BuiltinBug(GRExprEngine *eng, const char* n, const char* d)
- : BugType(n, "Logic error"), Eng(eng), desc(d) {}
-
- BuiltinBug(GRExprEngine *eng, const char* n)
- : BugType(n, "Logic error"), Eng(eng), desc(n) {}
-
- const std::string &getDescription() const { return desc; }
-
- virtual void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {}
-
- void FlushReports(BugReporter& BR) { FlushReportsImpl(BR, *Eng); }
-
- virtual void registerInitialVisitors(BugReporterContext& BRC,
- const ExplodedNode* N,
- BuiltinBugReport *R) {}
-
- template <typename ITER> void Emit(BugReporter& BR, ITER I, ITER E);
+ llvm::StringRef getDescription() const { return desc; }
};
} // end clang namespace
diff --git a/include/clang/Analysis/PathSensitive/Checker.h b/include/clang/Analysis/PathSensitive/Checker.h
index b7ed20f..91a4b6d 100644
--- a/include/clang/Analysis/PathSensitive/Checker.h
+++ b/include/clang/Analysis/PathSensitive/Checker.h
@@ -40,24 +40,35 @@ class CheckerContext {
SaveAndRestore<ProgramPoint::Kind> OldPointKind;
SaveOr OldHasGen;
const GRState *state;
-
+ const Stmt *statement;
+ const unsigned size;
+ bool DoneEvaluating; // FIXME: This is not a permanent API change.
public:
CheckerContext(ExplodedNodeSet &dst, GRStmtNodeBuilder &builder,
GRExprEngine &eng, ExplodedNode *pred,
const void *tag, ProgramPoint::Kind K,
- const GRState *st = 0)
+ const Stmt *stmt = 0, const GRState *st = 0)
: Dst(dst), B(builder), Eng(eng), Pred(pred),
OldSink(B.BuildSinks),
OldTag(B.Tag, tag),
OldPointKind(B.PointKind, K),
OldHasGen(B.HasGeneratedNode),
- state(st) {}
+ state(st), statement(stmt), size(Dst.size()),
+ DoneEvaluating(false) {}
- ~CheckerContext() {
- if (!B.BuildSinks && !B.HasGeneratedNode)
- Dst.Add(Pred);
+ ~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;
+ }
+
ConstraintManager &getConstraintManager() {
return Eng.getConstraintManager();
}
@@ -83,27 +94,70 @@ public:
return getBugReporter().getSourceManager();
}
- ExplodedNode *GenerateNode(const Stmt *S, bool markAsSink = false) {
- return GenerateNode(S, getState(), markAsSink);
+ ValueManager &getValueManager() {
+ return Eng.getValueManager();
}
- ExplodedNode *GenerateNode(const Stmt* S, const GRState *state,
- bool markAsSink = false) {
- ExplodedNode *node = B.generateNode(S, state, Pred);
+ ExplodedNode *GenerateNode(bool autoTransition = true) {
+ assert(statement && "Only transitions with statements currently supported");
+ ExplodedNode *N = GenerateNodeImpl(statement, getState(), false);
+ if (N && autoTransition)
+ Dst.Add(N);
+ return N;
+ }
+
+ ExplodedNode *GenerateNode(const Stmt *stmt, const GRState *state,
+ bool autoTransition = true) {
+ assert(state);
+ ExplodedNode *N = GenerateNodeImpl(stmt, state, false);
+ if (N && autoTransition)
+ addTransition(N);
+ return N;
+ }
- if (markAsSink && node)
- node->markAsSink();
+ ExplodedNode *GenerateNode(const GRState *state, bool autoTransition = true) {
+ assert(statement && "Only transitions with statements currently supported");
+ ExplodedNode *N = GenerateNodeImpl(statement, state, false);
+ if (N && autoTransition)
+ addTransition(N);
+ return N;
+ }
- return node;
+ ExplodedNode *GenerateSink(const Stmt *stmt, const GRState *state = 0) {
+ return GenerateNodeImpl(stmt, state ? state : getState(), true);
+ }
+
+ ExplodedNode *GenerateSink(const GRState *state = 0) {
+ assert(statement && "Only transitions with statements currently supported");
+ return GenerateNodeImpl(statement, state ? state : getState(), true);
}
void addTransition(ExplodedNode *node) {
Dst.Add(node);
}
+
+ void addTransition(const GRState *state) {
+ assert(state);
+ if (state != getState() ||
+ (state && state != B.GetState(Pred)))
+ GenerateNode(state, true);
+ else
+ Dst.Add(Pred);
+ }
void EmitReport(BugReport *R) {
Eng.getBugReporter().EmitReport(R);
}
+
+private:
+ ExplodedNode *GenerateNodeImpl(const Stmt* stmt, const GRState *state,
+ bool markAsSink) {
+ ExplodedNode *node = B.generateNode(stmt, state, Pred);
+ if (markAsSink && node)
+ node->markAsSink();
+ return node;
+ }
+
};
class Checker {
@@ -111,18 +165,19 @@ private:
friend class GRExprEngine;
// FIXME: Remove the 'tag' option.
- void GR_Visit(ExplodedNodeSet &Dst,
+ bool GR_Visit(ExplodedNodeSet &Dst,
GRStmtNodeBuilder &Builder,
GRExprEngine &Eng,
const Stmt *S,
ExplodedNode *Pred, void *tag, bool isPrevisit) {
CheckerContext C(Dst, Builder, Eng, Pred, tag,
isPrevisit ? ProgramPoint::PreStmtKind :
- ProgramPoint::PostStmtKind);
+ ProgramPoint::PostStmtKind, S);
if (isPrevisit)
_PreVisit(C, S);
else
_PostVisit(C, S);
+ return C.isDoneEvaluating();
}
// FIXME: Remove the 'tag' option.
@@ -134,7 +189,7 @@ private:
bool isPrevisit) {
CheckerContext C(Dst, Builder, Eng, Pred, tag,
isPrevisit ? ProgramPoint::PreStmtKind :
- ProgramPoint::PostStmtKind);
+ ProgramPoint::PostStmtKind, StoreE);
assert(isPrevisit && "Only previsit supported for now.");
PreVisitBind(C, AssignE, StoreE, location, val);
}
@@ -149,7 +204,7 @@ private:
void *tag, bool isLoad) {
CheckerContext C(Dst, Builder, Eng, Pred, tag,
isLoad ? ProgramPoint::PreLoadKind :
- ProgramPoint::PreStoreKind, state);
+ ProgramPoint::PreStoreKind, S, state);
VisitLocation(C, S, location);
}
@@ -157,12 +212,12 @@ private:
GRExprEngine &Eng, const Stmt *S, ExplodedNode *Pred,
SymbolReaper &SymReaper, void *tag) {
CheckerContext C(Dst, Builder, Eng, Pred, tag,
- ProgramPoint::PostPurgeDeadSymbolsKind, Pred->getState());
+ ProgramPoint::PostPurgeDeadSymbolsKind, S);
EvalDeadSymbols(C, S, SymReaper);
}
public:
- virtual ~Checker() {}
+ virtual ~Checker();
virtual void _PreVisit(CheckerContext &C, const Stmt *S) {}
virtual void _PostVisit(CheckerContext &C, const Stmt *S) {}
virtual void VisitLocation(CheckerContext &C, const Stmt *S, SVal location) {}
@@ -172,6 +227,10 @@ public:
SymbolReaper &SymReaper) {}
virtual void EvalEndPath(GREndPathNodeBuilder &B, void *tag,
GRExprEngine &Eng) {}
+
+ virtual void VisitBranchCondition(GRBranchNodeBuilder &Builder,
+ GRExprEngine &Eng,
+ Stmt *Condition, void *tag) {}
};
} // end clang namespace
diff --git a/include/clang/Analysis/PathSensitive/CheckerVisitor.def b/include/clang/Analysis/PathSensitive/CheckerVisitor.def
index 090a5d3..4144d1a 100644
--- a/include/clang/Analysis/PathSensitive/CheckerVisitor.def
+++ b/include/clang/Analysis/PathSensitive/CheckerVisitor.def
@@ -11,7 +11,14 @@
//
//===---------------------------------------------------------------------===//
-#ifdef PREVISIT
+#ifndef PREVISIT
+#define PREVISIT(NODE)
+#endif
+
+#ifndef POSTVISIT
+#define POSTVISIT(NODE)
+#endif
+
PREVISIT(ArraySubscriptExpr)
PREVISIT(BinaryOperator)
PREVISIT(CallExpr)
@@ -19,11 +26,10 @@ PREVISIT(CastExpr)
PREVISIT(DeclStmt)
PREVISIT(ObjCMessageExpr)
PREVISIT(ReturnStmt)
-#undef PREVISIT
-#endif
-#ifdef POSTVISIT
POSTVISIT(CallExpr)
-#undef POSTVISIT
-#endif
+POSTVISIT(BlockExpr)
+POSTVISIT(BinaryOperator)
+#undef PREVISIT
+#undef POSTVISIT
diff --git a/include/clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h b/include/clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h
deleted file mode 100644
index 13437eb..0000000
--- a/include/clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h
+++ /dev/null
@@ -1,33 +0,0 @@
-//===--- UndefinedAssignmentChecker.h ---------------------------*- C++ -*--==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This defines UndefinedAssginmentChecker, a builtin check in GRExprEngine that
-// checks for assigning undefined values.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_UNDEFASSIGNMENTCHECKER
-#define LLVM_CLANG_UNDEFASSIGNMENTCHECKER
-
-#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
-
-namespace clang {
-class UndefinedAssignmentChecker
- : public CheckerVisitor<UndefinedAssignmentChecker> {
- BugType *BT;
-public:
- UndefinedAssignmentChecker() : BT(0) {}
- static void *getTag();
- virtual void PreVisitBind(CheckerContext &C, const Stmt *AssignE,
- const Stmt *StoreE, SVal location,
- SVal val);
-};
-}
-#endif
-
diff --git a/include/clang/Analysis/PathSensitive/ExplodedGraph.h b/include/clang/Analysis/PathSensitive/ExplodedGraph.h
index a7bbdf9..76cab1d 100644
--- a/include/clang/Analysis/PathSensitive/ExplodedGraph.h
+++ b/include/clang/Analysis/PathSensitive/ExplodedGraph.h
@@ -352,10 +352,16 @@ public:
typedef ImplTy::iterator iterator;
typedef ImplTy::const_iterator const_iterator;
- inline unsigned size() const { return Impl.size(); }
- inline bool empty() const { return Impl.empty(); }
-
- inline void clear() { Impl.clear(); }
+ unsigned size() const { return Impl.size(); }
+ bool empty() const { return Impl.empty(); }
+
+ void clear() { Impl.clear(); }
+ void insert(const ExplodedNodeSet &S) {
+ if (empty())
+ Impl = S.Impl;
+ else
+ Impl.insert(S.begin(), S.end());
+ }
inline iterator begin() { return Impl.begin(); }
inline iterator end() { return Impl.end(); }
diff --git a/include/clang/Analysis/PathSensitive/GRCoreEngine.h b/include/clang/Analysis/PathSensitive/GRCoreEngine.h
index 02e0b027..b78cc6a 100644
--- a/include/clang/Analysis/PathSensitive/GRCoreEngine.h
+++ b/include/clang/Analysis/PathSensitive/GRCoreEngine.h
@@ -215,7 +215,7 @@ public:
void setAuditor(GRAuditor* A) { Auditor = A; }
const GRState* GetState(ExplodedNode* Pred) const {
- if ((ExplodedNode*) Pred == getBasePredecessor())
+ if (Pred == getBasePredecessor())
return CleanedState;
else
return Pred->getState();
@@ -405,6 +405,8 @@ class GREndPathNodeBuilder {
GRCoreEngine& Eng;
CFGBlock& B;
ExplodedNode* Pred;
+
+public:
bool HasGeneratedNode;
public:
diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h
index 1b6d0bd..a7302c0 100644
--- a/include/clang/Analysis/PathSensitive/GRExprEngine.h
+++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h
@@ -88,55 +88,6 @@ class GRExprEngine : public GRSubEngine {
GRBugReporter BR;
public:
- typedef llvm::SmallPtrSet<ExplodedNode*,2> ErrorNodes;
- typedef llvm::DenseMap<ExplodedNode*, Expr*> UndefArgsTy;
-
- /// NilReceiverStructRetExplicit - Nodes in the ExplodedGraph that resulted
- /// from [x ...] with 'x' definitely being nil and the result was a 'struct'
- // (an undefined value).
- ErrorNodes NilReceiverStructRetExplicit;
-
- /// NilReceiverStructRetImplicit - Nodes in the ExplodedGraph that resulted
- /// from [x ...] with 'x' possibly being nil and the result was a 'struct'
- // (an undefined value).
- ErrorNodes NilReceiverStructRetImplicit;
-
- /// NilReceiverLargerThanVoidPtrRetExplicit - Nodes in the ExplodedGraph that
- /// resulted from [x ...] with 'x' definitely being nil and the result's size
- // was larger than sizeof(void *) (an undefined value).
- ErrorNodes NilReceiverLargerThanVoidPtrRetExplicit;
-
- /// NilReceiverLargerThanVoidPtrRetImplicit - Nodes in the ExplodedGraph that
- /// resulted from [x ...] with 'x' possibly being nil and the result's size
- // was larger than sizeof(void *) (an undefined value).
- ErrorNodes NilReceiverLargerThanVoidPtrRetImplicit;
-
- /// UndefBranches - Nodes in the ExplodedGraph that result from
- /// taking a branch based on an undefined value.
- ErrorNodes UndefBranches;
-
- /// UndefStores - Sinks in the ExplodedGraph that result from
- /// making a store to an undefined lvalue.
- ErrorNodes UndefStores;
-
- /// NoReturnCalls - Sinks in the ExplodedGraph that result from
- // calling a function with the attribute "noreturn".
- ErrorNodes NoReturnCalls;
-
- /// UndefResults - Nodes in the ExplodedGraph where the operands are defined
- /// by the result is not. Excludes divide-by-zero errors.
- ErrorNodes UndefResults;
-
- /// UndefReceiver - Nodes in the ExplodedGraph resulting from message
- /// ObjC message expressions where the receiver is undefined (uninitialized).
- ErrorNodes UndefReceivers;
-
- /// MsgExprUndefArgs - Nodes in the ExplodedGraph resulting from
- /// message expressions where a pass-by-value argument has an undefined
- /// value.
- UndefArgsTy MsgExprUndefArgs;
-
-public:
GRExprEngine(AnalysisManager &mgr);
~GRExprEngine();
@@ -178,8 +129,6 @@ public:
ExplodedGraph& getGraph() { return G; }
const ExplodedGraph& getGraph() const { return G; }
- void RegisterInternalChecks();
-
template <typename CHECKER>
void registerCheck(CHECKER *check) {
unsigned entry = Checkers.size();
@@ -195,58 +144,6 @@ public:
return static_cast<CHECKER*>(lookupChecker(CHECKER::getTag()));
}
- bool isNoReturnCall(const ExplodedNode* N) const {
- return N->isSink() && NoReturnCalls.count(const_cast<ExplodedNode*>(N)) != 0;
- }
-
- typedef ErrorNodes::iterator undef_branch_iterator;
- undef_branch_iterator undef_branches_begin() { return UndefBranches.begin(); }
- undef_branch_iterator undef_branches_end() { return UndefBranches.end(); }
-
- typedef ErrorNodes::iterator nil_receiver_struct_ret_iterator;
-
- nil_receiver_struct_ret_iterator nil_receiver_struct_ret_begin() {
- return NilReceiverStructRetExplicit.begin();
- }
-
- nil_receiver_struct_ret_iterator nil_receiver_struct_ret_end() {
- return NilReceiverStructRetExplicit.end();
- }
-
- typedef ErrorNodes::iterator nil_receiver_larger_than_voidptr_ret_iterator;
-
- nil_receiver_larger_than_voidptr_ret_iterator
- nil_receiver_larger_than_voidptr_ret_begin() {
- return NilReceiverLargerThanVoidPtrRetExplicit.begin();
- }
-
- nil_receiver_larger_than_voidptr_ret_iterator
- nil_receiver_larger_than_voidptr_ret_end() {
- return NilReceiverLargerThanVoidPtrRetExplicit.end();
- }
-
- typedef ErrorNodes::iterator undef_result_iterator;
- undef_result_iterator undef_results_begin() { return UndefResults.begin(); }
- undef_result_iterator undef_results_end() { return UndefResults.end(); }
-
- typedef UndefArgsTy::iterator undef_arg_iterator;
- undef_arg_iterator msg_expr_undef_arg_begin() {
- return MsgExprUndefArgs.begin();
- }
- undef_arg_iterator msg_expr_undef_arg_end() {
- return MsgExprUndefArgs.end();
- }
-
- typedef ErrorNodes::iterator undef_receivers_iterator;
-
- undef_receivers_iterator undef_receivers_begin() {
- return UndefReceivers.begin();
- }
-
- undef_receivers_iterator undef_receivers_end() {
- return UndefReceivers.end();
- }
-
void AddCheck(GRSimpleAPICheck* A, Stmt::StmtClass C);
void AddCheck(GRSimpleAPICheck* A);
@@ -312,7 +209,7 @@ public:
protected:
/// CheckerVisit - Dispatcher for performing checker-specific logic
/// at specific statements.
- void CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
+ bool CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
bool isPrevisit);
void CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE,
@@ -345,6 +242,9 @@ protected:
AsmStmt::inputs_iterator I,
AsmStmt::inputs_iterator E,
ExplodedNode* Pred, ExplodedNodeSet& Dst);
+
+ /// VisitBlockExpr - Transfer function logic for BlockExprs.
+ void VisitBlockExpr(BlockExpr *BE, ExplodedNode *Pred, ExplodedNodeSet &Dst);
/// VisitBinaryOperator - Transfer function logic for binary operators.
void VisitBinaryOperator(BinaryOperator* B, ExplodedNode* Pred,
@@ -361,33 +261,38 @@ protected:
unsigned ParamIdx = 0);
/// VisitCast - Transfer function logic for all casts (implicit and explicit).
- void VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred, ExplodedNodeSet& Dst);
+ void VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst);
/// VisitCompoundLiteralExpr - Transfer function logic for compound literals.
void VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
/// VisitDeclRefExpr - Transfer function logic for DeclRefExprs.
- void VisitDeclRefExpr(DeclRefExpr* DR, ExplodedNode* Pred, ExplodedNodeSet& Dst,
- bool asLValue);
+ void VisitDeclRefExpr(DeclRefExpr* DR, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst, bool asLValue);
/// VisitDeclStmt - Transfer function logic for DeclStmts.
void VisitDeclStmt(DeclStmt* DS, ExplodedNode* Pred, ExplodedNodeSet& Dst);
/// VisitGuardedExpr - Transfer function logic for ?, __builtin_choose
- void VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R, ExplodedNode* Pred, ExplodedNodeSet& Dst);
+ void VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst);
- void VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred, ExplodedNodeSet& Dst);
+ void VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst);
/// VisitLogicalExpr - Transfer function logic for '&&', '||'
- void VisitLogicalExpr(BinaryOperator* B, ExplodedNode* Pred, ExplodedNodeSet& Dst);
+ void VisitLogicalExpr(BinaryOperator* B, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst);
/// VisitMemberExpr - Transfer function for member expressions.
- void VisitMemberExpr(MemberExpr* M, ExplodedNode* Pred, ExplodedNodeSet& Dst,bool asLValue);
+ void VisitMemberExpr(MemberExpr* M, ExplodedNode* Pred, ExplodedNodeSet& Dst,
+ bool asLValue);
/// VisitObjCIvarRefExpr - Transfer function logic for ObjCIvarRefExprs.
- void VisitObjCIvarRefExpr(ObjCIvarRefExpr* DR, ExplodedNode* Pred, ExplodedNodeSet& Dst,
- bool asLValue);
+ void VisitObjCIvarRefExpr(ObjCIvarRefExpr* DR, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst, bool asLValue);
/// VisitObjCForCollectionStmt - Transfer function logic for
/// ObjCForCollectionStmt.
diff --git a/include/clang/Analysis/PathSensitive/GRState.h b/include/clang/Analysis/PathSensitive/GRState.h
index ef0c36c..d8bc241 100644
--- a/include/clang/Analysis/PathSensitive/GRState.h
+++ b/include/clang/Analysis/PathSensitive/GRState.h
@@ -33,7 +33,6 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
#include <functional>
@@ -264,8 +263,21 @@ public:
const llvm::APSInt *getSymVal(SymbolRef sym);
bool scanReachableSymbols(SVal val, SymbolVisitor& visitor) const;
+
+ bool scanReachableSymbols(const SVal *I, const SVal *E,
+ SymbolVisitor &visitor) const;
+
+ bool scanReachableSymbols(const MemRegion * const *I,
+ const MemRegion * const *E,
+ SymbolVisitor &visitor) const;
template <typename CB> CB scanReachableSymbols(SVal val) const;
+ template <typename CB> CB scanReachableSymbols(const SVal *beg,
+ const SVal *end) const;
+
+ template <typename CB> CB
+ scanReachableSymbols(const MemRegion * const *beg,
+ const MemRegion * const *end) const;
//==---------------------------------------------------------------------==//
// Accessing the Generic Data Map (GDM).
@@ -726,7 +738,21 @@ CB GRState::scanReachableSymbols(SVal val) const {
scanReachableSymbols(val, cb);
return cb;
}
+
+template <typename CB>
+CB GRState::scanReachableSymbols(const SVal *beg, const SVal *end) const {
+ CB cb(this);
+ scanReachableSymbols(beg, end, cb);
+ return cb;
+}
+template <typename CB>
+CB GRState::scanReachableSymbols(const MemRegion * const *beg,
+ const MemRegion * const *end) const {
+ CB cb(this);
+ scanReachableSymbols(beg, end, cb);
+ return cb;
+}
} // end clang namespace
#endif
diff --git a/include/clang/Analysis/PathSensitive/MemRegion.h b/include/clang/Analysis/PathSensitive/MemRegion.h
index 06d0d97..ed96497 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 VarRegion;
//===----------------------------------------------------------------------===//
// Base region classes.
@@ -42,13 +43,16 @@ class LocationContext;
/// MemRegion - The root abstract class for all memory regions.
class MemRegion : public llvm::FoldingSetNode {
+ friend class MemRegionManager;
public:
enum Kind { MemSpaceRegionKind,
SymbolicRegionKind,
AllocaRegionKind,
// Typed regions.
BEG_TYPED_REGIONS,
- CodeTextRegionKind,
+ FunctionTextRegionKind,
+ BlockTextRegionKind,
+ BlockDataRegionKind,
CompoundLiteralRegionKind,
StringRegionKind, ElementRegionKind,
// Decl Regions.
@@ -237,45 +241,123 @@ public:
}
};
-/// CodeTextRegion - A region that represents code texts of a function. It wraps
-/// two kinds of code texts: real function and symbolic function. Real function
-/// is a function declared in the program. Symbolic function is a function
-/// pointer that we don't know which function it points to.
-class CodeTextRegion : public TypedRegion {
- const FunctionDecl *FD;
+class CodeTextRegion : public TypedRegion {
+protected:
+ CodeTextRegion(const MemRegion *sreg, Kind k) : TypedRegion(sreg, k) {}
public:
-
- CodeTextRegion(const FunctionDecl* fd, const MemRegion* sreg)
- : TypedRegion(sreg, CodeTextRegionKind), FD(fd) {}
-
QualType getValueType(ASTContext &C) const {
// Do not get the object type of a CodeTextRegion.
assert(0);
return QualType();
}
+
+ bool isBoundable() const { return false; }
+
+ static bool classof(const MemRegion* R) {
+ Kind k = R->getKind();
+ return k >= FunctionTextRegionKind && k <= BlockTextRegionKind;
+ }
+};
+/// FunctionTextRegion - A region that represents code texts of function.
+class FunctionTextRegion : public CodeTextRegion {
+ const FunctionDecl *FD;
+public:
+ FunctionTextRegion(const FunctionDecl* fd, const MemRegion* sreg)
+ : CodeTextRegion(sreg, FunctionTextRegionKind), FD(fd) {}
+
QualType getLocationType(ASTContext &C) const {
return C.getPointerType(FD->getType());
}
-
+
const FunctionDecl *getDecl() const {
return FD;
}
-
- bool isBoundable() const { return false; }
-
+
virtual void dumpToStream(llvm::raw_ostream& os) const;
-
+
void Profile(llvm::FoldingSetNodeID& ID) const;
-
+
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FunctionDecl *FD,
const MemRegion*);
-
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == FunctionTextRegionKind;
+ }
+};
+
+
+/// BlockTextRegion - A region that represents code texts of blocks (closures).
+/// Blocks are represented with two kinds of regions. BlockTextRegions
+/// represent the "code", while BlockDataRegions represent instances of blocks,
+/// which correspond to "code+data". The distinction is important, because
+/// like a closure a block captures the values of externally referenced
+/// variables.
+class BlockTextRegion : public CodeTextRegion {
+ const BlockDecl *BD;
+ CanQualType locTy;
+public:
+ BlockTextRegion(const BlockDecl *bd, CanQualType lTy, const MemRegion* sreg)
+ : CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), locTy(lTy) {}
+
+ QualType getLocationType(ASTContext &C) const {
+ return locTy;
+ }
+
+ const BlockDecl *getDecl() const {
+ return BD;
+ }
+
+ virtual void dumpToStream(llvm::raw_ostream& os) const;
+
+ void Profile(llvm::FoldingSetNodeID& ID) const;
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const BlockDecl *BD,
+ CanQualType, const MemRegion*);
+
static bool classof(const MemRegion* R) {
- return R->getKind() == CodeTextRegionKind;
+ return R->getKind() == BlockTextRegionKind;
}
};
+
+/// BlockDataRegion - A region that represents a block instance.
+/// Blocks are represented with two kinds of regions. BlockTextRegions
+/// represent the "code", while BlockDataRegions represent instances of blocks,
+/// which correspond to "code+data". The distinction is important, because
+/// like a closure a block captures the values of externally referenced
+/// variables.
+/// BlockDataRegion - A region that represents code texts of blocks (closures).
+class BlockDataRegion : public SubRegion {
+ const BlockTextRegion *BC;
+ const LocationContext *LC;
+ void *ReferencedVars;
+public:
+ BlockDataRegion(const BlockTextRegion *bc,
+ const LocationContext *lc,
+ const MemRegion *sreg)
+ : SubRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), ReferencedVars(0) {}
+
+ const BlockTextRegion *getCodeRegion() const { return BC; }
+
+ typedef const MemRegion * const * referenced_vars_iterator;
+ referenced_vars_iterator referenced_vars_begin() const;
+ referenced_vars_iterator referenced_vars_end() const;
+
+ virtual void dumpToStream(llvm::raw_ostream& os) const;
+
+ void Profile(llvm::FoldingSetNodeID& ID) const;
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID,
+ const BlockTextRegion *BC,
+ const LocationContext *LC, const MemRegion *);
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == BlockDataRegionKind;
+ }
+private:
+ void LazyInitializeReferencedVars();
+};
/// SymbolicRegion - A special, "non-concrete" region. Unlike other region
/// clases, SymbolicRegion represents a region that serves as an alias for
@@ -577,9 +659,11 @@ public:
: C(c), A(a), globals(0), stack(0), stackArguments(0), heap(0),
unknown(0), code(0) {}
- ~MemRegionManager() {}
+ ~MemRegionManager();
ASTContext &getContext() { return C; }
+
+ llvm::BumpPtrAllocator &getAllocator() { return A; }
/// getStackRegion - Retrieve the memory region associated with the
/// current stack frame.
@@ -656,7 +740,10 @@ public:
ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl* ivd,
const MemRegion* superRegion);
- CodeTextRegion *getCodeTextRegion(const FunctionDecl *FD);
+ FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD);
+ BlockTextRegion *getBlockTextRegion(const BlockDecl *BD, CanQualType locTy);
+ BlockDataRegion *getBlockDataRegion(const BlockTextRegion *bc,
+ const LocationContext *lc);
template <typename RegionTy, typename A1>
RegionTy* getRegion(const A1 a1);
@@ -667,6 +754,10 @@ public:
template <typename RegionTy, typename A1, typename A2>
RegionTy* getRegion(const A1 a1, const A2 a2);
+ template <typename RegionTy, typename A1, typename A2>
+ RegionTy* getSubRegion(const A1 a1, const A2 a2,
+ const MemRegion* superRegion);
+
bool isGlobalsRegion(const MemRegion* R) {
assert(R);
return R == globals;
@@ -745,6 +836,25 @@ RegionTy* MemRegionManager::getRegion(const A1 a1, const A2 a2) {
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.
@@ -801,18 +911,21 @@ template <> struct MemRegionManagerTrait<SymbolicRegion> {
}
};
-template<> struct MemRegionManagerTrait<CodeTextRegion> {
+template<> struct MemRegionManagerTrait<FunctionTextRegion> {
typedef MemSpaceRegion SuperRegionTy;
static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
const FunctionDecl*) {
return MRMgr.getCodeRegion();
}
+};
+template<> struct MemRegionManagerTrait<BlockTextRegion> {
+ typedef MemSpaceRegion SuperRegionTy;
static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
- SymbolRef, QualType) {
+ const BlockDecl*, CanQualType) {
return MRMgr.getCodeRegion();
}
};
-
+
} // end clang namespace
//===----------------------------------------------------------------------===//
diff --git a/include/clang/Analysis/PathSensitive/ValueManager.h b/include/clang/Analysis/PathSensitive/ValueManager.h
index 8d162a6..ef4e069 100644
--- a/include/clang/Analysis/PathSensitive/ValueManager.h
+++ b/include/clang/Analysis/PathSensitive/ValueManager.h
@@ -114,6 +114,9 @@ public:
const TypedRegion *R);
DefinedSVal getFunctionPointer(const FunctionDecl *FD);
+
+ DefinedSVal getBlockPointer(const BlockDecl *BD, CanQualType locTy,
+ const LocationContext *LC);
NonLoc makeCompoundVal(QualType T, llvm::ImmutableList<SVal> Vals) {
return nonloc::CompoundVal(BasicVals.getCompoundValData(T, Vals));
OpenPOWER on IntegriCloud