forked from OSchip/llvm-project
Rename GRState to ProgramState, and cleanup some code formatting along the way.
llvm-svn: 137665
This commit is contained in:
parent
8bc586e770
commit
001fd5b498
|
@ -186,7 +186,7 @@
|
|||
1AC1A7E71299A285006FBC77 /* GRExprEngineExperimentalChecks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = GRExprEngineExperimentalChecks.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AC1A7E81299A285006FBC77 /* GRExprEngineExperimentalChecks.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = GRExprEngineExperimentalChecks.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AC1A7E91299A285006FBC77 /* GRExprEngineInternalChecks.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = GRExprEngineInternalChecks.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AC1A7EA1299A285006FBC77 /* GRState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = GRState.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AC1A7EA1299A285006FBC77 /* ProgramState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = ProgramState.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AC1A7EB1299A285006FBC77 /* HTMLDiagnostics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLDiagnostics.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AC1A7EC1299A285006FBC77 /* IdempotentOperationChecker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = IdempotentOperationChecker.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AC1A7ED1299A285006FBC77 /* LLVMConventionsChecker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = LLVMConventionsChecker.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
|
@ -268,7 +268,7 @@
|
|||
3551068F0E9A857C006A4E44 /* ParsePragma.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = ParsePragma.h; path = lib/Parse/ParsePragma.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
3552E7540E520D80003A8CA5 /* PPCaching.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PPCaching.cpp; sourceTree = "<group>"; };
|
||||
3552E7580E520DD7003A8CA5 /* CGObjCMac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGObjCMac.cpp; path = lib/CodeGen/CGObjCMac.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
3553EB9A0E5F7089007D7359 /* GRStateTrait.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GRStateTrait.h; path = clang/Analysis/PathSensitive/GRStateTrait.h; sourceTree = "<group>"; };
|
||||
3553EB9A0E5F7089007D7359 /* ProgramStateTrait.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProgramStateTrait.h; path = clang/Analysis/PathSensitive/ProgramStateTrait.h; sourceTree = "<group>"; };
|
||||
35544B8B0F5C803200D92AA9 /* SemaTemplateInstantiate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = SemaTemplateInstantiate.cpp; path = lib/Sema/SemaTemplateInstantiate.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
35585DBE0EAFBC4500D0A97A /* SemaOverload.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = SemaOverload.cpp; path = lib/Sema/SemaOverload.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
3558F76F0E267C9A00A5B0DF /* Store.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Store.h; path = clang/Analysis/PathSensitive/Store.h; sourceTree = "<group>"; };
|
||||
|
@ -276,7 +276,7 @@
|
|||
357EA27C0F2526F300439B60 /* SemaLookup.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = SemaLookup.cpp; path = lib/Sema/SemaLookup.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
35847BE30CC7DB9000C40FFF /* StmtIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = StmtIterator.h; path = clang/AST/StmtIterator.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
358D23090E8BEB850003DDCC /* DeclGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = DeclGroup.h; path = clang/AST/DeclGroup.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
358F514F0E529A87007F2102 /* GRState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GRState.h; path = clang/Analysis/PathSensitive/GRState.h; sourceTree = "<group>"; };
|
||||
358F514F0E529A87007F2102 /* ProgramState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProgramState.h; path = clang/Analysis/PathSensitive/ProgramState.h; sourceTree = "<group>"; };
|
||||
3591853E0EFB1088000039AF /* SemaTemplate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = SemaTemplate.cpp; path = lib/Sema/SemaTemplate.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
359378FF0DA486490043B19C /* BugReporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BugReporter.h; path = clang/Analysis/PathSensitive/BugReporter.h; sourceTree = "<group>"; };
|
||||
3598EBEB0EDE23EF0070CA16 /* PTHManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PTHManager.h; sourceTree = "<group>"; };
|
||||
|
@ -452,7 +452,7 @@
|
|||
BBA5AB611309C2FA000B38F1 /* Environment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Environment.cpp; sourceTree = "<group>"; };
|
||||
BBA5AB621309C2FA000B38F1 /* ExplodedGraph.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExplodedGraph.cpp; sourceTree = "<group>"; };
|
||||
BBA5AB631309C2FA000B38F1 /* FlatStore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FlatStore.cpp; sourceTree = "<group>"; };
|
||||
BBA5AB641309C2FA000B38F1 /* GRState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GRState.cpp; sourceTree = "<group>"; };
|
||||
BBA5AB641309C2FA000B38F1 /* ProgramState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProgramState.cpp; sourceTree = "<group>"; };
|
||||
BBA5AB651309C2FA000B38F1 /* HTMLDiagnostics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLDiagnostics.cpp; sourceTree = "<group>"; };
|
||||
BBA5AB671309C2FA000B38F1 /* MemRegion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MemRegion.cpp; sourceTree = "<group>"; };
|
||||
BBA5AB681309C2FA000B38F1 /* ObjCMessage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjCMessage.cpp; sourceTree = "<group>"; };
|
||||
|
@ -856,7 +856,7 @@
|
|||
1AC1A7E71299A285006FBC77 /* GRExprEngineExperimentalChecks.cpp */,
|
||||
1AC1A7E81299A285006FBC77 /* GRExprEngineExperimentalChecks.h */,
|
||||
1AC1A7E91299A285006FBC77 /* GRExprEngineInternalChecks.h */,
|
||||
1AC1A7EA1299A285006FBC77 /* GRState.cpp */,
|
||||
1AC1A7EA1299A285006FBC77 /* ProgramState.cpp */,
|
||||
1AC1A7EB1299A285006FBC77 /* HTMLDiagnostics.cpp */,
|
||||
1AC1A7EC1299A285006FBC77 /* IdempotentOperationChecker.cpp */,
|
||||
1AC1A7ED1299A285006FBC77 /* LLVMConventionsChecker.cpp */,
|
||||
|
@ -1235,7 +1235,7 @@
|
|||
BBA5AB611309C2FA000B38F1 /* Environment.cpp */,
|
||||
BBA5AB621309C2FA000B38F1 /* ExplodedGraph.cpp */,
|
||||
BBA5AB631309C2FA000B38F1 /* FlatStore.cpp */,
|
||||
BBA5AB641309C2FA000B38F1 /* GRState.cpp */,
|
||||
BBA5AB641309C2FA000B38F1 /* ProgramState.cpp */,
|
||||
BBA5AB651309C2FA000B38F1 /* HTMLDiagnostics.cpp */,
|
||||
BBA5AB671309C2FA000B38F1 /* MemRegion.cpp */,
|
||||
BBA5AB681309C2FA000B38F1 /* ObjCMessage.cpp */,
|
||||
|
@ -1340,8 +1340,8 @@
|
|||
DE41211F0D7F1BBE0080F80A /* GRBlockCounter.h */,
|
||||
DE4121230D7F1BBE0080F80A /* GRCoreEngine.h */,
|
||||
DE4121210D7F1BBE0080F80A /* GRExprEngine.h */,
|
||||
358F514F0E529A87007F2102 /* GRState.h */,
|
||||
3553EB9A0E5F7089007D7359 /* GRStateTrait.h */,
|
||||
358F514F0E529A87007F2102 /* ProgramState.h */,
|
||||
3553EB9A0E5F7089007D7359 /* ProgramStateTrait.h */,
|
||||
35F8D0CA0D9B7E8200D91C5E /* GRSimpleAPICheck.h */,
|
||||
DE4121220D7F1BBE0080F80A /* GRTransferFuncs.h */,
|
||||
DE41211D0D7F1BBE0080F80A /* GRWorkList.h */,
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines BugReporter, a utility class for generating
|
||||
// PathDiagnostics for analyses based on GRState.
|
||||
// PathDiagnostics for analyses based on ProgramState.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
|||
#define LLVM_CLANG_GR_BUGREPORTER
|
||||
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/ImmutableList.h"
|
||||
#include "llvm/ADT/ImmutableSet.h"
|
||||
|
@ -40,7 +40,7 @@ class ExplodedGraph;
|
|||
class BugReporter;
|
||||
class BugReporterContext;
|
||||
class ExprEngine;
|
||||
class GRState;
|
||||
class ProgramState;
|
||||
class BugType;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -392,7 +392,7 @@ public:
|
|||
|
||||
/// getStateManager - Return the state manager used by the analysis
|
||||
/// engine.
|
||||
GRStateManager &getStateManager();
|
||||
ProgramStateManager &getStateManager();
|
||||
|
||||
virtual void GeneratePathDiagnostic(PathDiagnostic &pathDiagnostic,
|
||||
SmallVectorImpl<BugReport*> &bugReports);
|
||||
|
@ -442,7 +442,7 @@ public:
|
|||
return BR.isNotable(Sym);
|
||||
}
|
||||
|
||||
GRStateManager& getStateManager() {
|
||||
ProgramStateManager& getStateManager() {
|
||||
return BR.getStateManager();
|
||||
}
|
||||
|
||||
|
|
|
@ -228,7 +228,7 @@ public:
|
|||
|
||||
class LiveSymbols {
|
||||
template <typename CHECKER>
|
||||
static void _checkLiveSymbols(void *checker, const GRState *state,
|
||||
static void _checkLiveSymbols(void *checker, const ProgramState *state,
|
||||
SymbolReaper &SR) {
|
||||
((const CHECKER *)checker)->checkLiveSymbols(state, SR);
|
||||
}
|
||||
|
@ -258,15 +258,18 @@ public:
|
|||
|
||||
class RegionChanges {
|
||||
template <typename CHECKER>
|
||||
static const GRState *_checkRegionChanges(void *checker, const GRState *state,
|
||||
const StoreManager::InvalidatedSymbols *invalidated,
|
||||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End) {
|
||||
static const ProgramState *
|
||||
_checkRegionChanges(void *checker,
|
||||
const ProgramState *state,
|
||||
const StoreManager::InvalidatedSymbols *invalidated,
|
||||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End) {
|
||||
return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
|
||||
Begin, End);
|
||||
}
|
||||
template <typename CHECKER>
|
||||
static bool _wantsRegionChangeUpdate(void *checker, const GRState *state) {
|
||||
static bool _wantsRegionChangeUpdate(void *checker,
|
||||
const ProgramState *state) {
|
||||
return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state);
|
||||
}
|
||||
|
||||
|
@ -301,8 +304,10 @@ namespace eval {
|
|||
|
||||
class Assume {
|
||||
template <typename CHECKER>
|
||||
static const GRState *_evalAssume(void *checker, const GRState *state,
|
||||
const SVal &cond, bool assumption) {
|
||||
static const ProgramState *_evalAssume(void *checker,
|
||||
const ProgramState *state,
|
||||
const SVal &cond,
|
||||
bool assumption) {
|
||||
return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace ento {
|
|||
class ExplodedNode;
|
||||
class ExplodedNodeSet;
|
||||
class ExplodedGraph;
|
||||
class GRState;
|
||||
class ProgramState;
|
||||
class EndOfFunctionNodeBuilder;
|
||||
class BranchNodeBuilder;
|
||||
class MemRegion;
|
||||
|
@ -225,7 +225,7 @@ public:
|
|||
BranchNodeBuilder &B, ExprEngine &Eng);
|
||||
|
||||
/// \brief Run checkers for live symbols.
|
||||
void runCheckersForLiveSymbols(const GRState *state,
|
||||
void runCheckersForLiveSymbols(const ProgramState *state,
|
||||
SymbolReaper &SymReaper);
|
||||
|
||||
/// \brief Run checkers for dead symbols.
|
||||
|
@ -235,17 +235,17 @@ public:
|
|||
ExprEngine &Eng);
|
||||
|
||||
/// \brief True if at least one checker wants to check region changes.
|
||||
bool wantsRegionChangeUpdate(const GRState *state);
|
||||
bool wantsRegionChangeUpdate(const ProgramState *state);
|
||||
|
||||
/// \brief Run checkers for region changes.
|
||||
const GRState *
|
||||
runCheckersForRegionChanges(const GRState *state,
|
||||
const ProgramState *
|
||||
runCheckersForRegionChanges(const ProgramState *state,
|
||||
const StoreManager::InvalidatedSymbols *invalidated,
|
||||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End);
|
||||
|
||||
/// \brief Run checkers for handling assumptions on symbolic values.
|
||||
const GRState *runCheckersForEvalAssume(const GRState *state,
|
||||
const ProgramState *runCheckersForEvalAssume(const ProgramState *state,
|
||||
SVal Cond, bool Assumption);
|
||||
|
||||
/// \brief Run checkers for evaluating a call.
|
||||
|
@ -301,18 +301,18 @@ public:
|
|||
typedef CheckerFn<void (SymbolReaper &, CheckerContext &)>
|
||||
CheckDeadSymbolsFunc;
|
||||
|
||||
typedef CheckerFn<void (const GRState *,SymbolReaper &)> CheckLiveSymbolsFunc;
|
||||
typedef CheckerFn<void (const ProgramState *,SymbolReaper &)> CheckLiveSymbolsFunc;
|
||||
|
||||
typedef CheckerFn<const GRState * (const GRState *,
|
||||
typedef CheckerFn<const ProgramState * (const ProgramState *,
|
||||
const StoreManager::InvalidatedSymbols *symbols,
|
||||
const MemRegion * const *begin,
|
||||
const MemRegion * const *end)>
|
||||
CheckRegionChangesFunc;
|
||||
|
||||
typedef CheckerFn<bool (const GRState *)> WantsRegionChangeUpdateFunc;
|
||||
typedef CheckerFn<bool (const ProgramState *)> WantsRegionChangeUpdateFunc;
|
||||
|
||||
typedef CheckerFn<const GRState * (const GRState *,
|
||||
const SVal &cond, bool assumption)>
|
||||
typedef CheckerFn<const ProgramState * (const ProgramState *,
|
||||
const SVal &cond, bool assumption)>
|
||||
EvalAssumeFunc;
|
||||
|
||||
typedef CheckerFn<bool (const CallExpr *, CheckerContext &)>
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace clang {
|
|||
|
||||
namespace ento {
|
||||
|
||||
class GRState;
|
||||
class ProgramState;
|
||||
|
||||
class CompoundValData : public llvm::FoldingSetNode {
|
||||
QualType T;
|
||||
|
|
|
@ -31,23 +31,32 @@ class CheckerContext {
|
|||
const ProgramPointTag *checkerTag;
|
||||
SaveAndRestore<ProgramPoint::Kind> OldPointKind;
|
||||
SaveOr OldHasGen;
|
||||
const GRState *ST;
|
||||
const ProgramState *ST;
|
||||
const Stmt *statement;
|
||||
const unsigned size;
|
||||
public:
|
||||
bool *respondsToCallback;
|
||||
public:
|
||||
CheckerContext(ExplodedNodeSet &dst, StmtNodeBuilder &builder,
|
||||
ExprEngine &eng, ExplodedNode *pred,
|
||||
const ProgramPointTag *tag, ProgramPoint::Kind K,
|
||||
CheckerContext(ExplodedNodeSet &dst,
|
||||
StmtNodeBuilder &builder,
|
||||
ExprEngine &eng,
|
||||
ExplodedNode *pred,
|
||||
const ProgramPointTag *tag,
|
||||
ProgramPoint::Kind K,
|
||||
bool *respondsToCB = 0,
|
||||
const Stmt *stmt = 0, const GRState *st = 0)
|
||||
: Dst(dst), B(builder), Eng(eng), Pred(pred),
|
||||
const Stmt *stmt = 0,
|
||||
const ProgramState *st = 0)
|
||||
: Dst(dst),
|
||||
B(builder),
|
||||
Eng(eng),
|
||||
Pred(pred),
|
||||
OldSink(B.BuildSinks),
|
||||
checkerTag(tag),
|
||||
OldPointKind(B.PointKind, K),
|
||||
OldHasGen(B.hasGeneratedNode),
|
||||
ST(st), statement(stmt), size(Dst.size()),
|
||||
ST(st),
|
||||
statement(stmt),
|
||||
size(Dst.size()),
|
||||
respondsToCallback(respondsToCB) {}
|
||||
|
||||
~CheckerContext();
|
||||
|
@ -71,7 +80,7 @@ public:
|
|||
ExplodedNodeSet &getNodeSet() { return Dst; }
|
||||
StmtNodeBuilder &getNodeBuilder() { return B; }
|
||||
ExplodedNode *&getPredecessor() { return Pred; }
|
||||
const GRState *getState() { return ST ? ST : Pred->getState(); }
|
||||
const ProgramState *getState() { return ST ? ST : Pred->getState(); }
|
||||
const Stmt *getStmt() const { return statement; }
|
||||
|
||||
ASTContext &getASTContext() {
|
||||
|
@ -103,8 +112,10 @@ public:
|
|||
return N;
|
||||
}
|
||||
|
||||
ExplodedNode *generateNode(const Stmt *stmt, const GRState *state,
|
||||
bool autoTransition = true, const ProgramPointTag *tag = 0) {
|
||||
ExplodedNode *generateNode(const Stmt *stmt,
|
||||
const ProgramState *state,
|
||||
bool autoTransition = true,
|
||||
const ProgramPointTag *tag = 0) {
|
||||
assert(state);
|
||||
ExplodedNode *N = generateNodeImpl(stmt, state, false,
|
||||
tag ? tag : checkerTag);
|
||||
|
@ -113,7 +124,8 @@ public:
|
|||
return N;
|
||||
}
|
||||
|
||||
ExplodedNode *generateNode(const GRState *state, ExplodedNode *pred,
|
||||
ExplodedNode *generateNode(const ProgramState *state,
|
||||
ExplodedNode *pred,
|
||||
bool autoTransition = true) {
|
||||
assert(statement && "Only transitions with statements currently supported");
|
||||
ExplodedNode *N = generateNodeImpl(statement, state, pred, false);
|
||||
|
@ -122,7 +134,8 @@ public:
|
|||
return N;
|
||||
}
|
||||
|
||||
ExplodedNode *generateNode(const GRState *state, bool autoTransition = true,
|
||||
ExplodedNode *generateNode(const ProgramState *state,
|
||||
bool autoTransition = true,
|
||||
const ProgramPointTag *tag = 0) {
|
||||
assert(statement && "Only transitions with statements currently supported");
|
||||
ExplodedNode *N = generateNodeImpl(statement, state, false,
|
||||
|
@ -132,12 +145,12 @@ public:
|
|||
return N;
|
||||
}
|
||||
|
||||
ExplodedNode *generateSink(const Stmt *stmt, const GRState *state = 0) {
|
||||
ExplodedNode *generateSink(const Stmt *stmt, const ProgramState *state = 0) {
|
||||
return generateNodeImpl(stmt, state ? state : getState(), true,
|
||||
checkerTag);
|
||||
}
|
||||
|
||||
ExplodedNode *generateSink(const GRState *state = 0) {
|
||||
ExplodedNode *generateSink(const ProgramState *state = 0) {
|
||||
assert(statement && "Only transitions with statements currently supported");
|
||||
return generateNodeImpl(statement, state ? state : getState(), true,
|
||||
checkerTag);
|
||||
|
@ -147,7 +160,8 @@ public:
|
|||
Dst.Add(node);
|
||||
}
|
||||
|
||||
void addTransition(const GRState *state, const ProgramPointTag *tag = 0) {
|
||||
void addTransition(const ProgramState *state,
|
||||
const ProgramPointTag *tag = 0) {
|
||||
assert(state);
|
||||
// If the 'state' is not new, we need to check if the cached state 'ST'
|
||||
// is new.
|
||||
|
@ -167,16 +181,20 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
ExplodedNode *generateNodeImpl(const Stmt *stmt, const GRState *state,
|
||||
bool markAsSink, const ProgramPointTag *tag) {
|
||||
ExplodedNode *generateNodeImpl(const Stmt *stmt,
|
||||
const ProgramState *state,
|
||||
bool markAsSink,
|
||||
const ProgramPointTag *tag) {
|
||||
ExplodedNode *node = B.generateNode(stmt, state, Pred, tag);
|
||||
if (markAsSink && node)
|
||||
node->markAsSink();
|
||||
return node;
|
||||
}
|
||||
|
||||
ExplodedNode *generateNodeImpl(const Stmt *stmt, const GRState *state,
|
||||
ExplodedNode *pred, bool markAsSink) {
|
||||
ExplodedNode *generateNodeImpl(const Stmt *stmt,
|
||||
const ProgramState *state,
|
||||
ExplodedNode *pred,
|
||||
bool markAsSink) {
|
||||
ExplodedNode *node = B.generateNode(stmt, state, pred, checkerTag);
|
||||
if (markAsSink && node)
|
||||
node->markAsSink();
|
||||
|
|
|
@ -25,36 +25,41 @@ namespace clang {
|
|||
|
||||
namespace ento {
|
||||
|
||||
class GRState;
|
||||
class GRStateManager;
|
||||
class ProgramState;
|
||||
class ProgramStateManager;
|
||||
class SubEngine;
|
||||
class SVal;
|
||||
|
||||
class ConstraintManager {
|
||||
public:
|
||||
virtual ~ConstraintManager();
|
||||
virtual const GRState *assume(const GRState *state, DefinedSVal Cond,
|
||||
bool Assumption) = 0;
|
||||
virtual const ProgramState *assume(const ProgramState *state,
|
||||
DefinedSVal Cond,
|
||||
bool Assumption) = 0;
|
||||
|
||||
std::pair<const GRState*, const GRState*> assumeDual(const GRState *state,
|
||||
DefinedSVal Cond) {
|
||||
std::pair<const ProgramState*, const ProgramState*>
|
||||
assumeDual(const ProgramState *state, DefinedSVal Cond)
|
||||
{
|
||||
return std::make_pair(assume(state, Cond, true),
|
||||
assume(state, Cond, false));
|
||||
}
|
||||
|
||||
virtual const llvm::APSInt* getSymVal(const GRState *state,
|
||||
virtual const llvm::APSInt* getSymVal(const ProgramState *state,
|
||||
SymbolRef sym) const = 0;
|
||||
|
||||
virtual bool isEqual(const GRState *state, SymbolRef sym,
|
||||
virtual bool isEqual(const ProgramState *state,
|
||||
SymbolRef sym,
|
||||
const llvm::APSInt& V) const = 0;
|
||||
|
||||
virtual const GRState *removeDeadBindings(const GRState *state,
|
||||
SymbolReaper& SymReaper) = 0;
|
||||
virtual const ProgramState *removeDeadBindings(const ProgramState *state,
|
||||
SymbolReaper& SymReaper) = 0;
|
||||
|
||||
virtual void print(const GRState *state, raw_ostream &Out,
|
||||
const char* nl, const char *sep) = 0;
|
||||
virtual void print(const ProgramState *state,
|
||||
raw_ostream &Out,
|
||||
const char* nl,
|
||||
const char *sep) = 0;
|
||||
|
||||
virtual void EndPath(const GRState *state) {}
|
||||
virtual void EndPath(const ProgramState *state) {}
|
||||
|
||||
/// canReasonAbout - Not all ConstraintManagers can accurately reason about
|
||||
/// all SVal values. This method returns true if the ConstraintManager can
|
||||
|
@ -64,9 +69,9 @@ public:
|
|||
virtual bool canReasonAbout(SVal X) const = 0;
|
||||
};
|
||||
|
||||
ConstraintManager* CreateBasicConstraintManager(GRStateManager& statemgr,
|
||||
ConstraintManager* CreateBasicConstraintManager(ProgramStateManager& statemgr,
|
||||
SubEngine &subengine);
|
||||
ConstraintManager* CreateRangeConstraintManager(GRStateManager& statemgr,
|
||||
ConstraintManager* CreateRangeConstraintManager(ProgramStateManager& statemgr,
|
||||
SubEngine &subengine);
|
||||
|
||||
} // end GR namespace
|
||||
|
|
|
@ -79,7 +79,8 @@ private:
|
|||
/// usually because it could not reason about something.
|
||||
BlocksAborted blocksAborted;
|
||||
|
||||
void generateNode(const ProgramPoint &Loc, const GRState *State,
|
||||
void generateNode(const ProgramPoint &Loc,
|
||||
const ProgramState *State,
|
||||
ExplodedNode *Pred);
|
||||
|
||||
void HandleBlockEdge(const BlockEdge &E, ExplodedNode *Pred);
|
||||
|
@ -126,9 +127,10 @@ public:
|
|||
/// ExecuteWorkList - Run the worklist algorithm for a maximum number of
|
||||
/// steps. Returns true if there is still simulation state on the worklist.
|
||||
bool ExecuteWorkList(const LocationContext *L, unsigned Steps,
|
||||
const GRState *InitState);
|
||||
void ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps,
|
||||
const GRState *InitState,
|
||||
const ProgramState *InitState);
|
||||
void ExecuteWorkListWithInitialState(const LocationContext *L,
|
||||
unsigned Steps,
|
||||
const ProgramState *InitState,
|
||||
ExplodedNodeSet &Dst);
|
||||
|
||||
// Functions for external checking of whether we have unfinished work
|
||||
|
@ -165,7 +167,7 @@ class StmtNodeBuilder {
|
|||
const CFGBlock &B;
|
||||
const unsigned Idx;
|
||||
ExplodedNode *Pred;
|
||||
GRStateManager& Mgr;
|
||||
ProgramStateManager& Mgr;
|
||||
|
||||
public:
|
||||
bool PurgingDeadSymbols;
|
||||
|
@ -180,8 +182,11 @@ public:
|
|||
void GenerateAutoTransition(ExplodedNode *N);
|
||||
|
||||
public:
|
||||
StmtNodeBuilder(const CFGBlock *b, unsigned idx, ExplodedNode *N,
|
||||
CoreEngine* e, GRStateManager &mgr);
|
||||
StmtNodeBuilder(const CFGBlock *b,
|
||||
unsigned idx,
|
||||
ExplodedNode *N,
|
||||
CoreEngine* e,
|
||||
ProgramStateManager &mgr);
|
||||
|
||||
~StmtNodeBuilder();
|
||||
|
||||
|
@ -198,13 +203,17 @@ public:
|
|||
B.getBlockID());
|
||||
}
|
||||
|
||||
ExplodedNode *generateNode(PostStmt PP,const GRState *St,ExplodedNode *Pred) {
|
||||
ExplodedNode *generateNode(PostStmt PP,
|
||||
const ProgramState *St,
|
||||
ExplodedNode *Pred) {
|
||||
hasGeneratedNode = true;
|
||||
return generateNodeInternal(PP, St, Pred);
|
||||
}
|
||||
|
||||
ExplodedNode *generateNode(const Stmt *S, const GRState *St,
|
||||
ExplodedNode *Pred, ProgramPoint::Kind K,
|
||||
ExplodedNode *generateNode(const Stmt *S,
|
||||
const ProgramState *St,
|
||||
ExplodedNode *Pred,
|
||||
ProgramPoint::Kind K,
|
||||
const ProgramPointTag *tag = 0) {
|
||||
hasGeneratedNode = true;
|
||||
|
||||
|
@ -214,26 +223,31 @@ public:
|
|||
return generateNodeInternal(S, St, Pred, K, tag ? tag : Tag);
|
||||
}
|
||||
|
||||
ExplodedNode *generateNode(const Stmt *S, const GRState *St,
|
||||
ExplodedNode *generateNode(const Stmt *S,
|
||||
const ProgramState *St,
|
||||
ExplodedNode *Pred,
|
||||
const ProgramPointTag *tag = 0) {
|
||||
return generateNode(S, St, Pred, PointKind, tag);
|
||||
}
|
||||
|
||||
ExplodedNode *generateNode(const ProgramPoint &PP, const GRState *State,
|
||||
ExplodedNode *generateNode(const ProgramPoint &PP,
|
||||
const ProgramState *State,
|
||||
ExplodedNode *Pred) {
|
||||
hasGeneratedNode = true;
|
||||
return generateNodeInternal(PP, State, Pred);
|
||||
}
|
||||
|
||||
ExplodedNode*
|
||||
generateNodeInternal(const ProgramPoint &PP, const GRState *State,
|
||||
generateNodeInternal(const ProgramPoint &PP,
|
||||
const ProgramState *State,
|
||||
ExplodedNode *Pred);
|
||||
|
||||
ExplodedNode*
|
||||
generateNodeInternal(const Stmt *S, const GRState *State, ExplodedNode *Pred,
|
||||
ProgramPoint::Kind K = ProgramPoint::PostStmtKind,
|
||||
const ProgramPointTag *tag = 0);
|
||||
generateNodeInternal(const Stmt *S,
|
||||
const ProgramState *State,
|
||||
ExplodedNode *Pred,
|
||||
ProgramPoint::Kind K = ProgramPoint::PostStmtKind,
|
||||
const ProgramPointTag *tag = 0);
|
||||
|
||||
/// getStmt - Return the current block-level expression associated with
|
||||
/// this builder.
|
||||
|
@ -248,16 +262,23 @@ public:
|
|||
|
||||
unsigned getIndex() const { return Idx; }
|
||||
|
||||
ExplodedNode *MakeNode(ExplodedNodeSet &Dst, const Stmt *S,
|
||||
ExplodedNode *Pred, const GRState *St) {
|
||||
ExplodedNode *MakeNode(ExplodedNodeSet &Dst,
|
||||
const Stmt *S,
|
||||
ExplodedNode *Pred,
|
||||
const ProgramState *St) {
|
||||
return MakeNode(Dst, S, Pred, St, PointKind);
|
||||
}
|
||||
|
||||
ExplodedNode *MakeNode(ExplodedNodeSet &Dst, const Stmt *S,ExplodedNode *Pred,
|
||||
const GRState *St, ProgramPoint::Kind K);
|
||||
ExplodedNode *MakeNode(ExplodedNodeSet &Dst,
|
||||
const Stmt *S,
|
||||
ExplodedNode *Pred,
|
||||
const ProgramState *St,
|
||||
ProgramPoint::Kind K);
|
||||
|
||||
ExplodedNode *MakeSinkNode(ExplodedNodeSet &Dst, const Stmt *S,
|
||||
ExplodedNode *Pred, const GRState *St) {
|
||||
ExplodedNode *MakeSinkNode(ExplodedNodeSet &Dst,
|
||||
const Stmt *S,
|
||||
ExplodedNode *Pred,
|
||||
const ProgramState *St) {
|
||||
bool Tmp = BuildSinks;
|
||||
BuildSinks = true;
|
||||
ExplodedNode *N = MakeNode(Dst, S, Pred, St);
|
||||
|
@ -296,9 +317,9 @@ public:
|
|||
|
||||
BlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();}
|
||||
|
||||
ExplodedNode *generateNode(const Stmt *Condition, const GRState *State);
|
||||
ExplodedNode *generateNode(const Stmt *Condition, const ProgramState *State);
|
||||
|
||||
ExplodedNode *generateNode(const GRState *State, bool branch);
|
||||
ExplodedNode *generateNode(const ProgramState *State, bool branch);
|
||||
|
||||
const CFGBlock *getTargetBlock(bool branch) const {
|
||||
return branch ? DstT : DstF;
|
||||
|
@ -315,7 +336,7 @@ public:
|
|||
return branch ? !InFeasibleTrue : !InFeasibleFalse;
|
||||
}
|
||||
|
||||
const GRState *getState() const {
|
||||
const ProgramState *getState() const {
|
||||
return getPredecessor()->getState();
|
||||
}
|
||||
};
|
||||
|
@ -354,12 +375,13 @@ public:
|
|||
iterator begin() { return iterator(DispatchBlock.succ_begin()); }
|
||||
iterator end() { return iterator(DispatchBlock.succ_end()); }
|
||||
|
||||
ExplodedNode *generateNode(const iterator &I, const GRState *State,
|
||||
ExplodedNode *generateNode(const iterator &I,
|
||||
const ProgramState *State,
|
||||
bool isSink = false);
|
||||
|
||||
const Expr *getTarget() const { return E; }
|
||||
|
||||
const GRState *getState() const { return Pred->State; }
|
||||
const ProgramState *getState() const { return Pred->State; }
|
||||
};
|
||||
|
||||
class SwitchNodeBuilder {
|
||||
|
@ -400,14 +422,15 @@ public:
|
|||
return llvm::cast<SwitchStmt>(Src->getTerminator());
|
||||
}
|
||||
|
||||
ExplodedNode *generateCaseStmtNode(const iterator &I, const GRState *State);
|
||||
ExplodedNode *generateCaseStmtNode(const iterator &I,
|
||||
const ProgramState *State);
|
||||
|
||||
ExplodedNode *generateDefaultCaseNode(const GRState *State,
|
||||
ExplodedNode *generateDefaultCaseNode(const ProgramState *State,
|
||||
bool isSink = false);
|
||||
|
||||
const Expr *getCondition() const { return Condition; }
|
||||
|
||||
const GRState *getState() const { return Pred->State; }
|
||||
const ProgramState *getState() const { return Pred->State; }
|
||||
};
|
||||
|
||||
class GenericNodeBuilderImpl {
|
||||
|
@ -417,8 +440,10 @@ protected:
|
|||
ProgramPoint pp;
|
||||
SmallVector<ExplodedNode*, 2> sinksGenerated;
|
||||
|
||||
ExplodedNode *generateNodeImpl(const GRState *state, ExplodedNode *pred,
|
||||
ProgramPoint programPoint, bool asSink);
|
||||
ExplodedNode *generateNodeImpl(const ProgramState *state,
|
||||
ExplodedNode *pred,
|
||||
ProgramPoint programPoint,
|
||||
bool asSink);
|
||||
|
||||
GenericNodeBuilderImpl(CoreEngine &eng, ExplodedNode *pr, ProgramPoint p)
|
||||
: engine(eng), pred(pr), pp(p), hasGeneratedNode(false) {}
|
||||
|
@ -445,7 +470,7 @@ public:
|
|||
GenericNodeBuilder(CoreEngine &eng, ExplodedNode *pr, const PP_T &p)
|
||||
: GenericNodeBuilderImpl(eng, pr, p) {}
|
||||
|
||||
ExplodedNode *generateNode(const GRState *state, ExplodedNode *pred,
|
||||
ExplodedNode *generateNode(const ProgramState *state, ExplodedNode *pred,
|
||||
const ProgramPointTag *tag, bool asSink) {
|
||||
return generateNodeImpl(state, pred, cast<PP_T>(pp).withTag(tag),
|
||||
asSink);
|
||||
|
@ -488,14 +513,15 @@ public:
|
|||
B.getBlockID());
|
||||
}
|
||||
|
||||
ExplodedNode *generateNode(const GRState *State, ExplodedNode *P = 0,
|
||||
ExplodedNode *generateNode(const ProgramState *State,
|
||||
ExplodedNode *P = 0,
|
||||
const ProgramPointTag *tag = 0);
|
||||
|
||||
void GenerateCallExitNode(const GRState *state);
|
||||
void GenerateCallExitNode(const ProgramState *state);
|
||||
|
||||
const CFGBlock *getBlock() const { return &B; }
|
||||
|
||||
const GRState *getState() const {
|
||||
const ProgramState *getState() const {
|
||||
return getPredecessor()->getState();
|
||||
}
|
||||
};
|
||||
|
@ -524,7 +550,7 @@ public:
|
|||
const CFGBlock *blk, unsigned idx)
|
||||
: Eng(eng), Pred(pred), CE(s), CalleeCtx(callee), Block(blk), Index(idx) {}
|
||||
|
||||
const GRState *getState() const { return Pred->getState(); }
|
||||
const ProgramState *getState() const { return Pred->getState(); }
|
||||
|
||||
const LocationContext *getLocationContext() const {
|
||||
return Pred->getLocationContext();
|
||||
|
@ -538,7 +564,7 @@ public:
|
|||
|
||||
unsigned getIndex() const { return Index; }
|
||||
|
||||
void generateNode(const GRState *state);
|
||||
void generateNode(const ProgramState *state);
|
||||
};
|
||||
|
||||
class CallExitNodeBuilder {
|
||||
|
@ -551,9 +577,9 @@ public:
|
|||
|
||||
const ExplodedNode *getPredecessor() const { return Pred; }
|
||||
|
||||
const GRState *getState() const { return Pred->getState(); }
|
||||
const ProgramState *getState() const { return Pred->getState(); }
|
||||
|
||||
void generateNode(const GRState *state);
|
||||
void generateNode(const ProgramState *state);
|
||||
};
|
||||
|
||||
} // end GR namespace
|
||||
|
|
|
@ -96,7 +96,7 @@ public:
|
|||
SVal V);
|
||||
|
||||
Environment removeDeadBindings(Environment Env,
|
||||
SymbolReaper &SymReaper, const GRState *ST);
|
||||
SymbolReaper &SymReaper, const ProgramState *ST);
|
||||
};
|
||||
|
||||
} // end GR namespace
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include "llvm/ADT/DepthFirstIterator.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "clang/Analysis/Support/BumpVector.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
|
@ -106,7 +106,7 @@ class ExplodedNode : public llvm::FoldingSetNode {
|
|||
const ProgramPoint Location;
|
||||
|
||||
/// State - The state associated with this node.
|
||||
const GRState *State;
|
||||
const ProgramState *State;
|
||||
|
||||
/// Preds - The predecessors of this node.
|
||||
NodeGroup Preds;
|
||||
|
@ -116,13 +116,13 @@ class ExplodedNode : public llvm::FoldingSetNode {
|
|||
|
||||
public:
|
||||
|
||||
explicit ExplodedNode(const ProgramPoint &loc, const GRState *state)
|
||||
explicit ExplodedNode(const ProgramPoint &loc, const ProgramState *state)
|
||||
: Location(loc), State(state) {
|
||||
const_cast<GRState*>(State)->incrementReferenceCount();
|
||||
const_cast<ProgramState*>(State)->incrementReferenceCount();
|
||||
}
|
||||
|
||||
~ExplodedNode() {
|
||||
const_cast<GRState*>(State)->decrementReferenceCount();
|
||||
const_cast<ProgramState*>(State)->decrementReferenceCount();
|
||||
}
|
||||
|
||||
/// getLocation - Returns the edge associated with the given node.
|
||||
|
@ -142,13 +142,13 @@ public:
|
|||
return *getLocationContext()->getLiveVariables();
|
||||
}
|
||||
|
||||
const GRState *getState() const { return State; }
|
||||
const ProgramState *getState() const { return State; }
|
||||
|
||||
template <typename T>
|
||||
const T* getLocationAs() const { return llvm::dyn_cast<T>(&Location); }
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID,
|
||||
const ProgramPoint &Loc, const GRState *state) {
|
||||
const ProgramPoint &Loc, const ProgramState *state) {
|
||||
ID.Add(Loc);
|
||||
ID.AddPointer(state);
|
||||
}
|
||||
|
@ -275,7 +275,7 @@ public:
|
|||
/// this pair exists, it is created. IsNew is set to true if
|
||||
/// the node was freshly created.
|
||||
|
||||
ExplodedNode *getNode(const ProgramPoint &L, const GRState *State,
|
||||
ExplodedNode *getNode(const ProgramPoint &L, const ProgramState *State,
|
||||
bool* IsNew = 0);
|
||||
|
||||
ExplodedGraph* MakeEmptyGraph() const {
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
|
||||
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
|
||||
|
@ -49,7 +49,7 @@ class ExprEngine : public SubEngine {
|
|||
StmtNodeBuilder* Builder;
|
||||
|
||||
/// StateMgr - Object that manages the data for all created states.
|
||||
GRStateManager StateMgr;
|
||||
ProgramStateManager StateMgr;
|
||||
|
||||
/// SymMgr - Object that manages the symbol information.
|
||||
SymbolManager& SymMgr;
|
||||
|
@ -62,7 +62,7 @@ class ExprEngine : public SubEngine {
|
|||
|
||||
/// CleanedState - The state for EntryNode "cleaned" of all dead
|
||||
/// variables and symbols (as determined by a liveness analysis).
|
||||
const GRState *CleanedState;
|
||||
const ProgramState *CleanedState;
|
||||
|
||||
/// currentStmt - The current block-level statement.
|
||||
const Stmt *currentStmt;
|
||||
|
@ -94,7 +94,7 @@ public:
|
|||
/// of the function are added into the Dst set, which represent the exit
|
||||
/// state of the function call.
|
||||
void ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps,
|
||||
const GRState *InitState,
|
||||
const ProgramState *InitState,
|
||||
ExplodedNodeSet &Dst) {
|
||||
Engine.ExecuteWorkListWithInitialState(L, Steps, InitState, Dst);
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ public:
|
|||
|
||||
/// getInitialState - Return the initial state used for the root vertex
|
||||
/// in the ExplodedGraph.
|
||||
const GRState *getInitialState(const LocationContext *InitLoc);
|
||||
const ProgramState *getInitialState(const LocationContext *InitLoc);
|
||||
|
||||
ExplodedGraph& getGraph() { return G; }
|
||||
const ExplodedGraph& getGraph() const { return G; }
|
||||
|
@ -181,21 +181,21 @@ public:
|
|||
|
||||
/// evalAssume - Callback function invoked by the ConstraintManager when
|
||||
/// making assumptions about state values.
|
||||
const GRState *processAssume(const GRState *state, SVal cond,bool assumption);
|
||||
const ProgramState *processAssume(const ProgramState *state, SVal cond,bool assumption);
|
||||
|
||||
/// wantsRegionChangeUpdate - Called by GRStateManager to determine if a
|
||||
/// wantsRegionChangeUpdate - Called by ProgramStateManager to determine if a
|
||||
/// region change should trigger a processRegionChanges update.
|
||||
bool wantsRegionChangeUpdate(const GRState *state);
|
||||
bool wantsRegionChangeUpdate(const ProgramState *state);
|
||||
|
||||
/// processRegionChanges - Called by GRStateManager whenever a change is made
|
||||
/// processRegionChanges - Called by ProgramStateManager whenever a change is made
|
||||
/// to the store. Used to update checkers that track region values.
|
||||
const GRState *
|
||||
processRegionChanges(const GRState *state,
|
||||
const ProgramState *
|
||||
processRegionChanges(const ProgramState *state,
|
||||
const StoreManager::InvalidatedSymbols *invalidated,
|
||||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End);
|
||||
|
||||
virtual GRStateManager& getStateManager() { return StateMgr; }
|
||||
virtual ProgramStateManager& getStateManager() { return StateMgr; }
|
||||
|
||||
StoreManager& getStoreManager() { return StateMgr.getStoreManager(); }
|
||||
|
||||
|
@ -224,7 +224,7 @@ public:
|
|||
|
||||
public:
|
||||
ExplodedNode *MakeNode(ExplodedNodeSet &Dst, const Stmt *S,
|
||||
ExplodedNode *Pred, const GRState *St,
|
||||
ExplodedNode *Pred, const ProgramState *St,
|
||||
ProgramPoint::Kind K = ProgramPoint::PostStmtKind,
|
||||
const ProgramPointTag *tag = 0);
|
||||
|
||||
|
@ -391,35 +391,35 @@ public:
|
|||
|
||||
public:
|
||||
|
||||
SVal evalBinOp(const GRState *state, BinaryOperator::Opcode op,
|
||||
SVal evalBinOp(const ProgramState *state, BinaryOperator::Opcode op,
|
||||
NonLoc L, NonLoc R, QualType T) {
|
||||
return svalBuilder.evalBinOpNN(state, op, L, R, T);
|
||||
}
|
||||
|
||||
SVal evalBinOp(const GRState *state, BinaryOperator::Opcode op,
|
||||
SVal evalBinOp(const ProgramState *state, BinaryOperator::Opcode op,
|
||||
NonLoc L, SVal R, QualType T) {
|
||||
return R.isValid() ? svalBuilder.evalBinOpNN(state,op,L, cast<NonLoc>(R), T) : R;
|
||||
}
|
||||
|
||||
SVal evalBinOp(const GRState *ST, BinaryOperator::Opcode Op,
|
||||
SVal evalBinOp(const ProgramState *ST, BinaryOperator::Opcode Op,
|
||||
SVal LHS, SVal RHS, QualType T) {
|
||||
return svalBuilder.evalBinOp(ST, Op, LHS, RHS, T);
|
||||
}
|
||||
|
||||
protected:
|
||||
void evalObjCMessage(ExplodedNodeSet &Dst, const ObjCMessage &msg,
|
||||
ExplodedNode *Pred, const GRState *state) {
|
||||
ExplodedNode *Pred, const ProgramState *state) {
|
||||
assert (Builder && "StmtNodeBuilder must be defined.");
|
||||
getTF().evalObjCMessage(Dst, *this, *Builder, msg, Pred, state);
|
||||
}
|
||||
|
||||
const GRState *MarkBranch(const GRState *St, const Stmt *Terminator,
|
||||
const ProgramState *MarkBranch(const ProgramState *St, const Stmt *Terminator,
|
||||
bool branchTaken);
|
||||
|
||||
/// evalBind - Handle the semantics of binding a value to a specific location.
|
||||
/// This method is used by evalStore, VisitDeclStmt, and others.
|
||||
void evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE, ExplodedNode *Pred,
|
||||
const GRState *St, SVal location, SVal Val,
|
||||
const ProgramState *St, SVal location, SVal Val,
|
||||
bool atDeclInit = false);
|
||||
|
||||
public:
|
||||
|
@ -430,23 +430,23 @@ public:
|
|||
// same as state->getLValue(Ex).
|
||||
/// Simulate a read of the result of Ex.
|
||||
void evalLoad(ExplodedNodeSet &Dst, const Expr *Ex, ExplodedNode *Pred,
|
||||
const GRState *St, SVal location, const ProgramPointTag *tag = 0,
|
||||
const ProgramState *St, SVal location, const ProgramPointTag *tag = 0,
|
||||
QualType LoadTy = QualType());
|
||||
|
||||
// FIXME: 'tag' should be removed, and a LocationContext should be used
|
||||
// instead.
|
||||
void evalStore(ExplodedNodeSet &Dst, const Expr *AssignE, const Expr *StoreE,
|
||||
ExplodedNode *Pred, const GRState *St, SVal TargetLV, SVal Val,
|
||||
ExplodedNode *Pred, const ProgramState *St, SVal TargetLV, SVal Val,
|
||||
const ProgramPointTag *tag = 0);
|
||||
private:
|
||||
void evalLoadCommon(ExplodedNodeSet &Dst, const Expr *Ex, ExplodedNode *Pred,
|
||||
const GRState *St, SVal location, const ProgramPointTag *tag,
|
||||
const ProgramState *St, SVal location, const ProgramPointTag *tag,
|
||||
QualType LoadTy);
|
||||
|
||||
// FIXME: 'tag' should be removed, and a LocationContext should be used
|
||||
// instead.
|
||||
void evalLocation(ExplodedNodeSet &Dst, const Stmt *S, ExplodedNode *Pred,
|
||||
const GRState *St, SVal location,
|
||||
const ProgramState *St, SVal location,
|
||||
const ProgramPointTag *tag, bool isLoad);
|
||||
|
||||
bool InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, ExplodedNode *Pred);
|
||||
|
|
|
@ -26,7 +26,7 @@ class StmtNodeBuilderRef {
|
|||
StmtNodeBuilder &B;
|
||||
ExprEngine& Eng;
|
||||
ExplodedNode *Pred;
|
||||
const GRState *state;
|
||||
const ProgramState *state;
|
||||
const Stmt *stmt;
|
||||
const unsigned OldSize;
|
||||
const bool AutoCreateNode;
|
||||
|
@ -43,7 +43,7 @@ private:
|
|||
StmtNodeBuilder &builder,
|
||||
ExprEngine& eng,
|
||||
ExplodedNode *pred,
|
||||
const GRState *st,
|
||||
const ProgramState *st,
|
||||
const Stmt *s, bool auto_create_node)
|
||||
: Dst(dst), B(builder), Eng(eng), Pred(pred),
|
||||
state(st), stmt(s), OldSize(Dst.size()), AutoCreateNode(auto_create_node),
|
||||
|
@ -62,13 +62,13 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
const GRState *getState() { return state; }
|
||||
const ProgramState *getState() { return state; }
|
||||
|
||||
GRStateManager& getStateManager() {
|
||||
ProgramStateManager& getStateManager() {
|
||||
return Eng.getStateManager();
|
||||
}
|
||||
|
||||
ExplodedNode *MakeNode(const GRState *state) {
|
||||
ExplodedNode *MakeNode(const ProgramState *state) {
|
||||
return B.MakeNode(Dst, const_cast<Stmt*>(stmt), Pred, state);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,802 +0,0 @@
|
|||
//== GRState.h - Path-sensitive "State" for tracking values -----*- C++ -*--==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines SymbolRef, ExprBindKey, and GRState*.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_GR_VALUESTATE_H
|
||||
#define LLVM_CLANG_GR_VALUESTATE_H
|
||||
|
||||
#include "clang/Basic/LLVM.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/Environment.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/ImmutableMap.h"
|
||||
|
||||
namespace llvm {
|
||||
class APSInt;
|
||||
class BumpPtrAllocator;
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
|
||||
namespace ento {
|
||||
|
||||
class GRStateManager;
|
||||
|
||||
typedef ConstraintManager* (*ConstraintManagerCreator)(GRStateManager&,
|
||||
SubEngine&);
|
||||
typedef StoreManager* (*StoreManagerCreator)(GRStateManager&);
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// GRStateTrait - Traits used by the Generic Data Map of a GRState.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
template <typename T> struct GRStatePartialTrait;
|
||||
|
||||
template <typename T> struct GRStateTrait {
|
||||
typedef typename T::data_type data_type;
|
||||
static inline void *GDMIndex() { return &T::TagInt; }
|
||||
static inline void *MakeVoidPtr(data_type D) { return (void*) D; }
|
||||
static inline data_type MakeData(void *const* P) {
|
||||
return P ? (data_type) *P : (data_type) 0;
|
||||
}
|
||||
};
|
||||
|
||||
class GRStateManager;
|
||||
|
||||
/// GRState - This class encapsulates:
|
||||
///
|
||||
/// 1. A mapping from expressions to values (Environment)
|
||||
/// 2. A mapping from locations to values (Store)
|
||||
/// 3. Constraints on symbolic values (GenericDataMap)
|
||||
///
|
||||
/// Together these represent the "abstract state" of a program.
|
||||
///
|
||||
/// GRState is intended to be used as a functional object; that is,
|
||||
/// once it is created and made "persistent" in a FoldingSet, its
|
||||
/// values will never change.
|
||||
class GRState : public llvm::FoldingSetNode {
|
||||
public:
|
||||
typedef llvm::ImmutableSet<llvm::APSInt*> IntSetTy;
|
||||
typedef llvm::ImmutableMap<void*, void*> GenericDataMap;
|
||||
|
||||
private:
|
||||
void operator=(const GRState& R) const; // Do not implement.
|
||||
|
||||
friend class GRStateManager;
|
||||
friend class ExplodedGraph;
|
||||
friend class ExplodedNode;
|
||||
|
||||
GRStateManager *stateMgr;
|
||||
Environment Env; // Maps a Stmt to its current SVal.
|
||||
Store store; // Maps a location to its current value.
|
||||
GenericDataMap GDM; // Custom data stored by a client of this class.
|
||||
unsigned refCount;
|
||||
|
||||
/// makeWithStore - Return a GRState with the same values as the current
|
||||
/// state with the exception of using the specified Store.
|
||||
const GRState *makeWithStore(const StoreRef &store) const;
|
||||
|
||||
void setStore(const StoreRef &storeRef);
|
||||
|
||||
public:
|
||||
|
||||
/// This ctor is used when creating the first GRState object.
|
||||
GRState(GRStateManager *mgr, const Environment& env,
|
||||
StoreRef st, GenericDataMap gdm);
|
||||
|
||||
/// Copy ctor - We must explicitly define this or else the "Next" ptr
|
||||
/// in FoldingSetNode will also get copied.
|
||||
GRState(const GRState &RHS);
|
||||
|
||||
~GRState();
|
||||
|
||||
/// Return the GRStateManager associated with this state.
|
||||
GRStateManager &getStateManager() const { return *stateMgr; }
|
||||
|
||||
/// Return true if this state is referenced by a persistent ExplodedNode.
|
||||
bool referencedByExplodedNode() const { return refCount > 0; }
|
||||
|
||||
/// getEnvironment - Return the environment associated with this state.
|
||||
/// The environment is the mapping from expressions to values.
|
||||
const Environment& getEnvironment() const { return Env; }
|
||||
|
||||
/// Return the store associated with this state. The store
|
||||
/// is a mapping from locations to values.
|
||||
Store getStore() const { return store; }
|
||||
|
||||
|
||||
/// getGDM - Return the generic data map associated with this state.
|
||||
GenericDataMap getGDM() const { return GDM; }
|
||||
|
||||
void setGDM(GenericDataMap gdm) { GDM = gdm; }
|
||||
|
||||
/// Profile - Profile the contents of a GRState object for use in a
|
||||
/// FoldingSet. Two GRState objects are considered equal if they
|
||||
/// have the same Environment, Store, and GenericDataMap.
|
||||
static void Profile(llvm::FoldingSetNodeID& ID, const GRState *V) {
|
||||
V->Env.Profile(ID);
|
||||
ID.AddPointer(V->store);
|
||||
V->GDM.Profile(ID);
|
||||
}
|
||||
|
||||
/// Profile - Used to profile the contents of this object for inclusion
|
||||
/// in a FoldingSet.
|
||||
void Profile(llvm::FoldingSetNodeID& ID) const {
|
||||
Profile(ID, this);
|
||||
}
|
||||
|
||||
BasicValueFactory &getBasicVals() const;
|
||||
SymbolManager &getSymbolManager() const;
|
||||
|
||||
//==---------------------------------------------------------------------==//
|
||||
// Constraints on values.
|
||||
//==---------------------------------------------------------------------==//
|
||||
//
|
||||
// Each GRState records constraints on symbolic values. These constraints
|
||||
// are managed using the ConstraintManager associated with a GRStateManager.
|
||||
// As constraints gradually accrue on symbolic values, added constraints
|
||||
// may conflict and indicate that a state is infeasible (as no real values
|
||||
// could satisfy all the constraints). This is the principal mechanism
|
||||
// for modeling path-sensitivity in ExprEngine/GRState.
|
||||
//
|
||||
// Various "assume" methods form the interface for adding constraints to
|
||||
// symbolic values. A call to 'assume' indicates an assumption being placed
|
||||
// on one or symbolic values. 'assume' methods take the following inputs:
|
||||
//
|
||||
// (1) A GRState object representing the current state.
|
||||
//
|
||||
// (2) The assumed constraint (which is specific to a given "assume" method).
|
||||
//
|
||||
// (3) A binary value "Assumption" that indicates whether the constraint is
|
||||
// assumed to be true or false.
|
||||
//
|
||||
// The output of "assume*" is a new GRState object with the added constraints.
|
||||
// If no new state is feasible, NULL is returned.
|
||||
//
|
||||
|
||||
const GRState *assume(DefinedOrUnknownSVal cond, bool assumption) const;
|
||||
|
||||
/// This method assumes both "true" and "false" for 'cond', and
|
||||
/// returns both corresponding states. It's shorthand for doing
|
||||
/// 'assume' twice.
|
||||
std::pair<const GRState*, const GRState*>
|
||||
assume(DefinedOrUnknownSVal cond) const;
|
||||
|
||||
const GRState *assumeInBound(DefinedOrUnknownSVal idx,
|
||||
DefinedOrUnknownSVal upperBound,
|
||||
bool assumption) const;
|
||||
|
||||
//==---------------------------------------------------------------------==//
|
||||
// Utility methods for getting regions.
|
||||
//==---------------------------------------------------------------------==//
|
||||
|
||||
const VarRegion* getRegion(const VarDecl *D, const LocationContext *LC) const;
|
||||
|
||||
//==---------------------------------------------------------------------==//
|
||||
// Binding and retrieving values to/from the environment and symbolic store.
|
||||
//==---------------------------------------------------------------------==//
|
||||
|
||||
/// BindCompoundLiteral - Return the state that has the bindings currently
|
||||
/// in this state plus the bindings for the CompoundLiteral.
|
||||
const GRState *bindCompoundLiteral(const CompoundLiteralExpr *CL,
|
||||
const LocationContext *LC,
|
||||
SVal V) const;
|
||||
|
||||
/// Create a new state by binding the value 'V' to the statement 'S' in the
|
||||
/// state's environment.
|
||||
const GRState *BindExpr(const Stmt *S, SVal V, bool Invalidate = true) const;
|
||||
|
||||
/// Create a new state by binding the value 'V' and location 'locaton' to the
|
||||
/// statement 'S' in the state's environment.
|
||||
const GRState *bindExprAndLocation(const Stmt *S, SVal location, SVal V)
|
||||
const;
|
||||
|
||||
const GRState *bindDecl(const VarRegion *VR, SVal V) const;
|
||||
|
||||
const GRState *bindDeclWithNoInit(const VarRegion *VR) const;
|
||||
|
||||
const GRState *bindLoc(Loc location, SVal V) const;
|
||||
|
||||
const GRState *bindLoc(SVal location, SVal V) const;
|
||||
|
||||
const GRState *bindDefault(SVal loc, SVal V) const;
|
||||
|
||||
const GRState *unbindLoc(Loc LV) const;
|
||||
|
||||
/// invalidateRegion - Returns the state with bindings for the given region
|
||||
/// cleared from the store. See invalidateRegions.
|
||||
const GRState *invalidateRegion(const MemRegion *R,
|
||||
const Expr *E, unsigned BlockCount,
|
||||
StoreManager::InvalidatedSymbols *IS = NULL)
|
||||
const {
|
||||
return invalidateRegions(&R, &R+1, E, BlockCount, IS, false);
|
||||
}
|
||||
|
||||
/// invalidateRegions - Returns the state with bindings for the given regions
|
||||
/// cleared from the store. The regions are provided as a continuous array
|
||||
/// from Begin to End. Optionally invalidates global regions as well.
|
||||
const GRState *invalidateRegions(const MemRegion * const *Begin,
|
||||
const MemRegion * const *End,
|
||||
const Expr *E, unsigned BlockCount,
|
||||
StoreManager::InvalidatedSymbols *IS,
|
||||
bool invalidateGlobals) const;
|
||||
|
||||
/// enterStackFrame - Returns the state for entry to the given stack frame,
|
||||
/// preserving the current state.
|
||||
const GRState *enterStackFrame(const StackFrameContext *frame) const;
|
||||
|
||||
/// Get the lvalue for a variable reference.
|
||||
Loc getLValue(const VarDecl *D, const LocationContext *LC) const;
|
||||
|
||||
/// Get the lvalue for a StringLiteral.
|
||||
Loc getLValue(const StringLiteral *literal) const;
|
||||
|
||||
Loc getLValue(const CompoundLiteralExpr *literal,
|
||||
const LocationContext *LC) const;
|
||||
|
||||
/// Get the lvalue for an ivar reference.
|
||||
SVal getLValue(const ObjCIvarDecl *decl, SVal base) const;
|
||||
|
||||
/// Get the lvalue for a field reference.
|
||||
SVal getLValue(const FieldDecl *decl, SVal Base) const;
|
||||
|
||||
/// Get the lvalue for an array index.
|
||||
SVal getLValue(QualType ElementType, SVal Idx, SVal Base) const;
|
||||
|
||||
const llvm::APSInt *getSymVal(SymbolRef sym) const;
|
||||
|
||||
/// Returns the SVal bound to the statement 'S' in the state's environment.
|
||||
SVal getSVal(const Stmt *S, bool useOnlyDirectBindings = false) const;
|
||||
|
||||
SVal getSValAsScalarOrLoc(const Stmt *Ex) const;
|
||||
|
||||
SVal getSVal(Loc LV, QualType T = QualType()) const;
|
||||
|
||||
/// Returns the "raw" SVal bound to LV before any value simplfication.
|
||||
SVal getRawSVal(Loc LV, QualType T= QualType()) const;
|
||||
|
||||
SVal getSVal(const MemRegion* R) const;
|
||||
|
||||
SVal getSValAsScalarOrLoc(const MemRegion *R) const;
|
||||
|
||||
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).
|
||||
//==---------------------------------------------------------------------==//
|
||||
|
||||
void *const* FindGDM(void *K) const;
|
||||
|
||||
template<typename T>
|
||||
const GRState *add(typename GRStateTrait<T>::key_type K) const;
|
||||
|
||||
template <typename T>
|
||||
typename GRStateTrait<T>::data_type
|
||||
get() const {
|
||||
return GRStateTrait<T>::MakeData(FindGDM(GRStateTrait<T>::GDMIndex()));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
typename GRStateTrait<T>::lookup_type
|
||||
get(typename GRStateTrait<T>::key_type key) const {
|
||||
void *const* d = FindGDM(GRStateTrait<T>::GDMIndex());
|
||||
return GRStateTrait<T>::Lookup(GRStateTrait<T>::MakeData(d), key);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename GRStateTrait<T>::context_type get_context() const;
|
||||
|
||||
|
||||
template<typename T>
|
||||
const GRState *remove(typename GRStateTrait<T>::key_type K) const;
|
||||
|
||||
template<typename T>
|
||||
const GRState *remove(typename GRStateTrait<T>::key_type K,
|
||||
typename GRStateTrait<T>::context_type C) const;
|
||||
template <typename T>
|
||||
const GRState *remove() const;
|
||||
|
||||
template<typename T>
|
||||
const GRState *set(typename GRStateTrait<T>::data_type D) const;
|
||||
|
||||
template<typename T>
|
||||
const GRState *set(typename GRStateTrait<T>::key_type K,
|
||||
typename GRStateTrait<T>::value_type E) const;
|
||||
|
||||
template<typename T>
|
||||
const GRState *set(typename GRStateTrait<T>::key_type K,
|
||||
typename GRStateTrait<T>::value_type E,
|
||||
typename GRStateTrait<T>::context_type C) const;
|
||||
|
||||
template<typename T>
|
||||
bool contains(typename GRStateTrait<T>::key_type key) const {
|
||||
void *const* d = FindGDM(GRStateTrait<T>::GDMIndex());
|
||||
return GRStateTrait<T>::Contains(GRStateTrait<T>::MakeData(d), key);
|
||||
}
|
||||
|
||||
// State pretty-printing.
|
||||
class Printer {
|
||||
public:
|
||||
virtual ~Printer() {}
|
||||
virtual void Print(raw_ostream &Out, const GRState *state,
|
||||
const char* nl, const char* sep) = 0;
|
||||
};
|
||||
|
||||
// Pretty-printing.
|
||||
void print(raw_ostream &Out, CFG &C, const char *nl = "\n",
|
||||
const char *sep = "") const;
|
||||
|
||||
void printStdErr(CFG &C) const;
|
||||
|
||||
void printDOT(raw_ostream &Out, CFG &C) const;
|
||||
|
||||
private:
|
||||
/// Increments the number of times this state is referenced by ExplodeNodes.
|
||||
void incrementReferenceCount() { ++refCount; }
|
||||
|
||||
/// Decrement the number of times this state is referenced by ExplodeNodes.
|
||||
void decrementReferenceCount() {
|
||||
assert(refCount > 0);
|
||||
--refCount;
|
||||
}
|
||||
|
||||
const GRState *invalidateRegionsImpl(const MemRegion * const *Begin,
|
||||
const MemRegion * const *End,
|
||||
const Expr *E, unsigned BlockCount,
|
||||
StoreManager::InvalidatedSymbols &IS,
|
||||
bool invalidateGlobals) const;
|
||||
};
|
||||
|
||||
class GRStateSet {
|
||||
typedef llvm::SmallPtrSet<const GRState*,5> ImplTy;
|
||||
ImplTy Impl;
|
||||
public:
|
||||
GRStateSet() {}
|
||||
|
||||
inline void Add(const GRState *St) {
|
||||
Impl.insert(St);
|
||||
}
|
||||
|
||||
typedef ImplTy::const_iterator iterator;
|
||||
|
||||
inline unsigned size() const { return Impl.size(); }
|
||||
inline bool empty() const { return Impl.empty(); }
|
||||
|
||||
inline iterator begin() const { return Impl.begin(); }
|
||||
inline iterator end() const { return Impl.end(); }
|
||||
|
||||
class AutoPopulate {
|
||||
GRStateSet &S;
|
||||
unsigned StartSize;
|
||||
const GRState *St;
|
||||
public:
|
||||
AutoPopulate(GRStateSet &s, const GRState *st)
|
||||
: S(s), StartSize(S.size()), St(st) {}
|
||||
|
||||
~AutoPopulate() {
|
||||
if (StartSize == S.size())
|
||||
S.Add(St);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// GRStateManager - Factory object for GRStates.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class GRStateManager {
|
||||
friend class GRState;
|
||||
friend class ExprEngine; // FIXME: Remove.
|
||||
private:
|
||||
/// Eng - The SubEngine that owns this state manager.
|
||||
SubEngine *Eng; /* Can be null. */
|
||||
|
||||
EnvironmentManager EnvMgr;
|
||||
llvm::OwningPtr<StoreManager> StoreMgr;
|
||||
llvm::OwningPtr<ConstraintManager> ConstraintMgr;
|
||||
|
||||
GRState::GenericDataMap::Factory GDMFactory;
|
||||
|
||||
typedef llvm::DenseMap<void*,std::pair<void*,void (*)(void*)> > GDMContextsTy;
|
||||
GDMContextsTy GDMContexts;
|
||||
|
||||
/// Printers - A set of printer objects used for pretty-printing a GRState.
|
||||
/// GRStateManager owns these objects.
|
||||
std::vector<GRState::Printer*> Printers;
|
||||
|
||||
/// StateSet - FoldingSet containing all the states created for analyzing
|
||||
/// a particular function. This is used to unique states.
|
||||
llvm::FoldingSet<GRState> StateSet;
|
||||
|
||||
/// Object that manages the data for all created SVals.
|
||||
llvm::OwningPtr<SValBuilder> svalBuilder;
|
||||
|
||||
/// A BumpPtrAllocator to allocate states.
|
||||
llvm::BumpPtrAllocator &Alloc;
|
||||
|
||||
/// A vector of recently allocated GRStates that can potentially be
|
||||
/// reused.
|
||||
std::vector<GRState *> recentlyAllocatedStates;
|
||||
|
||||
/// A vector of GRStates that we can reuse.
|
||||
std::vector<GRState *> freeStates;
|
||||
|
||||
public:
|
||||
GRStateManager(ASTContext &Ctx,
|
||||
StoreManagerCreator CreateStoreManager,
|
||||
ConstraintManagerCreator CreateConstraintManager,
|
||||
llvm::BumpPtrAllocator& alloc,
|
||||
SubEngine &subeng)
|
||||
: Eng(&subeng),
|
||||
EnvMgr(alloc),
|
||||
GDMFactory(alloc),
|
||||
svalBuilder(createSimpleSValBuilder(alloc, Ctx, *this)),
|
||||
Alloc(alloc) {
|
||||
StoreMgr.reset((*CreateStoreManager)(*this));
|
||||
ConstraintMgr.reset((*CreateConstraintManager)(*this, subeng));
|
||||
}
|
||||
|
||||
GRStateManager(ASTContext &Ctx,
|
||||
StoreManagerCreator CreateStoreManager,
|
||||
ConstraintManager* ConstraintManagerPtr,
|
||||
llvm::BumpPtrAllocator& alloc)
|
||||
: Eng(0),
|
||||
EnvMgr(alloc),
|
||||
GDMFactory(alloc),
|
||||
svalBuilder(createSimpleSValBuilder(alloc, Ctx, *this)),
|
||||
Alloc(alloc) {
|
||||
StoreMgr.reset((*CreateStoreManager)(*this));
|
||||
ConstraintMgr.reset(ConstraintManagerPtr);
|
||||
}
|
||||
|
||||
~GRStateManager();
|
||||
|
||||
const GRState *getInitialState(const LocationContext *InitLoc);
|
||||
|
||||
ASTContext &getContext() { return svalBuilder->getContext(); }
|
||||
const ASTContext &getContext() const { return svalBuilder->getContext(); }
|
||||
|
||||
BasicValueFactory &getBasicVals() {
|
||||
return svalBuilder->getBasicValueFactory();
|
||||
}
|
||||
const BasicValueFactory& getBasicVals() const {
|
||||
return svalBuilder->getBasicValueFactory();
|
||||
}
|
||||
|
||||
SValBuilder &getSValBuilder() {
|
||||
return *svalBuilder;
|
||||
}
|
||||
|
||||
SymbolManager &getSymbolManager() {
|
||||
return svalBuilder->getSymbolManager();
|
||||
}
|
||||
const SymbolManager &getSymbolManager() const {
|
||||
return svalBuilder->getSymbolManager();
|
||||
}
|
||||
|
||||
llvm::BumpPtrAllocator& getAllocator() { return Alloc; }
|
||||
|
||||
MemRegionManager& getRegionManager() {
|
||||
return svalBuilder->getRegionManager();
|
||||
}
|
||||
const MemRegionManager& getRegionManager() const {
|
||||
return svalBuilder->getRegionManager();
|
||||
}
|
||||
|
||||
StoreManager& getStoreManager() { return *StoreMgr; }
|
||||
ConstraintManager& getConstraintManager() { return *ConstraintMgr; }
|
||||
SubEngine* getOwningEngine() { return Eng; }
|
||||
|
||||
const GRState *removeDeadBindings(const GRState *St,
|
||||
const StackFrameContext *LCtx,
|
||||
SymbolReaper& SymReaper);
|
||||
|
||||
/// Marshal a new state for the callee in another translation unit.
|
||||
/// 'state' is owned by the caller's engine.
|
||||
const GRState *MarshalState(const GRState *state, const StackFrameContext *L);
|
||||
|
||||
public:
|
||||
|
||||
SVal ArrayToPointer(Loc Array) {
|
||||
return StoreMgr->ArrayToPointer(Array);
|
||||
}
|
||||
|
||||
// Methods that manipulate the GDM.
|
||||
const GRState *addGDM(const GRState *St, void *Key, void *Data);
|
||||
const GRState *removeGDM(const GRState *state, void *Key);
|
||||
|
||||
// Methods that query & manipulate the Store.
|
||||
|
||||
void iterBindings(const GRState *state, StoreManager::BindingsHandler& F) {
|
||||
StoreMgr->iterBindings(state->getStore(), F);
|
||||
}
|
||||
|
||||
const GRState *getPersistentState(GRState &Impl);
|
||||
const GRState *getPersistentStateWithGDM(const GRState *FromState,
|
||||
const GRState *GDMState);
|
||||
|
||||
bool haveEqualEnvironments(const GRState * S1, const GRState * S2) {
|
||||
return S1->Env == S2->Env;
|
||||
}
|
||||
|
||||
bool haveEqualStores(const GRState * S1, const GRState * S2) {
|
||||
return S1->store == S2->store;
|
||||
}
|
||||
|
||||
/// Periodically called by ExprEngine to recycle GRStates that were
|
||||
/// created but never used for creating an ExplodedNode.
|
||||
void recycleUnusedStates();
|
||||
|
||||
//==---------------------------------------------------------------------==//
|
||||
// Generic Data Map methods.
|
||||
//==---------------------------------------------------------------------==//
|
||||
//
|
||||
// GRStateManager and GRState support a "generic data map" that allows
|
||||
// different clients of GRState objects to embed arbitrary data within a
|
||||
// GRState object. The generic data map is essentially an immutable map
|
||||
// from a "tag" (that acts as the "key" for a client) and opaque values.
|
||||
// Tags/keys and values are simply void* values. The typical way that clients
|
||||
// generate unique tags are by taking the address of a static variable.
|
||||
// Clients are responsible for ensuring that data values referred to by a
|
||||
// the data pointer are immutable (and thus are essentially purely functional
|
||||
// data).
|
||||
//
|
||||
// The templated methods below use the GRStateTrait<T> class
|
||||
// to resolve keys into the GDM and to return data values to clients.
|
||||
//
|
||||
|
||||
// Trait based GDM dispatch.
|
||||
template <typename T>
|
||||
const GRState *set(const GRState *st, typename GRStateTrait<T>::data_type D) {
|
||||
return addGDM(st, GRStateTrait<T>::GDMIndex(),
|
||||
GRStateTrait<T>::MakeVoidPtr(D));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const GRState *set(const GRState *st,
|
||||
typename GRStateTrait<T>::key_type K,
|
||||
typename GRStateTrait<T>::value_type V,
|
||||
typename GRStateTrait<T>::context_type C) {
|
||||
|
||||
return addGDM(st, GRStateTrait<T>::GDMIndex(),
|
||||
GRStateTrait<T>::MakeVoidPtr(GRStateTrait<T>::Set(st->get<T>(), K, V, C)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const GRState *add(const GRState *st,
|
||||
typename GRStateTrait<T>::key_type K,
|
||||
typename GRStateTrait<T>::context_type C) {
|
||||
return addGDM(st, GRStateTrait<T>::GDMIndex(),
|
||||
GRStateTrait<T>::MakeVoidPtr(GRStateTrait<T>::Add(st->get<T>(), K, C)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const GRState *remove(const GRState *st,
|
||||
typename GRStateTrait<T>::key_type K,
|
||||
typename GRStateTrait<T>::context_type C) {
|
||||
|
||||
return addGDM(st, GRStateTrait<T>::GDMIndex(),
|
||||
GRStateTrait<T>::MakeVoidPtr(GRStateTrait<T>::Remove(st->get<T>(), K, C)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const GRState *remove(const GRState *st) {
|
||||
return removeGDM(st, GRStateTrait<T>::GDMIndex());
|
||||
}
|
||||
|
||||
void *FindGDMContext(void *index,
|
||||
void *(*CreateContext)(llvm::BumpPtrAllocator&),
|
||||
void (*DeleteContext)(void*));
|
||||
|
||||
template <typename T>
|
||||
typename GRStateTrait<T>::context_type get_context() {
|
||||
void *p = FindGDMContext(GRStateTrait<T>::GDMIndex(),
|
||||
GRStateTrait<T>::CreateContext,
|
||||
GRStateTrait<T>::DeleteContext);
|
||||
|
||||
return GRStateTrait<T>::MakeContext(p);
|
||||
}
|
||||
|
||||
const llvm::APSInt* getSymVal(const GRState *St, SymbolRef sym) {
|
||||
return ConstraintMgr->getSymVal(St, sym);
|
||||
}
|
||||
|
||||
void EndPath(const GRState *St) {
|
||||
ConstraintMgr->EndPath(St);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Out-of-line method definitions for GRState.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
inline const VarRegion* GRState::getRegion(const VarDecl *D,
|
||||
const LocationContext *LC) const {
|
||||
return getStateManager().getRegionManager().getVarRegion(D, LC);
|
||||
}
|
||||
|
||||
inline const GRState *GRState::assume(DefinedOrUnknownSVal Cond,
|
||||
bool Assumption) const {
|
||||
if (Cond.isUnknown())
|
||||
return this;
|
||||
|
||||
return getStateManager().ConstraintMgr->assume(this, cast<DefinedSVal>(Cond),
|
||||
Assumption);
|
||||
}
|
||||
|
||||
inline std::pair<const GRState*, const GRState*>
|
||||
GRState::assume(DefinedOrUnknownSVal Cond) const {
|
||||
if (Cond.isUnknown())
|
||||
return std::make_pair(this, this);
|
||||
|
||||
return getStateManager().ConstraintMgr->assumeDual(this,
|
||||
cast<DefinedSVal>(Cond));
|
||||
}
|
||||
|
||||
inline const GRState *GRState::bindLoc(SVal LV, SVal V) const {
|
||||
return !isa<Loc>(LV) ? this : bindLoc(cast<Loc>(LV), V);
|
||||
}
|
||||
|
||||
inline Loc GRState::getLValue(const VarDecl *VD,
|
||||
const LocationContext *LC) const {
|
||||
return getStateManager().StoreMgr->getLValueVar(VD, LC);
|
||||
}
|
||||
|
||||
inline Loc GRState::getLValue(const StringLiteral *literal) const {
|
||||
return getStateManager().StoreMgr->getLValueString(literal);
|
||||
}
|
||||
|
||||
inline Loc 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 {
|
||||
return getStateManager().StoreMgr->getLValueIvar(D, Base);
|
||||
}
|
||||
|
||||
inline SVal GRState::getLValue(const FieldDecl *D, SVal Base) const {
|
||||
return getStateManager().StoreMgr->getLValueField(D, Base);
|
||||
}
|
||||
|
||||
inline SVal GRState::getLValue(QualType ElementType, SVal Idx, SVal Base) const{
|
||||
if (NonLoc *N = dyn_cast<NonLoc>(&Idx))
|
||||
return getStateManager().StoreMgr->getLValueElement(ElementType, *N, Base);
|
||||
return UnknownVal();
|
||||
}
|
||||
|
||||
inline const llvm::APSInt *GRState::getSymVal(SymbolRef sym) const {
|
||||
return getStateManager().getSymVal(this, sym);
|
||||
}
|
||||
|
||||
inline SVal GRState::getSVal(const Stmt *Ex, bool useOnlyDirectBindings) const{
|
||||
return Env.getSVal(Ex, *getStateManager().svalBuilder,
|
||||
useOnlyDirectBindings);
|
||||
}
|
||||
|
||||
inline SVal GRState::getSValAsScalarOrLoc(const Stmt *S) const {
|
||||
if (const Expr *Ex = dyn_cast<Expr>(S)) {
|
||||
QualType T = Ex->getType();
|
||||
if (Ex->isLValue() || Loc::isLocType(T) || T->isIntegerType())
|
||||
return getSVal(S);
|
||||
}
|
||||
|
||||
return UnknownVal();
|
||||
}
|
||||
|
||||
inline SVal GRState::getRawSVal(Loc LV, QualType T) const {
|
||||
return getStateManager().StoreMgr->Retrieve(getStore(), LV, T);
|
||||
}
|
||||
|
||||
inline SVal GRState::getSVal(const MemRegion* R) const {
|
||||
return getStateManager().StoreMgr->Retrieve(getStore(), loc::MemRegionVal(R));
|
||||
}
|
||||
|
||||
inline BasicValueFactory &GRState::getBasicVals() const {
|
||||
return getStateManager().getBasicVals();
|
||||
}
|
||||
|
||||
inline SymbolManager &GRState::getSymbolManager() const {
|
||||
return getStateManager().getSymbolManager();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const GRState *GRState::add(typename GRStateTrait<T>::key_type K) const {
|
||||
return getStateManager().add<T>(this, K, get_context<T>());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename GRStateTrait<T>::context_type GRState::get_context() const {
|
||||
return getStateManager().get_context<T>();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const GRState *GRState::remove(typename GRStateTrait<T>::key_type K) const {
|
||||
return getStateManager().remove<T>(this, K, get_context<T>());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const GRState *GRState::remove(typename GRStateTrait<T>::key_type K,
|
||||
typename GRStateTrait<T>::context_type C) const {
|
||||
return getStateManager().remove<T>(this, K, C);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const GRState *GRState::remove() const {
|
||||
return getStateManager().remove<T>(this);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const GRState *GRState::set(typename GRStateTrait<T>::data_type D) const {
|
||||
return getStateManager().set<T>(this, D);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const GRState *GRState::set(typename GRStateTrait<T>::key_type K,
|
||||
typename GRStateTrait<T>::value_type E) const {
|
||||
return getStateManager().set<T>(this, K, E, get_context<T>());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const GRState *GRState::set(typename GRStateTrait<T>::key_type K,
|
||||
typename GRStateTrait<T>::value_type E,
|
||||
typename GRStateTrait<T>::context_type C) const {
|
||||
return getStateManager().set<T>(this, K, E, C);
|
||||
}
|
||||
|
||||
template <typename CB>
|
||||
CB GRState::scanReachableSymbols(SVal val) const {
|
||||
CB cb(this);
|
||||
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 GR namespace
|
||||
|
||||
} // end clang namespace
|
||||
|
||||
#endif
|
|
@ -1,183 +0,0 @@
|
|||
//==- GRStateTrait.h - Partial implementations of GRStateTrait -----*- C++ -*-//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines partial implementations of template specializations of
|
||||
// the class GRStateTrait<>. GRStateTrait<> is used by GRState to implement
|
||||
// set/get methods for mapulating a GRState's generic data map.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#ifndef LLVM_CLANG_GR_GRSTATETRAIT_H
|
||||
#define LLVM_CLANG_GR_GRSTATETRAIT_H
|
||||
|
||||
namespace llvm {
|
||||
class BumpPtrAllocator;
|
||||
template <typename K, typename D, typename I> class ImmutableMap;
|
||||
template <typename K, typename I> class ImmutableSet;
|
||||
template <typename T> class ImmutableList;
|
||||
template <typename T> class ImmutableListImpl;
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
|
||||
namespace ento {
|
||||
template <typename T> struct GRStatePartialTrait;
|
||||
|
||||
// Partial-specialization for ImmutableMap.
|
||||
|
||||
template <typename Key, typename Data, typename Info>
|
||||
struct GRStatePartialTrait< llvm::ImmutableMap<Key,Data,Info> > {
|
||||
typedef llvm::ImmutableMap<Key,Data,Info> data_type;
|
||||
typedef typename data_type::Factory& context_type;
|
||||
typedef Key key_type;
|
||||
typedef Data value_type;
|
||||
typedef const value_type* lookup_type;
|
||||
|
||||
static inline data_type MakeData(void *const* p) {
|
||||
return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0);
|
||||
}
|
||||
static inline void *MakeVoidPtr(data_type B) {
|
||||
return B.getRoot();
|
||||
}
|
||||
static lookup_type Lookup(data_type B, key_type K) {
|
||||
return B.lookup(K);
|
||||
}
|
||||
static data_type Set(data_type B, key_type K, value_type E,context_type F){
|
||||
return F.add(B, K, E);
|
||||
}
|
||||
|
||||
static data_type Remove(data_type B, key_type K, context_type F) {
|
||||
return F.remove(B, K);
|
||||
}
|
||||
|
||||
static inline context_type MakeContext(void *p) {
|
||||
return *((typename data_type::Factory*) p);
|
||||
}
|
||||
|
||||
static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
|
||||
return new typename data_type::Factory(Alloc);
|
||||
}
|
||||
|
||||
static void DeleteContext(void *Ctx) {
|
||||
delete (typename data_type::Factory*) Ctx;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Partial-specialization for ImmutableSet.
|
||||
|
||||
template <typename Key, typename Info>
|
||||
struct GRStatePartialTrait< llvm::ImmutableSet<Key,Info> > {
|
||||
typedef llvm::ImmutableSet<Key,Info> data_type;
|
||||
typedef typename data_type::Factory& context_type;
|
||||
typedef Key key_type;
|
||||
|
||||
static inline data_type MakeData(void *const* p) {
|
||||
return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0);
|
||||
}
|
||||
|
||||
static inline void *MakeVoidPtr(data_type B) {
|
||||
return B.getRoot();
|
||||
}
|
||||
|
||||
static data_type Add(data_type B, key_type K, context_type F) {
|
||||
return F.add(B, K);
|
||||
}
|
||||
|
||||
static data_type Remove(data_type B, key_type K, context_type F) {
|
||||
return F.remove(B, K);
|
||||
}
|
||||
|
||||
static bool Contains(data_type B, key_type K) {
|
||||
return B.contains(K);
|
||||
}
|
||||
|
||||
static inline context_type MakeContext(void *p) {
|
||||
return *((typename data_type::Factory*) p);
|
||||
}
|
||||
|
||||
static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
|
||||
return new typename data_type::Factory(Alloc);
|
||||
}
|
||||
|
||||
static void DeleteContext(void *Ctx) {
|
||||
delete (typename data_type::Factory*) Ctx;
|
||||
}
|
||||
};
|
||||
|
||||
// Partial-specialization for ImmutableList.
|
||||
|
||||
template <typename T>
|
||||
struct GRStatePartialTrait< llvm::ImmutableList<T> > {
|
||||
typedef llvm::ImmutableList<T> data_type;
|
||||
typedef T key_type;
|
||||
typedef typename data_type::Factory& context_type;
|
||||
|
||||
static data_type Add(data_type L, key_type K, context_type F) {
|
||||
return F.add(K, L);
|
||||
}
|
||||
|
||||
static bool Contains(data_type L, key_type K) {
|
||||
return L.contains(K);
|
||||
}
|
||||
|
||||
static inline data_type MakeData(void *const* p) {
|
||||
return p ? data_type((const llvm::ImmutableListImpl<T>*) *p)
|
||||
: data_type(0);
|
||||
}
|
||||
|
||||
static inline void *MakeVoidPtr(data_type D) {
|
||||
return (void*) D.getInternalPointer();
|
||||
}
|
||||
|
||||
static inline context_type MakeContext(void *p) {
|
||||
return *((typename data_type::Factory*) p);
|
||||
}
|
||||
|
||||
static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
|
||||
return new typename data_type::Factory(Alloc);
|
||||
}
|
||||
|
||||
static void DeleteContext(void *Ctx) {
|
||||
delete (typename data_type::Factory*) Ctx;
|
||||
}
|
||||
};
|
||||
|
||||
// Partial specialization for bool.
|
||||
template <> struct GRStatePartialTrait<bool> {
|
||||
typedef bool data_type;
|
||||
|
||||
static inline data_type MakeData(void *const* p) {
|
||||
return p ? (data_type) (uintptr_t) *p
|
||||
: data_type();
|
||||
}
|
||||
static inline void *MakeVoidPtr(data_type d) {
|
||||
return (void*) (uintptr_t) d;
|
||||
}
|
||||
};
|
||||
|
||||
// Partial specialization for unsigned.
|
||||
template <> struct GRStatePartialTrait<unsigned> {
|
||||
typedef unsigned data_type;
|
||||
|
||||
static inline data_type MakeData(void *const* p) {
|
||||
return p ? (data_type) (uintptr_t) *p
|
||||
: data_type();
|
||||
}
|
||||
static inline void *MakeVoidPtr(data_type d) {
|
||||
return (void*) (uintptr_t) d;
|
||||
}
|
||||
};
|
||||
|
||||
} // end GR namespace
|
||||
|
||||
} // end clang namespace
|
||||
|
||||
#endif
|
|
@ -16,7 +16,7 @@
|
|||
#define LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_OBJCMESSAGE
|
||||
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
||||
#include "clang/AST/ExprObjC.h"
|
||||
|
||||
namespace clang {
|
||||
|
@ -118,7 +118,7 @@ public:
|
|||
return isPropertySetter() ? 1 : 0;
|
||||
}
|
||||
|
||||
SVal getArgSVal(unsigned i, const GRState *state) const {
|
||||
SVal getArgSVal(unsigned i, const ProgramState *state) const {
|
||||
assert(isValid() && "This ObjCMessage is uninitialized!");
|
||||
assert(i < getNumArgs() && "Invalid index for argument");
|
||||
if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
|
||||
|
@ -170,11 +170,11 @@ public:
|
|||
class CallOrObjCMessage {
|
||||
const CallExpr *CallE;
|
||||
ObjCMessage Msg;
|
||||
const GRState *State;
|
||||
const ProgramState *State;
|
||||
public:
|
||||
CallOrObjCMessage(const CallExpr *callE, const GRState *state)
|
||||
CallOrObjCMessage(const CallExpr *callE, const ProgramState *state)
|
||||
: CallE(callE), State(state) {}
|
||||
CallOrObjCMessage(const ObjCMessage &msg, const GRState *state)
|
||||
CallOrObjCMessage(const ObjCMessage &msg, const ProgramState *state)
|
||||
: CallE(0), Msg(msg), State(state) {}
|
||||
|
||||
QualType getResultType(ASTContext &ctx) const;
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace clang {
|
|||
|
||||
namespace ento {
|
||||
|
||||
class GRState;
|
||||
class ProgramState;
|
||||
|
||||
class SValBuilder {
|
||||
protected:
|
||||
|
@ -40,7 +40,7 @@ protected:
|
|||
/// Manages the creation of memory regions.
|
||||
MemRegionManager MemMgr;
|
||||
|
||||
GRStateManager &StateMgr;
|
||||
ProgramStateManager &StateMgr;
|
||||
|
||||
/// The scalar type to use for array indices.
|
||||
const QualType ArrayIndexTy;
|
||||
|
@ -56,7 +56,7 @@ public:
|
|||
|
||||
public:
|
||||
SValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context,
|
||||
GRStateManager &stateMgr)
|
||||
ProgramStateManager &stateMgr)
|
||||
: Context(context), BasicVals(context, alloc),
|
||||
SymMgr(context, BasicVals, alloc),
|
||||
MemMgr(context, alloc),
|
||||
|
@ -72,29 +72,29 @@ public:
|
|||
|
||||
virtual SVal evalComplement(NonLoc val) = 0;
|
||||
|
||||
virtual SVal evalBinOpNN(const GRState *state, BinaryOperator::Opcode op,
|
||||
virtual SVal evalBinOpNN(const ProgramState *state, BinaryOperator::Opcode op,
|
||||
NonLoc lhs, NonLoc rhs, QualType resultTy) = 0;
|
||||
|
||||
virtual SVal evalBinOpLL(const GRState *state, BinaryOperator::Opcode op,
|
||||
virtual SVal evalBinOpLL(const ProgramState *state, BinaryOperator::Opcode op,
|
||||
Loc lhs, Loc rhs, QualType resultTy) = 0;
|
||||
|
||||
virtual SVal evalBinOpLN(const GRState *state, BinaryOperator::Opcode op,
|
||||
virtual SVal evalBinOpLN(const ProgramState *state, BinaryOperator::Opcode op,
|
||||
Loc lhs, NonLoc rhs, QualType resultTy) = 0;
|
||||
|
||||
/// getKnownValue - evaluates a given SVal. If the SVal has only one possible
|
||||
/// (integer) value, that value is returned. Otherwise, returns NULL.
|
||||
virtual const llvm::APSInt *getKnownValue(const GRState *state, SVal val) = 0;
|
||||
virtual const llvm::APSInt *getKnownValue(const ProgramState *state, SVal val) = 0;
|
||||
|
||||
SVal evalBinOp(const GRState *state, BinaryOperator::Opcode op,
|
||||
SVal evalBinOp(const ProgramState *state, BinaryOperator::Opcode op,
|
||||
SVal lhs, SVal rhs, QualType type);
|
||||
|
||||
DefinedOrUnknownSVal evalEQ(const GRState *state, DefinedOrUnknownSVal lhs,
|
||||
DefinedOrUnknownSVal evalEQ(const ProgramState *state, DefinedOrUnknownSVal lhs,
|
||||
DefinedOrUnknownSVal rhs);
|
||||
|
||||
ASTContext &getContext() { return Context; }
|
||||
const ASTContext &getContext() const { return Context; }
|
||||
|
||||
GRStateManager &getStateManager() { return StateMgr; }
|
||||
ProgramStateManager &getStateManager() { return StateMgr; }
|
||||
|
||||
QualType getConditionType() const {
|
||||
return getContext().IntTy;
|
||||
|
@ -255,7 +255,7 @@ public:
|
|||
|
||||
SValBuilder* createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc,
|
||||
ASTContext &context,
|
||||
GRStateManager &stateMgr);
|
||||
ProgramStateManager &stateMgr);
|
||||
|
||||
} // end GR namespace
|
||||
|
||||
|
|
|
@ -29,12 +29,12 @@ namespace ento {
|
|||
|
||||
class CompoundValData;
|
||||
class LazyCompoundValData;
|
||||
class GRState;
|
||||
class ProgramState;
|
||||
class BasicValueFactory;
|
||||
class MemRegion;
|
||||
class TypedRegion;
|
||||
class MemRegionManager;
|
||||
class GRStateManager;
|
||||
class ProgramStateManager;
|
||||
class SValBuilder;
|
||||
|
||||
/// SVal - This represents a symbolic expression, which can be either
|
||||
|
|
|
@ -29,20 +29,20 @@ class StackFrameContext;
|
|||
|
||||
namespace ento {
|
||||
|
||||
class GRState;
|
||||
class GRStateManager;
|
||||
class ProgramState;
|
||||
class ProgramStateManager;
|
||||
class SubRegionMap;
|
||||
|
||||
class StoreManager {
|
||||
protected:
|
||||
SValBuilder &svalBuilder;
|
||||
GRStateManager &StateMgr;
|
||||
ProgramStateManager &StateMgr;
|
||||
|
||||
/// MRMgr - Manages region objects associated with this StoreManager.
|
||||
MemRegionManager &MRMgr;
|
||||
ASTContext &Ctx;
|
||||
|
||||
StoreManager(GRStateManager &stateMgr);
|
||||
StoreManager(ProgramStateManager &stateMgr);
|
||||
|
||||
public:
|
||||
virtual ~StoreManager() {}
|
||||
|
@ -60,7 +60,7 @@ public:
|
|||
/// \param[in] state The analysis state.
|
||||
/// \param[in] loc The symbolic memory location.
|
||||
/// \param[in] val The value to bind to location \c loc.
|
||||
/// \return A pointer to a GRState object that contains the same bindings as
|
||||
/// \return A pointer to a ProgramState object that contains the same bindings as
|
||||
/// \c state with the addition of having the value specified by \c val bound
|
||||
/// to the location given for \c loc.
|
||||
virtual StoreRef Bind(Store store, Loc loc, SVal val) = 0;
|
||||
|
@ -114,7 +114,7 @@ public:
|
|||
|
||||
// FIXME: This should soon be eliminated altogether; clients should deal with
|
||||
// region extents directly.
|
||||
virtual DefinedOrUnknownSVal getSizeInElements(const GRState *state,
|
||||
virtual DefinedOrUnknownSVal getSizeInElements(const ProgramState *state,
|
||||
const MemRegion *region,
|
||||
QualType EleTy) {
|
||||
return UnknownVal();
|
||||
|
@ -130,12 +130,12 @@ public:
|
|||
}
|
||||
|
||||
class CastResult {
|
||||
const GRState *state;
|
||||
const ProgramState *state;
|
||||
const MemRegion *region;
|
||||
public:
|
||||
const GRState *getState() const { return state; }
|
||||
const ProgramState *getState() const { return state; }
|
||||
const MemRegion* getRegion() const { return region; }
|
||||
CastResult(const GRState *s, const MemRegion* r = 0) : state(s), region(r){}
|
||||
CastResult(const ProgramState *s, const MemRegion* r = 0) : state(s), region(r){}
|
||||
};
|
||||
|
||||
const ElementRegion *GetElementZeroRegion(const MemRegion *R, QualType T);
|
||||
|
@ -196,7 +196,7 @@ public:
|
|||
|
||||
/// enterStackFrame - Let the StoreManager to do something when execution
|
||||
/// engine is about to execute into a callee.
|
||||
virtual StoreRef enterStackFrame(const GRState *state,
|
||||
virtual StoreRef enterStackFrame(const ProgramState *state,
|
||||
const StackFrameContext *frame);
|
||||
|
||||
virtual void print(Store store, raw_ostream &Out,
|
||||
|
@ -271,9 +271,9 @@ public:
|
|||
virtual bool iterSubRegions(const MemRegion *region, Visitor& V) const = 0;
|
||||
};
|
||||
|
||||
// FIXME: Do we need to pass GRStateManager anymore?
|
||||
StoreManager *CreateRegionStoreManager(GRStateManager& StMgr);
|
||||
StoreManager *CreateFieldsOnlyRegionStoreManager(GRStateManager& StMgr);
|
||||
// FIXME: Do we need to pass ProgramStateManager anymore?
|
||||
StoreManager *CreateRegionStoreManager(ProgramStateManager& StMgr);
|
||||
StoreManager *CreateFieldsOnlyRegionStoreManager(ProgramStateManager& StMgr);
|
||||
|
||||
} // end GR namespace
|
||||
|
||||
|
|
|
@ -30,8 +30,8 @@ template <typename PP> class GenericNodeBuilder;
|
|||
class AnalysisManager;
|
||||
class ExplodedNodeSet;
|
||||
class ExplodedNode;
|
||||
class GRState;
|
||||
class GRStateManager;
|
||||
class ProgramState;
|
||||
class ProgramStateManager;
|
||||
class BlockCounter;
|
||||
class StmtNodeBuilder;
|
||||
class BranchNodeBuilder;
|
||||
|
@ -46,11 +46,11 @@ class SubEngine {
|
|||
public:
|
||||
virtual ~SubEngine() {}
|
||||
|
||||
virtual const GRState *getInitialState(const LocationContext *InitLoc) = 0;
|
||||
virtual const ProgramState *getInitialState(const LocationContext *InitLoc) = 0;
|
||||
|
||||
virtual AnalysisManager &getAnalysisManager() = 0;
|
||||
|
||||
virtual GRStateManager &getStateManager() = 0;
|
||||
virtual ProgramStateManager &getStateManager() = 0;
|
||||
|
||||
/// Called by CoreEngine. Used to generate new successor
|
||||
/// nodes by processing the 'effects' of a block-level statement.
|
||||
|
@ -87,24 +87,24 @@ public:
|
|||
|
||||
/// Called by ConstraintManager. Used to call checker-specific
|
||||
/// logic for handling assumptions on symbolic values.
|
||||
virtual const GRState *processAssume(const GRState *state,
|
||||
virtual const ProgramState *processAssume(const ProgramState *state,
|
||||
SVal cond, bool assumption) = 0;
|
||||
|
||||
/// wantsRegionChangeUpdate - Called by GRStateManager to determine if a
|
||||
/// wantsRegionChangeUpdate - Called by ProgramStateManager to determine if a
|
||||
/// region change should trigger a processRegionChanges update.
|
||||
virtual bool wantsRegionChangeUpdate(const GRState *state) = 0;
|
||||
virtual bool wantsRegionChangeUpdate(const ProgramState *state) = 0;
|
||||
|
||||
/// processRegionChanges - Called by GRStateManager whenever a change is made
|
||||
/// processRegionChanges - Called by ProgramStateManager whenever a change is made
|
||||
/// to the store. Used to update checkers that track region values.
|
||||
virtual const GRState *
|
||||
processRegionChanges(const GRState *state,
|
||||
virtual const ProgramState *
|
||||
processRegionChanges(const ProgramState *state,
|
||||
const StoreManager::InvalidatedSymbols *invalidated,
|
||||
const MemRegion* const *Begin,
|
||||
const MemRegion* const *End) = 0;
|
||||
|
||||
|
||||
inline const GRState *
|
||||
processRegionChange(const GRState *state,
|
||||
inline const ProgramState *
|
||||
processRegionChange(const ProgramState *state,
|
||||
const MemRegion* MR) {
|
||||
return processRegionChanges(state, 0, &MR, &MR+1);
|
||||
}
|
||||
|
|
|
@ -522,7 +522,7 @@ private:
|
|||
|
||||
class SymbolVisitor {
|
||||
public:
|
||||
/// \brief A visitor method invoked by GRStateManager::scanReachableSymbols.
|
||||
/// \brief A visitor method invoked by ProgramStateManager::scanReachableSymbols.
|
||||
///
|
||||
/// The method returns \c true if symbols should continue be scanned and \c
|
||||
/// false otherwise.
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#ifndef LLVM_CLANG_GR_TRANSFERFUNCS
|
||||
#define LLVM_CLANG_GR_TRANSFERFUNCS
|
||||
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
|
||||
#include <vector>
|
||||
|
@ -36,7 +36,7 @@ public:
|
|||
TransferFuncs() {}
|
||||
virtual ~TransferFuncs() {}
|
||||
|
||||
virtual void RegisterPrinters(std::vector<GRState::Printer*>& Printers) {}
|
||||
virtual void RegisterPrinters(std::vector<ProgramState::Printer*>& Printers) {}
|
||||
virtual void RegisterChecks(ExprEngine& Eng) {}
|
||||
|
||||
|
||||
|
@ -53,7 +53,7 @@ public:
|
|||
StmtNodeBuilder& Builder,
|
||||
ObjCMessage msg,
|
||||
ExplodedNode *Pred,
|
||||
const GRState *state) {}
|
||||
const ProgramState *state) {}
|
||||
|
||||
// Stores.
|
||||
|
||||
|
@ -69,7 +69,7 @@ public:
|
|||
ExprEngine& Engine,
|
||||
StmtNodeBuilder& Builder,
|
||||
ExplodedNode *Pred,
|
||||
const GRState *state,
|
||||
const ProgramState *state,
|
||||
SymbolReaper& SymReaper) {}
|
||||
|
||||
// Return statements.
|
||||
|
@ -80,7 +80,7 @@ public:
|
|||
ExplodedNode *Pred) {}
|
||||
|
||||
// Assumptions.
|
||||
virtual const GRState *evalAssume(const GRState *state,
|
||||
virtual const ProgramState *evalAssume(const ProgramState *state,
|
||||
SVal Cond, bool Assumption) {
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ void AdjustedReturnValueChecker::checkPostStmt(const CallExpr *CE,
|
|||
QualType expectedResultTy = CE->getType();
|
||||
|
||||
// Fetch the signature of the called function.
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
|
||||
SVal V = state->getSVal(CE);
|
||||
|
||||
|
|
|
@ -50,15 +50,15 @@ void ArrayBoundChecker::checkLocation(SVal l, bool isLoad,
|
|||
if (Idx.isZeroConstant())
|
||||
return;
|
||||
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
|
||||
// Get the size of the array.
|
||||
DefinedOrUnknownSVal NumElements
|
||||
= C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(),
|
||||
ER->getValueType());
|
||||
|
||||
const GRState *StInBound = state->assumeInBound(Idx, NumElements, true);
|
||||
const GRState *StOutBound = state->assumeInBound(Idx, NumElements, false);
|
||||
const ProgramState *StInBound = state->assumeInBound(Idx, NumElements, true);
|
||||
const ProgramState *StOutBound = state->assumeInBound(Idx, NumElements, false);
|
||||
if (StOutBound && !StInBound) {
|
||||
ExplodedNode *N = C.generateSink(StOutBound);
|
||||
if (!N)
|
||||
|
|
|
@ -30,7 +30,7 @@ class ArrayBoundCheckerV2 :
|
|||
|
||||
enum OOB_Kind { OOB_Precedes, OOB_Excedes };
|
||||
|
||||
void reportOOB(CheckerContext &C, const GRState *errorState,
|
||||
void reportOOB(CheckerContext &C, const ProgramState *errorState,
|
||||
OOB_Kind kind) const;
|
||||
|
||||
public:
|
||||
|
@ -53,7 +53,7 @@ public:
|
|||
NonLoc getByteOffset() const { return cast<NonLoc>(byteOffset); }
|
||||
const SubRegion *getRegion() const { return baseRegion; }
|
||||
|
||||
static RegionRawOffsetV2 computeOffset(const GRState *state,
|
||||
static RegionRawOffsetV2 computeOffset(const ProgramState *state,
|
||||
SValBuilder &svalBuilder,
|
||||
SVal location);
|
||||
|
||||
|
@ -81,7 +81,7 @@ static SVal computeExtentBegin(SValBuilder &svalBuilder,
|
|||
void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
|
||||
CheckerContext &checkerContext) const {
|
||||
|
||||
// NOTE: Instead of using GRState::assumeInBound(), we are prototyping
|
||||
// NOTE: Instead of using ProgramState::assumeInBound(), we are prototyping
|
||||
// some new logic here that reasons directly about memory region extents.
|
||||
// Once that logic is more mature, we can bring it back to assumeInBound()
|
||||
// for all clients to use.
|
||||
|
@ -90,8 +90,8 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
|
|||
// memory access is within the extent of the base region. Since we
|
||||
// have some flexibility in defining the base region, we can achieve
|
||||
// various levels of conservatism in our buffer overflow checking.
|
||||
const GRState *state = checkerContext.getState();
|
||||
const GRState *originalState = state;
|
||||
const ProgramState *state = checkerContext.getState();
|
||||
const ProgramState *originalState = state;
|
||||
|
||||
SValBuilder &svalBuilder = checkerContext.getSValBuilder();
|
||||
const RegionRawOffsetV2 &rawOffset =
|
||||
|
@ -116,7 +116,7 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
|
|||
if (!lowerBoundToCheck)
|
||||
return;
|
||||
|
||||
const GRState *state_precedesLowerBound, *state_withinLowerBound;
|
||||
const ProgramState *state_precedesLowerBound, *state_withinLowerBound;
|
||||
llvm::tie(state_precedesLowerBound, state_withinLowerBound) =
|
||||
state->assume(*lowerBoundToCheck);
|
||||
|
||||
|
@ -148,7 +148,7 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
|
|||
if (!upperboundToCheck)
|
||||
break;
|
||||
|
||||
const GRState *state_exceedsUpperBound, *state_withinUpperBound;
|
||||
const ProgramState *state_exceedsUpperBound, *state_withinUpperBound;
|
||||
llvm::tie(state_exceedsUpperBound, state_withinUpperBound) =
|
||||
state->assume(*upperboundToCheck);
|
||||
|
||||
|
@ -168,7 +168,7 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
|
|||
}
|
||||
|
||||
void ArrayBoundCheckerV2::reportOOB(CheckerContext &checkerContext,
|
||||
const GRState *errorState,
|
||||
const ProgramState *errorState,
|
||||
OOB_Kind kind) const {
|
||||
|
||||
ExplodedNode *errorNode = checkerContext.generateSink(errorState);
|
||||
|
@ -219,7 +219,7 @@ static inline SVal getValue(SVal val, SValBuilder &svalBuilder) {
|
|||
|
||||
// Scale a base value by a scaling factor, and return the scaled
|
||||
// value as an SVal. Used by 'computeOffset'.
|
||||
static inline SVal scaleValue(const GRState *state,
|
||||
static inline SVal scaleValue(const ProgramState *state,
|
||||
NonLoc baseVal, CharUnits scaling,
|
||||
SValBuilder &sb) {
|
||||
return sb.evalBinOpNN(state, BO_Mul, baseVal,
|
||||
|
@ -229,7 +229,7 @@ static inline SVal scaleValue(const GRState *state,
|
|||
|
||||
// Add an SVal to another, treating unknown and undefined values as
|
||||
// summing to UnknownVal. Used by 'computeOffset'.
|
||||
static SVal addValue(const GRState *state, SVal x, SVal y,
|
||||
static SVal addValue(const ProgramState *state, SVal x, SVal y,
|
||||
SValBuilder &svalBuilder) {
|
||||
// We treat UnknownVals and UndefinedVals the same here because we
|
||||
// only care about computing offsets.
|
||||
|
@ -243,7 +243,7 @@ static SVal addValue(const GRState *state, SVal x, SVal y,
|
|||
|
||||
/// Compute a raw byte offset from a base region. Used for array bounds
|
||||
/// checking.
|
||||
RegionRawOffsetV2 RegionRawOffsetV2::computeOffset(const GRState *state,
|
||||
RegionRawOffsetV2 RegionRawOffsetV2::computeOffset(const ProgramState *state,
|
||||
SValBuilder &svalBuilder,
|
||||
SVal location)
|
||||
{
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
|
||||
void AttrNonNullChecker::checkPreStmt(const CallExpr *CE,
|
||||
CheckerContext &C) const {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
|
||||
// Check if the callee has a 'nonnull' attribute.
|
||||
SVal X = state->getSVal(CE->getCallee());
|
||||
|
@ -85,7 +85,7 @@ void AttrNonNullChecker::checkPreStmt(const CallExpr *CE,
|
|||
}
|
||||
|
||||
ConstraintManager &CM = C.getConstraintManager();
|
||||
const GRState *stateNotNull, *stateNull;
|
||||
const ProgramState *stateNotNull, *stateNull;
|
||||
llvm::tie(stateNotNull, stateNull) = CM.assumeDual(state, *DV);
|
||||
|
||||
if (stateNull && !stateNotNull) {
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
||||
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
|
@ -249,7 +249,7 @@ static const char* GetCFNumberTypeStr(uint64_t i) {
|
|||
void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE,
|
||||
CheckerContext &C) const {
|
||||
const Expr *Callee = CE->getCallee();
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
SVal CallV = state->getSVal(Callee);
|
||||
const FunctionDecl *FD = CallV.getAsFunctionDecl();
|
||||
|
||||
|
@ -363,7 +363,7 @@ void CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE,
|
|||
return;
|
||||
|
||||
// Get the function declaration of the callee.
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
SVal X = state->getSVal(CE->getCallee());
|
||||
const FunctionDecl *FD = X.getAsFunctionDecl();
|
||||
|
||||
|
@ -400,7 +400,7 @@ void CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE,
|
|||
DefinedOrUnknownSVal ArgIsNull = svalBuilder.evalEQ(state, zero, *DefArgVal);
|
||||
|
||||
// Are they equal?
|
||||
const GRState *stateTrue, *stateFalse;
|
||||
const ProgramState *stateTrue, *stateFalse;
|
||||
llvm::tie(stateTrue, stateFalse) = state->assume(ArgIsNull);
|
||||
|
||||
if (stateTrue && !stateFalse) {
|
||||
|
@ -586,7 +586,7 @@ void VariadicMethodTypeChecker::checkPreObjCMessage(ObjCMessage msg,
|
|||
|
||||
// Verify that all arguments have Objective-C types.
|
||||
llvm::Optional<ExplodedNode*> errorNode;
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
|
||||
for (unsigned I = variadicArgsBegin; I != variadicArgsEnd; ++I) {
|
||||
QualType ArgTy = msg.getArgType(I);
|
||||
|
|
|
@ -31,7 +31,7 @@ public:
|
|||
|
||||
bool BuiltinFunctionChecker::evalCall(const CallExpr *CE,
|
||||
CheckerContext &C) const{
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
SVal L = state->getSVal(Callee);
|
||||
const FunctionDecl *FD = L.getAsFunctionDecl();
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
|
||||
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
|
||||
using namespace clang;
|
||||
|
@ -40,14 +40,15 @@ public:
|
|||
|
||||
bool evalCall(const CallExpr *CE, CheckerContext &C) const;
|
||||
void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const;
|
||||
void checkLiveSymbols(const GRState *state, SymbolReaper &SR) const;
|
||||
void checkLiveSymbols(const ProgramState *state, SymbolReaper &SR) const;
|
||||
void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
|
||||
bool wantsRegionChangeUpdate(const GRState *state) const;
|
||||
bool wantsRegionChangeUpdate(const ProgramState *state) const;
|
||||
|
||||
const GRState *checkRegionChanges(const GRState *state,
|
||||
const StoreManager::InvalidatedSymbols *,
|
||||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End) const;
|
||||
const ProgramState *
|
||||
checkRegionChanges(const ProgramState *state,
|
||||
const StoreManager::InvalidatedSymbols *,
|
||||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End) const;
|
||||
|
||||
typedef void (CStringChecker::*FnCheck)(CheckerContext &,
|
||||
const CallExpr *) const;
|
||||
|
@ -57,8 +58,10 @@ public:
|
|||
void evalMemmove(CheckerContext &C, const CallExpr *CE) const;
|
||||
void evalBcopy(CheckerContext &C, const CallExpr *CE) const;
|
||||
void evalCopyCommon(CheckerContext &C, const CallExpr *CE,
|
||||
const GRState *state,
|
||||
const Expr *Size, const Expr *Source, const Expr *Dest,
|
||||
const ProgramState *state,
|
||||
const Expr *Size,
|
||||
const Expr *Source,
|
||||
const Expr *Dest,
|
||||
bool Restricted = false,
|
||||
bool IsMempcpy = false) const;
|
||||
|
||||
|
@ -66,14 +69,18 @@ public:
|
|||
|
||||
void evalstrLength(CheckerContext &C, const CallExpr *CE) const;
|
||||
void evalstrnLength(CheckerContext &C, const CallExpr *CE) const;
|
||||
void evalstrLengthCommon(CheckerContext &C, const CallExpr *CE,
|
||||
void evalstrLengthCommon(CheckerContext &C,
|
||||
const CallExpr *CE,
|
||||
bool IsStrnlen = false) const;
|
||||
|
||||
void evalStrcpy(CheckerContext &C, const CallExpr *CE) const;
|
||||
void evalStrncpy(CheckerContext &C, const CallExpr *CE) const;
|
||||
void evalStpcpy(CheckerContext &C, const CallExpr *CE) const;
|
||||
void evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, bool returnEnd,
|
||||
bool isBounded, bool isAppending) const;
|
||||
void evalStrcpyCommon(CheckerContext &C,
|
||||
const CallExpr *CE,
|
||||
bool returnEnd,
|
||||
bool isBounded,
|
||||
bool isAppending) const;
|
||||
|
||||
void evalStrcat(CheckerContext &C, const CallExpr *CE) const;
|
||||
void evalStrncat(CheckerContext &C, const CallExpr *CE) const;
|
||||
|
@ -82,64 +89,85 @@ public:
|
|||
void evalStrncmp(CheckerContext &C, const CallExpr *CE) const;
|
||||
void evalStrcasecmp(CheckerContext &C, const CallExpr *CE) const;
|
||||
void evalStrncasecmp(CheckerContext &C, const CallExpr *CE) const;
|
||||
void evalStrcmpCommon(CheckerContext &C, const CallExpr *CE,
|
||||
bool isBounded = false, bool ignoreCase = false) const;
|
||||
void evalStrcmpCommon(CheckerContext &C,
|
||||
const CallExpr *CE,
|
||||
bool isBounded = false,
|
||||
bool ignoreCase = false) const;
|
||||
|
||||
// Utility methods
|
||||
std::pair<const GRState*, const GRState*>
|
||||
std::pair<const ProgramState*, const ProgramState*>
|
||||
static assumeZero(CheckerContext &C,
|
||||
const GRState *state, SVal V, QualType Ty);
|
||||
const ProgramState *state, SVal V, QualType Ty);
|
||||
|
||||
static const GRState *setCStringLength(const GRState *state,
|
||||
const MemRegion *MR, SVal strLength);
|
||||
static const ProgramState *setCStringLength(const ProgramState *state,
|
||||
const MemRegion *MR,
|
||||
SVal strLength);
|
||||
static SVal getCStringLengthForRegion(CheckerContext &C,
|
||||
const GRState *&state,
|
||||
const Expr *Ex, const MemRegion *MR,
|
||||
const ProgramState *&state,
|
||||
const Expr *Ex,
|
||||
const MemRegion *MR,
|
||||
bool hypothetical);
|
||||
SVal getCStringLength(CheckerContext &C, const GRState *&state,
|
||||
const Expr *Ex, SVal Buf,
|
||||
SVal getCStringLength(CheckerContext &C,
|
||||
const ProgramState *&state,
|
||||
const Expr *Ex,
|
||||
SVal Buf,
|
||||
bool hypothetical = false) const;
|
||||
|
||||
const StringLiteral *getCStringLiteral(CheckerContext &C,
|
||||
const GRState *&state,
|
||||
const ProgramState *&state,
|
||||
const Expr *expr,
|
||||
SVal val) const;
|
||||
|
||||
static const GRState *InvalidateBuffer(CheckerContext &C,
|
||||
const GRState *state,
|
||||
const Expr *Ex, SVal V);
|
||||
static const ProgramState *InvalidateBuffer(CheckerContext &C,
|
||||
const ProgramState *state,
|
||||
const Expr *Ex, SVal V);
|
||||
|
||||
static bool SummarizeRegion(raw_ostream &os, ASTContext &Ctx,
|
||||
const MemRegion *MR);
|
||||
|
||||
// Re-usable checks
|
||||
const GRState *checkNonNull(CheckerContext &C, const GRState *state,
|
||||
const Expr *S, SVal l) const;
|
||||
const GRState *CheckLocation(CheckerContext &C, const GRState *state,
|
||||
const Expr *S, SVal l,
|
||||
const char *message = NULL) const;
|
||||
const GRState *CheckBufferAccess(CheckerContext &C, const GRState *state,
|
||||
const Expr *Size,
|
||||
const Expr *FirstBuf,
|
||||
const Expr *SecondBuf,
|
||||
const char *firstMessage = NULL,
|
||||
const char *secondMessage = NULL,
|
||||
bool WarnAboutSize = false) const;
|
||||
const GRState *CheckBufferAccess(CheckerContext &C, const GRState *state,
|
||||
const Expr *Size, const Expr *Buf,
|
||||
const char *message = NULL,
|
||||
bool WarnAboutSize = false) const {
|
||||
const ProgramState *checkNonNull(CheckerContext &C,
|
||||
const ProgramState *state,
|
||||
const Expr *S,
|
||||
SVal l) const;
|
||||
const ProgramState *CheckLocation(CheckerContext &C,
|
||||
const ProgramState *state,
|
||||
const Expr *S,
|
||||
SVal l,
|
||||
const char *message = NULL) const;
|
||||
const ProgramState *CheckBufferAccess(CheckerContext &C,
|
||||
const ProgramState *state,
|
||||
const Expr *Size,
|
||||
const Expr *FirstBuf,
|
||||
const Expr *SecondBuf,
|
||||
const char *firstMessage = NULL,
|
||||
const char *secondMessage = NULL,
|
||||
bool WarnAboutSize = false) const;
|
||||
|
||||
const ProgramState *CheckBufferAccess(CheckerContext &C,
|
||||
const ProgramState *state,
|
||||
const Expr *Size,
|
||||
const Expr *Buf,
|
||||
const char *message = NULL,
|
||||
bool WarnAboutSize = false) const {
|
||||
// This is a convenience override.
|
||||
return CheckBufferAccess(C, state, Size, Buf, NULL, message, NULL,
|
||||
WarnAboutSize);
|
||||
}
|
||||
const GRState *CheckOverlap(CheckerContext &C, const GRState *state,
|
||||
const Expr *Size, const Expr *First,
|
||||
const Expr *Second) const;
|
||||
void emitOverlapBug(CheckerContext &C, const GRState *state,
|
||||
const Stmt *First, const Stmt *Second) const;
|
||||
const GRState *checkAdditionOverflow(CheckerContext &C, const GRState *state,
|
||||
NonLoc left, NonLoc right) const;
|
||||
const ProgramState *CheckOverlap(CheckerContext &C,
|
||||
const ProgramState *state,
|
||||
const Expr *Size,
|
||||
const Expr *First,
|
||||
const Expr *Second) const;
|
||||
void emitOverlapBug(CheckerContext &C,
|
||||
const ProgramState *state,
|
||||
const Stmt *First,
|
||||
const Stmt *Second) const;
|
||||
|
||||
const ProgramState *checkAdditionOverflow(CheckerContext &C,
|
||||
const ProgramState *state,
|
||||
NonLoc left,
|
||||
NonLoc right) const;
|
||||
};
|
||||
|
||||
class CStringLength {
|
||||
|
@ -151,8 +179,8 @@ public:
|
|||
namespace clang {
|
||||
namespace ento {
|
||||
template <>
|
||||
struct GRStateTrait<CStringLength>
|
||||
: public GRStatePartialTrait<CStringLength::EntryMap> {
|
||||
struct ProgramStateTrait<CStringLength>
|
||||
: public ProgramStatePartialTrait<CStringLength::EntryMap> {
|
||||
static void *GDMIndex() { return CStringChecker::getTag(); }
|
||||
};
|
||||
}
|
||||
|
@ -162,26 +190,26 @@ namespace ento {
|
|||
// Individual checks and utility methods.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
std::pair<const GRState*, const GRState*>
|
||||
CStringChecker::assumeZero(CheckerContext &C, const GRState *state, SVal V,
|
||||
std::pair<const ProgramState*, const ProgramState*>
|
||||
CStringChecker::assumeZero(CheckerContext &C, const ProgramState *state, SVal V,
|
||||
QualType Ty) {
|
||||
DefinedSVal *val = dyn_cast<DefinedSVal>(&V);
|
||||
if (!val)
|
||||
return std::pair<const GRState*, const GRState *>(state, state);
|
||||
return std::pair<const ProgramState*, const ProgramState *>(state, state);
|
||||
|
||||
SValBuilder &svalBuilder = C.getSValBuilder();
|
||||
DefinedOrUnknownSVal zero = svalBuilder.makeZeroVal(Ty);
|
||||
return state->assume(svalBuilder.evalEQ(state, *val, zero));
|
||||
}
|
||||
|
||||
const GRState *CStringChecker::checkNonNull(CheckerContext &C,
|
||||
const GRState *state,
|
||||
const ProgramState *CStringChecker::checkNonNull(CheckerContext &C,
|
||||
const ProgramState *state,
|
||||
const Expr *S, SVal l) const {
|
||||
// If a previous check has failed, propagate the failure.
|
||||
if (!state)
|
||||
return NULL;
|
||||
|
||||
const GRState *stateNull, *stateNonNull;
|
||||
const ProgramState *stateNull, *stateNonNull;
|
||||
llvm::tie(stateNull, stateNonNull) = assumeZero(C, state, l, S->getType());
|
||||
|
||||
if (stateNull && !stateNonNull) {
|
||||
|
@ -214,8 +242,8 @@ const GRState *CStringChecker::checkNonNull(CheckerContext &C,
|
|||
}
|
||||
|
||||
// FIXME: This was originally copied from ArrayBoundChecker.cpp. Refactor?
|
||||
const GRState *CStringChecker::CheckLocation(CheckerContext &C,
|
||||
const GRState *state,
|
||||
const ProgramState *CStringChecker::CheckLocation(CheckerContext &C,
|
||||
const ProgramState *state,
|
||||
const Expr *S, SVal l,
|
||||
const char *warningMsg) const {
|
||||
// If a previous check has failed, propagate the failure.
|
||||
|
@ -244,8 +272,8 @@ const GRState *CStringChecker::CheckLocation(CheckerContext &C,
|
|||
// Get the index of the accessed element.
|
||||
DefinedOrUnknownSVal Idx = cast<DefinedOrUnknownSVal>(ER->getIndex());
|
||||
|
||||
const GRState *StInBound = state->assumeInBound(Idx, Size, true);
|
||||
const GRState *StOutBound = state->assumeInBound(Idx, Size, false);
|
||||
const ProgramState *StInBound = state->assumeInBound(Idx, Size, true);
|
||||
const ProgramState *StOutBound = state->assumeInBound(Idx, Size, false);
|
||||
if (StOutBound && !StInBound) {
|
||||
ExplodedNode *N = C.generateSink(StOutBound);
|
||||
if (!N)
|
||||
|
@ -287,8 +315,8 @@ const GRState *CStringChecker::CheckLocation(CheckerContext &C,
|
|||
return StInBound;
|
||||
}
|
||||
|
||||
const GRState *CStringChecker::CheckBufferAccess(CheckerContext &C,
|
||||
const GRState *state,
|
||||
const ProgramState *CStringChecker::CheckBufferAccess(CheckerContext &C,
|
||||
const ProgramState *state,
|
||||
const Expr *Size,
|
||||
const Expr *FirstBuf,
|
||||
const Expr *SecondBuf,
|
||||
|
@ -359,8 +387,8 @@ const GRState *CStringChecker::CheckBufferAccess(CheckerContext &C,
|
|||
return state;
|
||||
}
|
||||
|
||||
const GRState *CStringChecker::CheckOverlap(CheckerContext &C,
|
||||
const GRState *state,
|
||||
const ProgramState *CStringChecker::CheckOverlap(CheckerContext &C,
|
||||
const ProgramState *state,
|
||||
const Expr *Size,
|
||||
const Expr *First,
|
||||
const Expr *Second) const {
|
||||
|
@ -372,7 +400,7 @@ const GRState *CStringChecker::CheckOverlap(CheckerContext &C,
|
|||
if (!state)
|
||||
return NULL;
|
||||
|
||||
const GRState *stateTrue, *stateFalse;
|
||||
const ProgramState *stateTrue, *stateFalse;
|
||||
|
||||
// Get the buffer values and make sure they're known locations.
|
||||
SVal firstVal = state->getSVal(First);
|
||||
|
@ -470,7 +498,7 @@ const GRState *CStringChecker::CheckOverlap(CheckerContext &C,
|
|||
return stateFalse;
|
||||
}
|
||||
|
||||
void CStringChecker::emitOverlapBug(CheckerContext &C, const GRState *state,
|
||||
void CStringChecker::emitOverlapBug(CheckerContext &C, const ProgramState *state,
|
||||
const Stmt *First, const Stmt *Second) const {
|
||||
ExplodedNode *N = C.generateSink(state);
|
||||
if (!N)
|
||||
|
@ -489,8 +517,8 @@ void CStringChecker::emitOverlapBug(CheckerContext &C, const GRState *state,
|
|||
C.EmitReport(report);
|
||||
}
|
||||
|
||||
const GRState *CStringChecker::checkAdditionOverflow(CheckerContext &C,
|
||||
const GRState *state,
|
||||
const ProgramState *CStringChecker::checkAdditionOverflow(CheckerContext &C,
|
||||
const ProgramState *state,
|
||||
NonLoc left,
|
||||
NonLoc right) const {
|
||||
// If a previous check has failed, propagate the failure.
|
||||
|
@ -521,7 +549,7 @@ const GRState *CStringChecker::checkAdditionOverflow(CheckerContext &C,
|
|||
SVal willOverflow = svalBuilder.evalBinOpNN(state, BO_GT, left,
|
||||
*maxMinusRightNL, cmpTy);
|
||||
|
||||
const GRState *stateOverflow, *stateOkay;
|
||||
const ProgramState *stateOverflow, *stateOkay;
|
||||
llvm::tie(stateOverflow, stateOkay) =
|
||||
state->assume(cast<DefinedOrUnknownSVal>(willOverflow));
|
||||
|
||||
|
@ -557,7 +585,7 @@ const GRState *CStringChecker::checkAdditionOverflow(CheckerContext &C,
|
|||
return state;
|
||||
}
|
||||
|
||||
const GRState *CStringChecker::setCStringLength(const GRState *state,
|
||||
const ProgramState *CStringChecker::setCStringLength(const ProgramState *state,
|
||||
const MemRegion *MR,
|
||||
SVal strLength) {
|
||||
assert(!strLength.isUndef() && "Attempt to set an undefined string length");
|
||||
|
@ -598,7 +626,7 @@ const GRState *CStringChecker::setCStringLength(const GRState *state,
|
|||
}
|
||||
|
||||
SVal CStringChecker::getCStringLengthForRegion(CheckerContext &C,
|
||||
const GRState *&state,
|
||||
const ProgramState *&state,
|
||||
const Expr *Ex,
|
||||
const MemRegion *MR,
|
||||
bool hypothetical) {
|
||||
|
@ -622,7 +650,7 @@ SVal CStringChecker::getCStringLengthForRegion(CheckerContext &C,
|
|||
return strLength;
|
||||
}
|
||||
|
||||
SVal CStringChecker::getCStringLength(CheckerContext &C, const GRState *&state,
|
||||
SVal CStringChecker::getCStringLength(CheckerContext &C, const ProgramState *&state,
|
||||
const Expr *Ex, SVal Buf,
|
||||
bool hypothetical) const {
|
||||
const MemRegion *MR = Buf.getAsRegion();
|
||||
|
@ -717,7 +745,7 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, const GRState *&state,
|
|||
}
|
||||
|
||||
const StringLiteral *CStringChecker::getCStringLiteral(CheckerContext &C,
|
||||
const GRState *&state, const Expr *expr, SVal val) const {
|
||||
const ProgramState *&state, const Expr *expr, SVal val) const {
|
||||
|
||||
// Get the memory region pointed to by the val.
|
||||
const MemRegion *bufRegion = val.getAsRegion();
|
||||
|
@ -736,8 +764,8 @@ const StringLiteral *CStringChecker::getCStringLiteral(CheckerContext &C,
|
|||
return strRegion->getStringLiteral();
|
||||
}
|
||||
|
||||
const GRState *CStringChecker::InvalidateBuffer(CheckerContext &C,
|
||||
const GRState *state,
|
||||
const ProgramState *CStringChecker::InvalidateBuffer(CheckerContext &C,
|
||||
const ProgramState *state,
|
||||
const Expr *E, SVal V) {
|
||||
Loc *L = dyn_cast<Loc>(&V);
|
||||
if (!L)
|
||||
|
@ -810,7 +838,7 @@ bool CStringChecker::SummarizeRegion(raw_ostream &os, ASTContext &Ctx,
|
|||
|
||||
void CStringChecker::evalCopyCommon(CheckerContext &C,
|
||||
const CallExpr *CE,
|
||||
const GRState *state,
|
||||
const ProgramState *state,
|
||||
const Expr *Size, const Expr *Dest,
|
||||
const Expr *Source, bool Restricted,
|
||||
bool IsMempcpy) const {
|
||||
|
@ -820,7 +848,7 @@ void CStringChecker::evalCopyCommon(CheckerContext &C,
|
|||
SVal sizeVal = state->getSVal(Size);
|
||||
QualType sizeTy = Size->getType();
|
||||
|
||||
const GRState *stateZeroSize, *stateNonZeroSize;
|
||||
const ProgramState *stateZeroSize, *stateNonZeroSize;
|
||||
llvm::tie(stateZeroSize, stateNonZeroSize) =
|
||||
assumeZero(C, state, sizeVal, sizeTy);
|
||||
|
||||
|
@ -912,7 +940,7 @@ void CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE) const {
|
|||
// void *memcpy(void *restrict dst, const void *restrict src, size_t n);
|
||||
// The return value is the address of the destination buffer.
|
||||
const Expr *Dest = CE->getArg(0);
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
|
||||
evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1), true);
|
||||
}
|
||||
|
@ -921,7 +949,7 @@ void CStringChecker::evalMempcpy(CheckerContext &C, const CallExpr *CE) const {
|
|||
// void *mempcpy(void *restrict dst, const void *restrict src, size_t n);
|
||||
// The return value is a pointer to the byte following the last written byte.
|
||||
const Expr *Dest = CE->getArg(0);
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
|
||||
evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1), true, true);
|
||||
}
|
||||
|
@ -930,7 +958,7 @@ void CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) const {
|
|||
// void *memmove(void *dst, const void *src, size_t n);
|
||||
// The return value is the address of the destination buffer.
|
||||
const Expr *Dest = CE->getArg(0);
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
|
||||
evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1));
|
||||
}
|
||||
|
@ -949,14 +977,14 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const {
|
|||
const Expr *Right = CE->getArg(1);
|
||||
const Expr *Size = CE->getArg(2);
|
||||
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
SValBuilder &svalBuilder = C.getSValBuilder();
|
||||
|
||||
// See if the size argument is zero.
|
||||
SVal sizeVal = state->getSVal(Size);
|
||||
QualType sizeTy = Size->getType();
|
||||
|
||||
const GRState *stateZeroSize, *stateNonZeroSize;
|
||||
const ProgramState *stateZeroSize, *stateNonZeroSize;
|
||||
llvm::tie(stateZeroSize, stateNonZeroSize) =
|
||||
assumeZero(C, state, sizeVal, sizeTy);
|
||||
|
||||
|
@ -979,7 +1007,7 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const {
|
|||
|
||||
// See if they are the same.
|
||||
DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV);
|
||||
const GRState *StSameBuf, *StNotSameBuf;
|
||||
const ProgramState *StSameBuf, *StNotSameBuf;
|
||||
llvm::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);
|
||||
|
||||
// If the two arguments might be the same buffer, we know the result is 0,
|
||||
|
@ -1024,13 +1052,13 @@ void CStringChecker::evalstrnLength(CheckerContext &C,
|
|||
void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE,
|
||||
bool IsStrnlen) const {
|
||||
CurrentFunctionDescription = "string length function";
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
|
||||
if (IsStrnlen) {
|
||||
const Expr *maxlenExpr = CE->getArg(1);
|
||||
SVal maxlenVal = state->getSVal(maxlenExpr);
|
||||
|
||||
const GRState *stateZeroSize, *stateNonZeroSize;
|
||||
const ProgramState *stateZeroSize, *stateNonZeroSize;
|
||||
llvm::tie(stateZeroSize, stateNonZeroSize) =
|
||||
assumeZero(C, state, maxlenVal, maxlenExpr->getType());
|
||||
|
||||
|
@ -1082,7 +1110,7 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE,
|
|||
NonLoc *maxlenValNL = dyn_cast<NonLoc>(&maxlenVal);
|
||||
|
||||
if (strLengthNL && maxlenValNL) {
|
||||
const GRState *stateStringTooLong, *stateStringNotTooLong;
|
||||
const ProgramState *stateStringTooLong, *stateStringNotTooLong;
|
||||
|
||||
// Check if the strLength is greater than the maxlen.
|
||||
llvm::tie(stateStringTooLong, stateStringNotTooLong) =
|
||||
|
@ -1189,7 +1217,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
|
|||
bool returnEnd, bool isBounded,
|
||||
bool isAppending) const {
|
||||
CurrentFunctionDescription = "string copy function";
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
|
||||
// Check that the destination is non-null.
|
||||
const Expr *Dst = CE->getArg(0);
|
||||
|
@ -1239,7 +1267,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
|
|||
// If we know both values, we might be able to figure out how much
|
||||
// we're copying.
|
||||
if (strLengthNL && lenValNL) {
|
||||
const GRState *stateSourceTooLong, *stateSourceNotTooLong;
|
||||
const ProgramState *stateSourceTooLong, *stateSourceNotTooLong;
|
||||
|
||||
// Check if the max number to copy is less than the length of the src.
|
||||
// If the bound is equal to the source length, strncpy won't null-
|
||||
|
@ -1512,7 +1540,7 @@ void CStringChecker::evalStrncasecmp(CheckerContext &C,
|
|||
void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE,
|
||||
bool isBounded, bool ignoreCase) const {
|
||||
CurrentFunctionDescription = "string comparison function";
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
|
||||
// Check that the first string is non-null
|
||||
const Expr *s1 = CE->getArg(0);
|
||||
|
@ -1547,7 +1575,7 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE,
|
|||
// See if they are the same.
|
||||
SValBuilder &svalBuilder = C.getSValBuilder();
|
||||
DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV);
|
||||
const GRState *StSameBuf, *StNotSameBuf;
|
||||
const ProgramState *StSameBuf, *StNotSameBuf;
|
||||
llvm::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);
|
||||
|
||||
// If the two arguments might be the same buffer, we know the result is 0,
|
||||
|
@ -1638,7 +1666,7 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE,
|
|||
bool CStringChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
|
||||
// Get the callee. All the functions we care about are C functions
|
||||
// with simple identifiers.
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
const FunctionDecl *FD = state->getSVal(Callee).getAsFunctionDecl();
|
||||
|
||||
|
@ -1687,7 +1715,7 @@ bool CStringChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
|
|||
|
||||
void CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
|
||||
// Record string length for char a[] = "abc";
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
|
||||
for (DeclStmt::const_decl_iterator I = DS->decl_begin(), E = DS->decl_end();
|
||||
I != E; ++I) {
|
||||
|
@ -1721,13 +1749,13 @@ void CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
|
|||
C.addTransition(state);
|
||||
}
|
||||
|
||||
bool CStringChecker::wantsRegionChangeUpdate(const GRState *state) const {
|
||||
bool CStringChecker::wantsRegionChangeUpdate(const ProgramState *state) const {
|
||||
CStringLength::EntryMap Entries = state->get<CStringLength>();
|
||||
return !Entries.isEmpty();
|
||||
}
|
||||
|
||||
const GRState *
|
||||
CStringChecker::checkRegionChanges(const GRState *state,
|
||||
const ProgramState *
|
||||
CStringChecker::checkRegionChanges(const ProgramState *state,
|
||||
const StoreManager::InvalidatedSymbols *,
|
||||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End) const {
|
||||
|
@ -1777,7 +1805,7 @@ CStringChecker::checkRegionChanges(const GRState *state,
|
|||
return state->set<CStringLength>(Entries);
|
||||
}
|
||||
|
||||
void CStringChecker::checkLiveSymbols(const GRState *state,
|
||||
void CStringChecker::checkLiveSymbols(const ProgramState *state,
|
||||
SymbolReaper &SR) const {
|
||||
// Mark all symbols in our string length map as valid.
|
||||
CStringLength::EntryMap Entries = state->get<CStringLength>();
|
||||
|
@ -1797,7 +1825,7 @@ void CStringChecker::checkDeadSymbols(SymbolReaper &SR,
|
|||
if (!SR.hasDeadSymbols())
|
||||
return;
|
||||
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
CStringLength::EntryMap Entries = state->get<CStringLength>();
|
||||
if (Entries.isEmpty())
|
||||
return;
|
||||
|
|
|
@ -47,7 +47,8 @@ private:
|
|||
void emitNilReceiverBug(CheckerContext &C, const ObjCMessage &msg,
|
||||
ExplodedNode *N) const;
|
||||
|
||||
void HandleNilReceiver(CheckerContext &C, const GRState *state,
|
||||
void HandleNilReceiver(CheckerContext &C,
|
||||
const ProgramState *state,
|
||||
ObjCMessage msg) const;
|
||||
|
||||
static void LazyInit_BT(const char *desc, llvm::OwningPtr<BugType> &BT) {
|
||||
|
@ -216,7 +217,7 @@ void CallAndMessageChecker::checkPreStmt(const CallExpr *CE,
|
|||
void CallAndMessageChecker::checkPreObjCMessage(ObjCMessage msg,
|
||||
CheckerContext &C) const {
|
||||
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
|
||||
// FIXME: Handle 'super'?
|
||||
if (const Expr *receiver = msg.getInstanceReceiver()) {
|
||||
|
@ -238,7 +239,7 @@ void CallAndMessageChecker::checkPreObjCMessage(ObjCMessage msg,
|
|||
// Bifurcate the state into nil and non-nil ones.
|
||||
DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal);
|
||||
|
||||
const GRState *notNilState, *nilState;
|
||||
const ProgramState *notNilState, *nilState;
|
||||
llvm::tie(notNilState, nilState) = state->assume(receiverVal);
|
||||
|
||||
// Handle receiver must be nil.
|
||||
|
@ -288,7 +289,7 @@ static bool supportsNilWithFloatRet(const llvm::Triple &triple) {
|
|||
}
|
||||
|
||||
void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C,
|
||||
const GRState *state,
|
||||
const ProgramState *state,
|
||||
ObjCMessage msg) const {
|
||||
ASTContext &Ctx = C.getASTContext();
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ void CastSizeChecker::checkPreStmt(const CastExpr *CE,CheckerContext &C) const {
|
|||
if (ToPointeeTy->isIncompleteType())
|
||||
return;
|
||||
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
const MemRegion *R = state->getSVal(E).getAsRegion();
|
||||
if (R == 0)
|
||||
return;
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
|
||||
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
|
||||
#include "llvm/ADT/ImmutableMap.h"
|
||||
using namespace clang;
|
||||
|
@ -62,7 +62,7 @@ private:
|
|||
} // end anonymous namespace
|
||||
|
||||
bool ChrootChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
SVal L = state->getSVal(Callee);
|
||||
const FunctionDecl *FD = L.getAsFunctionDecl();
|
||||
|
@ -88,8 +88,8 @@ bool ChrootChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
|
|||
}
|
||||
|
||||
void ChrootChecker::Chroot(CheckerContext &C, const CallExpr *CE) const {
|
||||
const GRState *state = C.getState();
|
||||
GRStateManager &Mgr = state->getStateManager();
|
||||
const ProgramState *state = C.getState();
|
||||
ProgramStateManager &Mgr = state->getStateManager();
|
||||
|
||||
// Once encouter a chroot(), set the enum value ROOT_CHANGED directly in
|
||||
// the GDM.
|
||||
|
@ -98,8 +98,8 @@ void ChrootChecker::Chroot(CheckerContext &C, const CallExpr *CE) const {
|
|||
}
|
||||
|
||||
void ChrootChecker::Chdir(CheckerContext &C, const CallExpr *CE) const {
|
||||
const GRState *state = C.getState();
|
||||
GRStateManager &Mgr = state->getStateManager();
|
||||
const ProgramState *state = C.getState();
|
||||
ProgramStateManager &Mgr = state->getStateManager();
|
||||
|
||||
// If there are no jail state in the GDM, just return.
|
||||
const void *k = state->FindGDM(ChrootChecker::getTag());
|
||||
|
@ -125,7 +125,7 @@ void ChrootChecker::Chdir(CheckerContext &C, const CallExpr *CE) const {
|
|||
|
||||
// Check the jail state before any function call except chroot and chdir().
|
||||
void ChrootChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
SVal L = state->getSVal(Callee);
|
||||
const FunctionDecl *FD = L.getAsFunctionDecl();
|
||||
|
|
|
@ -89,8 +89,8 @@ void DereferenceChecker::checkLocation(SVal l, bool isLoad,
|
|||
return;
|
||||
|
||||
const Stmt *S = C.getStmt();
|
||||
const GRState *state = C.getState();
|
||||
const GRState *notNullState, *nullState;
|
||||
const ProgramState *state = C.getState();
|
||||
const ProgramState *notNullState, *nullState;
|
||||
llvm::tie(notNullState, nullState) = state->assume(location);
|
||||
|
||||
// The explicit NULL case.
|
||||
|
|
|
@ -52,7 +52,7 @@ void DivZeroChecker::checkPreStmt(const BinaryOperator *B,
|
|||
|
||||
// Check for divide by zero.
|
||||
ConstraintManager &CM = C.getConstraintManager();
|
||||
const GRState *stateNotZero, *stateZero;
|
||||
const ProgramState *stateNotZero, *stateZero;
|
||||
llvm::tie(stateNotZero, stateZero) = CM.assumeDual(C.getState(), *DV);
|
||||
|
||||
if (stateZero && !stateNotZero) {
|
||||
|
|
|
@ -44,7 +44,7 @@ void FixedAddressChecker::checkPreStmt(const BinaryOperator *B,
|
|||
if (!T->isPointerType())
|
||||
return;
|
||||
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
|
||||
SVal RV = state->getSVal(B->getRHS());
|
||||
|
||||
|
|
|
@ -143,7 +143,7 @@ void IdempotentOperationChecker::checkPreStmt(const BinaryOperator *B,
|
|||
|| containsNonLocalVarDecl(RHS);
|
||||
}
|
||||
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
|
||||
SVal LHSVal = state->getSVal(LHS);
|
||||
SVal RHSVal = state->getSVal(RHS);
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
|
||||
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
|
||||
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/Type.h"
|
||||
|
@ -117,16 +117,28 @@ public:
|
|||
CheckerContext &C) const;
|
||||
|
||||
private:
|
||||
const GRState *handleAssign(const GRState *state, const Expr *lexp,
|
||||
const Expr *rexp, const LocationContext *LC) const;
|
||||
const GRState *handleAssign(const GRState *state, const MemRegion *MR,
|
||||
const Expr *rexp, const LocationContext *LC) const;
|
||||
const GRState *invalidateIterators(const GRState *state, const MemRegion *MR,
|
||||
const MemberExpr *ME) const;
|
||||
const ProgramState *handleAssign(const ProgramState *state,
|
||||
const Expr *lexp,
|
||||
const Expr *rexp,
|
||||
const LocationContext *LC) const;
|
||||
|
||||
const ProgramState *handleAssign(const ProgramState *state,
|
||||
const MemRegion *MR,
|
||||
const Expr *rexp,
|
||||
const LocationContext *LC) const;
|
||||
|
||||
const ProgramState *invalidateIterators(const ProgramState *state,
|
||||
const MemRegion *MR,
|
||||
const MemberExpr *ME) const;
|
||||
|
||||
void checkExpr(CheckerContext &C, const Expr *E) const;
|
||||
|
||||
void checkArgs(CheckerContext &C, const CallExpr *CE) const;
|
||||
const MemRegion *getRegion(const GRState *state, const Expr *E,
|
||||
const LocationContext *LC) const;
|
||||
|
||||
const MemRegion *getRegion(const ProgramState *state,
|
||||
const Expr *E,
|
||||
const LocationContext *LC) const;
|
||||
|
||||
const DeclRefExpr *getDeclRefExpr(const Expr *E) const;
|
||||
};
|
||||
|
||||
|
@ -139,8 +151,8 @@ public:
|
|||
namespace clang {
|
||||
namespace ento {
|
||||
template <>
|
||||
struct GRStateTrait<IteratorState>
|
||||
: public GRStatePartialTrait<IteratorState::EntryMap> {
|
||||
struct ProgramStateTrait<IteratorState>
|
||||
: public ProgramStatePartialTrait<IteratorState::EntryMap> {
|
||||
static void *GDMIndex() { return IteratorsChecker::getTag(); }
|
||||
};
|
||||
}
|
||||
|
@ -215,7 +227,7 @@ static RefKind getTemplateKind(QualType T) {
|
|||
|
||||
// Iterate through our map and invalidate any iterators that were
|
||||
// initialized fromt the specified instance MemRegion.
|
||||
const GRState *IteratorsChecker::invalidateIterators(const GRState *state,
|
||||
const ProgramState *IteratorsChecker::invalidateIterators(const ProgramState *state,
|
||||
const MemRegion *MR, const MemberExpr *ME) const {
|
||||
IteratorState::EntryMap Map = state->get<IteratorState>();
|
||||
if (Map.isEmpty())
|
||||
|
@ -234,7 +246,7 @@ const GRState *IteratorsChecker::invalidateIterators(const GRState *state,
|
|||
}
|
||||
|
||||
// Handle assigning to an iterator where we don't have the LValue MemRegion.
|
||||
const GRState *IteratorsChecker::handleAssign(const GRState *state,
|
||||
const ProgramState *IteratorsChecker::handleAssign(const ProgramState *state,
|
||||
const Expr *lexp, const Expr *rexp, const LocationContext *LC) const {
|
||||
// Skip the cast if present.
|
||||
if (const MaterializeTemporaryExpr *M
|
||||
|
@ -259,7 +271,7 @@ const GRState *IteratorsChecker::handleAssign(const GRState *state,
|
|||
}
|
||||
|
||||
// handle assigning to an iterator
|
||||
const GRState *IteratorsChecker::handleAssign(const GRState *state,
|
||||
const ProgramState *IteratorsChecker::handleAssign(const ProgramState *state,
|
||||
const MemRegion *MR, const Expr *rexp, const LocationContext *LC) const {
|
||||
// Assume unknown until we find something definite.
|
||||
state = state->set<IteratorState>(MR, RefState::getUnknown());
|
||||
|
@ -364,7 +376,7 @@ const DeclRefExpr *IteratorsChecker::getDeclRefExpr(const Expr *E) const {
|
|||
}
|
||||
|
||||
// Get the MemRegion associated with the expresssion.
|
||||
const MemRegion *IteratorsChecker::getRegion(const GRState *state,
|
||||
const MemRegion *IteratorsChecker::getRegion(const ProgramState *state,
|
||||
const Expr *E, const LocationContext *LC) const {
|
||||
const DeclRefExpr *DRE = getDeclRefExpr(E);
|
||||
if (!DRE)
|
||||
|
@ -382,7 +394,7 @@ const MemRegion *IteratorsChecker::getRegion(const GRState *state,
|
|||
// use those nodes. We also cannot create multiple nodes at one ProgramPoint
|
||||
// with the same tag.
|
||||
void IteratorsChecker::checkExpr(CheckerContext &C, const Expr *E) const {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
const MemRegion *MR = getRegion(state, E,
|
||||
C.getPredecessor()->getLocationContext());
|
||||
if (!MR)
|
||||
|
@ -455,7 +467,7 @@ void IteratorsChecker::checkPreStmt(const CXXOperatorCallExpr *OCE,
|
|||
CheckerContext &C) const
|
||||
{
|
||||
const LocationContext *LC = C.getPredecessor()->getLocationContext();
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
OverloadedOperatorKind Kind = OCE->getOperator();
|
||||
if (Kind == OO_Equal) {
|
||||
checkExpr(C, OCE->getArg(1));
|
||||
|
@ -512,7 +524,7 @@ void IteratorsChecker::checkPreStmt(const DeclStmt *DS,
|
|||
return;
|
||||
|
||||
// Get the MemRegion associated with the iterator and mark it as Undefined.
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
Loc VarLoc = state->getLValue(VD, C.getPredecessor()->getLocationContext());
|
||||
const MemRegion *MR = VarLoc.getAsRegion();
|
||||
if (!MR)
|
||||
|
@ -544,8 +556,8 @@ void IteratorsChecker::checkPreStmt(const DeclStmt *DS,
|
|||
|
||||
namespace { struct CalledReserved {}; }
|
||||
namespace clang { namespace ento {
|
||||
template<> struct GRStateTrait<CalledReserved>
|
||||
: public GRStatePartialTrait<llvm::ImmutableSet<const MemRegion*> > {
|
||||
template<> struct ProgramStateTrait<CalledReserved>
|
||||
: public ProgramStatePartialTrait<llvm::ImmutableSet<const MemRegion*> > {
|
||||
static void *GDMIndex() { static int index = 0; return &index; }
|
||||
};
|
||||
}}
|
||||
|
@ -571,7 +583,7 @@ void IteratorsChecker::checkPreStmt(const CXXMemberCallExpr *MCE,
|
|||
return;
|
||||
// If we are calling a function that invalidates iterators, mark them
|
||||
// appropriately by finding matching instances.
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
StringRef mName = ME->getMemberDecl()->getName();
|
||||
if (llvm::StringSwitch<bool>(mName)
|
||||
.Cases("insert", "reserve", "push_back", true)
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
|
||||
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace ento;
|
||||
|
@ -90,13 +90,13 @@ private:
|
|||
|
||||
/// Check if RetSym evaluates to an error value in the current state.
|
||||
bool definitelyReturnedError(SymbolRef RetSym,
|
||||
const GRState *State,
|
||||
const ProgramState *State,
|
||||
SValBuilder &Builder,
|
||||
bool noError = false) const;
|
||||
|
||||
/// Check if RetSym evaluates to a NoErr value in the current state.
|
||||
bool definitelyDidnotReturnError(SymbolRef RetSym,
|
||||
const GRState *State,
|
||||
const ProgramState *State,
|
||||
SValBuilder &Builder) const {
|
||||
return definitelyReturnedError(RetSym, State, Builder, true);
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ private:
|
|||
};
|
||||
}
|
||||
|
||||
/// GRState traits to store the currently allocated (and not yet freed) symbols.
|
||||
/// ProgramState traits to store the currently allocated (and not yet freed) symbols.
|
||||
/// This is a map from the allocated content symbol to the corresponding
|
||||
/// AllocationState.
|
||||
typedef llvm::ImmutableMap<SymbolRef,
|
||||
|
@ -112,8 +112,8 @@ typedef llvm::ImmutableMap<SymbolRef,
|
|||
|
||||
namespace { struct AllocatedData {}; }
|
||||
namespace clang { namespace ento {
|
||||
template<> struct GRStateTrait<AllocatedData>
|
||||
: public GRStatePartialTrait<AllocatedSetTy > {
|
||||
template<> struct ProgramStateTrait<AllocatedData>
|
||||
: public ProgramStatePartialTrait<AllocatedSetTy > {
|
||||
static void *GDMIndex() { static int index = 0; return &index; }
|
||||
};
|
||||
}}
|
||||
|
@ -175,7 +175,7 @@ static bool isBadDeallocationArgument(const MemRegion *Arg) {
|
|||
/// that value is itself an address, and return the corresponding symbol.
|
||||
static SymbolRef getAsPointeeSymbol(const Expr *Expr,
|
||||
CheckerContext &C) {
|
||||
const GRState *State = C.getState();
|
||||
const ProgramState *State = C.getState();
|
||||
SVal ArgV = State->getSVal(Expr);
|
||||
|
||||
if (const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(&ArgV)) {
|
||||
|
@ -194,14 +194,14 @@ static SymbolRef getAsPointeeSymbol(const Expr *Expr,
|
|||
// If noError, returns true iff (1).
|
||||
// If !noError, returns true iff (2).
|
||||
bool MacOSKeychainAPIChecker::definitelyReturnedError(SymbolRef RetSym,
|
||||
const GRState *State,
|
||||
const ProgramState *State,
|
||||
SValBuilder &Builder,
|
||||
bool noError) const {
|
||||
DefinedOrUnknownSVal NoErrVal = Builder.makeIntVal(NoErr,
|
||||
Builder.getSymbolManager().getType(RetSym));
|
||||
DefinedOrUnknownSVal NoErr = Builder.evalEQ(State, NoErrVal,
|
||||
nonloc::SymbolVal(RetSym));
|
||||
const GRState *ErrState = State->assume(NoErr, noError);
|
||||
const ProgramState *ErrState = State->assume(NoErr, noError);
|
||||
if (ErrState == State) {
|
||||
return true;
|
||||
}
|
||||
|
@ -211,7 +211,7 @@ bool MacOSKeychainAPIChecker::definitelyReturnedError(SymbolRef RetSym,
|
|||
|
||||
void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
|
||||
CheckerContext &C) const {
|
||||
const GRState *State = C.getState();
|
||||
const ProgramState *State = C.getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
SVal L = State->getSVal(Callee);
|
||||
unsigned idx = InvalidIdx;
|
||||
|
@ -331,7 +331,7 @@ void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
|
|||
|
||||
void MacOSKeychainAPIChecker::checkPostStmt(const CallExpr *CE,
|
||||
CheckerContext &C) const {
|
||||
const GRState *State = C.getState();
|
||||
const ProgramState *State = C.getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
SVal L = State->getSVal(Callee);
|
||||
|
||||
|
@ -385,7 +385,7 @@ void MacOSKeychainAPIChecker::checkPreStmt(const ReturnStmt *S,
|
|||
return;
|
||||
|
||||
// Check if the value is escaping through the return.
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
const MemRegion *V = state->getSVal(retExpr).getAsRegion();
|
||||
if (!V)
|
||||
return;
|
||||
|
@ -413,7 +413,7 @@ RangedBugReport *MacOSKeychainAPIChecker::
|
|||
|
||||
void MacOSKeychainAPIChecker::checkDeadSymbols(SymbolReaper &SR,
|
||||
CheckerContext &C) const {
|
||||
const GRState *State = C.getState();
|
||||
const ProgramState *State = C.getState();
|
||||
AllocatedSetTy ASet = State->get<AllocatedData>();
|
||||
if (ASet.isEmpty())
|
||||
return;
|
||||
|
@ -451,7 +451,7 @@ void MacOSKeychainAPIChecker::checkDeadSymbols(SymbolReaper &SR,
|
|||
// TODO: Remove this after we ensure that checkDeadSymbols are always called.
|
||||
void MacOSKeychainAPIChecker::checkEndPath(EndOfFunctionNodeBuilder &B,
|
||||
ExprEngine &Eng) const {
|
||||
const GRState *state = B.getState();
|
||||
const ProgramState *state = B.getState();
|
||||
AllocatedSetTy AS = state->get<AllocatedData>();
|
||||
if (AS.isEmpty())
|
||||
return;
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
|
||||
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
|
@ -56,7 +56,7 @@ void MacOSXAPIChecker::CheckDispatchOnce(CheckerContext &C, const CallExpr *CE,
|
|||
|
||||
// Check if the first argument is stack allocated. If so, issue a warning
|
||||
// because that's likely to be bad news.
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
const MemRegion *R = state->getSVal(CE->getArg(0)).getAsRegion();
|
||||
if (!R || !isa<StackSpaceRegion>(R->getMemorySpace()))
|
||||
return;
|
||||
|
@ -94,7 +94,7 @@ void MacOSXAPIChecker::checkPreStmt(const CallExpr *CE,
|
|||
CheckerContext &C) const {
|
||||
// FIXME: This sort of logic is common to several checkers, including
|
||||
// UnixAPIChecker, PthreadLockChecker, and CStringChecker. Should refactor.
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
const FunctionDecl *Fn = state->getSVal(Callee).getAsFunctionDecl();
|
||||
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
|
||||
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
|
||||
#include "llvm/ADT/ImmutableMap.h"
|
||||
using namespace clang;
|
||||
|
@ -80,7 +80,7 @@ public:
|
|||
void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
|
||||
void checkEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng) const;
|
||||
void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
|
||||
const GRState *evalAssume(const GRState *state, SVal Cond,
|
||||
const ProgramState *evalAssume(const ProgramState *state, SVal Cond,
|
||||
bool Assumption) const;
|
||||
void checkLocation(SVal l, bool isLoad, CheckerContext &C) const;
|
||||
void checkBind(SVal location, SVal val, CheckerContext &C) const;
|
||||
|
@ -89,20 +89,20 @@ private:
|
|||
static void MallocMem(CheckerContext &C, const CallExpr *CE);
|
||||
static void MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE,
|
||||
const OwnershipAttr* Att);
|
||||
static const GRState *MallocMemAux(CheckerContext &C, const CallExpr *CE,
|
||||
static const ProgramState *MallocMemAux(CheckerContext &C, const CallExpr *CE,
|
||||
const Expr *SizeEx, SVal Init,
|
||||
const GRState *state) {
|
||||
const ProgramState *state) {
|
||||
return MallocMemAux(C, CE, state->getSVal(SizeEx), Init, state);
|
||||
}
|
||||
static const GRState *MallocMemAux(CheckerContext &C, const CallExpr *CE,
|
||||
static const ProgramState *MallocMemAux(CheckerContext &C, const CallExpr *CE,
|
||||
SVal SizeEx, SVal Init,
|
||||
const GRState *state);
|
||||
const ProgramState *state);
|
||||
|
||||
void FreeMem(CheckerContext &C, const CallExpr *CE) const;
|
||||
void FreeMemAttr(CheckerContext &C, const CallExpr *CE,
|
||||
const OwnershipAttr* Att) const;
|
||||
const GRState *FreeMemAux(CheckerContext &C, const CallExpr *CE,
|
||||
const GRState *state, unsigned Num, bool Hold) const;
|
||||
const ProgramState *FreeMemAux(CheckerContext &C, const CallExpr *CE,
|
||||
const ProgramState *state, unsigned Num, bool Hold) const;
|
||||
|
||||
void ReallocMem(CheckerContext &C, const CallExpr *CE) const;
|
||||
static void CallocMem(CheckerContext &C, const CallExpr *CE);
|
||||
|
@ -118,15 +118,15 @@ typedef llvm::ImmutableMap<SymbolRef, RefState> RegionStateTy;
|
|||
namespace clang {
|
||||
namespace ento {
|
||||
template <>
|
||||
struct GRStateTrait<RegionState>
|
||||
: public GRStatePartialTrait<RegionStateTy> {
|
||||
struct ProgramStateTrait<RegionState>
|
||||
: public ProgramStatePartialTrait<RegionStateTy> {
|
||||
static void *GDMIndex() { static int x; return &x; }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
bool MallocChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
SVal L = state->getSVal(Callee);
|
||||
|
||||
|
@ -193,7 +193,7 @@ bool MallocChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
|
|||
}
|
||||
|
||||
void MallocChecker::MallocMem(CheckerContext &C, const CallExpr *CE) {
|
||||
const GRState *state = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(),
|
||||
const ProgramState *state = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(),
|
||||
C.getState());
|
||||
C.addTransition(state);
|
||||
}
|
||||
|
@ -205,20 +205,20 @@ void MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE,
|
|||
|
||||
OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
|
||||
if (I != E) {
|
||||
const GRState *state =
|
||||
const ProgramState *state =
|
||||
MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), C.getState());
|
||||
C.addTransition(state);
|
||||
return;
|
||||
}
|
||||
const GRState *state = MallocMemAux(C, CE, UnknownVal(), UndefinedVal(),
|
||||
const ProgramState *state = MallocMemAux(C, CE, UnknownVal(), UndefinedVal(),
|
||||
C.getState());
|
||||
C.addTransition(state);
|
||||
}
|
||||
|
||||
const GRState *MallocChecker::MallocMemAux(CheckerContext &C,
|
||||
const ProgramState *MallocChecker::MallocMemAux(CheckerContext &C,
|
||||
const CallExpr *CE,
|
||||
SVal Size, SVal Init,
|
||||
const GRState *state) {
|
||||
const ProgramState *state) {
|
||||
unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
|
||||
SValBuilder &svalBuilder = C.getSValBuilder();
|
||||
|
||||
|
@ -247,7 +247,7 @@ const GRState *MallocChecker::MallocMemAux(CheckerContext &C,
|
|||
}
|
||||
|
||||
void MallocChecker::FreeMem(CheckerContext &C, const CallExpr *CE) const {
|
||||
const GRState *state = FreeMemAux(C, CE, C.getState(), 0, false);
|
||||
const ProgramState *state = FreeMemAux(C, CE, C.getState(), 0, false);
|
||||
|
||||
if (state)
|
||||
C.addTransition(state);
|
||||
|
@ -260,15 +260,15 @@ void MallocChecker::FreeMemAttr(CheckerContext &C, const CallExpr *CE,
|
|||
|
||||
for (OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
|
||||
I != E; ++I) {
|
||||
const GRState *state = FreeMemAux(C, CE, C.getState(), *I,
|
||||
const ProgramState *state = FreeMemAux(C, CE, C.getState(), *I,
|
||||
Att->getOwnKind() == OwnershipAttr::Holds);
|
||||
if (state)
|
||||
C.addTransition(state);
|
||||
}
|
||||
}
|
||||
|
||||
const GRState *MallocChecker::FreeMemAux(CheckerContext &C, const CallExpr *CE,
|
||||
const GRState *state, unsigned Num,
|
||||
const ProgramState *MallocChecker::FreeMemAux(CheckerContext &C, const CallExpr *CE,
|
||||
const ProgramState *state, unsigned Num,
|
||||
bool Hold) const {
|
||||
const Expr *ArgExpr = CE->getArg(Num);
|
||||
SVal ArgVal = state->getSVal(ArgExpr);
|
||||
|
@ -281,7 +281,7 @@ const GRState *MallocChecker::FreeMemAux(CheckerContext &C, const CallExpr *CE,
|
|||
|
||||
// FIXME: Technically using 'Assume' here can result in a path
|
||||
// bifurcation. In such cases we need to return two states, not just one.
|
||||
const GRState *notNullState, *nullState;
|
||||
const ProgramState *notNullState, *nullState;
|
||||
llvm::tie(notNullState, nullState) = state->assume(location);
|
||||
|
||||
// The explicit NULL case, no operation is performed.
|
||||
|
@ -491,7 +491,7 @@ void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal,
|
|||
}
|
||||
|
||||
void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) const {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
const Expr *arg0Expr = CE->getArg(0);
|
||||
DefinedOrUnknownSVal arg0Val
|
||||
= cast<DefinedOrUnknownSVal>(state->getSVal(arg0Expr));
|
||||
|
@ -517,7 +517,7 @@ void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) const {
|
|||
|
||||
// If the ptr is NULL and the size is not 0, the call is equivalent to
|
||||
// malloc(size).
|
||||
const GRState *stateEqual = state->assume(PtrEQ, true);
|
||||
const ProgramState *stateEqual = state->assume(PtrEQ, true);
|
||||
if (stateEqual && state->assume(SizeZero, false)) {
|
||||
// Hack: set the NULL symbolic region to released to suppress false warning.
|
||||
// In the future we should add more states for allocated regions, e.g.,
|
||||
|
@ -527,15 +527,15 @@ void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) const {
|
|||
if (Sym)
|
||||
stateEqual = stateEqual->set<RegionState>(Sym, RefState::getReleased(CE));
|
||||
|
||||
const GRState *stateMalloc = MallocMemAux(C, CE, CE->getArg(1),
|
||||
const ProgramState *stateMalloc = MallocMemAux(C, CE, CE->getArg(1),
|
||||
UndefinedVal(), stateEqual);
|
||||
C.addTransition(stateMalloc);
|
||||
}
|
||||
|
||||
if (const GRState *stateNotEqual = state->assume(PtrEQ, false)) {
|
||||
if (const ProgramState *stateNotEqual = state->assume(PtrEQ, false)) {
|
||||
// If the size is 0, free the memory.
|
||||
if (const GRState *stateSizeZero = stateNotEqual->assume(SizeZero, true))
|
||||
if (const GRState *stateFree =
|
||||
if (const ProgramState *stateSizeZero = stateNotEqual->assume(SizeZero, true))
|
||||
if (const ProgramState *stateFree =
|
||||
FreeMemAux(C, CE, stateSizeZero, 0, false)) {
|
||||
|
||||
// Add the state transition to set input pointer argument to be free.
|
||||
|
@ -544,11 +544,11 @@ void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) const {
|
|||
// Bind the return value to UndefinedVal because it is now free.
|
||||
C.addTransition(stateFree->BindExpr(CE, UndefinedVal(), true));
|
||||
}
|
||||
if (const GRState *stateSizeNotZero = stateNotEqual->assume(SizeZero,false))
|
||||
if (const GRState *stateFree = FreeMemAux(C, CE, stateSizeNotZero,
|
||||
if (const ProgramState *stateSizeNotZero = stateNotEqual->assume(SizeZero,false))
|
||||
if (const ProgramState *stateFree = FreeMemAux(C, CE, stateSizeNotZero,
|
||||
0, false)) {
|
||||
// FIXME: We should copy the content of the original buffer.
|
||||
const GRState *stateRealloc = MallocMemAux(C, CE, CE->getArg(1),
|
||||
const ProgramState *stateRealloc = MallocMemAux(C, CE, CE->getArg(1),
|
||||
UnknownVal(), stateFree);
|
||||
C.addTransition(stateRealloc);
|
||||
}
|
||||
|
@ -556,7 +556,7 @@ void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) const {
|
|||
}
|
||||
|
||||
void MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE) {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
SValBuilder &svalBuilder = C.getSValBuilder();
|
||||
|
||||
SVal count = state->getSVal(CE->getArg(0));
|
||||
|
@ -574,7 +574,7 @@ void MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper,
|
|||
if (!SymReaper.hasDeadSymbols())
|
||||
return;
|
||||
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
RegionStateTy RS = state->get<RegionState>();
|
||||
RegionStateTy::Factory &F = state->get_context<RegionState>();
|
||||
|
||||
|
@ -607,7 +607,7 @@ void MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper,
|
|||
|
||||
void MallocChecker::checkEndPath(EndOfFunctionNodeBuilder &B,
|
||||
ExprEngine &Eng) const {
|
||||
const GRState *state = B.getState();
|
||||
const ProgramState *state = B.getState();
|
||||
RegionStateTy M = state->get<RegionState>();
|
||||
|
||||
for (RegionStateTy::iterator I = M.begin(), E = M.end(); I != E; ++I) {
|
||||
|
@ -630,7 +630,7 @@ void MallocChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const {
|
|||
if (!retExpr)
|
||||
return;
|
||||
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
|
||||
SymbolRef Sym = state->getSVal(retExpr).getAsSymbol();
|
||||
if (!Sym)
|
||||
|
@ -647,7 +647,7 @@ void MallocChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const {
|
|||
C.addTransition(state);
|
||||
}
|
||||
|
||||
const GRState *MallocChecker::evalAssume(const GRState *state, SVal Cond,
|
||||
const ProgramState *MallocChecker::evalAssume(const ProgramState *state, SVal Cond,
|
||||
bool Assumption) const {
|
||||
// If a symblic region is assumed to NULL, set its state to AllocateFailed.
|
||||
// FIXME: should also check symbols assumed to non-null.
|
||||
|
@ -688,7 +688,7 @@ void MallocChecker::checkBind(SVal location, SVal val,CheckerContext &C) const {
|
|||
// assignment, let it go. However, assigning to fields of a stack-storage
|
||||
// structure does not transfer ownership.
|
||||
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
DefinedOrUnknownSVal l = cast<DefinedOrUnknownSVal>(location);
|
||||
|
||||
// Check for null dereferences.
|
||||
|
@ -701,7 +701,7 @@ void MallocChecker::checkBind(SVal location, SVal val,CheckerContext &C) const {
|
|||
if (Sym) {
|
||||
if (const RefState *RS = state->get<RegionState>(Sym)) {
|
||||
// If ptr is NULL, no operation is performed.
|
||||
const GRState *notNullState, *nullState;
|
||||
const ProgramState *notNullState, *nullState;
|
||||
llvm::tie(notNullState, nullState) = state->assume(l);
|
||||
|
||||
// Generate a transition for 'nullState' to record the assumption
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include "clang/StaticAnalyzer/Core/Checker.h"
|
||||
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
|
||||
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
|
@ -166,18 +166,18 @@ typedef llvm::ImmutableMap<SymbolRef, unsigned> ErrorOutFlag;
|
|||
namespace clang {
|
||||
namespace ento {
|
||||
template <>
|
||||
struct GRStateTrait<NSErrorOut> : public GRStatePartialTrait<ErrorOutFlag> {
|
||||
struct ProgramStateTrait<NSErrorOut> : public ProgramStatePartialTrait<ErrorOutFlag> {
|
||||
static void *GDMIndex() { static int index = 0; return &index; }
|
||||
};
|
||||
template <>
|
||||
struct GRStateTrait<CFErrorOut> : public GRStatePartialTrait<ErrorOutFlag> {
|
||||
struct ProgramStateTrait<CFErrorOut> : public ProgramStatePartialTrait<ErrorOutFlag> {
|
||||
static void *GDMIndex() { static int index = 0; return &index; }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static bool hasFlag(SVal val, const GRState *state) {
|
||||
static bool hasFlag(SVal val, const ProgramState *state) {
|
||||
if (SymbolRef sym = val.getAsSymbol())
|
||||
if (const unsigned *attachedFlags = state->get<T>(sym))
|
||||
return *attachedFlags;
|
||||
|
@ -185,7 +185,7 @@ static bool hasFlag(SVal val, const GRState *state) {
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
static void setFlag(const GRState *state, SVal val, CheckerContext &C) {
|
||||
static void setFlag(const ProgramState *state, SVal val, CheckerContext &C) {
|
||||
// We tag the symbol that the SVal wraps.
|
||||
if (SymbolRef sym = val.getAsSymbol())
|
||||
C.addTransition(state->set<T>(sym, true));
|
||||
|
@ -214,7 +214,7 @@ void NSOrCFErrorDerefChecker::checkLocation(SVal loc, bool isLoad,
|
|||
return;
|
||||
|
||||
ASTContext &Ctx = C.getASTContext();
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
|
||||
// If we are loading from NSError**/CFErrorRef* parameter, mark the resulting
|
||||
// SVal so that we can later check it when handling the
|
||||
|
@ -247,7 +247,7 @@ void NSOrCFErrorDerefChecker::checkEvent(ImplicitNullDerefEvent event) const {
|
|||
return;
|
||||
|
||||
SVal loc = event.Location;
|
||||
const GRState *state = event.SinkNode->getState();
|
||||
const ProgramState *state = event.SinkNode->getState();
|
||||
BugReporter &BR = *event.BR;
|
||||
|
||||
bool isNSError = hasFlag<NSErrorOut>(loc, state);
|
||||
|
|
|
@ -32,7 +32,7 @@ public:
|
|||
|
||||
void NoReturnFunctionChecker::checkPostStmt(const CallExpr *CE,
|
||||
CheckerContext &C) const {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
|
||||
bool BuildSinks = getFunctionExtInfo(Callee->getType()).getNoReturn();
|
||||
|
|
|
@ -33,7 +33,7 @@ private:
|
|||
}
|
||||
|
||||
bool OSAtomicChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
SVal L = state->getSVal(Callee);
|
||||
|
||||
|
@ -92,7 +92,7 @@ bool OSAtomicChecker::evalOSAtomicCompareAndSwap(CheckerContext &C,
|
|||
|
||||
// Load 'theValue'.
|
||||
ExprEngine &Engine = C.getEngine();
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
ExplodedNodeSet Tmp;
|
||||
SVal location = state->getSVal(theValueExpr);
|
||||
// Here we should use the value type of the region as the load type, because
|
||||
|
@ -123,7 +123,7 @@ bool OSAtomicChecker::evalOSAtomicCompareAndSwap(CheckerContext &C,
|
|||
I != E; ++I) {
|
||||
|
||||
ExplodedNode *N = *I;
|
||||
const GRState *stateLoad = N->getState();
|
||||
const ProgramState *stateLoad = N->getState();
|
||||
|
||||
// Use direct bindings from the environment since we are forcing a load
|
||||
// from a location that the Environment would typically not be used
|
||||
|
@ -148,7 +148,7 @@ bool OSAtomicChecker::evalOSAtomicCompareAndSwap(CheckerContext &C,
|
|||
DefinedOrUnknownSVal Cmp =
|
||||
svalBuilder.evalEQ(stateLoad,theValueVal,oldValueVal);
|
||||
|
||||
const GRState *stateEqual = stateLoad->assume(Cmp, true);
|
||||
const ProgramState *stateEqual = stateLoad->assume(Cmp, true);
|
||||
|
||||
// Were they equal?
|
||||
if (stateEqual) {
|
||||
|
@ -178,7 +178,7 @@ bool OSAtomicChecker::evalOSAtomicCompareAndSwap(CheckerContext &C,
|
|||
for (ExplodedNodeSet::iterator I2 = TmpStore.begin(),
|
||||
E2 = TmpStore.end(); I2 != E2; ++I2) {
|
||||
ExplodedNode *predNew = *I2;
|
||||
const GRState *stateNew = predNew->getState();
|
||||
const ProgramState *stateNew = predNew->getState();
|
||||
// Check for 'void' return type if we have a bogus function prototype.
|
||||
SVal Res = UnknownVal();
|
||||
QualType T = CE->getType();
|
||||
|
@ -189,7 +189,7 @@ bool OSAtomicChecker::evalOSAtomicCompareAndSwap(CheckerContext &C,
|
|||
}
|
||||
|
||||
// Were they not equal?
|
||||
if (const GRState *stateNotEqual = stateLoad->assume(Cmp, false)) {
|
||||
if (const ProgramState *stateNotEqual = stateLoad->assume(Cmp, false)) {
|
||||
// Check for 'void' return type if we have a bogus function prototype.
|
||||
SVal Res = UnknownVal();
|
||||
QualType T = CE->getType();
|
||||
|
|
|
@ -38,7 +38,7 @@ void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S,
|
|||
CheckerContext &C) const {
|
||||
|
||||
const Expr *Ex = S->getSynchExpr();
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
SVal V = state->getSVal(Ex);
|
||||
|
||||
// Uninitialized value used for the mutex?
|
||||
|
@ -59,7 +59,7 @@ void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S,
|
|||
return;
|
||||
|
||||
// Check for null mutexes.
|
||||
const GRState *notNullState, *nullState;
|
||||
const ProgramState *notNullState, *nullState;
|
||||
llvm::tie(notNullState, nullState) = state->assume(cast<DefinedSVal>(V));
|
||||
|
||||
if (nullState) {
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
#include "clang/StaticAnalyzer/Core/Checker.h"
|
||||
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
|
||||
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
|
||||
#include "clang/AST/ParentMap.h"
|
||||
|
||||
|
@ -109,11 +109,11 @@ namespace { struct PreCallSelfFlags {}; }
|
|||
namespace clang {
|
||||
namespace ento {
|
||||
template<>
|
||||
struct GRStateTrait<SelfFlag> : public GRStatePartialTrait<SelfFlag> {
|
||||
struct ProgramStateTrait<SelfFlag> : public ProgramStatePartialTrait<SelfFlag> {
|
||||
static void *GDMIndex() { static int index = 0; return &index; }
|
||||
};
|
||||
template <>
|
||||
struct GRStateTrait<CalledInit> : public GRStatePartialTrait<bool> {
|
||||
struct ProgramStateTrait<CalledInit> : public ProgramStatePartialTrait<bool> {
|
||||
static void *GDMIndex() { static int index = 0; return &index; }
|
||||
};
|
||||
|
||||
|
@ -122,13 +122,13 @@ namespace ento {
|
|||
/// object before the call so we can assign them to the new object that 'self'
|
||||
/// points to after the call.
|
||||
template <>
|
||||
struct GRStateTrait<PreCallSelfFlags> : public GRStatePartialTrait<unsigned> {
|
||||
struct ProgramStateTrait<PreCallSelfFlags> : public ProgramStatePartialTrait<unsigned> {
|
||||
static void *GDMIndex() { static int index = 0; return &index; }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static SelfFlagEnum getSelfFlags(SVal val, const GRState *state) {
|
||||
static SelfFlagEnum getSelfFlags(SVal val, const ProgramState *state) {
|
||||
if (SymbolRef sym = val.getAsSymbol())
|
||||
if (const unsigned *attachedFlags = state->get<SelfFlag>(sym))
|
||||
return (SelfFlagEnum)*attachedFlags;
|
||||
|
@ -139,7 +139,7 @@ static SelfFlagEnum getSelfFlags(SVal val, CheckerContext &C) {
|
|||
return getSelfFlags(val, C.getState());
|
||||
}
|
||||
|
||||
static void addSelfFlag(const GRState *state, SVal val,
|
||||
static void addSelfFlag(const ProgramState *state, SVal val,
|
||||
SelfFlagEnum flag, CheckerContext &C) {
|
||||
// We tag the symbol that the SVal wraps.
|
||||
if (SymbolRef sym = val.getAsSymbol())
|
||||
|
@ -197,7 +197,7 @@ void ObjCSelfInitChecker::checkPostObjCMessage(ObjCMessage msg,
|
|||
|
||||
if (isInitMessage(msg)) {
|
||||
// Tag the return value as the result of an initializer.
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
|
||||
// FIXME this really should be context sensitive, where we record
|
||||
// the current stack frame (for IPA). Also, we need to clean this
|
||||
|
@ -257,7 +257,7 @@ void ObjCSelfInitChecker::checkPreStmt(const ReturnStmt *S,
|
|||
|
||||
void ObjCSelfInitChecker::checkPreStmt(const CallExpr *CE,
|
||||
CheckerContext &C) const {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
for (CallExpr::const_arg_iterator
|
||||
I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) {
|
||||
SVal argV = state->getSVal(*I);
|
||||
|
@ -275,7 +275,7 @@ void ObjCSelfInitChecker::checkPreStmt(const CallExpr *CE,
|
|||
|
||||
void ObjCSelfInitChecker::checkPostStmt(const CallExpr *CE,
|
||||
CheckerContext &C) const {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
for (CallExpr::const_arg_iterator
|
||||
I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) {
|
||||
SVal argV = state->getSVal(*I);
|
||||
|
@ -297,7 +297,7 @@ void ObjCSelfInitChecker::checkLocation(SVal location, bool isLoad,
|
|||
CheckerContext &C) const {
|
||||
// Tag the result of a load from 'self' so that we can easily know that the
|
||||
// value is the object that 'self' points to.
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
if (isSelfVar(location, C))
|
||||
addSelfFlag(state, state->getSVal(cast<Loc>(location)), SelfFlag_Self, C);
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ void PointerArithChecker::checkPreStmt(const BinaryOperator *B,
|
|||
if (B->getOpcode() != BO_Sub && B->getOpcode() != BO_Add)
|
||||
return;
|
||||
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
SVal LV = state->getSVal(B->getLHS());
|
||||
SVal RV = state->getSVal(B->getRHS());
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ void PointerSubChecker::checkPreStmt(const BinaryOperator *B,
|
|||
if (B->getOpcode() != BO_Sub)
|
||||
return;
|
||||
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
SVal LV = state->getSVal(B->getLHS());
|
||||
SVal RV = state->getSVal(B->getRHS());
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
|
||||
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
|
||||
#include "llvm/ADT/ImmutableList.h"
|
||||
|
||||
using namespace clang;
|
||||
|
@ -46,8 +46,8 @@ public:
|
|||
namespace { class LockSet {}; }
|
||||
namespace clang {
|
||||
namespace ento {
|
||||
template <> struct GRStateTrait<LockSet> :
|
||||
public GRStatePartialTrait<llvm::ImmutableList<const MemRegion*> > {
|
||||
template <> struct ProgramStateTrait<LockSet> :
|
||||
public ProgramStatePartialTrait<llvm::ImmutableList<const MemRegion*> > {
|
||||
static void *GDMIndex() { static int x = 0; return &x; }
|
||||
};
|
||||
} // end GR namespace
|
||||
|
@ -56,7 +56,7 @@ template <> struct GRStateTrait<LockSet> :
|
|||
|
||||
void PthreadLockChecker::checkPostStmt(const CallExpr *CE,
|
||||
CheckerContext &C) const {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
const FunctionDecl *FD = state->getSVal(Callee).getAsFunctionDecl();
|
||||
|
||||
|
@ -103,7 +103,7 @@ void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE,
|
|||
if (!lockR)
|
||||
return;
|
||||
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
|
||||
SVal X = state->getSVal(CE);
|
||||
if (X.isUnknownOrUndef())
|
||||
|
@ -125,10 +125,10 @@ void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE,
|
|||
return;
|
||||
}
|
||||
|
||||
const GRState *lockSucc = state;
|
||||
const ProgramState *lockSucc = state;
|
||||
if (isTryLock) {
|
||||
// Bifurcate the state, and allow a mode where the lock acquisition fails.
|
||||
const GRState *lockFail;
|
||||
const ProgramState *lockFail;
|
||||
switch (semantics) {
|
||||
case PthreadSemantics:
|
||||
llvm::tie(lockFail, lockSucc) = state->assume(retVal);
|
||||
|
@ -166,7 +166,7 @@ void PthreadLockChecker::ReleaseLock(CheckerContext &C, const CallExpr *CE,
|
|||
if (!lockR)
|
||||
return;
|
||||
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
llvm::ImmutableList<const MemRegion*> LS = state->get<LockSet>();
|
||||
|
||||
// FIXME: Better analysis requires IPA for wrappers.
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
|
||||
void ReturnPointerRangeChecker::checkPreStmt(const ReturnStmt *RS,
|
||||
CheckerContext &C) const {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
|
||||
const Expr *RetE = RS->getRetValue();
|
||||
if (!RetE)
|
||||
|
@ -58,8 +58,8 @@ void ReturnPointerRangeChecker::checkPreStmt(const ReturnStmt *RS,
|
|||
= C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(),
|
||||
ER->getValueType());
|
||||
|
||||
const GRState *StInBound = state->assumeInBound(Idx, NumElements, true);
|
||||
const GRState *StOutBound = state->assumeInBound(Idx, NumElements, false);
|
||||
const ProgramState *StInBound = state->assumeInBound(Idx, NumElements, true);
|
||||
const ProgramState *StOutBound = state->assumeInBound(Idx, NumElements, false);
|
||||
if (StOutBound && !StInBound) {
|
||||
ExplodedNode *N = C.generateSink(StOutBound);
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
|
||||
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
using namespace clang;
|
||||
|
@ -134,7 +134,7 @@ void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS,
|
|||
void StackAddrEscapeChecker::checkEndPath(EndOfFunctionNodeBuilder &B,
|
||||
ExprEngine &Eng) const {
|
||||
|
||||
const GRState *state = B.getState();
|
||||
const ProgramState *state = B.getState();
|
||||
|
||||
// Iterate over all bindings to global variables and see if it contains
|
||||
// a memory region in the stack space.
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
|
||||
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
|
||||
#include "llvm/ADT/ImmutableMap.h"
|
||||
|
||||
|
@ -96,9 +96,9 @@ private:
|
|||
|
||||
void OpenFileAux(CheckerContext &C, const CallExpr *CE) const;
|
||||
|
||||
const GRState *CheckNullStream(SVal SV, const GRState *state,
|
||||
const ProgramState *CheckNullStream(SVal SV, const ProgramState *state,
|
||||
CheckerContext &C) const;
|
||||
const GRState *CheckDoubleClose(const CallExpr *CE, const GRState *state,
|
||||
const ProgramState *CheckDoubleClose(const CallExpr *CE, const ProgramState *state,
|
||||
CheckerContext &C) const;
|
||||
};
|
||||
|
||||
|
@ -107,15 +107,15 @@ private:
|
|||
namespace clang {
|
||||
namespace ento {
|
||||
template <>
|
||||
struct GRStateTrait<StreamState>
|
||||
: public GRStatePartialTrait<llvm::ImmutableMap<SymbolRef, StreamState> > {
|
||||
struct ProgramStateTrait<StreamState>
|
||||
: public ProgramStatePartialTrait<llvm::ImmutableMap<SymbolRef, StreamState> > {
|
||||
static void *GDMIndex() { static int x; return &x; }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
bool StreamChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
SVal L = state->getSVal(Callee);
|
||||
const FunctionDecl *FD = L.getAsFunctionDecl();
|
||||
|
@ -221,7 +221,7 @@ void StreamChecker::Tmpfile(CheckerContext &C, const CallExpr *CE) const {
|
|||
}
|
||||
|
||||
void StreamChecker::OpenFileAux(CheckerContext &C, const CallExpr *CE) const {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
|
||||
SValBuilder &svalBuilder = C.getSValBuilder();
|
||||
DefinedSVal RetVal =
|
||||
|
@ -231,7 +231,7 @@ void StreamChecker::OpenFileAux(CheckerContext &C, const CallExpr *CE) const {
|
|||
ConstraintManager &CM = C.getConstraintManager();
|
||||
// Bifurcate the state into two: one with a valid FILE* pointer, the other
|
||||
// with a NULL.
|
||||
const GRState *stateNotNull, *stateNull;
|
||||
const ProgramState *stateNotNull, *stateNull;
|
||||
llvm::tie(stateNotNull, stateNull) = CM.assumeDual(state, RetVal);
|
||||
|
||||
if (SymbolRef Sym = RetVal.getAsSymbol()) {
|
||||
|
@ -247,25 +247,25 @@ void StreamChecker::OpenFileAux(CheckerContext &C, const CallExpr *CE) const {
|
|||
}
|
||||
|
||||
void StreamChecker::Fclose(CheckerContext &C, const CallExpr *CE) const {
|
||||
const GRState *state = CheckDoubleClose(CE, C.getState(), C);
|
||||
const ProgramState *state = CheckDoubleClose(CE, C.getState(), C);
|
||||
if (state)
|
||||
C.addTransition(state);
|
||||
}
|
||||
|
||||
void StreamChecker::Fread(CheckerContext &C, const CallExpr *CE) const {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
if (!CheckNullStream(state->getSVal(CE->getArg(3)), state, C))
|
||||
return;
|
||||
}
|
||||
|
||||
void StreamChecker::Fwrite(CheckerContext &C, const CallExpr *CE) const {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
if (!CheckNullStream(state->getSVal(CE->getArg(3)), state, C))
|
||||
return;
|
||||
}
|
||||
|
||||
void StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) const {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
if (!(state = CheckNullStream(state->getSVal(CE->getArg(0)), state, C)))
|
||||
return;
|
||||
// Check the legality of the 'whence' argument of 'fseek'.
|
||||
|
@ -291,61 +291,61 @@ void StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) const {
|
|||
}
|
||||
|
||||
void StreamChecker::Ftell(CheckerContext &C, const CallExpr *CE) const {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
|
||||
return;
|
||||
}
|
||||
|
||||
void StreamChecker::Rewind(CheckerContext &C, const CallExpr *CE) const {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
|
||||
return;
|
||||
}
|
||||
|
||||
void StreamChecker::Fgetpos(CheckerContext &C, const CallExpr *CE) const {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
|
||||
return;
|
||||
}
|
||||
|
||||
void StreamChecker::Fsetpos(CheckerContext &C, const CallExpr *CE) const {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
|
||||
return;
|
||||
}
|
||||
|
||||
void StreamChecker::Clearerr(CheckerContext &C, const CallExpr *CE) const {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
|
||||
return;
|
||||
}
|
||||
|
||||
void StreamChecker::Feof(CheckerContext &C, const CallExpr *CE) const {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
|
||||
return;
|
||||
}
|
||||
|
||||
void StreamChecker::Ferror(CheckerContext &C, const CallExpr *CE) const {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
|
||||
return;
|
||||
}
|
||||
|
||||
void StreamChecker::Fileno(CheckerContext &C, const CallExpr *CE) const {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
|
||||
return;
|
||||
}
|
||||
|
||||
const GRState *StreamChecker::CheckNullStream(SVal SV, const GRState *state,
|
||||
const ProgramState *StreamChecker::CheckNullStream(SVal SV, const ProgramState *state,
|
||||
CheckerContext &C) const {
|
||||
const DefinedSVal *DV = dyn_cast<DefinedSVal>(&SV);
|
||||
if (!DV)
|
||||
return 0;
|
||||
|
||||
ConstraintManager &CM = C.getConstraintManager();
|
||||
const GRState *stateNotNull, *stateNull;
|
||||
const ProgramState *stateNotNull, *stateNull;
|
||||
llvm::tie(stateNotNull, stateNull) = CM.assumeDual(state, *DV);
|
||||
|
||||
if (!stateNotNull && stateNull) {
|
||||
|
@ -361,8 +361,8 @@ const GRState *StreamChecker::CheckNullStream(SVal SV, const GRState *state,
|
|||
return stateNotNull;
|
||||
}
|
||||
|
||||
const GRState *StreamChecker::CheckDoubleClose(const CallExpr *CE,
|
||||
const GRState *state,
|
||||
const ProgramState *StreamChecker::CheckDoubleClose(const CallExpr *CE,
|
||||
const ProgramState *state,
|
||||
CheckerContext &C) const {
|
||||
SymbolRef Sym = state->getSVal(CE->getArg(0)).getAsSymbol();
|
||||
if (!Sym)
|
||||
|
@ -399,7 +399,7 @@ void StreamChecker::checkDeadSymbols(SymbolReaper &SymReaper,
|
|||
for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
|
||||
E = SymReaper.dead_end(); I != E; ++I) {
|
||||
SymbolRef Sym = *I;
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
const StreamState *SS = state->get<StreamState>(Sym);
|
||||
if (!SS)
|
||||
return;
|
||||
|
@ -420,7 +420,7 @@ void StreamChecker::checkDeadSymbols(SymbolReaper &SymReaper,
|
|||
|
||||
void StreamChecker::checkEndPath(EndOfFunctionNodeBuilder &B,
|
||||
ExprEngine &Eng) const {
|
||||
const GRState *state = B.getState();
|
||||
const ProgramState *state = B.getState();
|
||||
typedef llvm::ImmutableMap<SymbolRef, StreamState> SymMap;
|
||||
SymMap M = state->get<StreamState>();
|
||||
|
||||
|
@ -445,7 +445,7 @@ void StreamChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const {
|
|||
if (!RetE)
|
||||
return;
|
||||
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
SymbolRef Sym = state->getSVal(RetE).getAsSymbol();
|
||||
|
||||
if (!Sym)
|
||||
|
|
|
@ -27,10 +27,10 @@ class UndefBranchChecker : public Checker<check::BranchCondition> {
|
|||
mutable llvm::OwningPtr<BuiltinBug> BT;
|
||||
|
||||
struct FindUndefExpr {
|
||||
GRStateManager& VM;
|
||||
const GRState *St;
|
||||
ProgramStateManager& VM;
|
||||
const ProgramState *St;
|
||||
|
||||
FindUndefExpr(GRStateManager& V, const GRState *S) : VM(V), St(S) {}
|
||||
FindUndefExpr(ProgramStateManager& V, const ProgramState *S) : VM(V), St(S) {}
|
||||
|
||||
const Expr *FindExpr(const Expr *Ex) {
|
||||
if (!MatchesCriteria(Ex))
|
||||
|
@ -59,7 +59,7 @@ public:
|
|||
void UndefBranchChecker::checkBranchCondition(const Stmt *Condition,
|
||||
BranchNodeBuilder &Builder,
|
||||
ExprEngine &Eng) const {
|
||||
const GRState *state = Builder.getState();
|
||||
const ProgramState *state = Builder.getState();
|
||||
SVal X = state->getSVal(Condition);
|
||||
if (X.isUndef()) {
|
||||
ExplodedNode *N = Builder.generateNode(state, true);
|
||||
|
@ -89,7 +89,7 @@ void UndefBranchChecker::checkBranchCondition(const Stmt *Condition,
|
|||
// had to already be undefined.
|
||||
ExplodedNode *PrevN = *N->pred_begin();
|
||||
ProgramPoint P = PrevN->getLocation();
|
||||
const GRState *St = N->getState();
|
||||
const ProgramState *St = N->getState();
|
||||
|
||||
if (PostStmt *PS = dyn_cast<PostStmt>(&P))
|
||||
if (PS->getStmt() == Ex)
|
||||
|
|
|
@ -55,7 +55,7 @@ UndefCapturedBlockVarChecker::checkPostStmt(const BlockExpr *BE,
|
|||
if (!BE->getBlockDecl()->hasCaptures())
|
||||
return;
|
||||
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
const BlockDataRegion *R =
|
||||
cast<BlockDataRegion>(state->getSVal(BE).getAsRegion());
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ public:
|
|||
|
||||
void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
|
||||
CheckerContext &C) const {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
if (state->getSVal(B).isUndef()) {
|
||||
// Generate an error node.
|
||||
ExplodedNode *N = C.generateSink();
|
||||
|
|
|
@ -53,7 +53,7 @@ void UndefinedAssignmentChecker::checkBind(SVal location, SVal val,
|
|||
while (StoreE) {
|
||||
if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) {
|
||||
if (B->isCompoundAssignmentOp()) {
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
if (state->getSVal(B->getLHS()).isUndef()) {
|
||||
str = "The left expression of the compound assignment is an "
|
||||
"uninitialized value. The computed value will also be garbage";
|
||||
|
|
|
@ -73,7 +73,7 @@ void UnixAPIChecker::CheckOpen(CheckerContext &C, const CallExpr *CE) const {
|
|||
}
|
||||
|
||||
// Look at the 'oflags' argument for the O_CREAT flag.
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
|
||||
if (CE->getNumArgs() < 2) {
|
||||
// The frontend should issue a warning for this case, so this is a sanity
|
||||
|
@ -101,7 +101,7 @@ void UnixAPIChecker::CheckOpen(CheckerContext &C, const CallExpr *CE) const {
|
|||
DefinedSVal maskedFlags = cast<DefinedSVal>(maskedFlagsUC);
|
||||
|
||||
// Check if maskedFlags is non-zero.
|
||||
const GRState *trueState, *falseState;
|
||||
const ProgramState *trueState, *falseState;
|
||||
llvm::tie(trueState, falseState) = state->assume(maskedFlags);
|
||||
|
||||
// Only emit an error if the value of 'maskedFlags' is properly
|
||||
|
@ -140,7 +140,7 @@ void UnixAPIChecker::CheckPthreadOnce(CheckerContext &C,
|
|||
|
||||
// Check if the first argument is stack allocated. If so, issue a warning
|
||||
// because that's likely to be bad news.
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
const MemRegion *R = state->getSVal(CE->getArg(0)).getAsRegion();
|
||||
if (!R || !isa<StackSpaceRegion>(R->getMemorySpace()))
|
||||
return;
|
||||
|
@ -182,13 +182,13 @@ void UnixAPIChecker::CheckMallocZero(CheckerContext &C,
|
|||
return;
|
||||
|
||||
// Check if the allocation size is 0.
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
SVal argVal = state->getSVal(CE->getArg(0));
|
||||
|
||||
if (argVal.isUnknownOrUndef())
|
||||
return;
|
||||
|
||||
const GRState *trueState, *falseState;
|
||||
const ProgramState *trueState, *falseState;
|
||||
llvm::tie(trueState, falseState) = state->assume(cast<DefinedSVal>(argVal));
|
||||
|
||||
// Is the value perfectly constrained to zero?
|
||||
|
@ -225,7 +225,7 @@ void UnixAPIChecker::CheckMallocZero(CheckerContext &C,
|
|||
void UnixAPIChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const {
|
||||
// Get the callee. All the functions we care about are C functions
|
||||
// with simple identifiers.
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
const FunctionDecl *Fn = state->getSVal(Callee).getAsFunctionDecl();
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ void VLASizeChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
|
|||
|
||||
// FIXME: Handle multi-dimensional VLAs.
|
||||
const Expr *SE = VLA->getSizeExpr();
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
SVal sizeV = state->getSVal(SE);
|
||||
|
||||
if (sizeV.isUndef()) {
|
||||
|
@ -78,7 +78,7 @@ void VLASizeChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
|
|||
// Check if the size is zero.
|
||||
DefinedSVal sizeD = cast<DefinedSVal>(sizeV);
|
||||
|
||||
const GRState *stateNotZero, *stateZero;
|
||||
const ProgramState *stateNotZero, *stateZero;
|
||||
llvm::tie(stateNotZero, stateZero) = state->assume(sizeD);
|
||||
|
||||
if (stateZero && !stateNotZero) {
|
||||
|
|
|
@ -8,13 +8,13 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines BasicConstraintManager, a class that tracks simple
|
||||
// equality and inequality constraints on symbolic values of GRState.
|
||||
// equality and inequality constraints on symbolic values of ProgramState.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "SimpleConstraintManager.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
|
@ -25,7 +25,7 @@ using namespace ento;
|
|||
namespace { class ConstNotEq {}; }
|
||||
namespace { class ConstEq {}; }
|
||||
|
||||
typedef llvm::ImmutableMap<SymbolRef,GRState::IntSetTy> ConstNotEqTy;
|
||||
typedef llvm::ImmutableMap<SymbolRef,ProgramState::IntSetTy> ConstNotEqTy;
|
||||
typedef llvm::ImmutableMap<SymbolRef,const llvm::APSInt*> ConstEqTy;
|
||||
|
||||
static int ConstEqIndex = 0;
|
||||
|
@ -34,12 +34,13 @@ static int ConstNotEqIndex = 0;
|
|||
namespace clang {
|
||||
namespace ento {
|
||||
template<>
|
||||
struct GRStateTrait<ConstNotEq> : public GRStatePartialTrait<ConstNotEqTy> {
|
||||
struct ProgramStateTrait<ConstNotEq> :
|
||||
public ProgramStatePartialTrait<ConstNotEqTy> {
|
||||
static inline void *GDMIndex() { return &ConstNotEqIndex; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct GRStateTrait<ConstEq> : public GRStatePartialTrait<ConstEqTy> {
|
||||
struct ProgramStateTrait<ConstEq> : public ProgramStatePartialTrait<ConstEqTy> {
|
||||
static inline void *GDMIndex() { return &ConstEqIndex; }
|
||||
};
|
||||
}
|
||||
|
@ -50,62 +51,81 @@ namespace {
|
|||
// constants and integer variables.
|
||||
class BasicConstraintManager
|
||||
: public SimpleConstraintManager {
|
||||
GRState::IntSetTy::Factory ISetFactory;
|
||||
ProgramState::IntSetTy::Factory ISetFactory;
|
||||
public:
|
||||
BasicConstraintManager(GRStateManager &statemgr, SubEngine &subengine)
|
||||
BasicConstraintManager(ProgramStateManager &statemgr, SubEngine &subengine)
|
||||
: SimpleConstraintManager(subengine),
|
||||
ISetFactory(statemgr.getAllocator()) {}
|
||||
|
||||
const GRState *assumeSymNE(const GRState *state, SymbolRef sym,
|
||||
const llvm::APSInt& V,
|
||||
const llvm::APSInt& Adjustment);
|
||||
const ProgramState *assumeSymNE(const ProgramState *state,
|
||||
SymbolRef sym,
|
||||
const llvm::APSInt& V,
|
||||
const llvm::APSInt& Adjustment);
|
||||
|
||||
const GRState *assumeSymEQ(const GRState *state, SymbolRef sym,
|
||||
const llvm::APSInt& V,
|
||||
const llvm::APSInt& Adjustment);
|
||||
const ProgramState *assumeSymEQ(const ProgramState *state,
|
||||
SymbolRef sym,
|
||||
const llvm::APSInt& V,
|
||||
const llvm::APSInt& Adjustment);
|
||||
|
||||
const GRState *assumeSymLT(const GRState *state, SymbolRef sym,
|
||||
const llvm::APSInt& V,
|
||||
const llvm::APSInt& Adjustment);
|
||||
const ProgramState *assumeSymLT(const ProgramState *state,
|
||||
SymbolRef sym,
|
||||
const llvm::APSInt& V,
|
||||
const llvm::APSInt& Adjustment);
|
||||
|
||||
const GRState *assumeSymGT(const GRState *state, SymbolRef sym,
|
||||
const llvm::APSInt& V,
|
||||
const llvm::APSInt& Adjustment);
|
||||
const ProgramState *assumeSymGT(const ProgramState *state,
|
||||
SymbolRef sym,
|
||||
const llvm::APSInt& V,
|
||||
const llvm::APSInt& Adjustment);
|
||||
|
||||
const GRState *assumeSymGE(const GRState *state, SymbolRef sym,
|
||||
const llvm::APSInt& V,
|
||||
const llvm::APSInt& Adjustment);
|
||||
const ProgramState *assumeSymGE(const ProgramState *state,
|
||||
SymbolRef sym,
|
||||
const llvm::APSInt& V,
|
||||
const llvm::APSInt& Adjustment);
|
||||
|
||||
const GRState *assumeSymLE(const GRState *state, SymbolRef sym,
|
||||
const llvm::APSInt& V,
|
||||
const llvm::APSInt& Adjustment);
|
||||
const ProgramState *assumeSymLE(const ProgramState *state,
|
||||
SymbolRef sym,
|
||||
const llvm::APSInt& V,
|
||||
const llvm::APSInt& Adjustment);
|
||||
|
||||
const GRState *AddEQ(const GRState *state, SymbolRef sym, const llvm::APSInt& V);
|
||||
const ProgramState *AddEQ(const ProgramState *state,
|
||||
SymbolRef sym,
|
||||
const llvm::APSInt& V);
|
||||
|
||||
const GRState *AddNE(const GRState *state, SymbolRef sym, const llvm::APSInt& V);
|
||||
const ProgramState *AddNE(const ProgramState *state,
|
||||
SymbolRef sym,
|
||||
const llvm::APSInt& V);
|
||||
|
||||
const llvm::APSInt* getSymVal(const GRState *state, SymbolRef sym) const;
|
||||
bool isNotEqual(const GRState *state, SymbolRef sym, const llvm::APSInt& V)
|
||||
const;
|
||||
bool isEqual(const GRState *state, SymbolRef sym, const llvm::APSInt& V)
|
||||
const;
|
||||
const llvm::APSInt* getSymVal(const ProgramState *state,
|
||||
SymbolRef sym) const;
|
||||
|
||||
const GRState *removeDeadBindings(const GRState *state, SymbolReaper& SymReaper);
|
||||
bool isNotEqual(const ProgramState *state,
|
||||
SymbolRef sym,
|
||||
const llvm::APSInt& V) const;
|
||||
|
||||
void print(const GRState *state, raw_ostream &Out,
|
||||
const char* nl, const char *sep);
|
||||
bool isEqual(const ProgramState *state,
|
||||
SymbolRef sym,
|
||||
const llvm::APSInt& V) const;
|
||||
|
||||
const ProgramState *removeDeadBindings(const ProgramState *state,
|
||||
SymbolReaper& SymReaper);
|
||||
|
||||
void print(const ProgramState *state,
|
||||
raw_ostream &Out,
|
||||
const char* nl,
|
||||
const char *sep);
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
ConstraintManager* ento::CreateBasicConstraintManager(GRStateManager& statemgr,
|
||||
SubEngine &subengine) {
|
||||
ConstraintManager*
|
||||
ento::CreateBasicConstraintManager(ProgramStateManager& statemgr,
|
||||
SubEngine &subengine) {
|
||||
return new BasicConstraintManager(statemgr, subengine);
|
||||
}
|
||||
|
||||
|
||||
const GRState*
|
||||
BasicConstraintManager::assumeSymNE(const GRState *state, SymbolRef sym,
|
||||
const ProgramState*
|
||||
BasicConstraintManager::assumeSymNE(const ProgramState *state,
|
||||
SymbolRef sym,
|
||||
const llvm::APSInt &V,
|
||||
const llvm::APSInt &Adjustment) {
|
||||
// First, determine if sym == X, where X+Adjustment != V.
|
||||
|
@ -124,8 +144,9 @@ BasicConstraintManager::assumeSymNE(const GRState *state, SymbolRef sym,
|
|||
return AddNE(state, sym, Adjusted);
|
||||
}
|
||||
|
||||
const GRState*
|
||||
BasicConstraintManager::assumeSymEQ(const GRState *state, SymbolRef sym,
|
||||
const ProgramState*
|
||||
BasicConstraintManager::assumeSymEQ(const ProgramState *state,
|
||||
SymbolRef sym,
|
||||
const llvm::APSInt &V,
|
||||
const llvm::APSInt &Adjustment) {
|
||||
// First, determine if sym == X, where X+Adjustment != V.
|
||||
|
@ -145,8 +166,9 @@ BasicConstraintManager::assumeSymEQ(const GRState *state, SymbolRef sym,
|
|||
}
|
||||
|
||||
// The logic for these will be handled in another ConstraintManager.
|
||||
const GRState*
|
||||
BasicConstraintManager::assumeSymLT(const GRState *state, SymbolRef sym,
|
||||
const ProgramState*
|
||||
BasicConstraintManager::assumeSymLT(const ProgramState *state,
|
||||
SymbolRef sym,
|
||||
const llvm::APSInt &V,
|
||||
const llvm::APSInt &Adjustment) {
|
||||
// Is 'V' the smallest possible value?
|
||||
|
@ -159,8 +181,9 @@ BasicConstraintManager::assumeSymLT(const GRState *state, SymbolRef sym,
|
|||
return assumeSymNE(state, sym, V, Adjustment);
|
||||
}
|
||||
|
||||
const GRState*
|
||||
BasicConstraintManager::assumeSymGT(const GRState *state, SymbolRef sym,
|
||||
const ProgramState*
|
||||
BasicConstraintManager::assumeSymGT(const ProgramState *state,
|
||||
SymbolRef sym,
|
||||
const llvm::APSInt &V,
|
||||
const llvm::APSInt &Adjustment) {
|
||||
// Is 'V' the largest possible value?
|
||||
|
@ -173,8 +196,9 @@ BasicConstraintManager::assumeSymGT(const GRState *state, SymbolRef sym,
|
|||
return assumeSymNE(state, sym, V, Adjustment);
|
||||
}
|
||||
|
||||
const GRState*
|
||||
BasicConstraintManager::assumeSymGE(const GRState *state, SymbolRef sym,
|
||||
const ProgramState*
|
||||
BasicConstraintManager::assumeSymGE(const ProgramState *state,
|
||||
SymbolRef sym,
|
||||
const llvm::APSInt &V,
|
||||
const llvm::APSInt &Adjustment) {
|
||||
// Reject a path if the value of sym is a constant X and !(X+Adj >= V).
|
||||
|
@ -201,8 +225,9 @@ BasicConstraintManager::assumeSymGE(const GRState *state, SymbolRef sym,
|
|||
return state;
|
||||
}
|
||||
|
||||
const GRState*
|
||||
BasicConstraintManager::assumeSymLE(const GRState *state, SymbolRef sym,
|
||||
const ProgramState*
|
||||
BasicConstraintManager::assumeSymLE(const ProgramState *state,
|
||||
SymbolRef sym,
|
||||
const llvm::APSInt &V,
|
||||
const llvm::APSInt &Adjustment) {
|
||||
// Reject a path if the value of sym is a constant X and !(X+Adj <= V).
|
||||
|
@ -229,18 +254,20 @@ BasicConstraintManager::assumeSymLE(const GRState *state, SymbolRef sym,
|
|||
return state;
|
||||
}
|
||||
|
||||
const GRState *BasicConstraintManager::AddEQ(const GRState *state, SymbolRef sym,
|
||||
const ProgramState *BasicConstraintManager::AddEQ(const ProgramState *state,
|
||||
SymbolRef sym,
|
||||
const llvm::APSInt& V) {
|
||||
// Create a new state with the old binding replaced.
|
||||
return state->set<ConstEq>(sym, &state->getBasicVals().getValue(V));
|
||||
}
|
||||
|
||||
const GRState *BasicConstraintManager::AddNE(const GRState *state, SymbolRef sym,
|
||||
const llvm::APSInt& V) {
|
||||
const ProgramState *BasicConstraintManager::AddNE(const ProgramState *state,
|
||||
SymbolRef sym,
|
||||
const llvm::APSInt& V) {
|
||||
|
||||
// First, retrieve the NE-set associated with the given symbol.
|
||||
ConstNotEqTy::data_type* T = state->get<ConstNotEq>(sym);
|
||||
GRState::IntSetTy S = T ? *T : ISetFactory.getEmptySet();
|
||||
ProgramState::IntSetTy S = T ? *T : ISetFactory.getEmptySet();
|
||||
|
||||
// Now add V to the NE set.
|
||||
S = ISetFactory.add(S, &state->getBasicVals().getValue(V));
|
||||
|
@ -249,13 +276,14 @@ const GRState *BasicConstraintManager::AddNE(const GRState *state, SymbolRef sym
|
|||
return state->set<ConstNotEq>(sym, S);
|
||||
}
|
||||
|
||||
const llvm::APSInt* BasicConstraintManager::getSymVal(const GRState *state,
|
||||
const llvm::APSInt* BasicConstraintManager::getSymVal(const ProgramState *state,
|
||||
SymbolRef sym) const {
|
||||
const ConstEqTy::data_type* T = state->get<ConstEq>(sym);
|
||||
return T ? *T : NULL;
|
||||
}
|
||||
|
||||
bool BasicConstraintManager::isNotEqual(const GRState *state, SymbolRef sym,
|
||||
bool BasicConstraintManager::isNotEqual(const ProgramState *state,
|
||||
SymbolRef sym,
|
||||
const llvm::APSInt& V) const {
|
||||
|
||||
// Retrieve the NE-set associated with the given symbol.
|
||||
|
@ -265,7 +293,8 @@ bool BasicConstraintManager::isNotEqual(const GRState *state, SymbolRef sym,
|
|||
return T ? T->contains(&state->getBasicVals().getValue(V)) : false;
|
||||
}
|
||||
|
||||
bool BasicConstraintManager::isEqual(const GRState *state, SymbolRef sym,
|
||||
bool BasicConstraintManager::isEqual(const ProgramState *state,
|
||||
SymbolRef sym,
|
||||
const llvm::APSInt& V) const {
|
||||
// Retrieve the EQ-set associated with the given symbol.
|
||||
const ConstEqTy::data_type* T = state->get<ConstEq>(sym);
|
||||
|
@ -275,8 +304,8 @@ bool BasicConstraintManager::isEqual(const GRState *state, SymbolRef sym,
|
|||
|
||||
/// Scan all symbols referenced by the constraints. If the symbol is not alive
|
||||
/// as marked in LSymbols, mark it as dead in DSymbols.
|
||||
const GRState*
|
||||
BasicConstraintManager::removeDeadBindings(const GRState *state,
|
||||
const ProgramState*
|
||||
BasicConstraintManager::removeDeadBindings(const ProgramState *state,
|
||||
SymbolReaper& SymReaper) {
|
||||
|
||||
ConstEqTy CE = state->get<ConstEq>();
|
||||
|
@ -301,7 +330,8 @@ BasicConstraintManager::removeDeadBindings(const GRState *state,
|
|||
return state->set<ConstNotEq>(CNE);
|
||||
}
|
||||
|
||||
void BasicConstraintManager::print(const GRState *state, raw_ostream &Out,
|
||||
void BasicConstraintManager::print(const ProgramState *state,
|
||||
raw_ostream &Out,
|
||||
const char* nl, const char *sep) {
|
||||
// Print equality constraints.
|
||||
|
||||
|
@ -324,7 +354,7 @@ void BasicConstraintManager::print(const GRState *state, raw_ostream &Out,
|
|||
Out << nl << " $" << I.getKey() << " : ";
|
||||
bool isFirst = true;
|
||||
|
||||
GRState::IntSetTy::iterator J = I.getData().begin(),
|
||||
ProgramState::IntSetTy::iterator J = I.getData().begin(),
|
||||
EJ = I.getData().end();
|
||||
|
||||
for ( ; J != EJ; ++J) {
|
||||
|
|
|
@ -346,9 +346,9 @@ PathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) {
|
|||
// ScanNotableSymbols: closure-like callback for scanning Store bindings.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static const VarDecl*
|
||||
GetMostRecentVarDeclBinding(const ExplodedNode *N,
|
||||
GRStateManager& VMgr, SVal X) {
|
||||
static const VarDecl* GetMostRecentVarDeclBinding(const ExplodedNode *N,
|
||||
ProgramStateManager& VMgr,
|
||||
SVal X) {
|
||||
|
||||
for ( ; N ; N = N->pred_empty() ? 0 : *N->pred_begin()) {
|
||||
|
||||
|
@ -383,19 +383,29 @@ class NotableSymbolHandler
|
|||
: public StoreManager::BindingsHandler {
|
||||
|
||||
SymbolRef Sym;
|
||||
const GRState *PrevSt;
|
||||
const ProgramState *PrevSt;
|
||||
const Stmt *S;
|
||||
GRStateManager& VMgr;
|
||||
ProgramStateManager& VMgr;
|
||||
const ExplodedNode *Pred;
|
||||
PathDiagnostic& PD;
|
||||
BugReporter& BR;
|
||||
|
||||
public:
|
||||
|
||||
NotableSymbolHandler(SymbolRef sym, const GRState *prevst, const Stmt *s,
|
||||
GRStateManager& vmgr, const ExplodedNode *pred,
|
||||
PathDiagnostic& pd, BugReporter& br)
|
||||
: Sym(sym), PrevSt(prevst), S(s), VMgr(vmgr), Pred(pred), PD(pd), BR(br) {}
|
||||
NotableSymbolHandler(SymbolRef sym,
|
||||
const ProgramState *prevst,
|
||||
const Stmt *s,
|
||||
ProgramStateManager& vmgr,
|
||||
const ExplodedNode *pred,
|
||||
PathDiagnostic& pd,
|
||||
BugReporter& br)
|
||||
: Sym(sym),
|
||||
PrevSt(prevst),
|
||||
S(s),
|
||||
VMgr(vmgr),
|
||||
Pred(pred),
|
||||
PD(pd),
|
||||
BR(br) {}
|
||||
|
||||
bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R,
|
||||
SVal V) {
|
||||
|
@ -466,14 +476,14 @@ static void HandleNotableSymbol(const ExplodedNode *N,
|
|||
PathDiagnostic& PD) {
|
||||
|
||||
const ExplodedNode *Pred = N->pred_empty() ? 0 : *N->pred_begin();
|
||||
const GRState *PrevSt = Pred ? Pred->getState() : 0;
|
||||
const ProgramState *PrevSt = Pred ? Pred->getState() : 0;
|
||||
|
||||
if (!PrevSt)
|
||||
return;
|
||||
|
||||
// Look at the region bindings of the current state that map to the
|
||||
// specified symbol. Are any of them not in the previous state?
|
||||
GRStateManager& VMgr = cast<GRBugReporter>(BR).getStateManager();
|
||||
ProgramStateManager& VMgr = cast<GRBugReporter>(BR).getStateManager();
|
||||
NotableSymbolHandler H(Sym, PrevSt, S, VMgr, Pred, PD, BR);
|
||||
cast<GRBugReporter>(BR).getStateManager().iterBindings(N->getState(), H);
|
||||
}
|
||||
|
@ -1314,7 +1324,7 @@ BugReporterData::~BugReporterData() {}
|
|||
|
||||
ExplodedGraph &GRBugReporter::getGraph() { return Eng.getGraph(); }
|
||||
|
||||
GRStateManager&
|
||||
ProgramStateManager&
|
||||
GRBugReporter::getStateManager() { return Eng.getStateManager(); }
|
||||
|
||||
BugReporter::~BugReporter() { FlushReports(); }
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
|
||||
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace ento;
|
||||
|
@ -311,7 +311,7 @@ void bugreporter::registerTrackNullOrUndefValue(BugReporterContext &BRC,
|
|||
if (!S)
|
||||
return;
|
||||
|
||||
GRStateManager &StateMgr = BRC.getStateManager();
|
||||
ProgramStateManager &StateMgr = BRC.getStateManager();
|
||||
|
||||
// Walk through nodes until we get one that matches the statement
|
||||
// exactly.
|
||||
|
@ -327,7 +327,7 @@ void bugreporter::registerTrackNullOrUndefValue(BugReporterContext &BRC,
|
|||
if (!N)
|
||||
return;
|
||||
|
||||
const GRState *state = N->getState();
|
||||
const ProgramState *state = N->getState();
|
||||
|
||||
// Walk through lvalue-to-rvalue conversions.
|
||||
if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S)) {
|
||||
|
@ -374,7 +374,7 @@ void bugreporter::registerFindLastStore(BugReporterContext &BRC,
|
|||
if (!R)
|
||||
return;
|
||||
|
||||
const GRState *state = N->getState();
|
||||
const ProgramState *state = N->getState();
|
||||
SVal V = state->getSVal(R);
|
||||
|
||||
if (V.isUnknown())
|
||||
|
@ -407,7 +407,7 @@ public:
|
|||
const Expr *Receiver = ME->getInstanceReceiver();
|
||||
if (!Receiver)
|
||||
return 0;
|
||||
const GRState *state = N->getState();
|
||||
const ProgramState *state = N->getState();
|
||||
const SVal &V = state->getSVal(Receiver);
|
||||
const DefinedOrUnknownSVal *DV = dyn_cast<DefinedOrUnknownSVal>(&V);
|
||||
if (!DV)
|
||||
|
@ -446,8 +446,8 @@ void bugreporter::registerVarDeclsLastStore(BugReporterContext &BRC,
|
|||
const Stmt *Head = WorkList.front();
|
||||
WorkList.pop_front();
|
||||
|
||||
GRStateManager &StateMgr = BRC.getStateManager();
|
||||
const GRState *state = N->getState();
|
||||
ProgramStateManager &StateMgr = BRC.getStateManager();
|
||||
const ProgramState *state = N->getState();
|
||||
|
||||
if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Head)) {
|
||||
if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
|
||||
|
@ -486,8 +486,8 @@ public:
|
|||
BugReporterContext &BRC);
|
||||
|
||||
PathDiagnosticPiece *VisitTerminator(const Stmt *Term,
|
||||
const GRState *CurrentState,
|
||||
const GRState *PrevState,
|
||||
const ProgramState *CurrentState,
|
||||
const ProgramState *PrevState,
|
||||
const CFGBlock *srcBlk,
|
||||
const CFGBlock *dstBlk,
|
||||
BugReporterContext &BRC);
|
||||
|
@ -516,8 +516,8 @@ PathDiagnosticPiece *ConditionVisitor::VisitNode(const ExplodedNode *N,
|
|||
const CFGBlock *srcBlk = BE->getSrc();
|
||||
|
||||
if (const Stmt *term = srcBlk->getTerminator()) {
|
||||
const GRState *CurrentState = N->getState();
|
||||
const GRState *PrevState = Prev->getState();
|
||||
const ProgramState *CurrentState = N->getState();
|
||||
const ProgramState *PrevState = Prev->getState();
|
||||
if (CurrentState != PrevState)
|
||||
return VisitTerminator(term, CurrentState, PrevState,
|
||||
srcBlk, BE->getDst(),
|
||||
|
@ -532,8 +532,8 @@ PathDiagnosticPiece *ConditionVisitor::VisitNode(const ExplodedNode *N,
|
|||
|
||||
PathDiagnosticPiece *
|
||||
ConditionVisitor::VisitTerminator(const Stmt *Term,
|
||||
const GRState *CurrentState,
|
||||
const GRState *PrevState,
|
||||
const ProgramState *CurrentState,
|
||||
const ProgramState *PrevState,
|
||||
const CFGBlock *srcBlk,
|
||||
const CFGBlock *dstBlk,
|
||||
BugReporterContext &BRC) {
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
|
||||
#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngineBuilders.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
|
@ -56,7 +56,7 @@ public:
|
|||
return isValid();
|
||||
}
|
||||
|
||||
SVal getSValAsScalarOrLoc(const GRState *state) {
|
||||
SVal getSValAsScalarOrLoc(const ProgramState *state) {
|
||||
assert(isValid());
|
||||
// We have an expression for the receiver? Fetch the value
|
||||
// of that expression.
|
||||
|
@ -98,7 +98,7 @@ public:
|
|||
GenericNodeBuilderRefCount(EndOfFunctionNodeBuilder &enb)
|
||||
: SNB(0), S(0), tag(0), ENB(&enb) {}
|
||||
|
||||
ExplodedNode *MakeNode(const GRState *state, ExplodedNode *Pred) {
|
||||
ExplodedNode *MakeNode(const ProgramState *state, ExplodedNode *Pred) {
|
||||
if (SNB)
|
||||
return SNB->generateNode(PostStmt(S, Pred->getLocationContext(), tag),
|
||||
state, Pred);
|
||||
|
@ -396,13 +396,14 @@ typedef llvm::ImmutableMap<SymbolRef, RefVal> RefBindings;
|
|||
|
||||
namespace clang {
|
||||
namespace ento {
|
||||
template<>
|
||||
struct GRStateTrait<RefBindings> : public GRStatePartialTrait<RefBindings> {
|
||||
static void *GDMIndex() {
|
||||
static int RefBIndex = 0;
|
||||
return &RefBIndex;
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct ProgramStateTrait<RefBindings>
|
||||
: public ProgramStatePartialTrait<RefBindings> {
|
||||
static void *GDMIndex() {
|
||||
static int RefBIndex = 0;
|
||||
return &RefBIndex;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -814,7 +815,7 @@ public:
|
|||
RetainSummary* getSummary(const FunctionDecl *FD);
|
||||
|
||||
RetainSummary *getInstanceMethodSummary(const ObjCMessage &msg,
|
||||
const GRState *state,
|
||||
const ProgramState *state,
|
||||
const LocationContext *LC);
|
||||
|
||||
RetainSummary* getInstanceMethodSummary(const ObjCMessage &msg,
|
||||
|
@ -1358,7 +1359,7 @@ RetainSummaryManager::getCommonMethodSummary(const ObjCMethodDecl *MD,
|
|||
|
||||
RetainSummary*
|
||||
RetainSummaryManager::getInstanceMethodSummary(const ObjCMessage &msg,
|
||||
const GRState *state,
|
||||
const ProgramState *state,
|
||||
const LocationContext *LC) {
|
||||
|
||||
// We need the type-information of the tracked receiver object
|
||||
|
@ -1609,26 +1610,27 @@ namespace { class AutoreleaseStack {}; }
|
|||
|
||||
namespace clang {
|
||||
namespace ento {
|
||||
template<> struct GRStateTrait<AutoreleaseStack>
|
||||
: public GRStatePartialTrait<ARStack> {
|
||||
template<> struct ProgramStateTrait<AutoreleaseStack>
|
||||
: public ProgramStatePartialTrait<ARStack> {
|
||||
static inline void *GDMIndex() { return &AutoRBIndex; }
|
||||
};
|
||||
|
||||
template<> struct GRStateTrait<AutoreleasePoolContents>
|
||||
: public GRStatePartialTrait<ARPoolContents> {
|
||||
template<> struct ProgramStateTrait<AutoreleasePoolContents>
|
||||
: public ProgramStatePartialTrait<ARPoolContents> {
|
||||
static inline void *GDMIndex() { return &AutoRCIndex; }
|
||||
};
|
||||
} // end GR namespace
|
||||
} // end clang namespace
|
||||
|
||||
static SymbolRef GetCurrentAutoreleasePool(const GRState *state) {
|
||||
static SymbolRef GetCurrentAutoreleasePool(const ProgramState *state) {
|
||||
ARStack stack = state->get<AutoreleaseStack>();
|
||||
return stack.isEmpty() ? SymbolRef() : stack.getHead();
|
||||
}
|
||||
|
||||
static const GRState * SendAutorelease(const GRState *state,
|
||||
ARCounts::Factory &F, SymbolRef sym) {
|
||||
|
||||
static const ProgramState *
|
||||
SendAutorelease(const ProgramState *state,
|
||||
ARCounts::Factory &F,
|
||||
SymbolRef sym) {
|
||||
SymbolRef pool = GetCurrentAutoreleasePool(state);
|
||||
const ARCounts *cnts = state->get<AutoreleasePoolContents>(pool);
|
||||
ARCounts newCnts(0);
|
||||
|
@ -1651,10 +1653,12 @@ namespace {
|
|||
|
||||
class CFRefCount : public TransferFuncs {
|
||||
public:
|
||||
class BindingsPrinter : public GRState::Printer {
|
||||
class BindingsPrinter : public ProgramState::Printer {
|
||||
public:
|
||||
virtual void Print(raw_ostream &Out, const GRState *state,
|
||||
const char* nl, const char* sep);
|
||||
virtual void Print(raw_ostream &Out,
|
||||
const ProgramState *state,
|
||||
const char* nl,
|
||||
const char* sep);
|
||||
};
|
||||
|
||||
typedef llvm::DenseMap<const ExplodedNode*, const RetainSummary*>
|
||||
|
@ -1674,24 +1678,31 @@ public:
|
|||
|
||||
llvm::DenseMap<SymbolRef, const SimpleProgramPointTag*> DeadSymbolTags;
|
||||
|
||||
const GRState * Update(const GRState * state, SymbolRef sym, RefVal V,
|
||||
ArgEffect E, RefVal::Kind& hasErr);
|
||||
const ProgramState *Update(const ProgramState * state,
|
||||
SymbolRef sym,
|
||||
RefVal V,
|
||||
ArgEffect E,
|
||||
RefVal::Kind& hasErr);
|
||||
|
||||
void ProcessNonLeakError(ExplodedNodeSet &Dst,
|
||||
StmtNodeBuilder& Builder,
|
||||
const Expr *NodeExpr, SourceRange ErrorRange,
|
||||
const Expr *NodeExpr,
|
||||
SourceRange ErrorRange,
|
||||
ExplodedNode *Pred,
|
||||
const GRState *St,
|
||||
RefVal::Kind hasErr, SymbolRef Sym);
|
||||
const ProgramState *St,
|
||||
RefVal::Kind hasErr,
|
||||
SymbolRef Sym);
|
||||
|
||||
const GRState * HandleSymbolDeath(const GRState * state, SymbolRef sid, RefVal V,
|
||||
SmallVectorImpl<SymbolRef> &Leaked);
|
||||
const ProgramState *HandleSymbolDeath(const ProgramState * state,
|
||||
SymbolRef sid,
|
||||
RefVal V,
|
||||
SmallVectorImpl<SymbolRef> &Leaked);
|
||||
|
||||
ExplodedNode *ProcessLeaks(const GRState * state,
|
||||
SmallVectorImpl<SymbolRef> &Leaked,
|
||||
GenericNodeBuilderRefCount &Builder,
|
||||
ExprEngine &Eng,
|
||||
ExplodedNode *Pred = 0);
|
||||
ExplodedNode *ProcessLeaks(const ProgramState * state,
|
||||
SmallVectorImpl<SymbolRef> &Leaked,
|
||||
GenericNodeBuilderRefCount &Builder,
|
||||
ExprEngine &Eng,
|
||||
ExplodedNode *Pred = 0);
|
||||
|
||||
public:
|
||||
CFRefCount(ASTContext &Ctx, bool gcenabled, const LangOptions& lopts)
|
||||
|
@ -1709,7 +1720,7 @@ public:
|
|||
|
||||
void RegisterChecks(ExprEngine &Eng);
|
||||
|
||||
virtual void RegisterPrinters(std::vector<GRState::Printer*>& Printers) {
|
||||
virtual void RegisterPrinters(std::vector<ProgramState::Printer*>& Printers) {
|
||||
Printers.push_back(new BindingsPrinter());
|
||||
}
|
||||
|
||||
|
@ -1733,7 +1744,7 @@ public:
|
|||
InstanceReceiver Receiver,
|
||||
const RetainSummary& Summ,
|
||||
const MemRegion *Callee,
|
||||
ExplodedNode *Pred, const GRState *state);
|
||||
ExplodedNode *Pred, const ProgramState *state);
|
||||
|
||||
virtual void evalCall(ExplodedNodeSet &Dst,
|
||||
ExprEngine& Eng,
|
||||
|
@ -1747,7 +1758,7 @@ public:
|
|||
StmtNodeBuilder& Builder,
|
||||
ObjCMessage msg,
|
||||
ExplodedNode *Pred,
|
||||
const GRState *state);
|
||||
const ProgramState *state);
|
||||
// Stores.
|
||||
virtual void evalBind(StmtNodeBuilderRef& B, SVal location, SVal val);
|
||||
|
||||
|
@ -1760,15 +1771,19 @@ public:
|
|||
ExprEngine& Engine,
|
||||
StmtNodeBuilder& Builder,
|
||||
ExplodedNode *Pred,
|
||||
const GRState *state,
|
||||
const ProgramState *state,
|
||||
SymbolReaper& SymReaper);
|
||||
|
||||
const ProgramPointTag *getDeadSymbolTag(SymbolRef sym);
|
||||
|
||||
std::pair<ExplodedNode*, const GRState *>
|
||||
HandleAutoreleaseCounts(const GRState * state, GenericNodeBuilderRefCount Bd,
|
||||
ExplodedNode *Pred, ExprEngine &Eng,
|
||||
SymbolRef Sym, RefVal V, bool &stop);
|
||||
std::pair<ExplodedNode*, const ProgramState *>
|
||||
HandleAutoreleaseCounts(const ProgramState * state,
|
||||
GenericNodeBuilderRefCount Bd,
|
||||
ExplodedNode *Pred,
|
||||
ExprEngine &Eng,
|
||||
SymbolRef Sym,
|
||||
RefVal V,
|
||||
bool &stop);
|
||||
// Return statements.
|
||||
|
||||
virtual void evalReturn(ExplodedNodeSet &Dst,
|
||||
|
@ -1783,19 +1798,21 @@ public:
|
|||
const ReturnStmt *S,
|
||||
ExplodedNode *Pred,
|
||||
RetEffect RE, RefVal X,
|
||||
SymbolRef Sym, const GRState *state);
|
||||
SymbolRef Sym, const ProgramState *state);
|
||||
|
||||
|
||||
// Assumptions.
|
||||
|
||||
virtual const GRState *evalAssume(const GRState *state, SVal condition,
|
||||
bool assumption);
|
||||
virtual const ProgramState *evalAssume(const ProgramState *state,
|
||||
SVal condition,
|
||||
bool assumption);
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
static void PrintPool(raw_ostream &Out, SymbolRef Sym,
|
||||
const GRState *state) {
|
||||
static void PrintPool(raw_ostream &Out,
|
||||
SymbolRef Sym,
|
||||
const ProgramState *state) {
|
||||
Out << ' ';
|
||||
if (Sym)
|
||||
Out << Sym->getSymbolID();
|
||||
|
@ -1812,7 +1829,7 @@ static void PrintPool(raw_ostream &Out, SymbolRef Sym,
|
|||
}
|
||||
|
||||
void CFRefCount::BindingsPrinter::Print(raw_ostream &Out,
|
||||
const GRState *state,
|
||||
const ProgramState *state,
|
||||
const char* nl, const char* sep) {
|
||||
|
||||
RefBindings B = state->get<RefBindings>();
|
||||
|
@ -2060,8 +2077,8 @@ PathDiagnosticPiece *CFRefReport::VisitNode(const ExplodedNode *N,
|
|||
return NULL;
|
||||
|
||||
// Check if the type state has changed.
|
||||
const GRState *PrevSt = PrevN->getState();
|
||||
const GRState *CurrSt = N->getState();
|
||||
const ProgramState *PrevSt = PrevN->getState();
|
||||
const ProgramState *CurrSt = N->getState();
|
||||
|
||||
const RefVal* CurrT = CurrSt->get<RefBindings>(Sym);
|
||||
if (!CurrT) return NULL;
|
||||
|
@ -2329,7 +2346,7 @@ namespace {
|
|||
}
|
||||
|
||||
static std::pair<const ExplodedNode*,const MemRegion*>
|
||||
GetAllocationSite(GRStateManager& StateMgr, const ExplodedNode *N,
|
||||
GetAllocationSite(ProgramStateManager& StateMgr, const ExplodedNode *N,
|
||||
SymbolRef Sym) {
|
||||
|
||||
// Find both first node that referred to the tracked symbol and the
|
||||
|
@ -2338,7 +2355,7 @@ GetAllocationSite(GRStateManager& StateMgr, const ExplodedNode *N,
|
|||
const MemRegion* FirstBinding = 0;
|
||||
|
||||
while (N) {
|
||||
const GRState *St = N->getState();
|
||||
const ProgramState *St = N->getState();
|
||||
RefBindings B = St->get<RefBindings>();
|
||||
|
||||
if (!B.lookup(Sym))
|
||||
|
@ -2555,7 +2572,8 @@ void CFRefCount::evalSummary(ExplodedNodeSet &Dst,
|
|||
InstanceReceiver Receiver,
|
||||
const RetainSummary& Summ,
|
||||
const MemRegion *Callee,
|
||||
ExplodedNode *Pred, const GRState *state) {
|
||||
ExplodedNode *Pred,
|
||||
const ProgramState *state) {
|
||||
|
||||
// Evaluate the effect of the arguments.
|
||||
RefVal::Kind hasErr = (RefVal::Kind) 0;
|
||||
|
@ -2850,7 +2868,7 @@ void CFRefCount::evalObjCMessage(ExplodedNodeSet &Dst,
|
|||
StmtNodeBuilder& Builder,
|
||||
ObjCMessage msg,
|
||||
ExplodedNode *Pred,
|
||||
const GRState *state) {
|
||||
const ProgramState *state) {
|
||||
RetainSummary *Summ =
|
||||
msg.isInstanceMessage()
|
||||
? Summaries.getInstanceMethodSummary(msg, state,Pred->getLocationContext())
|
||||
|
@ -2865,10 +2883,10 @@ void CFRefCount::evalObjCMessage(ExplodedNodeSet &Dst,
|
|||
|
||||
namespace {
|
||||
class StopTrackingCallback : public SymbolVisitor {
|
||||
const GRState *state;
|
||||
const ProgramState *state;
|
||||
public:
|
||||
StopTrackingCallback(const GRState *st) : state(st) {}
|
||||
const GRState *getState() const { return state; }
|
||||
StopTrackingCallback(const ProgramState *st) : state(st) {}
|
||||
const ProgramState *getState() const { return state; }
|
||||
|
||||
bool VisitSymbol(SymbolRef sym) {
|
||||
state = state->remove<RefBindings>(sym);
|
||||
|
@ -2888,7 +2906,7 @@ void CFRefCount::evalBind(StmtNodeBuilderRef& B, SVal location, SVal val) {
|
|||
// (2) we are binding to a memregion that does not have stack storage
|
||||
// (3) we are binding to a memregion with stack storage that the store
|
||||
// does not understand.
|
||||
const GRState *state = B.getState();
|
||||
const ProgramState *state = B.getState();
|
||||
|
||||
if (!isa<loc::MemRegionVal>(location))
|
||||
escapes = true;
|
||||
|
@ -2927,7 +2945,7 @@ void CFRefCount::evalReturn(ExplodedNodeSet &Dst,
|
|||
if (!RetE)
|
||||
return;
|
||||
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
SymbolRef Sym = state->getSValAsScalarOrLoc(RetE).getAsLocSymbol();
|
||||
|
||||
if (!Sym)
|
||||
|
@ -3016,7 +3034,8 @@ void CFRefCount::evalReturnWithRetEffect(ExplodedNodeSet &Dst,
|
|||
const ReturnStmt *S,
|
||||
ExplodedNode *Pred,
|
||||
RetEffect RE, RefVal X,
|
||||
SymbolRef Sym, const GRState *state) {
|
||||
SymbolRef Sym,
|
||||
const ProgramState *state) {
|
||||
// Any leaks or other errors?
|
||||
if (X.isReturnedOwned() && X.getCount() == 0) {
|
||||
if (RE.getKind() != RetEffect::NoRet) {
|
||||
|
@ -3078,8 +3097,9 @@ void CFRefCount::evalReturnWithRetEffect(ExplodedNodeSet &Dst,
|
|||
|
||||
// Assumptions.
|
||||
|
||||
const GRState *CFRefCount::evalAssume(const GRState *state,
|
||||
SVal Cond, bool Assumption) {
|
||||
const ProgramState *CFRefCount::evalAssume(const ProgramState *state,
|
||||
SVal Cond,
|
||||
bool Assumption) {
|
||||
|
||||
// FIXME: We may add to the interface of evalAssume the list of symbols
|
||||
// whose assumptions have changed. For now we just iterate through the
|
||||
|
@ -3110,9 +3130,11 @@ const GRState *CFRefCount::evalAssume(const GRState *state,
|
|||
return state;
|
||||
}
|
||||
|
||||
const GRState * CFRefCount::Update(const GRState * state, SymbolRef sym,
|
||||
RefVal V, ArgEffect E,
|
||||
RefVal::Kind& hasErr) {
|
||||
const ProgramState * CFRefCount::Update(const ProgramState * state,
|
||||
SymbolRef sym,
|
||||
RefVal V,
|
||||
ArgEffect E,
|
||||
RefVal::Kind& hasErr) {
|
||||
|
||||
// In GC mode [... release] and [... retain] do nothing.
|
||||
switch (E) {
|
||||
|
@ -3250,12 +3272,14 @@ const GRState * CFRefCount::Update(const GRState * state, SymbolRef sym,
|
|||
// Handle dead symbols and end-of-path.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
std::pair<ExplodedNode*, const GRState *>
|
||||
CFRefCount::HandleAutoreleaseCounts(const GRState * state,
|
||||
std::pair<ExplodedNode*, const ProgramState *>
|
||||
CFRefCount::HandleAutoreleaseCounts(const ProgramState *state,
|
||||
GenericNodeBuilderRefCount Bd,
|
||||
ExplodedNode *Pred,
|
||||
ExprEngine &Eng,
|
||||
SymbolRef Sym, RefVal V, bool &stop) {
|
||||
SymbolRef Sym,
|
||||
RefVal V,
|
||||
bool &stop) {
|
||||
|
||||
unsigned ACnt = V.getAutoreleaseCount();
|
||||
stop = false;
|
||||
|
@ -3315,8 +3339,10 @@ CFRefCount::HandleAutoreleaseCounts(const GRState * state,
|
|||
return std::make_pair((ExplodedNode*)0, state);
|
||||
}
|
||||
|
||||
const GRState *
|
||||
CFRefCount::HandleSymbolDeath(const GRState * state, SymbolRef sid, RefVal V,
|
||||
const ProgramState *
|
||||
CFRefCount::HandleSymbolDeath(const ProgramState *state,
|
||||
SymbolRef sid,
|
||||
RefVal V,
|
||||
SmallVectorImpl<SymbolRef> &Leaked) {
|
||||
|
||||
bool hasLeak = V.isOwned() ||
|
||||
|
@ -3330,7 +3356,7 @@ CFRefCount::HandleSymbolDeath(const GRState * state, SymbolRef sid, RefVal V,
|
|||
}
|
||||
|
||||
ExplodedNode*
|
||||
CFRefCount::ProcessLeaks(const GRState * state,
|
||||
CFRefCount::ProcessLeaks(const ProgramState * state,
|
||||
SmallVectorImpl<SymbolRef> &Leaked,
|
||||
GenericNodeBuilderRefCount &Builder,
|
||||
ExprEngine& Eng,
|
||||
|
@ -3360,7 +3386,7 @@ CFRefCount::ProcessLeaks(const GRState * state,
|
|||
void CFRefCount::evalEndPath(ExprEngine& Eng,
|
||||
EndOfFunctionNodeBuilder& Builder) {
|
||||
|
||||
const GRState *state = Builder.getState();
|
||||
const ProgramState *state = Builder.getState();
|
||||
GenericNodeBuilderRefCount Bd(Builder);
|
||||
RefBindings B = state->get<RefBindings>();
|
||||
ExplodedNode *Pred = 0;
|
||||
|
@ -3399,7 +3425,7 @@ void CFRefCount::evalDeadSymbols(ExplodedNodeSet &Dst,
|
|||
ExprEngine& Eng,
|
||||
StmtNodeBuilder& Builder,
|
||||
ExplodedNode *Pred,
|
||||
const GRState *state,
|
||||
const ProgramState *state,
|
||||
SymbolReaper& SymReaper) {
|
||||
const Stmt *S = Builder.getStmt();
|
||||
RefBindings B = state->get<RefBindings>();
|
||||
|
@ -3454,7 +3480,7 @@ void CFRefCount::ProcessNonLeakError(ExplodedNodeSet &Dst,
|
|||
const Expr *NodeExpr,
|
||||
SourceRange ErrorRange,
|
||||
ExplodedNode *Pred,
|
||||
const GRState *St,
|
||||
const ProgramState *St,
|
||||
RefVal::Kind hasErr, SymbolRef Sym) {
|
||||
Builder.BuildSinks = true;
|
||||
ExplodedNode *N = Builder.MakeNode(Dst, NodeExpr, Pred, St);
|
||||
|
@ -3508,19 +3534,19 @@ public:
|
|||
|
||||
void checkPostStmt(const CastExpr *CE, CheckerContext &C) const;
|
||||
|
||||
const GRState *checkRegionChanges(const GRState *state,
|
||||
const ProgramState *checkRegionChanges(const ProgramState *state,
|
||||
const StoreManager::InvalidatedSymbols *invalidated,
|
||||
const MemRegion * const *begin,
|
||||
const MemRegion * const *end) const;
|
||||
|
||||
bool wantsRegionChangeUpdate(const GRState *state) const {
|
||||
bool wantsRegionChangeUpdate(const ProgramState *state) const {
|
||||
return wantsRegionUpdate;
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
const GRState *
|
||||
RetainReleaseChecker::checkRegionChanges(const GRState *state,
|
||||
const ProgramState *
|
||||
RetainReleaseChecker::checkRegionChanges(const ProgramState *state,
|
||||
const StoreManager::InvalidatedSymbols *invalidated,
|
||||
const MemRegion * const *begin,
|
||||
const MemRegion * const *end) const {
|
||||
|
@ -3546,7 +3572,7 @@ void RetainReleaseChecker::checkPostStmt(const BlockExpr *BE,
|
|||
if (!BE->getBlockDecl()->hasCaptures())
|
||||
return;
|
||||
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
const BlockDataRegion *R =
|
||||
cast<BlockDataRegion>(state->getSVal(BE).getAsRegion());
|
||||
|
||||
|
@ -3597,7 +3623,7 @@ void RetainReleaseChecker::checkPostStmt(const CastExpr *CE,
|
|||
break;
|
||||
}
|
||||
|
||||
const GRState *state = C.getState();
|
||||
const ProgramState *state = C.getState();
|
||||
SymbolRef Sym = state->getSVal(CE).getAsLocSymbol();
|
||||
if (!Sym)
|
||||
return;
|
||||
|
|
|
@ -20,12 +20,12 @@ add_clang_library(clangStaticAnalyzerCore
|
|||
Environment.cpp
|
||||
ExplodedGraph.cpp
|
||||
ExprEngine.cpp
|
||||
GRState.cpp
|
||||
HTMLDiagnostics.cpp
|
||||
MemRegion.cpp
|
||||
ObjCMessage.cpp
|
||||
PathDiagnostic.cpp
|
||||
PlistDiagnostics.cpp
|
||||
ProgramState.cpp
|
||||
RangeConstraintManager.cpp
|
||||
RegionStore.cpp
|
||||
SValBuilder.cpp
|
||||
|
|
|
@ -109,7 +109,7 @@ void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
|
|||
ExplodedNodeSet Tmp;
|
||||
Visit(ME->GetTemporaryExpr(), Pred, Tmp);
|
||||
for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) {
|
||||
const GRState *state = (*I)->getState();
|
||||
const ProgramState *state = (*I)->getState();
|
||||
|
||||
// Bind the temporary object to the value of the expression. Then bind
|
||||
// the expression to the location of the object.
|
||||
|
@ -187,7 +187,7 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
|
|||
|
||||
for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(),
|
||||
NE = argsEvaluated.end(); NI != NE; ++NI) {
|
||||
const GRState *state = (*NI)->getState();
|
||||
const ProgramState *state = (*NI)->getState();
|
||||
// Setup 'this' region, so that the ctor is evaluated on the object pointed
|
||||
// by 'Dest'.
|
||||
state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
|
||||
|
@ -216,7 +216,7 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
|
|||
i != e; ++i)
|
||||
{
|
||||
ExplodedNode *Pred = *i;
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
|
||||
// Accumulate list of regions that are invalidated.
|
||||
for (CXXConstructExpr::const_arg_iterator
|
||||
|
@ -259,7 +259,7 @@ void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
|
|||
|
||||
CallEnter PP(S, SFC, Pred->getLocationContext());
|
||||
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
|
||||
ExplodedNode *N = Builder->generateNode(PP, state, Pred);
|
||||
if (N)
|
||||
|
@ -280,7 +280,7 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
|
|||
if (CNE->isArray()) {
|
||||
// FIXME: allocating an array requires simulating the constructors.
|
||||
// For now, just return a symbolicated region.
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
|
||||
MakeNode(Dst, CNE, Pred, state);
|
||||
return;
|
||||
|
@ -299,7 +299,7 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
|
|||
for (ExplodedNodeSet::iterator I = argsEvaluated.begin(),
|
||||
E = argsEvaluated.end(); I != E; ++I) {
|
||||
|
||||
const GRState *state = (*I)->getState();
|
||||
const ProgramState *state = (*I)->getState();
|
||||
|
||||
// Accumulate list of regions that are invalidated.
|
||||
// FIXME: Eventually we should unify the logic for constructor
|
||||
|
@ -352,7 +352,7 @@ void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
|
|||
Visit(CDE->getArgument(), Pred, Argevaluated);
|
||||
for (ExplodedNodeSet::iterator I = Argevaluated.begin(),
|
||||
E = Argevaluated.end(); I != E; ++I) {
|
||||
const GRState *state = (*I)->getState();
|
||||
const ProgramState *state = (*I)->getState();
|
||||
MakeNode(Dst, CDE, *I, state);
|
||||
}
|
||||
}
|
||||
|
@ -365,7 +365,7 @@ void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
|
|||
getContext().getCanonicalType(TE->getType()),
|
||||
Pred->getLocationContext());
|
||||
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
SVal V = state->getSVal(loc::MemRegionVal(R));
|
||||
MakeNode(Dst, TE, Pred, state->BindExpr(TE, V));
|
||||
}
|
||||
|
|
|
@ -294,7 +294,7 @@ void CheckerManager::runCheckersForBranchCondition(const Stmt *condition,
|
|||
}
|
||||
|
||||
/// \brief Run checkers for live symbols.
|
||||
void CheckerManager::runCheckersForLiveSymbols(const GRState *state,
|
||||
void CheckerManager::runCheckersForLiveSymbols(const ProgramState *state,
|
||||
SymbolReaper &SymReaper) {
|
||||
for (unsigned i = 0, e = LiveSymbolsCheckers.size(); i != e; ++i)
|
||||
LiveSymbolsCheckers[i](state, SymReaper);
|
||||
|
@ -335,7 +335,7 @@ void CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
|
|||
}
|
||||
|
||||
/// \brief True if at least one checker wants to check region changes.
|
||||
bool CheckerManager::wantsRegionChangeUpdate(const GRState *state) {
|
||||
bool CheckerManager::wantsRegionChangeUpdate(const ProgramState *state) {
|
||||
for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i)
|
||||
if (RegionChangesCheckers[i].WantUpdateFn(state))
|
||||
return true;
|
||||
|
@ -344,8 +344,8 @@ bool CheckerManager::wantsRegionChangeUpdate(const GRState *state) {
|
|||
}
|
||||
|
||||
/// \brief Run checkers for region changes.
|
||||
const GRState *
|
||||
CheckerManager::runCheckersForRegionChanges(const GRState *state,
|
||||
const ProgramState *
|
||||
CheckerManager::runCheckersForRegionChanges(const ProgramState *state,
|
||||
const StoreManager::InvalidatedSymbols *invalidated,
|
||||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End) {
|
||||
|
@ -360,8 +360,8 @@ CheckerManager::runCheckersForRegionChanges(const GRState *state,
|
|||
}
|
||||
|
||||
/// \brief Run checkers for handling assumptions on symbolic values.
|
||||
const GRState *
|
||||
CheckerManager::runCheckersForEvalAssume(const GRState *state,
|
||||
const ProgramState *
|
||||
CheckerManager::runCheckersForEvalAssume(const ProgramState *state,
|
||||
SVal Cond, bool Assumption) {
|
||||
for (unsigned i = 0, e = EvalAssumeCheckers.size(); i != e; ++i) {
|
||||
// If any checker declares the state infeasible (or if it starts that way),
|
||||
|
|
|
@ -159,7 +159,7 @@ WorkList* WorkList::makeBFSBlockDFSContents() {
|
|||
|
||||
/// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps.
|
||||
bool CoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps,
|
||||
const GRState *InitState) {
|
||||
const ProgramState *InitState) {
|
||||
|
||||
if (G->num_roots() == 0) { // Initialize the analysis by constructing
|
||||
// the root if none exists.
|
||||
|
@ -243,9 +243,9 @@ bool CoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps,
|
|||
}
|
||||
|
||||
void CoreEngine::ExecuteWorkListWithInitialState(const LocationContext *L,
|
||||
unsigned Steps,
|
||||
const GRState *InitState,
|
||||
ExplodedNodeSet &Dst) {
|
||||
unsigned Steps,
|
||||
const ProgramState *InitState,
|
||||
ExplodedNodeSet &Dst) {
|
||||
ExecuteWorkList(L, Steps, InitState);
|
||||
for (SmallVectorImpl<ExplodedNode*>::iterator I = G->EndNodes.begin(),
|
||||
E = G->EndNodes.end(); I != E; ++I) {
|
||||
|
@ -443,7 +443,8 @@ void CoreEngine::HandlePostStmt(const CFGBlock *B, unsigned StmtIdx,
|
|||
/// generateNode - Utility method to generate nodes, hook up successors,
|
||||
/// and add nodes to the worklist.
|
||||
void CoreEngine::generateNode(const ProgramPoint &Loc,
|
||||
const GRState *State, ExplodedNode *Pred) {
|
||||
const ProgramState *State,
|
||||
ExplodedNode *Pred) {
|
||||
|
||||
bool IsNew;
|
||||
ExplodedNode *Node = G->getNode(Loc, State, &IsNew);
|
||||
|
@ -460,7 +461,7 @@ void CoreEngine::generateNode(const ProgramPoint &Loc,
|
|||
}
|
||||
|
||||
ExplodedNode *
|
||||
GenericNodeBuilderImpl::generateNodeImpl(const GRState *state,
|
||||
GenericNodeBuilderImpl::generateNodeImpl(const ProgramState *state,
|
||||
ExplodedNode *pred,
|
||||
ProgramPoint programPoint,
|
||||
bool asSink) {
|
||||
|
@ -480,9 +481,11 @@ GenericNodeBuilderImpl::generateNodeImpl(const GRState *state,
|
|||
return 0;
|
||||
}
|
||||
|
||||
StmtNodeBuilder::StmtNodeBuilder(const CFGBlock *b, unsigned idx,
|
||||
ExplodedNode *N, CoreEngine* e,
|
||||
GRStateManager &mgr)
|
||||
StmtNodeBuilder::StmtNodeBuilder(const CFGBlock *b,
|
||||
unsigned idx,
|
||||
ExplodedNode *N,
|
||||
CoreEngine* e,
|
||||
ProgramStateManager &mgr)
|
||||
: Eng(*e), B(*b), Idx(idx), Pred(N), Mgr(mgr),
|
||||
PurgingDeadSymbols(false), BuildSinks(false), hasGeneratedNode(false),
|
||||
PointKind(ProgramPoint::PostStmtKind), Tag(0) {
|
||||
|
@ -529,9 +532,11 @@ void StmtNodeBuilder::GenerateAutoTransition(ExplodedNode *N) {
|
|||
Eng.WList->enqueue(Succ, &B, Idx+1);
|
||||
}
|
||||
|
||||
ExplodedNode *StmtNodeBuilder::MakeNode(ExplodedNodeSet &Dst, const Stmt *S,
|
||||
ExplodedNode *Pred, const GRState *St,
|
||||
ProgramPoint::Kind K) {
|
||||
ExplodedNode *StmtNodeBuilder::MakeNode(ExplodedNodeSet &Dst,
|
||||
const Stmt *S,
|
||||
ExplodedNode *Pred,
|
||||
const ProgramState *St,
|
||||
ProgramPoint::Kind K) {
|
||||
|
||||
ExplodedNode *N = generateNode(S, St, Pred, K);
|
||||
|
||||
|
@ -571,7 +576,8 @@ static ProgramPoint GetProgramPoint(const Stmt *S, ProgramPoint::Kind K,
|
|||
}
|
||||
|
||||
ExplodedNode*
|
||||
StmtNodeBuilder::generateNodeInternal(const Stmt *S, const GRState *state,
|
||||
StmtNodeBuilder::generateNodeInternal(const Stmt *S,
|
||||
const ProgramState *state,
|
||||
ExplodedNode *Pred,
|
||||
ProgramPoint::Kind K,
|
||||
const ProgramPointTag *tag) {
|
||||
|
@ -583,8 +589,8 @@ StmtNodeBuilder::generateNodeInternal(const Stmt *S, const GRState *state,
|
|||
|
||||
ExplodedNode*
|
||||
StmtNodeBuilder::generateNodeInternal(const ProgramPoint &Loc,
|
||||
const GRState *State,
|
||||
ExplodedNode *Pred) {
|
||||
const ProgramState *State,
|
||||
ExplodedNode *Pred) {
|
||||
bool IsNew;
|
||||
ExplodedNode *N = Eng.G->getNode(Loc, State, &IsNew);
|
||||
N->addPredecessor(Pred, *Eng.G);
|
||||
|
@ -600,7 +606,7 @@ StmtNodeBuilder::generateNodeInternal(const ProgramPoint &Loc,
|
|||
|
||||
// This function generate a new ExplodedNode but not a new branch(block edge).
|
||||
ExplodedNode *BranchNodeBuilder::generateNode(const Stmt *Condition,
|
||||
const GRState *State) {
|
||||
const ProgramState *State) {
|
||||
bool IsNew;
|
||||
|
||||
ExplodedNode *Succ
|
||||
|
@ -617,8 +623,8 @@ ExplodedNode *BranchNodeBuilder::generateNode(const Stmt *Condition,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ExplodedNode *BranchNodeBuilder::generateNode(const GRState *State,
|
||||
bool branch) {
|
||||
ExplodedNode *BranchNodeBuilder::generateNode(const ProgramState *State,
|
||||
bool branch) {
|
||||
|
||||
// If the branch has been marked infeasible we should not generate a node.
|
||||
if (!isFeasible(branch))
|
||||
|
@ -655,8 +661,9 @@ BranchNodeBuilder::~BranchNodeBuilder() {
|
|||
|
||||
|
||||
ExplodedNode*
|
||||
IndirectGotoNodeBuilder::generateNode(const iterator &I, const GRState *St,
|
||||
bool isSink) {
|
||||
IndirectGotoNodeBuilder::generateNode(const iterator &I,
|
||||
const ProgramState *St,
|
||||
bool isSink) {
|
||||
bool IsNew;
|
||||
|
||||
ExplodedNode *Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(),
|
||||
|
@ -679,26 +686,25 @@ IndirectGotoNodeBuilder::generateNode(const iterator &I, const GRState *St,
|
|||
|
||||
|
||||
ExplodedNode*
|
||||
SwitchNodeBuilder::generateCaseStmtNode(const iterator &I, const GRState *St){
|
||||
SwitchNodeBuilder::generateCaseStmtNode(const iterator &I,
|
||||
const ProgramState *St) {
|
||||
|
||||
bool IsNew;
|
||||
|
||||
ExplodedNode *Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(),
|
||||
Pred->getLocationContext()), St, &IsNew);
|
||||
Pred->getLocationContext()),
|
||||
St, &IsNew);
|
||||
Succ->addPredecessor(Pred, *Eng.G);
|
||||
|
||||
if (IsNew) {
|
||||
Eng.WList->enqueue(Succ);
|
||||
return Succ;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
ExplodedNode*
|
||||
SwitchNodeBuilder::generateDefaultCaseNode(const GRState *St, bool isSink) {
|
||||
|
||||
SwitchNodeBuilder::generateDefaultCaseNode(const ProgramState *St,
|
||||
bool isSink) {
|
||||
// Get the block for the default case.
|
||||
assert (Src->succ_rbegin() != Src->succ_rend());
|
||||
CFGBlock *DefaultBlock = *Src->succ_rbegin();
|
||||
|
@ -733,7 +739,7 @@ EndOfFunctionNodeBuilder::~EndOfFunctionNodeBuilder() {
|
|||
}
|
||||
|
||||
ExplodedNode*
|
||||
EndOfFunctionNodeBuilder::generateNode(const GRState *State,
|
||||
EndOfFunctionNodeBuilder::generateNode(const ProgramState *State,
|
||||
ExplodedNode *P,
|
||||
const ProgramPointTag *tag) {
|
||||
hasGeneratedNode = true;
|
||||
|
@ -753,7 +759,7 @@ EndOfFunctionNodeBuilder::generateNode(const GRState *State,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void EndOfFunctionNodeBuilder::GenerateCallExitNode(const GRState *state) {
|
||||
void EndOfFunctionNodeBuilder::GenerateCallExitNode(const ProgramState *state) {
|
||||
hasGeneratedNode = true;
|
||||
// Create a CallExit node and enqueue it.
|
||||
const StackFrameContext *LocCtx
|
||||
|
@ -772,7 +778,7 @@ void EndOfFunctionNodeBuilder::GenerateCallExitNode(const GRState *state) {
|
|||
}
|
||||
|
||||
|
||||
void CallEnterNodeBuilder::generateNode(const GRState *state) {
|
||||
void CallEnterNodeBuilder::generateNode(const ProgramState *state) {
|
||||
// Check if the callee is in the same translation unit.
|
||||
if (CalleeCtx->getTranslationUnit() !=
|
||||
Pred->getLocationContext()->getTranslationUnit()) {
|
||||
|
@ -824,8 +830,8 @@ void CallEnterNodeBuilder::generateNode(const GRState *state) {
|
|||
OldLocCtx->getIndex());
|
||||
|
||||
// Now create an initial state for the new engine.
|
||||
const GRState *NewState = NewEng.getStateManager().MarshalState(state,
|
||||
NewLocCtx);
|
||||
const ProgramState *NewState =
|
||||
NewEng.getStateManager().MarshalState(state, NewLocCtx);
|
||||
ExplodedNodeSet ReturnNodes;
|
||||
NewEng.ExecuteWorkListWithInitialState(NewLocCtx, AMgr.getMaxNodes(),
|
||||
NewState, ReturnNodes);
|
||||
|
@ -851,7 +857,7 @@ void CallEnterNodeBuilder::generateNode(const GRState *state) {
|
|||
Eng.WList->enqueue(Node);
|
||||
}
|
||||
|
||||
void CallExitNodeBuilder::generateNode(const GRState *state) {
|
||||
void CallExitNodeBuilder::generateNode(const ProgramState *state) {
|
||||
// Get the callee's location context.
|
||||
const StackFrameContext *LocCtx
|
||||
= cast<StackFrameContext>(Pred->getLocationContext());
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include "clang/Analysis/AnalysisContext.h"
|
||||
#include "clang/Analysis/CFG.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace ento;
|
||||
|
@ -143,7 +143,7 @@ static inline bool IsLocation(const Stmt *S) {
|
|||
Environment
|
||||
EnvironmentManager::removeDeadBindings(Environment Env,
|
||||
SymbolReaper &SymReaper,
|
||||
const GRState *ST) {
|
||||
const ProgramState *ST) {
|
||||
|
||||
// We construct a new Environment object entirely, as this is cheaper than
|
||||
// individually removing all the subexpression bindings (which will greatly
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
||||
#include "clang/AST/Stmt.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
|
@ -103,8 +103,8 @@ void ExplodedGraph::reclaimRecentlyAllocatedNodes() {
|
|||
continue;
|
||||
|
||||
// Conditions 5, 6, and 7.
|
||||
const GRState *state = node->getState();
|
||||
const GRState *pred_state = pred->getState();
|
||||
const ProgramState *state = node->getState();
|
||||
const ProgramState *pred_state = pred->getState();
|
||||
if (state->store != pred_state->store || state->GDM != pred_state->GDM ||
|
||||
progPoint.getLocationContext() != pred->getLocationContext())
|
||||
continue;
|
||||
|
@ -216,7 +216,7 @@ ExplodedNode** ExplodedNode::NodeGroup::end() const {
|
|||
}
|
||||
|
||||
ExplodedNode *ExplodedGraph::getNode(const ProgramPoint &L,
|
||||
const GRState *State, bool* IsNew) {
|
||||
const ProgramState *State, bool* IsNew) {
|
||||
// Profile 'State' to determine if we already have an existing node.
|
||||
llvm::FoldingSetNodeID profile;
|
||||
void *InsertPos = 0;
|
||||
|
|
|
@ -93,8 +93,8 @@ ExprEngine::~ExprEngine() {
|
|||
// Utility methods.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
const GRState *ExprEngine::getInitialState(const LocationContext *InitLoc) {
|
||||
const GRState *state = StateMgr.getInitialState(InitLoc);
|
||||
const ProgramState *ExprEngine::getInitialState(const LocationContext *InitLoc) {
|
||||
const ProgramState *state = StateMgr.getInitialState(InitLoc);
|
||||
|
||||
// Preconditions.
|
||||
|
||||
|
@ -129,7 +129,7 @@ const GRState *ExprEngine::getInitialState(const LocationContext *InitLoc) {
|
|||
if (!Constraint)
|
||||
break;
|
||||
|
||||
if (const GRState *newState = state->assume(*Constraint, true))
|
||||
if (const ProgramState *newState = state->assume(*Constraint, true))
|
||||
state = newState;
|
||||
|
||||
break;
|
||||
|
@ -180,7 +180,7 @@ ExprEngine::doesInvalidateGlobals(const CallOrObjCMessage &callOrMessage) const
|
|||
|
||||
/// evalAssume - Called by ConstraintManager. Used to call checker-specific
|
||||
/// logic for handling assumptions on symbolic values.
|
||||
const GRState *ExprEngine::processAssume(const GRState *state, SVal cond,
|
||||
const ProgramState *ExprEngine::processAssume(const ProgramState *state, SVal cond,
|
||||
bool assumption) {
|
||||
state = getCheckerManager().runCheckersForEvalAssume(state, cond, assumption);
|
||||
|
||||
|
@ -191,12 +191,12 @@ const GRState *ExprEngine::processAssume(const GRState *state, SVal cond,
|
|||
return TF->evalAssume(state, cond, assumption);
|
||||
}
|
||||
|
||||
bool ExprEngine::wantsRegionChangeUpdate(const GRState *state) {
|
||||
bool ExprEngine::wantsRegionChangeUpdate(const ProgramState *state) {
|
||||
return getCheckerManager().wantsRegionChangeUpdate(state);
|
||||
}
|
||||
|
||||
const GRState *
|
||||
ExprEngine::processRegionChanges(const GRState *state,
|
||||
const ProgramState *
|
||||
ExprEngine::processRegionChanges(const ProgramState *state,
|
||||
const StoreManager::InvalidatedSymbols *invalidated,
|
||||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End) {
|
||||
|
@ -234,7 +234,7 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) {
|
|||
|
||||
// Reclaim any unnecessary nodes in the ExplodedGraph.
|
||||
G.reclaimRecentlyAllocatedNodes();
|
||||
// Recycle any unused states in the GRStateManager.
|
||||
// Recycle any unused states in the ProgramStateManager.
|
||||
StateMgr.recycleUnusedStates();
|
||||
|
||||
currentStmt = S.getStmt();
|
||||
|
@ -247,7 +247,7 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) {
|
|||
Builder = &builder;
|
||||
EntryNode = builder.getPredecessor();
|
||||
|
||||
const GRState *EntryState = EntryNode->getState();
|
||||
const ProgramState *EntryState = EntryNode->getState();
|
||||
CleanedState = EntryState;
|
||||
ExplodedNode *CleanedNode = 0;
|
||||
|
||||
|
@ -299,7 +299,7 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) {
|
|||
// states as the predecessors.
|
||||
for (ExplodedNodeSet::const_iterator I = Tmp3.begin(), E = Tmp3.end();
|
||||
I != E; ++I) {
|
||||
const GRState *CheckerState = (*I)->getState();
|
||||
const ProgramState *CheckerState = (*I)->getState();
|
||||
|
||||
// The constraint manager has not been cleaned up yet, so clean up now.
|
||||
CheckerState = getConstraintManager().removeDeadBindings(CheckerState,
|
||||
|
@ -314,7 +314,7 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) {
|
|||
|
||||
// Create a state based on CleanedState with CheckerState GDM and
|
||||
// generate a transition to that state.
|
||||
const GRState *CleanedCheckerSt =
|
||||
const ProgramState *CleanedCheckerSt =
|
||||
StateMgr.getPersistentStateWithGDM(CleanedState, CheckerState);
|
||||
ExplodedNode *CleanedNode = Builder->generateNode(currentStmt,
|
||||
CleanedCheckerSt, *I,
|
||||
|
@ -358,7 +358,7 @@ void ExprEngine::ProcessInitializer(const CFGInitializer Init,
|
|||
|
||||
for (ExplodedNodeSet::iterator I = Dst.begin(), E = Dst.end(); I != E; ++I){
|
||||
ExplodedNode *Pred = *I;
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
|
||||
const FieldDecl *FD = BMI->getAnyMember();
|
||||
|
||||
|
@ -415,7 +415,7 @@ void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D,
|
|||
void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor dtor,
|
||||
StmtNodeBuilder &builder) {
|
||||
ExplodedNode *pred = builder.getPredecessor();
|
||||
const GRState *state = pred->getState();
|
||||
const ProgramState *state = pred->getState();
|
||||
const VarDecl *varDecl = dtor.getVarDecl();
|
||||
|
||||
QualType varType = varDecl->getType();
|
||||
|
@ -535,7 +535,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
|
|||
|
||||
case Stmt::GNUNullExprClass: {
|
||||
// GNU __null is a pointer-width integer, not an actual pointer.
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
state = state->BindExpr(S, svalBuilder.makeIntValWithPtrWidth(0, false));
|
||||
MakeNode(Dst, S, Pred, state);
|
||||
break;
|
||||
|
@ -550,7 +550,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
|
|||
break;
|
||||
|
||||
case Stmt::ImplicitValueInitExprClass: {
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
QualType ty = cast<ImplicitValueInitExpr>(S)->getType();
|
||||
SVal val = svalBuilder.makeZeroVal(ty);
|
||||
MakeNode(Dst, S, Pred, state->BindExpr(S, val));
|
||||
|
@ -621,7 +621,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
|
|||
break;
|
||||
}
|
||||
else if (B->getOpcode() == BO_Comma) {
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
MakeNode(Dst, B, Pred, state->BindExpr(B, state->getSVal(B->getRHS())));
|
||||
break;
|
||||
}
|
||||
|
@ -791,7 +791,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
|
|||
}
|
||||
|
||||
if (Expr *LastExpr = dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) {
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
MakeNode(Dst, SE, Pred, state->BindExpr(SE, state->getSVal(LastExpr)));
|
||||
}
|
||||
else
|
||||
|
@ -801,7 +801,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
|
|||
}
|
||||
|
||||
case Stmt::StringLiteralClass: {
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
SVal V = state->getLValue(cast<StringLiteral>(S));
|
||||
MakeNode(Dst, S, Pred, state->BindExpr(S, V));
|
||||
return;
|
||||
|
@ -845,7 +845,7 @@ void ExprEngine::processCFGBlockEntrance(ExplodedNodeSet &dstNodes,
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
ExplodedNode *ExprEngine::MakeNode(ExplodedNodeSet &Dst, const Stmt *S,
|
||||
ExplodedNode *Pred, const GRState *St,
|
||||
ExplodedNode *Pred, const ProgramState *St,
|
||||
ProgramPoint::Kind K,
|
||||
const ProgramPointTag *tag) {
|
||||
assert (Builder && "StmtNodeBuilder not present.");
|
||||
|
@ -858,7 +858,7 @@ ExplodedNode *ExprEngine::MakeNode(ExplodedNodeSet &Dst, const Stmt *S,
|
|||
// Branch processing.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
const GRState *ExprEngine::MarkBranch(const GRState *state,
|
||||
const ProgramState *ExprEngine::MarkBranch(const ProgramState *state,
|
||||
const Stmt *Terminator,
|
||||
bool branchTaken) {
|
||||
|
||||
|
@ -919,7 +919,7 @@ const GRState *ExprEngine::MarkBranch(const GRState *state,
|
|||
/// integers that promote their values (which are currently not tracked well).
|
||||
/// This function returns the SVal bound to Condition->IgnoreCasts if all the
|
||||
// cast(s) did was sign-extend the original value.
|
||||
static SVal RecoverCastedSymbol(GRStateManager& StateMgr, const GRState *state,
|
||||
static SVal RecoverCastedSymbol(ProgramStateManager& StateMgr, const ProgramState *state,
|
||||
const Stmt *Condition, ASTContext &Ctx) {
|
||||
|
||||
const Expr *Ex = dyn_cast<Expr>(Condition);
|
||||
|
@ -972,7 +972,7 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
|
|||
if (!builder.isFeasible(true) && !builder.isFeasible(false))
|
||||
return;
|
||||
|
||||
const GRState *PrevState = builder.getState();
|
||||
const ProgramState *PrevState = builder.getState();
|
||||
SVal X = PrevState->getSVal(Condition);
|
||||
|
||||
if (X.isUnknownOrUndef()) {
|
||||
|
@ -1004,7 +1004,7 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
|
|||
|
||||
// Process the true branch.
|
||||
if (builder.isFeasible(true)) {
|
||||
if (const GRState *state = PrevState->assume(V, true))
|
||||
if (const ProgramState *state = PrevState->assume(V, true))
|
||||
builder.generateNode(MarkBranch(state, Term, true), true);
|
||||
else
|
||||
builder.markInfeasible(true);
|
||||
|
@ -1012,7 +1012,7 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
|
|||
|
||||
// Process the false branch.
|
||||
if (builder.isFeasible(false)) {
|
||||
if (const GRState *state = PrevState->assume(V, false))
|
||||
if (const ProgramState *state = PrevState->assume(V, false))
|
||||
builder.generateNode(MarkBranch(state, Term, false), false);
|
||||
else
|
||||
builder.markInfeasible(false);
|
||||
|
@ -1023,7 +1023,7 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
|
|||
/// nodes by processing the 'effects' of a computed goto jump.
|
||||
void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) {
|
||||
|
||||
const GRState *state = builder.getState();
|
||||
const ProgramState *state = builder.getState();
|
||||
SVal V = state->getSVal(builder.getTarget());
|
||||
|
||||
// Three possibilities:
|
||||
|
@ -1072,7 +1072,7 @@ void ExprEngine::VisitGuardedExpr(const Expr *Ex, const Expr *L,
|
|||
assert(Ex == currentStmt &&
|
||||
Pred->getLocationContext()->getCFG()->isBlkExpr(Ex));
|
||||
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
SVal X = state->getSVal(Ex);
|
||||
|
||||
assert (X.isUndef());
|
||||
|
@ -1097,7 +1097,7 @@ void ExprEngine::processEndOfFunction(EndOfFunctionNodeBuilder& builder) {
|
|||
/// nodes by processing the 'effects' of a switch statement.
|
||||
void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
|
||||
typedef SwitchNodeBuilder::iterator iterator;
|
||||
const GRState *state = builder.getState();
|
||||
const ProgramState *state = builder.getState();
|
||||
const Expr *CondE = builder.getCondition();
|
||||
SVal CondV_untested = state->getSVal(CondE);
|
||||
|
||||
|
@ -1110,7 +1110,7 @@ void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
|
|||
}
|
||||
DefinedOrUnknownSVal CondV = cast<DefinedOrUnknownSVal>(CondV_untested);
|
||||
|
||||
const GRState *DefaultSt = state;
|
||||
const ProgramState *DefaultSt = state;
|
||||
|
||||
iterator I = builder.begin(), EI = builder.end();
|
||||
bool defaultIsFeasible = I == EI;
|
||||
|
@ -1155,7 +1155,7 @@ void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
|
|||
CondV, CaseVal);
|
||||
|
||||
// Now "assume" that the case matches.
|
||||
if (const GRState *stateNew = state->assume(Res, true)) {
|
||||
if (const ProgramState *stateNew = state->assume(Res, true)) {
|
||||
builder.generateCaseStmtNode(I, stateNew);
|
||||
|
||||
// If CondV evaluates to a constant, then we know that this
|
||||
|
@ -1168,7 +1168,7 @@ void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
|
|||
// Now "assume" that the case doesn't match. Add this state
|
||||
// to the default state (if it is feasible).
|
||||
if (DefaultSt) {
|
||||
if (const GRState *stateNew = DefaultSt->assume(Res, false)) {
|
||||
if (const ProgramState *stateNew = DefaultSt->assume(Res, false)) {
|
||||
defaultIsFeasible = true;
|
||||
DefaultSt = stateNew;
|
||||
}
|
||||
|
@ -1209,12 +1209,12 @@ void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
|
|||
}
|
||||
|
||||
void ExprEngine::processCallEnter(CallEnterNodeBuilder &B) {
|
||||
const GRState *state = B.getState()->enterStackFrame(B.getCalleeContext());
|
||||
const ProgramState *state = B.getState()->enterStackFrame(B.getCalleeContext());
|
||||
B.generateNode(state);
|
||||
}
|
||||
|
||||
void ExprEngine::processCallExit(CallExitNodeBuilder &B) {
|
||||
const GRState *state = B.getState();
|
||||
const ProgramState *state = B.getState();
|
||||
const ExplodedNode *Pred = B.getPredecessor();
|
||||
const StackFrameContext *calleeCtx =
|
||||
cast<StackFrameContext>(Pred->getLocationContext());
|
||||
|
@ -1254,7 +1254,7 @@ void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred,
|
|||
|
||||
assert(B==currentStmt && Pred->getLocationContext()->getCFG()->isBlkExpr(B));
|
||||
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
SVal X = state->getSVal(B);
|
||||
assert(X.isUndef());
|
||||
|
||||
|
@ -1278,11 +1278,11 @@ void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred,
|
|||
// value later when necessary. We don't have the machinery in place for
|
||||
// this right now, and since most logical expressions are used for branches,
|
||||
// the payoff is not likely to be large. Instead, we do eager evaluation.
|
||||
if (const GRState *newState = state->assume(XD, true))
|
||||
if (const ProgramState *newState = state->assume(XD, true))
|
||||
MakeNode(Dst, B, Pred,
|
||||
newState->BindExpr(B, svalBuilder.makeIntVal(1U, B->getType())));
|
||||
|
||||
if (const GRState *newState = state->assume(XD, false))
|
||||
if (const ProgramState *newState = state->assume(XD, false))
|
||||
MakeNode(Dst, B, Pred,
|
||||
newState->BindExpr(B, svalBuilder.makeIntVal(0U, B->getType())));
|
||||
}
|
||||
|
@ -1319,7 +1319,7 @@ void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
|
|||
void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
|
||||
ExplodedNode *Pred,
|
||||
ExplodedNodeSet &Dst) {
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
|
||||
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
|
||||
assert(Ex->isLValue());
|
||||
|
@ -1368,7 +1368,7 @@ void ExprEngine::VisitLvalArraySubscriptExpr(const ArraySubscriptExpr *A,
|
|||
|
||||
for (ExplodedNodeSet::iterator it = checkerPreStmt.begin(),
|
||||
ei = checkerPreStmt.end(); it != ei; ++it) {
|
||||
const GRState *state = (*it)->getState();
|
||||
const ProgramState *state = (*it)->getState();
|
||||
SVal V = state->getLValue(A->getType(), state->getSVal(Idx),
|
||||
state->getSVal(Base));
|
||||
assert(A->isLValue());
|
||||
|
@ -1385,7 +1385,7 @@ void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
|
|||
return;
|
||||
|
||||
Expr *baseExpr = M->getBase()->IgnoreParens();
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
SVal baseExprVal = state->getSVal(baseExpr);
|
||||
if (isa<nonloc::LazyCompoundVal>(baseExprVal) ||
|
||||
isa<nonloc::CompoundVal>(baseExprVal) ||
|
||||
|
@ -1412,7 +1412,7 @@ void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
|
|||
/// evalBind - Handle the semantics of binding a value to a specific location.
|
||||
/// This method is used by evalStore and (soon) VisitDeclStmt, and others.
|
||||
void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
|
||||
ExplodedNode *Pred, const GRState *state,
|
||||
ExplodedNode *Pred, const ProgramState *state,
|
||||
SVal location, SVal Val, bool atDeclInit) {
|
||||
|
||||
|
||||
|
@ -1428,7 +1428,7 @@ void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
|
|||
if (Pred != *I)
|
||||
state = (*I)->getState();
|
||||
|
||||
const GRState *newState = 0;
|
||||
const ProgramState *newState = 0;
|
||||
|
||||
if (atDeclInit) {
|
||||
const VarRegion *VR =
|
||||
|
@ -1475,7 +1475,7 @@ void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
|
|||
void ExprEngine::evalStore(ExplodedNodeSet &Dst, const Expr *AssignE,
|
||||
const Expr *LocationE,
|
||||
ExplodedNode *Pred,
|
||||
const GRState *state, SVal location, SVal Val,
|
||||
const ProgramState *state, SVal location, SVal Val,
|
||||
const ProgramPointTag *tag) {
|
||||
|
||||
assert(Builder && "StmtNodeBuilder must be defined.");
|
||||
|
@ -1509,7 +1509,7 @@ void ExprEngine::evalStore(ExplodedNodeSet &Dst, const Expr *AssignE,
|
|||
|
||||
void ExprEngine::evalLoad(ExplodedNodeSet &Dst, const Expr *Ex,
|
||||
ExplodedNode *Pred,
|
||||
const GRState *state, SVal location,
|
||||
const ProgramState *state, SVal location,
|
||||
const ProgramPointTag *tag, QualType LoadTy) {
|
||||
assert(!isa<NonLoc>(location) && "location cannot be a NonLoc.");
|
||||
|
||||
|
@ -1548,7 +1548,7 @@ void ExprEngine::evalLoad(ExplodedNodeSet &Dst, const Expr *Ex,
|
|||
|
||||
void ExprEngine::evalLoadCommon(ExplodedNodeSet &Dst, const Expr *Ex,
|
||||
ExplodedNode *Pred,
|
||||
const GRState *state, SVal location,
|
||||
const ProgramState *state, SVal location,
|
||||
const ProgramPointTag *tag, QualType LoadTy) {
|
||||
|
||||
// Evaluate the location (checks for bad dereferences).
|
||||
|
@ -1584,7 +1584,7 @@ void ExprEngine::evalLoadCommon(ExplodedNodeSet &Dst, const Expr *Ex,
|
|||
|
||||
void ExprEngine::evalLocation(ExplodedNodeSet &Dst, const Stmt *S,
|
||||
ExplodedNode *Pred,
|
||||
const GRState *state, SVal location,
|
||||
const ProgramState *state, SVal location,
|
||||
const ProgramPointTag *tag, bool isLoad) {
|
||||
// Early checks for performance reason.
|
||||
if (location.isUnknown()) {
|
||||
|
@ -1626,7 +1626,7 @@ bool ExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE,
|
|||
// cases as well.
|
||||
|
||||
#if 0
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
SVal L = state->getSVal(Callee);
|
||||
|
||||
|
@ -1721,7 +1721,7 @@ void ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred,
|
|||
|
||||
// Dispatch to transfer function logic to handle the call itself.
|
||||
const Expr *Callee = CE->getCallee()->IgnoreParens();
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
SVal L = state->getSVal(Callee);
|
||||
Eng.getTF().evalCall(Dst, Eng, Builder, CE, L, Pred);
|
||||
|
||||
|
@ -1778,11 +1778,11 @@ void ExprEngine::evalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
|
|||
continue;
|
||||
}
|
||||
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
SVal V = state->getSVal(Ex);
|
||||
if (nonloc::SymExprVal *SEV = dyn_cast<nonloc::SymExprVal>(&V)) {
|
||||
// First assume that the condition is true.
|
||||
if (const GRState *stateTrue = state->assume(*SEV, true)) {
|
||||
if (const ProgramState *stateTrue = state->assume(*SEV, true)) {
|
||||
stateTrue = stateTrue->BindExpr(Ex,
|
||||
svalBuilder.makeIntVal(1U, Ex->getType()));
|
||||
Dst.Add(Builder->generateNode(PostStmtCustom(Ex,
|
||||
|
@ -1791,7 +1791,7 @@ void ExprEngine::evalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
|
|||
}
|
||||
|
||||
// Next, assume that the condition is false.
|
||||
if (const GRState *stateFalse = state->assume(*SEV, false)) {
|
||||
if (const ProgramState *stateFalse = state->assume(*SEV, false)) {
|
||||
stateFalse = stateFalse->BindExpr(Ex,
|
||||
svalBuilder.makeIntVal(0U, Ex->getType()));
|
||||
Dst.Add(Builder->generateNode(PostStmtCustom(Ex, &EagerlyAssumeTag,
|
||||
|
@ -1822,7 +1822,7 @@ void ExprEngine::VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *Ex,
|
|||
ExplodedNode *Pred,
|
||||
ExplodedNodeSet &Dst) {
|
||||
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
SVal baseVal = state->getSVal(Ex->getBase());
|
||||
SVal location = state->getLValue(Ex->getDecl(), baseVal);
|
||||
|
||||
|
@ -1867,7 +1867,7 @@ void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
|
|||
// result in state splitting.
|
||||
|
||||
const Stmt *elem = S->getElement();
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
SVal elementV;
|
||||
|
||||
if (const DeclStmt *DS = dyn_cast<DeclStmt>(elem)) {
|
||||
|
@ -1888,15 +1888,15 @@ void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
|
|||
for (ExplodedNodeSet::iterator NI = dstLocation.begin(),
|
||||
NE = dstLocation.end(); NI!=NE; ++NI) {
|
||||
Pred = *NI;
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
|
||||
// Handle the case where the container still has elements.
|
||||
SVal TrueV = svalBuilder.makeTruthVal(1);
|
||||
const GRState *hasElems = state->BindExpr(S, TrueV);
|
||||
const ProgramState *hasElems = state->BindExpr(S, TrueV);
|
||||
|
||||
// Handle the case where the container has no elements.
|
||||
SVal FalseV = svalBuilder.makeTruthVal(0);
|
||||
const GRState *noElems = state->BindExpr(S, FalseV);
|
||||
const ProgramState *noElems = state->BindExpr(S, FalseV);
|
||||
|
||||
if (loc::MemRegionVal *MV = dyn_cast<loc::MemRegionVal>(&elementV))
|
||||
if (const TypedValueRegion *R =
|
||||
|
@ -1947,13 +1947,13 @@ void ExprEngine::VisitObjCMessage(const ObjCMessage &msg,
|
|||
SaveOr OldHasGen(Builder->hasGeneratedNode);
|
||||
|
||||
if (const Expr *Receiver = msg.getInstanceReceiver()) {
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
SVal recVal = state->getSVal(Receiver);
|
||||
if (!recVal.isUndef()) {
|
||||
// Bifurcate the state into nil and non-nil ones.
|
||||
DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal);
|
||||
|
||||
const GRState *notNilState, *nilState;
|
||||
const ProgramState *notNilState, *nilState;
|
||||
llvm::tie(notNilState, nilState) = state->assume(receiverVal);
|
||||
|
||||
// There are three cases: can be nil or non-nil, must be nil, must be
|
||||
|
@ -2053,7 +2053,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
|
|||
for (ExplodedNodeSet::iterator I = dstPreStmt.begin(), E = dstPreStmt.end();
|
||||
I!=E; ++I) {
|
||||
ExplodedNode *subExprNode = *I;
|
||||
const GRState *state = subExprNode->getState();
|
||||
const ProgramState *state = subExprNode->getState();
|
||||
evalLoad(Dst, CastE, subExprNode, state, state->getSVal(Ex));
|
||||
}
|
||||
return;
|
||||
|
@ -2088,7 +2088,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
|
|||
case CK_NoOp:
|
||||
case CK_FunctionToPointerDecay: {
|
||||
// Copy the SVal of Ex to CastE.
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
SVal V = state->getSVal(Ex);
|
||||
state = state->BindExpr(CastE, V);
|
||||
MakeNode(Dst, CastE, Pred, state);
|
||||
|
@ -2122,7 +2122,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
|
|||
case CK_AnyPointerToBlockPointerCast:
|
||||
case CK_ObjCObjectLValueCast: {
|
||||
// Delegate to SValBuilder to process.
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
SVal V = state->getSVal(Ex);
|
||||
V = svalBuilder.evalCast(V, T, ExTy);
|
||||
state = state->BindExpr(CastE, V);
|
||||
|
@ -2132,7 +2132,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
|
|||
case CK_DerivedToBase:
|
||||
case CK_UncheckedDerivedToBase: {
|
||||
// For DerivedToBase cast, delegate to the store manager.
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
SVal val = state->getSVal(Ex);
|
||||
val = getStoreManager().evalDerivedToBase(val, T);
|
||||
state = state->BindExpr(CastE, val);
|
||||
|
@ -2159,7 +2159,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
|
|||
svalBuilder.getConjuredSymbolVal(NULL, CastE, resultType,
|
||||
Builder->getCurrentBlockCount());
|
||||
|
||||
const GRState *state = Pred->getState()->BindExpr(CastE, result);
|
||||
const ProgramState *state = Pred->getState()->BindExpr(CastE, result);
|
||||
MakeNode(Dst, CastE, Pred, state);
|
||||
continue;
|
||||
}
|
||||
|
@ -2173,7 +2173,7 @@ void ExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL,
|
|||
const InitListExpr *ILE
|
||||
= cast<InitListExpr>(CL->getInitializer()->IgnoreParens());
|
||||
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
SVal ILV = state->getSVal(ILE);
|
||||
|
||||
const LocationContext *LC = Pred->getLocationContext();
|
||||
|
@ -2209,7 +2209,7 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
|
|||
I!=E; ++I)
|
||||
{
|
||||
ExplodedNode *N = *I;
|
||||
const GRState *state = N->getState();
|
||||
const ProgramState *state = N->getState();
|
||||
|
||||
// Decls without InitExpr are not initialized explicitly.
|
||||
const LocationContext *LC = N->getLocationContext();
|
||||
|
@ -2246,7 +2246,7 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
|
|||
void ExprEngine::VisitInitListExpr(const InitListExpr *IE, ExplodedNode *Pred,
|
||||
ExplodedNodeSet &Dst) {
|
||||
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
QualType T = getContext().getCanonicalType(IE->getType());
|
||||
unsigned NumInitElements = IE->getNumInits();
|
||||
|
||||
|
@ -2302,7 +2302,7 @@ void ExprEngine::VisitUnaryExprOrTypeTraitExpr(
|
|||
// Get the size by getting the extent of the sub-expression.
|
||||
// First, visit the sub-expression to find its region.
|
||||
const Expr *Arg = Ex->getArgumentExpr();
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
const MemRegion *MR = state->getSVal(Arg).getAsRegion();
|
||||
|
||||
// If the subexpression can't be resolved to a region, we don't know
|
||||
|
@ -2377,7 +2377,7 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
|
|||
|
||||
// For all other types, UO_Real is an identity operation.
|
||||
assert (U->getType() == Ex->getType());
|
||||
const GRState *state = (*I)->getState();
|
||||
const ProgramState *state = (*I)->getState();
|
||||
MakeNode(Dst, U, *I, state->BindExpr(U, state->getSVal(Ex)));
|
||||
}
|
||||
|
||||
|
@ -2399,7 +2399,7 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
|
|||
}
|
||||
|
||||
// For all other types, UO_Imag returns 0.
|
||||
const GRState *state = (*I)->getState();
|
||||
const ProgramState *state = (*I)->getState();
|
||||
SVal X = svalBuilder.makeZeroVal(Ex->getType());
|
||||
MakeNode(Dst, U, *I, state->BindExpr(U, X));
|
||||
}
|
||||
|
@ -2424,7 +2424,7 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
|
|||
Visit(Ex, Pred, Tmp);
|
||||
|
||||
for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
|
||||
const GRState *state = (*I)->getState();
|
||||
const ProgramState *state = (*I)->getState();
|
||||
MakeNode(Dst, U, *I, state->BindExpr(U, state->getSVal(Ex)));
|
||||
}
|
||||
|
||||
|
@ -2440,7 +2440,7 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
|
|||
Visit(Ex, Pred, Tmp);
|
||||
|
||||
for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
|
||||
const GRState *state = (*I)->getState();
|
||||
const ProgramState *state = (*I)->getState();
|
||||
|
||||
// Get the value of the subexpression.
|
||||
SVal V = state->getSVal(Ex);
|
||||
|
@ -2515,7 +2515,7 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
|
|||
|
||||
for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I) {
|
||||
|
||||
const GRState *state = (*I)->getState();
|
||||
const ProgramState *state = (*I)->getState();
|
||||
SVal loc = state->getSVal(Ex);
|
||||
|
||||
// Perform a load.
|
||||
|
@ -2626,7 +2626,7 @@ void ExprEngine::VisitAsmStmtHelperInputs(const AsmStmt *A,
|
|||
// which interprets the inline asm and stores proper results in the
|
||||
// outputs.
|
||||
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
|
||||
for (AsmStmt::const_outputs_iterator OI = A->begin_outputs(),
|
||||
OE = A->end_outputs(); OI != OE; ++OI) {
|
||||
|
@ -2659,7 +2659,7 @@ void ExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred,
|
|||
// processCallExit to bind the return value to the call expr.
|
||||
{
|
||||
static SimpleProgramPointTag tag("ExprEngine: ReturnStmt");
|
||||
const GRState *state = Pred->getState();
|
||||
const ProgramState *state = Pred->getState();
|
||||
state = state->set<ReturnExpr>(RetE);
|
||||
Pred = Builder->generateNode(RetE, state, Pred, &tag);
|
||||
}
|
||||
|
@ -2721,7 +2721,7 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
|
|||
for (ExplodedNodeSet::iterator I2=CheckedSet.begin(), E2=CheckedSet.end();
|
||||
I2 != E2; ++I2) {
|
||||
|
||||
const GRState *state = (*I2)->getState();
|
||||
const ProgramState *state = (*I2)->getState();
|
||||
SVal RightV = state->getSVal(RHS);
|
||||
|
||||
BinaryOperator::Opcode Op = B->getOpcode();
|
||||
|
@ -3025,7 +3025,7 @@ struct DOTGraphTraits<ExplodedNode*> :
|
|||
}
|
||||
}
|
||||
|
||||
const GRState *state = N->getState();
|
||||
const ProgramState *state = N->getState();
|
||||
Out << "\\|StateID: " << (void*) state
|
||||
<< " NodeID: " << (void*) N << "\\|";
|
||||
state->printDOT(Out, *N->getLocationContext()->getCFG());
|
||||
|
|
|
@ -1,662 +0,0 @@
|
|||
//= GRState.cpp - Path-Sensitive "State" for tracking values -----*- C++ -*--=//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements GRState and GRStateManager.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Analysis/CFG.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace ento;
|
||||
|
||||
// Give the vtable for ConstraintManager somewhere to live.
|
||||
// FIXME: Move this elsewhere.
|
||||
ConstraintManager::~ConstraintManager() {}
|
||||
|
||||
GRState::GRState(GRStateManager *mgr, const Environment& env,
|
||||
StoreRef st, GenericDataMap gdm)
|
||||
: stateMgr(mgr),
|
||||
Env(env),
|
||||
store(st.getStore()),
|
||||
GDM(gdm),
|
||||
refCount(0) {
|
||||
stateMgr->getStoreManager().incrementReferenceCount(store);
|
||||
}
|
||||
|
||||
GRState::GRState(const GRState &RHS)
|
||||
: llvm::FoldingSetNode(),
|
||||
stateMgr(RHS.stateMgr),
|
||||
Env(RHS.Env),
|
||||
store(RHS.store),
|
||||
GDM(RHS.GDM),
|
||||
refCount(0) {
|
||||
stateMgr->getStoreManager().incrementReferenceCount(store);
|
||||
}
|
||||
|
||||
GRState::~GRState() {
|
||||
if (store)
|
||||
stateMgr->getStoreManager().decrementReferenceCount(store);
|
||||
}
|
||||
|
||||
GRStateManager::~GRStateManager() {
|
||||
for (std::vector<GRState::Printer*>::iterator I=Printers.begin(),
|
||||
E=Printers.end(); I!=E; ++I)
|
||||
delete *I;
|
||||
|
||||
for (GDMContextsTy::iterator I=GDMContexts.begin(), E=GDMContexts.end();
|
||||
I!=E; ++I)
|
||||
I->second.second(I->second.first);
|
||||
}
|
||||
|
||||
const GRState*
|
||||
GRStateManager::removeDeadBindings(const GRState *state,
|
||||
const StackFrameContext *LCtx,
|
||||
SymbolReaper& SymReaper) {
|
||||
|
||||
// This code essentially performs a "mark-and-sweep" of the VariableBindings.
|
||||
// The roots are any Block-level exprs and Decls that our liveness algorithm
|
||||
// tells us are live. We then see what Decls they may reference, and keep
|
||||
// those around. This code more than likely can be made faster, and the
|
||||
// frequency of which this method is called should be experimented with
|
||||
// for optimum performance.
|
||||
GRState NewState = *state;
|
||||
|
||||
NewState.Env = EnvMgr.removeDeadBindings(NewState.Env, SymReaper, state);
|
||||
|
||||
// Clean up the store.
|
||||
StoreRef newStore = StoreMgr->removeDeadBindings(NewState.getStore(), LCtx,
|
||||
SymReaper);
|
||||
NewState.setStore(newStore);
|
||||
SymReaper.setReapedStore(newStore);
|
||||
|
||||
return getPersistentState(NewState);
|
||||
}
|
||||
|
||||
const GRState *GRStateManager::MarshalState(const GRState *state,
|
||||
const StackFrameContext *InitLoc) {
|
||||
// make up an empty state for now.
|
||||
GRState State(this,
|
||||
EnvMgr.getInitialEnvironment(),
|
||||
StoreMgr->getInitialStore(InitLoc),
|
||||
GDMFactory.getEmptyMap());
|
||||
|
||||
return getPersistentState(State);
|
||||
}
|
||||
|
||||
const GRState *GRState::bindCompoundLiteral(const CompoundLiteralExpr *CL,
|
||||
const LocationContext *LC,
|
||||
SVal V) const {
|
||||
const StoreRef &newStore =
|
||||
getStateManager().StoreMgr->BindCompoundLiteral(getStore(), CL, LC, V);
|
||||
return makeWithStore(newStore);
|
||||
}
|
||||
|
||||
const GRState *GRState::bindDecl(const VarRegion* VR, SVal IVal) const {
|
||||
const StoreRef &newStore =
|
||||
getStateManager().StoreMgr->BindDecl(getStore(), VR, IVal);
|
||||
return makeWithStore(newStore);
|
||||
}
|
||||
|
||||
const GRState *GRState::bindDeclWithNoInit(const VarRegion* VR) const {
|
||||
const StoreRef &newStore =
|
||||
getStateManager().StoreMgr->BindDeclWithNoInit(getStore(), VR);
|
||||
return makeWithStore(newStore);
|
||||
}
|
||||
|
||||
const GRState *GRState::bindLoc(Loc LV, SVal V) const {
|
||||
GRStateManager &Mgr = getStateManager();
|
||||
const GRState *newState = makeWithStore(Mgr.StoreMgr->Bind(getStore(),
|
||||
LV, V));
|
||||
const MemRegion *MR = LV.getAsRegion();
|
||||
if (MR && Mgr.getOwningEngine())
|
||||
return Mgr.getOwningEngine()->processRegionChange(newState, MR);
|
||||
|
||||
return newState;
|
||||
}
|
||||
|
||||
const GRState *GRState::bindDefault(SVal loc, SVal V) const {
|
||||
GRStateManager &Mgr = getStateManager();
|
||||
const MemRegion *R = cast<loc::MemRegionVal>(loc).getRegion();
|
||||
const StoreRef &newStore = Mgr.StoreMgr->BindDefault(getStore(), R, V);
|
||||
const GRState *new_state = makeWithStore(newStore);
|
||||
return Mgr.getOwningEngine() ?
|
||||
Mgr.getOwningEngine()->processRegionChange(new_state, R) :
|
||||
new_state;
|
||||
}
|
||||
|
||||
const GRState *GRState::invalidateRegions(const MemRegion * const *Begin,
|
||||
const MemRegion * const *End,
|
||||
const Expr *E, unsigned Count,
|
||||
StoreManager::InvalidatedSymbols *IS,
|
||||
bool invalidateGlobals) const {
|
||||
if (!IS) {
|
||||
StoreManager::InvalidatedSymbols invalidated;
|
||||
return invalidateRegionsImpl(Begin, End, E, Count,
|
||||
invalidated, invalidateGlobals);
|
||||
}
|
||||
return invalidateRegionsImpl(Begin, End, E, Count, *IS, invalidateGlobals);
|
||||
}
|
||||
|
||||
const GRState *
|
||||
GRState::invalidateRegionsImpl(const MemRegion * const *Begin,
|
||||
const MemRegion * const *End,
|
||||
const Expr *E, unsigned Count,
|
||||
StoreManager::InvalidatedSymbols &IS,
|
||||
bool invalidateGlobals) const {
|
||||
GRStateManager &Mgr = getStateManager();
|
||||
SubEngine* Eng = Mgr.getOwningEngine();
|
||||
|
||||
if (Eng && Eng->wantsRegionChangeUpdate(this)) {
|
||||
StoreManager::InvalidatedRegions Regions;
|
||||
const StoreRef &newStore
|
||||
= Mgr.StoreMgr->invalidateRegions(getStore(), Begin, End, E, Count, IS,
|
||||
invalidateGlobals, &Regions);
|
||||
const GRState *newState = makeWithStore(newStore);
|
||||
return Eng->processRegionChanges(newState, &IS,
|
||||
&Regions.front(),
|
||||
&Regions.back()+1);
|
||||
}
|
||||
|
||||
const StoreRef &newStore =
|
||||
Mgr.StoreMgr->invalidateRegions(getStore(), Begin, End, E, Count, IS,
|
||||
invalidateGlobals, NULL);
|
||||
return makeWithStore(newStore);
|
||||
}
|
||||
|
||||
const GRState *GRState::unbindLoc(Loc LV) const {
|
||||
assert(!isa<loc::MemRegionVal>(LV) && "Use invalidateRegion instead.");
|
||||
|
||||
Store OldStore = getStore();
|
||||
const StoreRef &newStore = getStateManager().StoreMgr->Remove(OldStore, LV);
|
||||
|
||||
if (newStore.getStore() == OldStore)
|
||||
return this;
|
||||
|
||||
return makeWithStore(newStore);
|
||||
}
|
||||
|
||||
const GRState *GRState::enterStackFrame(const StackFrameContext *frame) const {
|
||||
const StoreRef &new_store =
|
||||
getStateManager().StoreMgr->enterStackFrame(this, frame);
|
||||
return makeWithStore(new_store);
|
||||
}
|
||||
|
||||
SVal GRState::getSValAsScalarOrLoc(const MemRegion *R) const {
|
||||
// We only want to do fetches from regions that we can actually bind
|
||||
// values. For example, SymbolicRegions of type 'id<...>' cannot
|
||||
// have direct bindings (but their can be bindings on their subregions).
|
||||
if (!R->isBoundable())
|
||||
return UnknownVal();
|
||||
|
||||
if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
|
||||
QualType T = TR->getValueType();
|
||||
if (Loc::isLocType(T) || T->isIntegerType())
|
||||
return getSVal(R);
|
||||
}
|
||||
|
||||
return UnknownVal();
|
||||
}
|
||||
|
||||
SVal GRState::getSVal(Loc location, QualType T) const {
|
||||
SVal V = getRawSVal(cast<Loc>(location), T);
|
||||
|
||||
// If 'V' is a symbolic value that is *perfectly* constrained to
|
||||
// be a constant value, use that value instead to lessen the burden
|
||||
// on later analysis stages (so we have less symbolic values to reason
|
||||
// about).
|
||||
if (!T.isNull()) {
|
||||
if (SymbolRef sym = V.getAsSymbol()) {
|
||||
if (const llvm::APSInt *Int = getSymVal(sym)) {
|
||||
// FIXME: Because we don't correctly model (yet) sign-extension
|
||||
// and truncation of symbolic values, we need to convert
|
||||
// the integer value to the correct signedness and bitwidth.
|
||||
//
|
||||
// This shows up in the following:
|
||||
//
|
||||
// char foo();
|
||||
// unsigned x = foo();
|
||||
// if (x == 54)
|
||||
// ...
|
||||
//
|
||||
// The symbolic value stored to 'x' is actually the conjured
|
||||
// symbol for the call to foo(); the type of that symbol is 'char',
|
||||
// not unsigned.
|
||||
const llvm::APSInt &NewV = getBasicVals().Convert(T, *Int);
|
||||
|
||||
if (isa<Loc>(V))
|
||||
return loc::ConcreteInt(NewV);
|
||||
else
|
||||
return nonloc::ConcreteInt(NewV);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return V;
|
||||
}
|
||||
|
||||
const GRState *GRState::BindExpr(const Stmt *S, SVal V, bool Invalidate) const{
|
||||
Environment NewEnv = getStateManager().EnvMgr.bindExpr(Env, S, V,
|
||||
Invalidate);
|
||||
if (NewEnv == Env)
|
||||
return this;
|
||||
|
||||
GRState NewSt = *this;
|
||||
NewSt.Env = NewEnv;
|
||||
return getStateManager().getPersistentState(NewSt);
|
||||
}
|
||||
|
||||
const GRState *GRState::bindExprAndLocation(const Stmt *S, SVal location,
|
||||
SVal V) const {
|
||||
Environment NewEnv =
|
||||
getStateManager().EnvMgr.bindExprAndLocation(Env, S, location, V);
|
||||
|
||||
if (NewEnv == Env)
|
||||
return this;
|
||||
|
||||
GRState NewSt = *this;
|
||||
NewSt.Env = NewEnv;
|
||||
return getStateManager().getPersistentState(NewSt);
|
||||
}
|
||||
|
||||
const GRState *GRState::assumeInBound(DefinedOrUnknownSVal Idx,
|
||||
DefinedOrUnknownSVal UpperBound,
|
||||
bool Assumption) const {
|
||||
if (Idx.isUnknown() || UpperBound.isUnknown())
|
||||
return this;
|
||||
|
||||
// Build an expression for 0 <= Idx < UpperBound.
|
||||
// This is the same as Idx + MIN < UpperBound + MIN, if overflow is allowed.
|
||||
// FIXME: This should probably be part of SValBuilder.
|
||||
GRStateManager &SM = getStateManager();
|
||||
SValBuilder &svalBuilder = SM.getSValBuilder();
|
||||
ASTContext &Ctx = svalBuilder.getContext();
|
||||
|
||||
// Get the offset: the minimum value of the array index type.
|
||||
BasicValueFactory &BVF = svalBuilder.getBasicValueFactory();
|
||||
// FIXME: This should be using ValueManager::ArrayindexTy...somehow.
|
||||
QualType indexTy = Ctx.IntTy;
|
||||
nonloc::ConcreteInt Min(BVF.getMinValue(indexTy));
|
||||
|
||||
// Adjust the index.
|
||||
SVal newIdx = svalBuilder.evalBinOpNN(this, BO_Add,
|
||||
cast<NonLoc>(Idx), Min, indexTy);
|
||||
if (newIdx.isUnknownOrUndef())
|
||||
return this;
|
||||
|
||||
// Adjust the upper bound.
|
||||
SVal newBound =
|
||||
svalBuilder.evalBinOpNN(this, BO_Add, cast<NonLoc>(UpperBound),
|
||||
Min, indexTy);
|
||||
|
||||
if (newBound.isUnknownOrUndef())
|
||||
return this;
|
||||
|
||||
// Build the actual comparison.
|
||||
SVal inBound = svalBuilder.evalBinOpNN(this, BO_LT,
|
||||
cast<NonLoc>(newIdx), cast<NonLoc>(newBound),
|
||||
Ctx.IntTy);
|
||||
if (inBound.isUnknownOrUndef())
|
||||
return this;
|
||||
|
||||
// Finally, let the constraint manager take care of it.
|
||||
ConstraintManager &CM = SM.getConstraintManager();
|
||||
return CM.assume(this, cast<DefinedSVal>(inBound), Assumption);
|
||||
}
|
||||
|
||||
const GRState *GRStateManager::getInitialState(const LocationContext *InitLoc) {
|
||||
GRState State(this,
|
||||
EnvMgr.getInitialEnvironment(),
|
||||
StoreMgr->getInitialStore(InitLoc),
|
||||
GDMFactory.getEmptyMap());
|
||||
|
||||
return getPersistentState(State);
|
||||
}
|
||||
|
||||
void GRStateManager::recycleUnusedStates() {
|
||||
for (std::vector<GRState*>::iterator i = recentlyAllocatedStates.begin(),
|
||||
e = recentlyAllocatedStates.end(); i != e; ++i) {
|
||||
GRState *state = *i;
|
||||
if (state->referencedByExplodedNode())
|
||||
continue;
|
||||
StateSet.RemoveNode(state);
|
||||
freeStates.push_back(state);
|
||||
state->~GRState();
|
||||
}
|
||||
recentlyAllocatedStates.clear();
|
||||
}
|
||||
|
||||
const GRState *GRStateManager::getPersistentStateWithGDM(
|
||||
const GRState *FromState,
|
||||
const GRState *GDMState) {
|
||||
GRState NewState = *FromState;
|
||||
NewState.GDM = GDMState->GDM;
|
||||
return getPersistentState(NewState);
|
||||
}
|
||||
|
||||
const GRState *GRStateManager::getPersistentState(GRState &State) {
|
||||
|
||||
llvm::FoldingSetNodeID ID;
|
||||
State.Profile(ID);
|
||||
void *InsertPos;
|
||||
|
||||
if (GRState *I = StateSet.FindNodeOrInsertPos(ID, InsertPos))
|
||||
return I;
|
||||
|
||||
GRState *newState = 0;
|
||||
if (!freeStates.empty()) {
|
||||
newState = freeStates.back();
|
||||
freeStates.pop_back();
|
||||
}
|
||||
else {
|
||||
newState = (GRState*) Alloc.Allocate<GRState>();
|
||||
}
|
||||
new (newState) GRState(State);
|
||||
StateSet.InsertNode(newState, InsertPos);
|
||||
recentlyAllocatedStates.push_back(newState);
|
||||
return newState;
|
||||
}
|
||||
|
||||
const GRState *GRState::makeWithStore(const StoreRef &store) const {
|
||||
GRState NewSt = *this;
|
||||
NewSt.setStore(store);
|
||||
return getStateManager().getPersistentState(NewSt);
|
||||
}
|
||||
|
||||
void GRState::setStore(const StoreRef &newStore) {
|
||||
Store newStoreStore = newStore.getStore();
|
||||
if (newStoreStore)
|
||||
stateMgr->getStoreManager().incrementReferenceCount(newStoreStore);
|
||||
if (store)
|
||||
stateMgr->getStoreManager().decrementReferenceCount(store);
|
||||
store = newStoreStore;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// State pretty-printing.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static bool IsEnvLoc(const Stmt *S) {
|
||||
// FIXME: This is a layering violation. Should be in environment.
|
||||
return (bool) (((uintptr_t) S) & 0x1);
|
||||
}
|
||||
|
||||
void GRState::print(raw_ostream &Out, CFG &C, const char* nl,
|
||||
const char* sep) const {
|
||||
// Print the store.
|
||||
GRStateManager &Mgr = getStateManager();
|
||||
Mgr.getStoreManager().print(getStore(), Out, nl, sep);
|
||||
|
||||
// Print Subexpression bindings.
|
||||
bool isFirst = true;
|
||||
|
||||
// FIXME: All environment printing should be moved inside Environment.
|
||||
for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) {
|
||||
if (C.isBlkExpr(I.getKey()) || IsEnvLoc(I.getKey()))
|
||||
continue;
|
||||
|
||||
if (isFirst) {
|
||||
Out << nl << nl << "Sub-Expressions:" << nl;
|
||||
isFirst = false;
|
||||
}
|
||||
else { Out << nl; }
|
||||
|
||||
Out << " (" << (void*) I.getKey() << ") ";
|
||||
LangOptions LO; // FIXME.
|
||||
I.getKey()->printPretty(Out, 0, PrintingPolicy(LO));
|
||||
Out << " : " << I.getData();
|
||||
}
|
||||
|
||||
// Print block-expression bindings.
|
||||
isFirst = true;
|
||||
|
||||
for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) {
|
||||
if (!C.isBlkExpr(I.getKey()))
|
||||
continue;
|
||||
|
||||
if (isFirst) {
|
||||
Out << nl << nl << "Block-level Expressions:" << nl;
|
||||
isFirst = false;
|
||||
}
|
||||
else { Out << nl; }
|
||||
|
||||
Out << " (" << (void*) I.getKey() << ") ";
|
||||
LangOptions LO; // FIXME.
|
||||
I.getKey()->printPretty(Out, 0, PrintingPolicy(LO));
|
||||
Out << " : " << I.getData();
|
||||
}
|
||||
|
||||
// Print locations.
|
||||
isFirst = true;
|
||||
|
||||
for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) {
|
||||
if (!IsEnvLoc(I.getKey()))
|
||||
continue;
|
||||
|
||||
if (isFirst) {
|
||||
Out << nl << nl << "Load/store locations:" << nl;
|
||||
isFirst = false;
|
||||
}
|
||||
else { Out << nl; }
|
||||
|
||||
const Stmt *S = (Stmt*) (((uintptr_t) I.getKey()) & ((uintptr_t) ~0x1));
|
||||
|
||||
Out << " (" << (void*) S << ") ";
|
||||
LangOptions LO; // FIXME.
|
||||
S->printPretty(Out, 0, PrintingPolicy(LO));
|
||||
Out << " : " << I.getData();
|
||||
}
|
||||
|
||||
Mgr.getConstraintManager().print(this, Out, nl, sep);
|
||||
|
||||
// Print checker-specific data.
|
||||
for (std::vector<Printer*>::iterator I = Mgr.Printers.begin(),
|
||||
E = Mgr.Printers.end(); I != E; ++I) {
|
||||
(*I)->Print(Out, this, nl, sep);
|
||||
}
|
||||
}
|
||||
|
||||
void GRState::printDOT(raw_ostream &Out, CFG &C) const {
|
||||
print(Out, C, "\\l", "\\|");
|
||||
}
|
||||
|
||||
void GRState::printStdErr(CFG &C) const {
|
||||
print(llvm::errs(), C);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Generic Data Map.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void *const* GRState::FindGDM(void *K) const {
|
||||
return GDM.lookup(K);
|
||||
}
|
||||
|
||||
void*
|
||||
GRStateManager::FindGDMContext(void *K,
|
||||
void *(*CreateContext)(llvm::BumpPtrAllocator&),
|
||||
void (*DeleteContext)(void*)) {
|
||||
|
||||
std::pair<void*, void (*)(void*)>& p = GDMContexts[K];
|
||||
if (!p.first) {
|
||||
p.first = CreateContext(Alloc);
|
||||
p.second = DeleteContext;
|
||||
}
|
||||
|
||||
return p.first;
|
||||
}
|
||||
|
||||
const GRState *GRStateManager::addGDM(const GRState *St, void *Key, void *Data){
|
||||
GRState::GenericDataMap M1 = St->getGDM();
|
||||
GRState::GenericDataMap M2 = GDMFactory.add(M1, Key, Data);
|
||||
|
||||
if (M1 == M2)
|
||||
return St;
|
||||
|
||||
GRState NewSt = *St;
|
||||
NewSt.GDM = M2;
|
||||
return getPersistentState(NewSt);
|
||||
}
|
||||
|
||||
const GRState *GRStateManager::removeGDM(const GRState *state, void *Key) {
|
||||
GRState::GenericDataMap OldM = state->getGDM();
|
||||
GRState::GenericDataMap NewM = GDMFactory.remove(OldM, Key);
|
||||
|
||||
if (NewM == OldM)
|
||||
return state;
|
||||
|
||||
GRState NewState = *state;
|
||||
NewState.GDM = NewM;
|
||||
return getPersistentState(NewState);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Utility.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
class ScanReachableSymbols : public SubRegionMap::Visitor {
|
||||
typedef llvm::DenseMap<const void*, unsigned> VisitedItems;
|
||||
|
||||
VisitedItems visited;
|
||||
const GRState *state;
|
||||
SymbolVisitor &visitor;
|
||||
llvm::OwningPtr<SubRegionMap> SRM;
|
||||
public:
|
||||
|
||||
ScanReachableSymbols(const GRState *st, SymbolVisitor& v)
|
||||
: state(st), visitor(v) {}
|
||||
|
||||
bool scan(nonloc::CompoundVal val);
|
||||
bool scan(SVal val);
|
||||
bool scan(const MemRegion *R);
|
||||
bool scan(const SymExpr *sym);
|
||||
|
||||
// From SubRegionMap::Visitor.
|
||||
bool Visit(const MemRegion* Parent, const MemRegion* SubRegion) {
|
||||
return scan(SubRegion);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
bool ScanReachableSymbols::scan(nonloc::CompoundVal val) {
|
||||
for (nonloc::CompoundVal::iterator I=val.begin(), E=val.end(); I!=E; ++I)
|
||||
if (!scan(*I))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScanReachableSymbols::scan(const SymExpr *sym) {
|
||||
unsigned &isVisited = visited[sym];
|
||||
if (isVisited)
|
||||
return true;
|
||||
isVisited = 1;
|
||||
|
||||
if (const SymbolData *sData = dyn_cast<SymbolData>(sym))
|
||||
if (!visitor.VisitSymbol(sData))
|
||||
return false;
|
||||
|
||||
switch (sym->getKind()) {
|
||||
case SymExpr::RegionValueKind:
|
||||
case SymExpr::ConjuredKind:
|
||||
case SymExpr::DerivedKind:
|
||||
case SymExpr::ExtentKind:
|
||||
case SymExpr::MetadataKind:
|
||||
break;
|
||||
case SymExpr::SymIntKind:
|
||||
return scan(cast<SymIntExpr>(sym)->getLHS());
|
||||
case SymExpr::SymSymKind: {
|
||||
const SymSymExpr *x = cast<SymSymExpr>(sym);
|
||||
return scan(x->getLHS()) && scan(x->getRHS());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScanReachableSymbols::scan(SVal val) {
|
||||
if (loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(&val))
|
||||
return scan(X->getRegion());
|
||||
|
||||
if (nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(&val))
|
||||
return scan(X->getLoc());
|
||||
|
||||
if (SymbolRef Sym = val.getAsSymbol())
|
||||
return scan(Sym);
|
||||
|
||||
if (const SymExpr *Sym = val.getAsSymbolicExpression())
|
||||
return scan(Sym);
|
||||
|
||||
if (nonloc::CompoundVal *X = dyn_cast<nonloc::CompoundVal>(&val))
|
||||
return scan(*X);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScanReachableSymbols::scan(const MemRegion *R) {
|
||||
if (isa<MemSpaceRegion>(R))
|
||||
return true;
|
||||
|
||||
unsigned &isVisited = visited[R];
|
||||
if (isVisited)
|
||||
return true;
|
||||
isVisited = 1;
|
||||
|
||||
// If this is a symbolic region, visit the symbol for the region.
|
||||
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
|
||||
if (!visitor.VisitSymbol(SR->getSymbol()))
|
||||
return false;
|
||||
|
||||
// If this is a subregion, also visit the parent regions.
|
||||
if (const SubRegion *SR = dyn_cast<SubRegion>(R))
|
||||
if (!scan(SR->getSuperRegion()))
|
||||
return false;
|
||||
|
||||
// Now look at the binding to this region (if any).
|
||||
if (!scan(state->getSValAsScalarOrLoc(R)))
|
||||
return false;
|
||||
|
||||
// Now look at the subregions.
|
||||
if (!SRM.get())
|
||||
SRM.reset(state->getStateManager().getStoreManager().
|
||||
getSubRegionMap(state->getStore()));
|
||||
|
||||
return SRM->iterSubRegions(R, *this);
|
||||
}
|
||||
|
||||
bool GRState::scanReachableSymbols(SVal val, SymbolVisitor& visitor) const {
|
||||
ScanReachableSymbols S(this, visitor);
|
||||
return S.scan(val);
|
||||
}
|
||||
|
||||
bool GRState::scanReachableSymbols(const SVal *I, const SVal *E,
|
||||
SymbolVisitor &visitor) const {
|
||||
ScanReachableSymbols S(this, visitor);
|
||||
for ( ; I != E; ++I) {
|
||||
if (!S.scan(*I))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GRState::scanReachableSymbols(const MemRegion * const *I,
|
||||
const MemRegion * const *E,
|
||||
SymbolVisitor &visitor) const {
|
||||
ScanReachableSymbols S(this, visitor);
|
||||
for ( ; I != E; ++I) {
|
||||
if (!S.scan(*I))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
|
@ -8,13 +8,13 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines RangeConstraintManager, a class that tracks simple
|
||||
// equality and inequality constraints on symbolic values of GRState.
|
||||
// equality and inequality constraints on symbolic values of ProgramState.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "SimpleConstraintManager.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
|
@ -196,8 +196,8 @@ typedef llvm::ImmutableMap<SymbolRef,RangeSet> ConstraintRangeTy;
|
|||
namespace clang {
|
||||
namespace ento {
|
||||
template<>
|
||||
struct GRStateTrait<ConstraintRange>
|
||||
: public GRStatePartialTrait<ConstraintRangeTy> {
|
||||
struct ProgramStateTrait<ConstraintRange>
|
||||
: public ProgramStatePartialTrait<ConstraintRangeTy> {
|
||||
static inline void *GDMIndex() { return &ConstraintRangeIndex; }
|
||||
};
|
||||
}
|
||||
|
@ -205,46 +205,46 @@ struct GRStateTrait<ConstraintRange>
|
|||
|
||||
namespace {
|
||||
class RangeConstraintManager : public SimpleConstraintManager{
|
||||
RangeSet GetRange(const GRState *state, SymbolRef sym);
|
||||
RangeSet GetRange(const ProgramState *state, SymbolRef sym);
|
||||
public:
|
||||
RangeConstraintManager(SubEngine &subengine)
|
||||
: SimpleConstraintManager(subengine) {}
|
||||
|
||||
const GRState *assumeSymNE(const GRState *state, SymbolRef sym,
|
||||
const ProgramState *assumeSymNE(const ProgramState *state, SymbolRef sym,
|
||||
const llvm::APSInt& Int,
|
||||
const llvm::APSInt& Adjustment);
|
||||
|
||||
const GRState *assumeSymEQ(const GRState *state, SymbolRef sym,
|
||||
const ProgramState *assumeSymEQ(const ProgramState *state, SymbolRef sym,
|
||||
const llvm::APSInt& Int,
|
||||
const llvm::APSInt& Adjustment);
|
||||
|
||||
const GRState *assumeSymLT(const GRState *state, SymbolRef sym,
|
||||
const ProgramState *assumeSymLT(const ProgramState *state, SymbolRef sym,
|
||||
const llvm::APSInt& Int,
|
||||
const llvm::APSInt& Adjustment);
|
||||
|
||||
const GRState *assumeSymGT(const GRState *state, SymbolRef sym,
|
||||
const ProgramState *assumeSymGT(const ProgramState *state, SymbolRef sym,
|
||||
const llvm::APSInt& Int,
|
||||
const llvm::APSInt& Adjustment);
|
||||
|
||||
const GRState *assumeSymGE(const GRState *state, SymbolRef sym,
|
||||
const ProgramState *assumeSymGE(const ProgramState *state, SymbolRef sym,
|
||||
const llvm::APSInt& Int,
|
||||
const llvm::APSInt& Adjustment);
|
||||
|
||||
const GRState *assumeSymLE(const GRState *state, SymbolRef sym,
|
||||
const ProgramState *assumeSymLE(const ProgramState *state, SymbolRef sym,
|
||||
const llvm::APSInt& Int,
|
||||
const llvm::APSInt& Adjustment);
|
||||
|
||||
const llvm::APSInt* getSymVal(const GRState *St, SymbolRef sym) const;
|
||||
const llvm::APSInt* getSymVal(const ProgramState *St, SymbolRef sym) const;
|
||||
|
||||
// FIXME: Refactor into SimpleConstraintManager?
|
||||
bool isEqual(const GRState *St, SymbolRef sym, const llvm::APSInt& V) const {
|
||||
bool isEqual(const ProgramState *St, SymbolRef sym, const llvm::APSInt& V) const {
|
||||
const llvm::APSInt *i = getSymVal(St, sym);
|
||||
return i ? *i == V : false;
|
||||
}
|
||||
|
||||
const GRState *removeDeadBindings(const GRState *St, SymbolReaper& SymReaper);
|
||||
const ProgramState *removeDeadBindings(const ProgramState *St, SymbolReaper& SymReaper);
|
||||
|
||||
void print(const GRState *St, raw_ostream &Out,
|
||||
void print(const ProgramState *St, raw_ostream &Out,
|
||||
const char* nl, const char *sep);
|
||||
|
||||
private:
|
||||
|
@ -253,12 +253,12 @@ private:
|
|||
|
||||
} // end anonymous namespace
|
||||
|
||||
ConstraintManager* ento::CreateRangeConstraintManager(GRStateManager&,
|
||||
ConstraintManager* ento::CreateRangeConstraintManager(ProgramStateManager&,
|
||||
SubEngine &subeng) {
|
||||
return new RangeConstraintManager(subeng);
|
||||
}
|
||||
|
||||
const llvm::APSInt* RangeConstraintManager::getSymVal(const GRState *St,
|
||||
const llvm::APSInt* RangeConstraintManager::getSymVal(const ProgramState *St,
|
||||
SymbolRef sym) const {
|
||||
const ConstraintRangeTy::data_type *T = St->get<ConstraintRange>(sym);
|
||||
return T ? T->getConcreteValue() : NULL;
|
||||
|
@ -266,8 +266,8 @@ const llvm::APSInt* RangeConstraintManager::getSymVal(const GRState *St,
|
|||
|
||||
/// Scan all symbols referenced by the constraints. If the symbol is not alive
|
||||
/// as marked in LSymbols, mark it as dead in DSymbols.
|
||||
const GRState*
|
||||
RangeConstraintManager::removeDeadBindings(const GRState *state,
|
||||
const ProgramState*
|
||||
RangeConstraintManager::removeDeadBindings(const ProgramState *state,
|
||||
SymbolReaper& SymReaper) {
|
||||
|
||||
ConstraintRangeTy CR = state->get<ConstraintRange>();
|
||||
|
@ -283,7 +283,7 @@ RangeConstraintManager::removeDeadBindings(const GRState *state,
|
|||
}
|
||||
|
||||
RangeSet
|
||||
RangeConstraintManager::GetRange(const GRState *state, SymbolRef sym) {
|
||||
RangeConstraintManager::GetRange(const ProgramState *state, SymbolRef sym) {
|
||||
if (ConstraintRangeTy::data_type* V = state->get<ConstraintRange>(sym))
|
||||
return *V;
|
||||
|
||||
|
@ -306,8 +306,8 @@ RangeConstraintManager::GetRange(const GRState *state, SymbolRef sym) {
|
|||
// As an example, the range [UINT_MAX-1, 3) contains five values: UINT_MAX-1,
|
||||
// UINT_MAX, 0, 1, and 2.
|
||||
|
||||
const GRState*
|
||||
RangeConstraintManager::assumeSymNE(const GRState *state, SymbolRef sym,
|
||||
const ProgramState*
|
||||
RangeConstraintManager::assumeSymNE(const ProgramState *state, SymbolRef sym,
|
||||
const llvm::APSInt& Int,
|
||||
const llvm::APSInt& Adjustment) {
|
||||
BasicValueFactory &BV = state->getBasicVals();
|
||||
|
@ -323,8 +323,8 @@ RangeConstraintManager::assumeSymNE(const GRState *state, SymbolRef sym,
|
|||
return New.isEmpty() ? NULL : state->set<ConstraintRange>(sym, New);
|
||||
}
|
||||
|
||||
const GRState*
|
||||
RangeConstraintManager::assumeSymEQ(const GRState *state, SymbolRef sym,
|
||||
const ProgramState*
|
||||
RangeConstraintManager::assumeSymEQ(const ProgramState *state, SymbolRef sym,
|
||||
const llvm::APSInt& Int,
|
||||
const llvm::APSInt& Adjustment) {
|
||||
// [Int-Adjustment, Int-Adjustment]
|
||||
|
@ -334,8 +334,8 @@ RangeConstraintManager::assumeSymEQ(const GRState *state, SymbolRef sym,
|
|||
return New.isEmpty() ? NULL : state->set<ConstraintRange>(sym, New);
|
||||
}
|
||||
|
||||
const GRState*
|
||||
RangeConstraintManager::assumeSymLT(const GRState *state, SymbolRef sym,
|
||||
const ProgramState*
|
||||
RangeConstraintManager::assumeSymLT(const ProgramState *state, SymbolRef sym,
|
||||
const llvm::APSInt& Int,
|
||||
const llvm::APSInt& Adjustment) {
|
||||
BasicValueFactory &BV = state->getBasicVals();
|
||||
|
@ -355,8 +355,8 @@ RangeConstraintManager::assumeSymLT(const GRState *state, SymbolRef sym,
|
|||
return New.isEmpty() ? NULL : state->set<ConstraintRange>(sym, New);
|
||||
}
|
||||
|
||||
const GRState*
|
||||
RangeConstraintManager::assumeSymGT(const GRState *state, SymbolRef sym,
|
||||
const ProgramState*
|
||||
RangeConstraintManager::assumeSymGT(const ProgramState *state, SymbolRef sym,
|
||||
const llvm::APSInt& Int,
|
||||
const llvm::APSInt& Adjustment) {
|
||||
BasicValueFactory &BV = state->getBasicVals();
|
||||
|
@ -376,8 +376,8 @@ RangeConstraintManager::assumeSymGT(const GRState *state, SymbolRef sym,
|
|||
return New.isEmpty() ? NULL : state->set<ConstraintRange>(sym, New);
|
||||
}
|
||||
|
||||
const GRState*
|
||||
RangeConstraintManager::assumeSymGE(const GRState *state, SymbolRef sym,
|
||||
const ProgramState*
|
||||
RangeConstraintManager::assumeSymGE(const ProgramState *state, SymbolRef sym,
|
||||
const llvm::APSInt& Int,
|
||||
const llvm::APSInt& Adjustment) {
|
||||
BasicValueFactory &BV = state->getBasicVals();
|
||||
|
@ -398,8 +398,8 @@ RangeConstraintManager::assumeSymGE(const GRState *state, SymbolRef sym,
|
|||
return New.isEmpty() ? NULL : state->set<ConstraintRange>(sym, New);
|
||||
}
|
||||
|
||||
const GRState*
|
||||
RangeConstraintManager::assumeSymLE(const GRState *state, SymbolRef sym,
|
||||
const ProgramState*
|
||||
RangeConstraintManager::assumeSymLE(const ProgramState *state, SymbolRef sym,
|
||||
const llvm::APSInt& Int,
|
||||
const llvm::APSInt& Adjustment) {
|
||||
BasicValueFactory &BV = state->getBasicVals();
|
||||
|
@ -424,7 +424,7 @@ RangeConstraintManager::assumeSymLE(const GRState *state, SymbolRef sym,
|
|||
// Pretty-printing.
|
||||
//===------------------------------------------------------------------------===/
|
||||
|
||||
void RangeConstraintManager::print(const GRState *St, raw_ostream &Out,
|
||||
void RangeConstraintManager::print(const ProgramState *St, raw_ostream &Out,
|
||||
const char* nl, const char *sep) {
|
||||
|
||||
ConstraintRangeTy Ranges = St->get<ConstraintRange>();
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
#include "clang/Analysis/Analyses/LiveVariables.h"
|
||||
#include "clang/Analysis/AnalysisContext.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
|
||||
#include "llvm/ADT/ImmutableList.h"
|
||||
#include "llvm/ADT/ImmutableMap.h"
|
||||
|
@ -196,7 +196,7 @@ class RegionStoreManager : public StoreManager {
|
|||
RegionBindings::Factory RBFactory;
|
||||
|
||||
public:
|
||||
RegionStoreManager(GRStateManager& mgr, const RegionStoreFeatures &f)
|
||||
RegionStoreManager(ProgramStateManager& mgr, const RegionStoreFeatures &f)
|
||||
: StoreManager(mgr),
|
||||
Features(f),
|
||||
RBFactory(mgr.getAllocator()) {}
|
||||
|
@ -376,7 +376,7 @@ public: // Part of public interface to class.
|
|||
StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx,
|
||||
SymbolReaper& SymReaper);
|
||||
|
||||
StoreRef enterStackFrame(const GRState *state,
|
||||
StoreRef enterStackFrame(const ProgramState *state,
|
||||
const StackFrameContext *frame);
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
|
@ -384,7 +384,7 @@ public: // Part of public interface to class.
|
|||
//===------------------------------------------------------------------===//
|
||||
|
||||
// FIXME: This method will soon be eliminated; see the note in Store.h.
|
||||
DefinedOrUnknownSVal getSizeInElements(const GRState *state,
|
||||
DefinedOrUnknownSVal getSizeInElements(const ProgramState *state,
|
||||
const MemRegion* R, QualType EleTy);
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
|
@ -419,12 +419,12 @@ public: // Part of public interface to class.
|
|||
// RegionStore creation.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
StoreManager *ento::CreateRegionStoreManager(GRStateManager& StMgr) {
|
||||
StoreManager *ento::CreateRegionStoreManager(ProgramStateManager& StMgr) {
|
||||
RegionStoreFeatures F = maximal_features_tag();
|
||||
return new RegionStoreManager(StMgr, F);
|
||||
}
|
||||
|
||||
StoreManager *ento::CreateFieldsOnlyRegionStoreManager(GRStateManager &StMgr) {
|
||||
StoreManager *ento::CreateFieldsOnlyRegionStoreManager(ProgramStateManager &StMgr) {
|
||||
RegionStoreFeatures F = minimal_features_tag();
|
||||
F.enableFields(true);
|
||||
return new RegionStoreManager(StMgr, F);
|
||||
|
@ -480,7 +480,7 @@ protected:
|
|||
const bool includeGlobals;
|
||||
|
||||
public:
|
||||
ClusterAnalysis(RegionStoreManager &rm, GRStateManager &StateMgr,
|
||||
ClusterAnalysis(RegionStoreManager &rm, ProgramStateManager &StateMgr,
|
||||
RegionBindings b, const bool includeGlobals)
|
||||
: RM(rm), Ctx(StateMgr.getContext()),
|
||||
svalBuilder(StateMgr.getSValBuilder()),
|
||||
|
@ -593,7 +593,7 @@ class invalidateRegionsWorker : public ClusterAnalysis<invalidateRegionsWorker>
|
|||
StoreManager::InvalidatedRegions *Regions;
|
||||
public:
|
||||
invalidateRegionsWorker(RegionStoreManager &rm,
|
||||
GRStateManager &stateMgr,
|
||||
ProgramStateManager &stateMgr,
|
||||
RegionBindings b,
|
||||
const Expr *ex, unsigned count,
|
||||
StoreManager::InvalidatedSymbols &is,
|
||||
|
@ -766,7 +766,7 @@ StoreRef RegionStoreManager::invalidateRegions(Store store,
|
|||
// Extents for regions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state,
|
||||
DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const ProgramState *state,
|
||||
const MemRegion *R,
|
||||
QualType EleTy) {
|
||||
SVal Size = cast<SubRegion>(R)->getExtent(svalBuilder);
|
||||
|
@ -1644,7 +1644,7 @@ class removeDeadBindingsWorker :
|
|||
const StackFrameContext *CurrentLCtx;
|
||||
|
||||
public:
|
||||
removeDeadBindingsWorker(RegionStoreManager &rm, GRStateManager &stateMgr,
|
||||
removeDeadBindingsWorker(RegionStoreManager &rm, ProgramStateManager &stateMgr,
|
||||
RegionBindings b, SymbolReaper &symReaper,
|
||||
const StackFrameContext *LCtx)
|
||||
: ClusterAnalysis<removeDeadBindingsWorker>(rm, stateMgr, b,
|
||||
|
@ -1819,7 +1819,7 @@ StoreRef RegionStoreManager::removeDeadBindings(Store store,
|
|||
}
|
||||
|
||||
|
||||
StoreRef RegionStoreManager::enterStackFrame(const GRState *state,
|
||||
StoreRef RegionStoreManager::enterStackFrame(const ProgramState *state,
|
||||
const StackFrameContext *frame) {
|
||||
FunctionDecl const *FD = cast<FunctionDecl>(frame->getDecl());
|
||||
FunctionDecl::param_const_iterator PI = FD->param_begin(),
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
|
||||
|
||||
using namespace clang;
|
||||
|
@ -162,7 +162,7 @@ DefinedSVal SValBuilder::getBlockPointer(const BlockDecl *block,
|
|||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
SVal SValBuilder::evalBinOp(const GRState *state, BinaryOperator::Opcode op,
|
||||
SVal SValBuilder::evalBinOp(const ProgramState *state, BinaryOperator::Opcode op,
|
||||
SVal lhs, SVal rhs, QualType type) {
|
||||
|
||||
if (lhs.isUndef() || rhs.isUndef())
|
||||
|
@ -190,7 +190,7 @@ SVal SValBuilder::evalBinOp(const GRState *state, BinaryOperator::Opcode op,
|
|||
return evalBinOpNN(state, op, cast<NonLoc>(lhs), cast<NonLoc>(rhs), type);
|
||||
}
|
||||
|
||||
DefinedOrUnknownSVal SValBuilder::evalEQ(const GRState *state,
|
||||
DefinedOrUnknownSVal SValBuilder::evalEQ(const ProgramState *state,
|
||||
DefinedOrUnknownSVal lhs,
|
||||
DefinedOrUnknownSVal rhs) {
|
||||
return cast<DefinedOrUnknownSVal>(evalBinOp(state, BO_EQ, lhs, rhs,
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
||||
#include "clang/AST/ExprObjC.h"
|
||||
#include "clang/Basic/IdentifierTable.h"
|
||||
using namespace clang;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#include "SimpleConstraintManager.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
|
@ -56,7 +56,7 @@ bool SimpleConstraintManager::canReasonAbout(SVal X) const {
|
|||
return true;
|
||||
}
|
||||
|
||||
const GRState *SimpleConstraintManager::assume(const GRState *state,
|
||||
const ProgramState *SimpleConstraintManager::assume(const ProgramState *state,
|
||||
DefinedSVal Cond,
|
||||
bool Assumption) {
|
||||
if (isa<NonLoc>(Cond))
|
||||
|
@ -65,13 +65,13 @@ const GRState *SimpleConstraintManager::assume(const GRState *state,
|
|||
return assume(state, cast<Loc>(Cond), Assumption);
|
||||
}
|
||||
|
||||
const GRState *SimpleConstraintManager::assume(const GRState *state, Loc cond,
|
||||
const ProgramState *SimpleConstraintManager::assume(const ProgramState *state, Loc cond,
|
||||
bool assumption) {
|
||||
state = assumeAux(state, cond, assumption);
|
||||
return SU.processAssume(state, cond, assumption);
|
||||
}
|
||||
|
||||
const GRState *SimpleConstraintManager::assumeAux(const GRState *state,
|
||||
const ProgramState *SimpleConstraintManager::assumeAux(const ProgramState *state,
|
||||
Loc Cond, bool Assumption) {
|
||||
|
||||
BasicValueFactory &BasicVals = state->getBasicVals();
|
||||
|
@ -113,7 +113,7 @@ const GRState *SimpleConstraintManager::assumeAux(const GRState *state,
|
|||
} // end switch
|
||||
}
|
||||
|
||||
const GRState *SimpleConstraintManager::assume(const GRState *state,
|
||||
const ProgramState *SimpleConstraintManager::assume(const ProgramState *state,
|
||||
NonLoc cond,
|
||||
bool assumption) {
|
||||
state = assumeAux(state, cond, assumption);
|
||||
|
@ -135,7 +135,7 @@ static BinaryOperator::Opcode NegateComparison(BinaryOperator::Opcode op) {
|
|||
}
|
||||
}
|
||||
|
||||
const GRState *SimpleConstraintManager::assumeAux(const GRState *state,
|
||||
const ProgramState *SimpleConstraintManager::assumeAux(const ProgramState *state,
|
||||
NonLoc Cond,
|
||||
bool Assumption) {
|
||||
|
||||
|
@ -202,7 +202,7 @@ const GRState *SimpleConstraintManager::assumeAux(const GRState *state,
|
|||
} // end switch
|
||||
}
|
||||
|
||||
const GRState *SimpleConstraintManager::assumeSymRel(const GRState *state,
|
||||
const ProgramState *SimpleConstraintManager::assumeSymRel(const ProgramState *state,
|
||||
const SymExpr *LHS,
|
||||
BinaryOperator::Opcode op,
|
||||
const llvm::APSInt& Int) {
|
||||
|
@ -256,7 +256,7 @@ const GRState *SimpleConstraintManager::assumeSymRel(const GRState *state,
|
|||
// be of the same type as the symbol, which is not always correct. Really the
|
||||
// comparisons should be performed using the Int's type, then mapped back to
|
||||
// the symbol's range of values.
|
||||
GRStateManager &StateMgr = state->getStateManager();
|
||||
ProgramStateManager &StateMgr = state->getStateManager();
|
||||
ASTContext &Ctx = StateMgr.getContext();
|
||||
|
||||
QualType T = Sym->getType(Ctx);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#define LLVM_CLANG_GR_SIMPLE_CONSTRAINT_MANAGER_H
|
||||
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
|
@ -33,14 +33,14 @@ public:
|
|||
|
||||
bool canReasonAbout(SVal X) const;
|
||||
|
||||
const GRState *assume(const GRState *state, DefinedSVal Cond,
|
||||
const ProgramState *assume(const ProgramState *state, DefinedSVal Cond,
|
||||
bool Assumption);
|
||||
|
||||
const GRState *assume(const GRState *state, Loc Cond, bool Assumption);
|
||||
const ProgramState *assume(const ProgramState *state, Loc Cond, bool Assumption);
|
||||
|
||||
const GRState *assume(const GRState *state, NonLoc Cond, bool Assumption);
|
||||
const ProgramState *assume(const ProgramState *state, NonLoc Cond, bool Assumption);
|
||||
|
||||
const GRState *assumeSymRel(const GRState *state,
|
||||
const ProgramState *assumeSymRel(const ProgramState *state,
|
||||
const SymExpr *LHS,
|
||||
BinaryOperator::Opcode op,
|
||||
const llvm::APSInt& Int);
|
||||
|
@ -53,27 +53,27 @@ protected:
|
|||
|
||||
// Each of these is of the form "$sym+Adj <> V", where "<>" is the comparison
|
||||
// operation for the method being invoked.
|
||||
virtual const GRState *assumeSymNE(const GRState *state, SymbolRef sym,
|
||||
virtual const ProgramState *assumeSymNE(const ProgramState *state, SymbolRef sym,
|
||||
const llvm::APSInt& V,
|
||||
const llvm::APSInt& Adjustment) = 0;
|
||||
|
||||
virtual const GRState *assumeSymEQ(const GRState *state, SymbolRef sym,
|
||||
virtual const ProgramState *assumeSymEQ(const ProgramState *state, SymbolRef sym,
|
||||
const llvm::APSInt& V,
|
||||
const llvm::APSInt& Adjustment) = 0;
|
||||
|
||||
virtual const GRState *assumeSymLT(const GRState *state, SymbolRef sym,
|
||||
virtual const ProgramState *assumeSymLT(const ProgramState *state, SymbolRef sym,
|
||||
const llvm::APSInt& V,
|
||||
const llvm::APSInt& Adjustment) = 0;
|
||||
|
||||
virtual const GRState *assumeSymGT(const GRState *state, SymbolRef sym,
|
||||
virtual const ProgramState *assumeSymGT(const ProgramState *state, SymbolRef sym,
|
||||
const llvm::APSInt& V,
|
||||
const llvm::APSInt& Adjustment) = 0;
|
||||
|
||||
virtual const GRState *assumeSymLE(const GRState *state, SymbolRef sym,
|
||||
virtual const ProgramState *assumeSymLE(const ProgramState *state, SymbolRef sym,
|
||||
const llvm::APSInt& V,
|
||||
const llvm::APSInt& Adjustment) = 0;
|
||||
|
||||
virtual const GRState *assumeSymGE(const GRState *state, SymbolRef sym,
|
||||
virtual const ProgramState *assumeSymGE(const ProgramState *state, SymbolRef sym,
|
||||
const llvm::APSInt& V,
|
||||
const llvm::APSInt& Adjustment) = 0;
|
||||
|
||||
|
@ -81,9 +81,9 @@ protected:
|
|||
// Internal implementation.
|
||||
//===------------------------------------------------------------------===//
|
||||
|
||||
const GRState *assumeAux(const GRState *state, Loc Cond,bool Assumption);
|
||||
const ProgramState *assumeAux(const ProgramState *state, Loc Cond,bool Assumption);
|
||||
|
||||
const GRState *assumeAux(const GRState *state, NonLoc Cond, bool Assumption);
|
||||
const ProgramState *assumeAux(const ProgramState *state, NonLoc Cond, bool Assumption);
|
||||
};
|
||||
|
||||
} // end GR namespace
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace ento;
|
||||
|
@ -25,22 +25,22 @@ protected:
|
|||
|
||||
public:
|
||||
SimpleSValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context,
|
||||
GRStateManager &stateMgr)
|
||||
ProgramStateManager &stateMgr)
|
||||
: SValBuilder(alloc, context, stateMgr) {}
|
||||
virtual ~SimpleSValBuilder() {}
|
||||
|
||||
virtual SVal evalMinus(NonLoc val);
|
||||
virtual SVal evalComplement(NonLoc val);
|
||||
virtual SVal evalBinOpNN(const GRState *state, BinaryOperator::Opcode op,
|
||||
virtual SVal evalBinOpNN(const ProgramState *state, BinaryOperator::Opcode op,
|
||||
NonLoc lhs, NonLoc rhs, QualType resultTy);
|
||||
virtual SVal evalBinOpLL(const GRState *state, BinaryOperator::Opcode op,
|
||||
virtual SVal evalBinOpLL(const ProgramState *state, BinaryOperator::Opcode op,
|
||||
Loc lhs, Loc rhs, QualType resultTy);
|
||||
virtual SVal evalBinOpLN(const GRState *state, BinaryOperator::Opcode op,
|
||||
virtual SVal evalBinOpLN(const ProgramState *state, BinaryOperator::Opcode op,
|
||||
Loc lhs, NonLoc rhs, QualType resultTy);
|
||||
|
||||
/// getKnownValue - evaluates a given SVal. If the SVal has only one possible
|
||||
/// (integer) value, that value is returned. Otherwise, returns NULL.
|
||||
virtual const llvm::APSInt *getKnownValue(const GRState *state, SVal V);
|
||||
virtual const llvm::APSInt *getKnownValue(const ProgramState *state, SVal V);
|
||||
|
||||
SVal MakeSymIntVal(const SymExpr *LHS, BinaryOperator::Opcode op,
|
||||
const llvm::APSInt &RHS, QualType resultTy);
|
||||
|
@ -49,7 +49,7 @@ public:
|
|||
|
||||
SValBuilder *ento::createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc,
|
||||
ASTContext &context,
|
||||
GRStateManager &stateMgr) {
|
||||
ProgramStateManager &stateMgr) {
|
||||
return new SimpleSValBuilder(alloc, context, stateMgr);
|
||||
}
|
||||
|
||||
|
@ -270,7 +270,7 @@ SVal SimpleSValBuilder::MakeSymIntVal(const SymExpr *LHS,
|
|||
return makeNonLoc(LHS, op, RHS, resultTy);
|
||||
}
|
||||
|
||||
SVal SimpleSValBuilder::evalBinOpNN(const GRState *state,
|
||||
SVal SimpleSValBuilder::evalBinOpNN(const ProgramState *state,
|
||||
BinaryOperator::Opcode op,
|
||||
NonLoc lhs, NonLoc rhs,
|
||||
QualType resultTy) {
|
||||
|
@ -539,7 +539,7 @@ SVal SimpleSValBuilder::evalBinOpNN(const GRState *state,
|
|||
}
|
||||
|
||||
// FIXME: all this logic will change if/when we have MemRegion::getLocation().
|
||||
SVal SimpleSValBuilder::evalBinOpLL(const GRState *state,
|
||||
SVal SimpleSValBuilder::evalBinOpLL(const ProgramState *state,
|
||||
BinaryOperator::Opcode op,
|
||||
Loc lhs, Loc rhs,
|
||||
QualType resultTy) {
|
||||
|
@ -836,7 +836,7 @@ SVal SimpleSValBuilder::evalBinOpLL(const GRState *state,
|
|||
}
|
||||
}
|
||||
|
||||
SVal SimpleSValBuilder::evalBinOpLN(const GRState *state,
|
||||
SVal SimpleSValBuilder::evalBinOpLN(const ProgramState *state,
|
||||
BinaryOperator::Opcode op,
|
||||
Loc lhs, NonLoc rhs, QualType resultTy) {
|
||||
|
||||
|
@ -930,7 +930,7 @@ SVal SimpleSValBuilder::evalBinOpLN(const GRState *state,
|
|||
return UnknownVal();
|
||||
}
|
||||
|
||||
const llvm::APSInt *SimpleSValBuilder::getKnownValue(const GRState *state,
|
||||
const llvm::APSInt *SimpleSValBuilder::getKnownValue(const ProgramState *state,
|
||||
SVal V) {
|
||||
if (V.isUnknownOrUndef())
|
||||
return NULL;
|
||||
|
|
|
@ -12,17 +12,17 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
||||
#include "clang/AST/CharUnits.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace ento;
|
||||
|
||||
StoreManager::StoreManager(GRStateManager &stateMgr)
|
||||
StoreManager::StoreManager(ProgramStateManager &stateMgr)
|
||||
: svalBuilder(stateMgr.getSValBuilder()), StateMgr(stateMgr),
|
||||
MRMgr(svalBuilder.getRegionManager()), Ctx(stateMgr.getContext()) {}
|
||||
|
||||
StoreRef StoreManager::enterStackFrame(const GRState *state,
|
||||
StoreRef StoreManager::enterStackFrame(const ProgramState *state,
|
||||
const StackFrameContext *frame) {
|
||||
return StoreRef(state->getStore(), *this);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ The analyzer is inspired by several foundational research papers ([1],
|
|||
In a nutshell, the analyzer is basically a source code simulator that
|
||||
traces out possible paths of execution. The state of the program
|
||||
(values of variables and expressions) is encapsulated by the state
|
||||
(GRState). A location in the program is called a program point
|
||||
(ProgramState). A location in the program is called a program point
|
||||
(ProgramPoint), and the combination of state and program point is a
|
||||
node in an exploded graph (ExplodedGraph). The term "exploded" comes
|
||||
from exploding the control-flow edges in the control-flow graph (CFG).
|
||||
|
@ -39,7 +39,7 @@ then bifurcating the state: on the true branch the conditions of the
|
|||
branch are assumed to be true and on the false branch the conditions
|
||||
of the branch are assumed to be false. Such "assumptions" create
|
||||
constraints on the values of the program, and those constraints are
|
||||
recorded in the GRState object (and are manipulated by the
|
||||
recorded in the ProgramState object (and are manipulated by the
|
||||
ConstraintManager). If assuming the conditions of a branch would
|
||||
cause the constraints to be unsatisfiable, the branch is considered
|
||||
infeasible and that path is not taken. This is how we get
|
||||
|
@ -49,9 +49,9 @@ would get generated, the path "caches out" and we simply reuse the
|
|||
existing node. Thus the ExplodedGraph is not a DAG; it can contain
|
||||
cycles as paths loop back onto each other and cache out.
|
||||
|
||||
GRState and ExplodedNodes are basically immutable once created. Once
|
||||
one creates a GRState, you need to create a new one to get a new
|
||||
GRState. This immutability is key since the ExplodedGraph represents
|
||||
ProgramState and ExplodedNodes are basically immutable once created. Once
|
||||
one creates a ProgramState, you need to create a new one to get a new
|
||||
ProgramState. This immutability is key since the ExplodedGraph represents
|
||||
the behavior of the analyzed program from the entry point. To
|
||||
represent these efficiently, we use functional data structures (e.g.,
|
||||
ImmutableMaps) which share data between instances.
|
||||
|
@ -62,7 +62,7 @@ For example, the PreVisitCallExpr() method is called by GRExprEngine
|
|||
to tell the Checker that we are about to analyze a CallExpr, and the
|
||||
checker is asked to check for any preconditions that might not be
|
||||
satisfied. The checker can do nothing, or it can generate a new
|
||||
GRState and ExplodedNode which contains updated checker state. If it
|
||||
ProgramState and ExplodedNode which contains updated checker state. If it
|
||||
finds a bug, it can tell the BugReporter object about the bug,
|
||||
providing it an ExplodedNode which is the last node in the path that
|
||||
triggered the problem.
|
||||
|
|
Loading…
Reference in New Issue