Rename GRState to ProgramState, and cleanup some code formatting along the way.

llvm-svn: 137665
This commit is contained in:
Ted Kremenek 2011-08-15 22:09:50 +00:00
parent 8bc586e770
commit 001fd5b498
77 changed files with 1048 additions and 2528 deletions

View File

@ -186,7 +186,7 @@
1AC1A7E71299A285006FBC77 /* GRExprEngineExperimentalChecks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = GRExprEngineExperimentalChecks.cpp; sourceTree = "<group>"; tabWidth = 2; }; 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; }; 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; }; 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; }; 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; }; 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; }; 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; }; 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>"; }; 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; }; 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; }; 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; }; 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>"; }; 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; }; 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; }; 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; }; 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; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; BBA5AB681309C2FA000B38F1 /* ObjCMessage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjCMessage.cpp; sourceTree = "<group>"; };
@ -856,7 +856,7 @@
1AC1A7E71299A285006FBC77 /* GRExprEngineExperimentalChecks.cpp */, 1AC1A7E71299A285006FBC77 /* GRExprEngineExperimentalChecks.cpp */,
1AC1A7E81299A285006FBC77 /* GRExprEngineExperimentalChecks.h */, 1AC1A7E81299A285006FBC77 /* GRExprEngineExperimentalChecks.h */,
1AC1A7E91299A285006FBC77 /* GRExprEngineInternalChecks.h */, 1AC1A7E91299A285006FBC77 /* GRExprEngineInternalChecks.h */,
1AC1A7EA1299A285006FBC77 /* GRState.cpp */, 1AC1A7EA1299A285006FBC77 /* ProgramState.cpp */,
1AC1A7EB1299A285006FBC77 /* HTMLDiagnostics.cpp */, 1AC1A7EB1299A285006FBC77 /* HTMLDiagnostics.cpp */,
1AC1A7EC1299A285006FBC77 /* IdempotentOperationChecker.cpp */, 1AC1A7EC1299A285006FBC77 /* IdempotentOperationChecker.cpp */,
1AC1A7ED1299A285006FBC77 /* LLVMConventionsChecker.cpp */, 1AC1A7ED1299A285006FBC77 /* LLVMConventionsChecker.cpp */,
@ -1235,7 +1235,7 @@
BBA5AB611309C2FA000B38F1 /* Environment.cpp */, BBA5AB611309C2FA000B38F1 /* Environment.cpp */,
BBA5AB621309C2FA000B38F1 /* ExplodedGraph.cpp */, BBA5AB621309C2FA000B38F1 /* ExplodedGraph.cpp */,
BBA5AB631309C2FA000B38F1 /* FlatStore.cpp */, BBA5AB631309C2FA000B38F1 /* FlatStore.cpp */,
BBA5AB641309C2FA000B38F1 /* GRState.cpp */, BBA5AB641309C2FA000B38F1 /* ProgramState.cpp */,
BBA5AB651309C2FA000B38F1 /* HTMLDiagnostics.cpp */, BBA5AB651309C2FA000B38F1 /* HTMLDiagnostics.cpp */,
BBA5AB671309C2FA000B38F1 /* MemRegion.cpp */, BBA5AB671309C2FA000B38F1 /* MemRegion.cpp */,
BBA5AB681309C2FA000B38F1 /* ObjCMessage.cpp */, BBA5AB681309C2FA000B38F1 /* ObjCMessage.cpp */,
@ -1340,8 +1340,8 @@
DE41211F0D7F1BBE0080F80A /* GRBlockCounter.h */, DE41211F0D7F1BBE0080F80A /* GRBlockCounter.h */,
DE4121230D7F1BBE0080F80A /* GRCoreEngine.h */, DE4121230D7F1BBE0080F80A /* GRCoreEngine.h */,
DE4121210D7F1BBE0080F80A /* GRExprEngine.h */, DE4121210D7F1BBE0080F80A /* GRExprEngine.h */,
358F514F0E529A87007F2102 /* GRState.h */, 358F514F0E529A87007F2102 /* ProgramState.h */,
3553EB9A0E5F7089007D7359 /* GRStateTrait.h */, 3553EB9A0E5F7089007D7359 /* ProgramStateTrait.h */,
35F8D0CA0D9B7E8200D91C5E /* GRSimpleAPICheck.h */, 35F8D0CA0D9B7E8200D91C5E /* GRSimpleAPICheck.h */,
DE4121220D7F1BBE0080F80A /* GRTransferFuncs.h */, DE4121220D7F1BBE0080F80A /* GRTransferFuncs.h */,
DE41211D0D7F1BBE0080F80A /* GRWorkList.h */, DE41211D0D7F1BBE0080F80A /* GRWorkList.h */,

View File

@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// //
// This file defines BugReporter, a utility class for generating // 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 #define LLVM_CLANG_GR_BUGREPORTER
#include "clang/Basic/SourceLocation.h" #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/FoldingSet.h"
#include "llvm/ADT/ImmutableList.h" #include "llvm/ADT/ImmutableList.h"
#include "llvm/ADT/ImmutableSet.h" #include "llvm/ADT/ImmutableSet.h"
@ -40,7 +40,7 @@ class ExplodedGraph;
class BugReporter; class BugReporter;
class BugReporterContext; class BugReporterContext;
class ExprEngine; class ExprEngine;
class GRState; class ProgramState;
class BugType; class BugType;
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -392,7 +392,7 @@ public:
/// getStateManager - Return the state manager used by the analysis /// getStateManager - Return the state manager used by the analysis
/// engine. /// engine.
GRStateManager &getStateManager(); ProgramStateManager &getStateManager();
virtual void GeneratePathDiagnostic(PathDiagnostic &pathDiagnostic, virtual void GeneratePathDiagnostic(PathDiagnostic &pathDiagnostic,
SmallVectorImpl<BugReport*> &bugReports); SmallVectorImpl<BugReport*> &bugReports);
@ -442,7 +442,7 @@ public:
return BR.isNotable(Sym); return BR.isNotable(Sym);
} }
GRStateManager& getStateManager() { ProgramStateManager& getStateManager() {
return BR.getStateManager(); return BR.getStateManager();
} }

View File

@ -228,7 +228,7 @@ public:
class LiveSymbols { class LiveSymbols {
template <typename CHECKER> template <typename CHECKER>
static void _checkLiveSymbols(void *checker, const GRState *state, static void _checkLiveSymbols(void *checker, const ProgramState *state,
SymbolReaper &SR) { SymbolReaper &SR) {
((const CHECKER *)checker)->checkLiveSymbols(state, SR); ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
} }
@ -258,15 +258,18 @@ public:
class RegionChanges { class RegionChanges {
template <typename CHECKER> template <typename CHECKER>
static const GRState *_checkRegionChanges(void *checker, const GRState *state, static const ProgramState *
const StoreManager::InvalidatedSymbols *invalidated, _checkRegionChanges(void *checker,
const MemRegion * const *Begin, const ProgramState *state,
const MemRegion * const *End) { const StoreManager::InvalidatedSymbols *invalidated,
const MemRegion * const *Begin,
const MemRegion * const *End) {
return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated, return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
Begin, End); Begin, End);
} }
template <typename CHECKER> 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); return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state);
} }
@ -301,8 +304,10 @@ namespace eval {
class Assume { class Assume {
template <typename CHECKER> template <typename CHECKER>
static const GRState *_evalAssume(void *checker, const GRState *state, static const ProgramState *_evalAssume(void *checker,
const SVal &cond, bool assumption) { const ProgramState *state,
const SVal &cond,
bool assumption) {
return ((const CHECKER *)checker)->evalAssume(state, cond, assumption); return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
} }

View File

@ -37,7 +37,7 @@ namespace ento {
class ExplodedNode; class ExplodedNode;
class ExplodedNodeSet; class ExplodedNodeSet;
class ExplodedGraph; class ExplodedGraph;
class GRState; class ProgramState;
class EndOfFunctionNodeBuilder; class EndOfFunctionNodeBuilder;
class BranchNodeBuilder; class BranchNodeBuilder;
class MemRegion; class MemRegion;
@ -225,7 +225,7 @@ public:
BranchNodeBuilder &B, ExprEngine &Eng); BranchNodeBuilder &B, ExprEngine &Eng);
/// \brief Run checkers for live symbols. /// \brief Run checkers for live symbols.
void runCheckersForLiveSymbols(const GRState *state, void runCheckersForLiveSymbols(const ProgramState *state,
SymbolReaper &SymReaper); SymbolReaper &SymReaper);
/// \brief Run checkers for dead symbols. /// \brief Run checkers for dead symbols.
@ -235,17 +235,17 @@ public:
ExprEngine &Eng); ExprEngine &Eng);
/// \brief True if at least one checker wants to check region changes. /// \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. /// \brief Run checkers for region changes.
const GRState * const ProgramState *
runCheckersForRegionChanges(const GRState *state, runCheckersForRegionChanges(const ProgramState *state,
const StoreManager::InvalidatedSymbols *invalidated, const StoreManager::InvalidatedSymbols *invalidated,
const MemRegion * const *Begin, const MemRegion * const *Begin,
const MemRegion * const *End); const MemRegion * const *End);
/// \brief Run checkers for handling assumptions on symbolic values. /// \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); SVal Cond, bool Assumption);
/// \brief Run checkers for evaluating a call. /// \brief Run checkers for evaluating a call.
@ -301,18 +301,18 @@ public:
typedef CheckerFn<void (SymbolReaper &, CheckerContext &)> typedef CheckerFn<void (SymbolReaper &, CheckerContext &)>
CheckDeadSymbolsFunc; 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 StoreManager::InvalidatedSymbols *symbols,
const MemRegion * const *begin, const MemRegion * const *begin,
const MemRegion * const *end)> const MemRegion * const *end)>
CheckRegionChangesFunc; CheckRegionChangesFunc;
typedef CheckerFn<bool (const GRState *)> WantsRegionChangeUpdateFunc; typedef CheckerFn<bool (const ProgramState *)> WantsRegionChangeUpdateFunc;
typedef CheckerFn<const GRState * (const GRState *, typedef CheckerFn<const ProgramState * (const ProgramState *,
const SVal &cond, bool assumption)> const SVal &cond, bool assumption)>
EvalAssumeFunc; EvalAssumeFunc;
typedef CheckerFn<bool (const CallExpr *, CheckerContext &)> typedef CheckerFn<bool (const CallExpr *, CheckerContext &)>

View File

@ -27,7 +27,7 @@ namespace clang {
namespace ento { namespace ento {
class GRState; class ProgramState;
class CompoundValData : public llvm::FoldingSetNode { class CompoundValData : public llvm::FoldingSetNode {
QualType T; QualType T;

View File

@ -31,23 +31,32 @@ class CheckerContext {
const ProgramPointTag *checkerTag; const ProgramPointTag *checkerTag;
SaveAndRestore<ProgramPoint::Kind> OldPointKind; SaveAndRestore<ProgramPoint::Kind> OldPointKind;
SaveOr OldHasGen; SaveOr OldHasGen;
const GRState *ST; const ProgramState *ST;
const Stmt *statement; const Stmt *statement;
const unsigned size; const unsigned size;
public: public:
bool *respondsToCallback; bool *respondsToCallback;
public: public:
CheckerContext(ExplodedNodeSet &dst, StmtNodeBuilder &builder, CheckerContext(ExplodedNodeSet &dst,
ExprEngine &eng, ExplodedNode *pred, StmtNodeBuilder &builder,
const ProgramPointTag *tag, ProgramPoint::Kind K, ExprEngine &eng,
ExplodedNode *pred,
const ProgramPointTag *tag,
ProgramPoint::Kind K,
bool *respondsToCB = 0, bool *respondsToCB = 0,
const Stmt *stmt = 0, const GRState *st = 0) const Stmt *stmt = 0,
: Dst(dst), B(builder), Eng(eng), Pred(pred), const ProgramState *st = 0)
: Dst(dst),
B(builder),
Eng(eng),
Pred(pred),
OldSink(B.BuildSinks), OldSink(B.BuildSinks),
checkerTag(tag), checkerTag(tag),
OldPointKind(B.PointKind, K), OldPointKind(B.PointKind, K),
OldHasGen(B.hasGeneratedNode), OldHasGen(B.hasGeneratedNode),
ST(st), statement(stmt), size(Dst.size()), ST(st),
statement(stmt),
size(Dst.size()),
respondsToCallback(respondsToCB) {} respondsToCallback(respondsToCB) {}
~CheckerContext(); ~CheckerContext();
@ -71,7 +80,7 @@ public:
ExplodedNodeSet &getNodeSet() { return Dst; } ExplodedNodeSet &getNodeSet() { return Dst; }
StmtNodeBuilder &getNodeBuilder() { return B; } StmtNodeBuilder &getNodeBuilder() { return B; }
ExplodedNode *&getPredecessor() { return Pred; } 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; } const Stmt *getStmt() const { return statement; }
ASTContext &getASTContext() { ASTContext &getASTContext() {
@ -103,8 +112,10 @@ public:
return N; return N;
} }
ExplodedNode *generateNode(const Stmt *stmt, const GRState *state, ExplodedNode *generateNode(const Stmt *stmt,
bool autoTransition = true, const ProgramPointTag *tag = 0) { const ProgramState *state,
bool autoTransition = true,
const ProgramPointTag *tag = 0) {
assert(state); assert(state);
ExplodedNode *N = generateNodeImpl(stmt, state, false, ExplodedNode *N = generateNodeImpl(stmt, state, false,
tag ? tag : checkerTag); tag ? tag : checkerTag);
@ -113,7 +124,8 @@ public:
return N; return N;
} }
ExplodedNode *generateNode(const GRState *state, ExplodedNode *pred, ExplodedNode *generateNode(const ProgramState *state,
ExplodedNode *pred,
bool autoTransition = true) { bool autoTransition = true) {
assert(statement && "Only transitions with statements currently supported"); assert(statement && "Only transitions with statements currently supported");
ExplodedNode *N = generateNodeImpl(statement, state, pred, false); ExplodedNode *N = generateNodeImpl(statement, state, pred, false);
@ -122,7 +134,8 @@ public:
return N; return N;
} }
ExplodedNode *generateNode(const GRState *state, bool autoTransition = true, ExplodedNode *generateNode(const ProgramState *state,
bool autoTransition = true,
const ProgramPointTag *tag = 0) { const ProgramPointTag *tag = 0) {
assert(statement && "Only transitions with statements currently supported"); assert(statement && "Only transitions with statements currently supported");
ExplodedNode *N = generateNodeImpl(statement, state, false, ExplodedNode *N = generateNodeImpl(statement, state, false,
@ -132,12 +145,12 @@ public:
return N; 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, return generateNodeImpl(stmt, state ? state : getState(), true,
checkerTag); checkerTag);
} }
ExplodedNode *generateSink(const GRState *state = 0) { ExplodedNode *generateSink(const ProgramState *state = 0) {
assert(statement && "Only transitions with statements currently supported"); assert(statement && "Only transitions with statements currently supported");
return generateNodeImpl(statement, state ? state : getState(), true, return generateNodeImpl(statement, state ? state : getState(), true,
checkerTag); checkerTag);
@ -147,7 +160,8 @@ public:
Dst.Add(node); Dst.Add(node);
} }
void addTransition(const GRState *state, const ProgramPointTag *tag = 0) { void addTransition(const ProgramState *state,
const ProgramPointTag *tag = 0) {
assert(state); assert(state);
// If the 'state' is not new, we need to check if the cached state 'ST' // If the 'state' is not new, we need to check if the cached state 'ST'
// is new. // is new.
@ -167,16 +181,20 @@ public:
} }
private: private:
ExplodedNode *generateNodeImpl(const Stmt *stmt, const GRState *state, ExplodedNode *generateNodeImpl(const Stmt *stmt,
bool markAsSink, const ProgramPointTag *tag) { const ProgramState *state,
bool markAsSink,
const ProgramPointTag *tag) {
ExplodedNode *node = B.generateNode(stmt, state, Pred, tag); ExplodedNode *node = B.generateNode(stmt, state, Pred, tag);
if (markAsSink && node) if (markAsSink && node)
node->markAsSink(); node->markAsSink();
return node; return node;
} }
ExplodedNode *generateNodeImpl(const Stmt *stmt, const GRState *state, ExplodedNode *generateNodeImpl(const Stmt *stmt,
ExplodedNode *pred, bool markAsSink) { const ProgramState *state,
ExplodedNode *pred,
bool markAsSink) {
ExplodedNode *node = B.generateNode(stmt, state, pred, checkerTag); ExplodedNode *node = B.generateNode(stmt, state, pred, checkerTag);
if (markAsSink && node) if (markAsSink && node)
node->markAsSink(); node->markAsSink();

View File

@ -25,36 +25,41 @@ namespace clang {
namespace ento { namespace ento {
class GRState; class ProgramState;
class GRStateManager; class ProgramStateManager;
class SubEngine; class SubEngine;
class SVal; class SVal;
class ConstraintManager { class ConstraintManager {
public: public:
virtual ~ConstraintManager(); virtual ~ConstraintManager();
virtual const GRState *assume(const GRState *state, DefinedSVal Cond, virtual const ProgramState *assume(const ProgramState *state,
bool Assumption) = 0; DefinedSVal Cond,
bool Assumption) = 0;
std::pair<const GRState*, const GRState*> assumeDual(const GRState *state, std::pair<const ProgramState*, const ProgramState*>
DefinedSVal Cond) { assumeDual(const ProgramState *state, DefinedSVal Cond)
{
return std::make_pair(assume(state, Cond, true), return std::make_pair(assume(state, Cond, true),
assume(state, Cond, false)); assume(state, Cond, false));
} }
virtual const llvm::APSInt* getSymVal(const GRState *state, virtual const llvm::APSInt* getSymVal(const ProgramState *state,
SymbolRef sym) const = 0; 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; const llvm::APSInt& V) const = 0;
virtual const GRState *removeDeadBindings(const GRState *state, virtual const ProgramState *removeDeadBindings(const ProgramState *state,
SymbolReaper& SymReaper) = 0; SymbolReaper& SymReaper) = 0;
virtual void print(const GRState *state, raw_ostream &Out, virtual void print(const ProgramState *state,
const char* nl, const char *sep) = 0; 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 /// canReasonAbout - Not all ConstraintManagers can accurately reason about
/// all SVal values. This method returns true if the ConstraintManager can /// all SVal values. This method returns true if the ConstraintManager can
@ -64,9 +69,9 @@ public:
virtual bool canReasonAbout(SVal X) const = 0; virtual bool canReasonAbout(SVal X) const = 0;
}; };
ConstraintManager* CreateBasicConstraintManager(GRStateManager& statemgr, ConstraintManager* CreateBasicConstraintManager(ProgramStateManager& statemgr,
SubEngine &subengine); SubEngine &subengine);
ConstraintManager* CreateRangeConstraintManager(GRStateManager& statemgr, ConstraintManager* CreateRangeConstraintManager(ProgramStateManager& statemgr,
SubEngine &subengine); SubEngine &subengine);
} // end GR namespace } // end GR namespace

View File

@ -79,7 +79,8 @@ private:
/// usually because it could not reason about something. /// usually because it could not reason about something.
BlocksAborted blocksAborted; BlocksAborted blocksAborted;
void generateNode(const ProgramPoint &Loc, const GRState *State, void generateNode(const ProgramPoint &Loc,
const ProgramState *State,
ExplodedNode *Pred); ExplodedNode *Pred);
void HandleBlockEdge(const BlockEdge &E, ExplodedNode *Pred); void HandleBlockEdge(const BlockEdge &E, ExplodedNode *Pred);
@ -126,9 +127,10 @@ public:
/// ExecuteWorkList - Run the worklist algorithm for a maximum number of /// ExecuteWorkList - Run the worklist algorithm for a maximum number of
/// steps. Returns true if there is still simulation state on the worklist. /// steps. Returns true if there is still simulation state on the worklist.
bool ExecuteWorkList(const LocationContext *L, unsigned Steps, bool ExecuteWorkList(const LocationContext *L, unsigned Steps,
const GRState *InitState); const ProgramState *InitState);
void ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps, void ExecuteWorkListWithInitialState(const LocationContext *L,
const GRState *InitState, unsigned Steps,
const ProgramState *InitState,
ExplodedNodeSet &Dst); ExplodedNodeSet &Dst);
// Functions for external checking of whether we have unfinished work // Functions for external checking of whether we have unfinished work
@ -165,7 +167,7 @@ class StmtNodeBuilder {
const CFGBlock &B; const CFGBlock &B;
const unsigned Idx; const unsigned Idx;
ExplodedNode *Pred; ExplodedNode *Pred;
GRStateManager& Mgr; ProgramStateManager& Mgr;
public: public:
bool PurgingDeadSymbols; bool PurgingDeadSymbols;
@ -180,8 +182,11 @@ public:
void GenerateAutoTransition(ExplodedNode *N); void GenerateAutoTransition(ExplodedNode *N);
public: public:
StmtNodeBuilder(const CFGBlock *b, unsigned idx, ExplodedNode *N, StmtNodeBuilder(const CFGBlock *b,
CoreEngine* e, GRStateManager &mgr); unsigned idx,
ExplodedNode *N,
CoreEngine* e,
ProgramStateManager &mgr);
~StmtNodeBuilder(); ~StmtNodeBuilder();
@ -198,13 +203,17 @@ public:
B.getBlockID()); B.getBlockID());
} }
ExplodedNode *generateNode(PostStmt PP,const GRState *St,ExplodedNode *Pred) { ExplodedNode *generateNode(PostStmt PP,
const ProgramState *St,
ExplodedNode *Pred) {
hasGeneratedNode = true; hasGeneratedNode = true;
return generateNodeInternal(PP, St, Pred); return generateNodeInternal(PP, St, Pred);
} }
ExplodedNode *generateNode(const Stmt *S, const GRState *St, ExplodedNode *generateNode(const Stmt *S,
ExplodedNode *Pred, ProgramPoint::Kind K, const ProgramState *St,
ExplodedNode *Pred,
ProgramPoint::Kind K,
const ProgramPointTag *tag = 0) { const ProgramPointTag *tag = 0) {
hasGeneratedNode = true; hasGeneratedNode = true;
@ -214,26 +223,31 @@ public:
return generateNodeInternal(S, St, Pred, K, tag ? tag : Tag); 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, ExplodedNode *Pred,
const ProgramPointTag *tag = 0) { const ProgramPointTag *tag = 0) {
return generateNode(S, St, Pred, PointKind, tag); 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) { ExplodedNode *Pred) {
hasGeneratedNode = true; hasGeneratedNode = true;
return generateNodeInternal(PP, State, Pred); return generateNodeInternal(PP, State, Pred);
} }
ExplodedNode* ExplodedNode*
generateNodeInternal(const ProgramPoint &PP, const GRState *State, generateNodeInternal(const ProgramPoint &PP,
const ProgramState *State,
ExplodedNode *Pred); ExplodedNode *Pred);
ExplodedNode* ExplodedNode*
generateNodeInternal(const Stmt *S, const GRState *State, ExplodedNode *Pred, generateNodeInternal(const Stmt *S,
ProgramPoint::Kind K = ProgramPoint::PostStmtKind, const ProgramState *State,
const ProgramPointTag *tag = 0); ExplodedNode *Pred,
ProgramPoint::Kind K = ProgramPoint::PostStmtKind,
const ProgramPointTag *tag = 0);
/// getStmt - Return the current block-level expression associated with /// getStmt - Return the current block-level expression associated with
/// this builder. /// this builder.
@ -248,16 +262,23 @@ public:
unsigned getIndex() const { return Idx; } unsigned getIndex() const { return Idx; }
ExplodedNode *MakeNode(ExplodedNodeSet &Dst, const Stmt *S, ExplodedNode *MakeNode(ExplodedNodeSet &Dst,
ExplodedNode *Pred, const GRState *St) { const Stmt *S,
ExplodedNode *Pred,
const ProgramState *St) {
return MakeNode(Dst, S, Pred, St, PointKind); return MakeNode(Dst, S, Pred, St, PointKind);
} }
ExplodedNode *MakeNode(ExplodedNodeSet &Dst, const Stmt *S,ExplodedNode *Pred, ExplodedNode *MakeNode(ExplodedNodeSet &Dst,
const GRState *St, ProgramPoint::Kind K); const Stmt *S,
ExplodedNode *Pred,
const ProgramState *St,
ProgramPoint::Kind K);
ExplodedNode *MakeSinkNode(ExplodedNodeSet &Dst, const Stmt *S, ExplodedNode *MakeSinkNode(ExplodedNodeSet &Dst,
ExplodedNode *Pred, const GRState *St) { const Stmt *S,
ExplodedNode *Pred,
const ProgramState *St) {
bool Tmp = BuildSinks; bool Tmp = BuildSinks;
BuildSinks = true; BuildSinks = true;
ExplodedNode *N = MakeNode(Dst, S, Pred, St); ExplodedNode *N = MakeNode(Dst, S, Pred, St);
@ -296,9 +317,9 @@ public:
BlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();} 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 { const CFGBlock *getTargetBlock(bool branch) const {
return branch ? DstT : DstF; return branch ? DstT : DstF;
@ -315,7 +336,7 @@ public:
return branch ? !InFeasibleTrue : !InFeasibleFalse; return branch ? !InFeasibleTrue : !InFeasibleFalse;
} }
const GRState *getState() const { const ProgramState *getState() const {
return getPredecessor()->getState(); return getPredecessor()->getState();
} }
}; };
@ -354,12 +375,13 @@ public:
iterator begin() { return iterator(DispatchBlock.succ_begin()); } iterator begin() { return iterator(DispatchBlock.succ_begin()); }
iterator end() { return iterator(DispatchBlock.succ_end()); } 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); bool isSink = false);
const Expr *getTarget() const { return E; } const Expr *getTarget() const { return E; }
const GRState *getState() const { return Pred->State; } const ProgramState *getState() const { return Pred->State; }
}; };
class SwitchNodeBuilder { class SwitchNodeBuilder {
@ -400,14 +422,15 @@ public:
return llvm::cast<SwitchStmt>(Src->getTerminator()); 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); bool isSink = false);
const Expr *getCondition() const { return Condition; } const Expr *getCondition() const { return Condition; }
const GRState *getState() const { return Pred->State; } const ProgramState *getState() const { return Pred->State; }
}; };
class GenericNodeBuilderImpl { class GenericNodeBuilderImpl {
@ -417,8 +440,10 @@ protected:
ProgramPoint pp; ProgramPoint pp;
SmallVector<ExplodedNode*, 2> sinksGenerated; SmallVector<ExplodedNode*, 2> sinksGenerated;
ExplodedNode *generateNodeImpl(const GRState *state, ExplodedNode *pred, ExplodedNode *generateNodeImpl(const ProgramState *state,
ProgramPoint programPoint, bool asSink); ExplodedNode *pred,
ProgramPoint programPoint,
bool asSink);
GenericNodeBuilderImpl(CoreEngine &eng, ExplodedNode *pr, ProgramPoint p) GenericNodeBuilderImpl(CoreEngine &eng, ExplodedNode *pr, ProgramPoint p)
: engine(eng), pred(pr), pp(p), hasGeneratedNode(false) {} : engine(eng), pred(pr), pp(p), hasGeneratedNode(false) {}
@ -445,7 +470,7 @@ public:
GenericNodeBuilder(CoreEngine &eng, ExplodedNode *pr, const PP_T &p) GenericNodeBuilder(CoreEngine &eng, ExplodedNode *pr, const PP_T &p)
: GenericNodeBuilderImpl(eng, pr, p) {} : GenericNodeBuilderImpl(eng, pr, p) {}
ExplodedNode *generateNode(const GRState *state, ExplodedNode *pred, ExplodedNode *generateNode(const ProgramState *state, ExplodedNode *pred,
const ProgramPointTag *tag, bool asSink) { const ProgramPointTag *tag, bool asSink) {
return generateNodeImpl(state, pred, cast<PP_T>(pp).withTag(tag), return generateNodeImpl(state, pred, cast<PP_T>(pp).withTag(tag),
asSink); asSink);
@ -488,14 +513,15 @@ public:
B.getBlockID()); B.getBlockID());
} }
ExplodedNode *generateNode(const GRState *State, ExplodedNode *P = 0, ExplodedNode *generateNode(const ProgramState *State,
ExplodedNode *P = 0,
const ProgramPointTag *tag = 0); const ProgramPointTag *tag = 0);
void GenerateCallExitNode(const GRState *state); void GenerateCallExitNode(const ProgramState *state);
const CFGBlock *getBlock() const { return &B; } const CFGBlock *getBlock() const { return &B; }
const GRState *getState() const { const ProgramState *getState() const {
return getPredecessor()->getState(); return getPredecessor()->getState();
} }
}; };
@ -524,7 +550,7 @@ public:
const CFGBlock *blk, unsigned idx) const CFGBlock *blk, unsigned idx)
: Eng(eng), Pred(pred), CE(s), CalleeCtx(callee), Block(blk), Index(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 { const LocationContext *getLocationContext() const {
return Pred->getLocationContext(); return Pred->getLocationContext();
@ -538,7 +564,7 @@ public:
unsigned getIndex() const { return Index; } unsigned getIndex() const { return Index; }
void generateNode(const GRState *state); void generateNode(const ProgramState *state);
}; };
class CallExitNodeBuilder { class CallExitNodeBuilder {
@ -551,9 +577,9 @@ public:
const ExplodedNode *getPredecessor() const { return Pred; } 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 } // end GR namespace

View File

@ -96,7 +96,7 @@ public:
SVal V); SVal V);
Environment removeDeadBindings(Environment Env, Environment removeDeadBindings(Environment Env,
SymbolReaper &SymReaper, const GRState *ST); SymbolReaper &SymReaper, const ProgramState *ST);
}; };
} // end GR namespace } // end GR namespace

View File

@ -31,7 +31,7 @@
#include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/Support/Casting.h" #include "llvm/Support/Casting.h"
#include "clang/Analysis/Support/BumpVector.h" #include "clang/Analysis/Support/BumpVector.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
namespace clang { namespace clang {
@ -106,7 +106,7 @@ class ExplodedNode : public llvm::FoldingSetNode {
const ProgramPoint Location; const ProgramPoint Location;
/// State - The state associated with this node. /// State - The state associated with this node.
const GRState *State; const ProgramState *State;
/// Preds - The predecessors of this node. /// Preds - The predecessors of this node.
NodeGroup Preds; NodeGroup Preds;
@ -116,13 +116,13 @@ class ExplodedNode : public llvm::FoldingSetNode {
public: public:
explicit ExplodedNode(const ProgramPoint &loc, const GRState *state) explicit ExplodedNode(const ProgramPoint &loc, const ProgramState *state)
: Location(loc), State(state) { : Location(loc), State(state) {
const_cast<GRState*>(State)->incrementReferenceCount(); const_cast<ProgramState*>(State)->incrementReferenceCount();
} }
~ExplodedNode() { ~ExplodedNode() {
const_cast<GRState*>(State)->decrementReferenceCount(); const_cast<ProgramState*>(State)->decrementReferenceCount();
} }
/// getLocation - Returns the edge associated with the given node. /// getLocation - Returns the edge associated with the given node.
@ -142,13 +142,13 @@ public:
return *getLocationContext()->getLiveVariables(); return *getLocationContext()->getLiveVariables();
} }
const GRState *getState() const { return State; } const ProgramState *getState() const { return State; }
template <typename T> template <typename T>
const T* getLocationAs() const { return llvm::dyn_cast<T>(&Location); } const T* getLocationAs() const { return llvm::dyn_cast<T>(&Location); }
static void Profile(llvm::FoldingSetNodeID &ID, static void Profile(llvm::FoldingSetNodeID &ID,
const ProgramPoint &Loc, const GRState *state) { const ProgramPoint &Loc, const ProgramState *state) {
ID.Add(Loc); ID.Add(Loc);
ID.AddPointer(state); ID.AddPointer(state);
} }
@ -275,7 +275,7 @@ public:
/// this pair exists, it is created. IsNew is set to true if /// this pair exists, it is created. IsNew is set to true if
/// the node was freshly created. /// the node was freshly created.
ExplodedNode *getNode(const ProgramPoint &L, const GRState *State, ExplodedNode *getNode(const ProgramPoint &L, const ProgramState *State,
bool* IsNew = 0); bool* IsNew = 0);
ExplodedGraph* MakeEmptyGraph() const { ExplodedGraph* MakeEmptyGraph() const {

View File

@ -19,7 +19,7 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.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/TransferFuncs.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
@ -49,7 +49,7 @@ class ExprEngine : public SubEngine {
StmtNodeBuilder* Builder; StmtNodeBuilder* Builder;
/// StateMgr - Object that manages the data for all created states. /// StateMgr - Object that manages the data for all created states.
GRStateManager StateMgr; ProgramStateManager StateMgr;
/// SymMgr - Object that manages the symbol information. /// SymMgr - Object that manages the symbol information.
SymbolManager& SymMgr; SymbolManager& SymMgr;
@ -62,7 +62,7 @@ class ExprEngine : public SubEngine {
/// CleanedState - The state for EntryNode "cleaned" of all dead /// CleanedState - The state for EntryNode "cleaned" of all dead
/// variables and symbols (as determined by a liveness analysis). /// variables and symbols (as determined by a liveness analysis).
const GRState *CleanedState; const ProgramState *CleanedState;
/// currentStmt - The current block-level statement. /// currentStmt - The current block-level statement.
const Stmt *currentStmt; const Stmt *currentStmt;
@ -94,7 +94,7 @@ public:
/// of the function are added into the Dst set, which represent the exit /// of the function are added into the Dst set, which represent the exit
/// state of the function call. /// state of the function call.
void ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps, void ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps,
const GRState *InitState, const ProgramState *InitState,
ExplodedNodeSet &Dst) { ExplodedNodeSet &Dst) {
Engine.ExecuteWorkListWithInitialState(L, Steps, InitState, Dst); Engine.ExecuteWorkListWithInitialState(L, Steps, InitState, Dst);
} }
@ -127,7 +127,7 @@ public:
/// getInitialState - Return the initial state used for the root vertex /// getInitialState - Return the initial state used for the root vertex
/// in the ExplodedGraph. /// in the ExplodedGraph.
const GRState *getInitialState(const LocationContext *InitLoc); const ProgramState *getInitialState(const LocationContext *InitLoc);
ExplodedGraph& getGraph() { return G; } ExplodedGraph& getGraph() { return G; }
const ExplodedGraph& getGraph() const { return G; } const ExplodedGraph& getGraph() const { return G; }
@ -181,21 +181,21 @@ public:
/// evalAssume - Callback function invoked by the ConstraintManager when /// evalAssume - Callback function invoked by the ConstraintManager when
/// making assumptions about state values. /// 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. /// 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. /// to the store. Used to update checkers that track region values.
const GRState * const ProgramState *
processRegionChanges(const GRState *state, processRegionChanges(const ProgramState *state,
const StoreManager::InvalidatedSymbols *invalidated, const StoreManager::InvalidatedSymbols *invalidated,
const MemRegion * const *Begin, const MemRegion * const *Begin,
const MemRegion * const *End); const MemRegion * const *End);
virtual GRStateManager& getStateManager() { return StateMgr; } virtual ProgramStateManager& getStateManager() { return StateMgr; }
StoreManager& getStoreManager() { return StateMgr.getStoreManager(); } StoreManager& getStoreManager() { return StateMgr.getStoreManager(); }
@ -224,7 +224,7 @@ public:
public: public:
ExplodedNode *MakeNode(ExplodedNodeSet &Dst, const Stmt *S, ExplodedNode *MakeNode(ExplodedNodeSet &Dst, const Stmt *S,
ExplodedNode *Pred, const GRState *St, ExplodedNode *Pred, const ProgramState *St,
ProgramPoint::Kind K = ProgramPoint::PostStmtKind, ProgramPoint::Kind K = ProgramPoint::PostStmtKind,
const ProgramPointTag *tag = 0); const ProgramPointTag *tag = 0);
@ -391,35 +391,35 @@ public:
public: public:
SVal evalBinOp(const GRState *state, BinaryOperator::Opcode op, SVal evalBinOp(const ProgramState *state, BinaryOperator::Opcode op,
NonLoc L, NonLoc R, QualType T) { NonLoc L, NonLoc R, QualType T) {
return svalBuilder.evalBinOpNN(state, op, L, R, 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) { NonLoc L, SVal R, QualType T) {
return R.isValid() ? svalBuilder.evalBinOpNN(state,op,L, cast<NonLoc>(R), T) : R; 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) { SVal LHS, SVal RHS, QualType T) {
return svalBuilder.evalBinOp(ST, Op, LHS, RHS, T); return svalBuilder.evalBinOp(ST, Op, LHS, RHS, T);
} }
protected: protected:
void evalObjCMessage(ExplodedNodeSet &Dst, const ObjCMessage &msg, void evalObjCMessage(ExplodedNodeSet &Dst, const ObjCMessage &msg,
ExplodedNode *Pred, const GRState *state) { ExplodedNode *Pred, const ProgramState *state) {
assert (Builder && "StmtNodeBuilder must be defined."); assert (Builder && "StmtNodeBuilder must be defined.");
getTF().evalObjCMessage(Dst, *this, *Builder, msg, Pred, state); 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); bool branchTaken);
/// evalBind - Handle the semantics of binding a value to a specific location. /// evalBind - Handle the semantics of binding a value to a specific location.
/// This method is used by evalStore, VisitDeclStmt, and others. /// This method is used by evalStore, VisitDeclStmt, and others.
void evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE, ExplodedNode *Pred, 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); bool atDeclInit = false);
public: public:
@ -430,23 +430,23 @@ public:
// same as state->getLValue(Ex). // same as state->getLValue(Ex).
/// Simulate a read of the result of Ex. /// Simulate a read of the result of Ex.
void evalLoad(ExplodedNodeSet &Dst, const Expr *Ex, ExplodedNode *Pred, 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()); QualType LoadTy = QualType());
// FIXME: 'tag' should be removed, and a LocationContext should be used // FIXME: 'tag' should be removed, and a LocationContext should be used
// instead. // instead.
void evalStore(ExplodedNodeSet &Dst, const Expr *AssignE, const Expr *StoreE, 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); const ProgramPointTag *tag = 0);
private: private:
void evalLoadCommon(ExplodedNodeSet &Dst, const Expr *Ex, ExplodedNode *Pred, 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); QualType LoadTy);
// FIXME: 'tag' should be removed, and a LocationContext should be used // FIXME: 'tag' should be removed, and a LocationContext should be used
// instead. // instead.
void evalLocation(ExplodedNodeSet &Dst, const Stmt *S, ExplodedNode *Pred, void evalLocation(ExplodedNodeSet &Dst, const Stmt *S, ExplodedNode *Pred,
const GRState *St, SVal location, const ProgramState *St, SVal location,
const ProgramPointTag *tag, bool isLoad); const ProgramPointTag *tag, bool isLoad);
bool InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, ExplodedNode *Pred); bool InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, ExplodedNode *Pred);

View File

@ -26,7 +26,7 @@ class StmtNodeBuilderRef {
StmtNodeBuilder &B; StmtNodeBuilder &B;
ExprEngine& Eng; ExprEngine& Eng;
ExplodedNode *Pred; ExplodedNode *Pred;
const GRState *state; const ProgramState *state;
const Stmt *stmt; const Stmt *stmt;
const unsigned OldSize; const unsigned OldSize;
const bool AutoCreateNode; const bool AutoCreateNode;
@ -43,7 +43,7 @@ private:
StmtNodeBuilder &builder, StmtNodeBuilder &builder,
ExprEngine& eng, ExprEngine& eng,
ExplodedNode *pred, ExplodedNode *pred,
const GRState *st, const ProgramState *st,
const Stmt *s, bool auto_create_node) const Stmt *s, bool auto_create_node)
: Dst(dst), B(builder), Eng(eng), Pred(pred), : Dst(dst), B(builder), Eng(eng), Pred(pred),
state(st), stmt(s), OldSize(Dst.size()), AutoCreateNode(auto_create_node), 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(); return Eng.getStateManager();
} }
ExplodedNode *MakeNode(const GRState *state) { ExplodedNode *MakeNode(const ProgramState *state) {
return B.MakeNode(Dst, const_cast<Stmt*>(stmt), Pred, state); return B.MakeNode(Dst, const_cast<Stmt*>(stmt), Pred, state);
} }
}; };

View File

@ -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

View File

@ -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

View File

@ -16,7 +16,7 @@
#define LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_OBJCMESSAGE #define LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_OBJCMESSAGE
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #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" #include "clang/AST/ExprObjC.h"
namespace clang { namespace clang {
@ -118,7 +118,7 @@ public:
return isPropertySetter() ? 1 : 0; 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(isValid() && "This ObjCMessage is uninitialized!");
assert(i < getNumArgs() && "Invalid index for argument"); assert(i < getNumArgs() && "Invalid index for argument");
if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
@ -170,11 +170,11 @@ public:
class CallOrObjCMessage { class CallOrObjCMessage {
const CallExpr *CallE; const CallExpr *CallE;
ObjCMessage Msg; ObjCMessage Msg;
const GRState *State; const ProgramState *State;
public: public:
CallOrObjCMessage(const CallExpr *callE, const GRState *state) CallOrObjCMessage(const CallExpr *callE, const ProgramState *state)
: CallE(callE), State(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) {} : CallE(0), Msg(msg), State(state) {}
QualType getResultType(ASTContext &ctx) const; QualType getResultType(ASTContext &ctx) const;

View File

@ -25,7 +25,7 @@ namespace clang {
namespace ento { namespace ento {
class GRState; class ProgramState;
class SValBuilder { class SValBuilder {
protected: protected:
@ -40,7 +40,7 @@ protected:
/// Manages the creation of memory regions. /// Manages the creation of memory regions.
MemRegionManager MemMgr; MemRegionManager MemMgr;
GRStateManager &StateMgr; ProgramStateManager &StateMgr;
/// The scalar type to use for array indices. /// The scalar type to use for array indices.
const QualType ArrayIndexTy; const QualType ArrayIndexTy;
@ -56,7 +56,7 @@ public:
public: public:
SValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context, SValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context,
GRStateManager &stateMgr) ProgramStateManager &stateMgr)
: Context(context), BasicVals(context, alloc), : Context(context), BasicVals(context, alloc),
SymMgr(context, BasicVals, alloc), SymMgr(context, BasicVals, alloc),
MemMgr(context, alloc), MemMgr(context, alloc),
@ -72,29 +72,29 @@ public:
virtual SVal evalComplement(NonLoc val) = 0; 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; 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; 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; Loc lhs, NonLoc rhs, QualType resultTy) = 0;
/// getKnownValue - evaluates a given SVal. If the SVal has only one possible /// getKnownValue - evaluates a given SVal. If the SVal has only one possible
/// (integer) value, that value is returned. Otherwise, returns NULL. /// (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); SVal lhs, SVal rhs, QualType type);
DefinedOrUnknownSVal evalEQ(const GRState *state, DefinedOrUnknownSVal lhs, DefinedOrUnknownSVal evalEQ(const ProgramState *state, DefinedOrUnknownSVal lhs,
DefinedOrUnknownSVal rhs); DefinedOrUnknownSVal rhs);
ASTContext &getContext() { return Context; } ASTContext &getContext() { return Context; }
const ASTContext &getContext() const { return Context; } const ASTContext &getContext() const { return Context; }
GRStateManager &getStateManager() { return StateMgr; } ProgramStateManager &getStateManager() { return StateMgr; }
QualType getConditionType() const { QualType getConditionType() const {
return getContext().IntTy; return getContext().IntTy;
@ -255,7 +255,7 @@ public:
SValBuilder* createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc, SValBuilder* createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc,
ASTContext &context, ASTContext &context,
GRStateManager &stateMgr); ProgramStateManager &stateMgr);
} // end GR namespace } // end GR namespace

View File

@ -29,12 +29,12 @@ namespace ento {
class CompoundValData; class CompoundValData;
class LazyCompoundValData; class LazyCompoundValData;
class GRState; class ProgramState;
class BasicValueFactory; class BasicValueFactory;
class MemRegion; class MemRegion;
class TypedRegion; class TypedRegion;
class MemRegionManager; class MemRegionManager;
class GRStateManager; class ProgramStateManager;
class SValBuilder; class SValBuilder;
/// SVal - This represents a symbolic expression, which can be either /// SVal - This represents a symbolic expression, which can be either

View File

@ -29,20 +29,20 @@ class StackFrameContext;
namespace ento { namespace ento {
class GRState; class ProgramState;
class GRStateManager; class ProgramStateManager;
class SubRegionMap; class SubRegionMap;
class StoreManager { class StoreManager {
protected: protected:
SValBuilder &svalBuilder; SValBuilder &svalBuilder;
GRStateManager &StateMgr; ProgramStateManager &StateMgr;
/// MRMgr - Manages region objects associated with this StoreManager. /// MRMgr - Manages region objects associated with this StoreManager.
MemRegionManager &MRMgr; MemRegionManager &MRMgr;
ASTContext &Ctx; ASTContext &Ctx;
StoreManager(GRStateManager &stateMgr); StoreManager(ProgramStateManager &stateMgr);
public: public:
virtual ~StoreManager() {} virtual ~StoreManager() {}
@ -60,7 +60,7 @@ public:
/// \param[in] state The analysis state. /// \param[in] state The analysis state.
/// \param[in] loc The symbolic memory location. /// \param[in] loc The symbolic memory location.
/// \param[in] val The value to bind to location \c loc. /// \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 /// \c state with the addition of having the value specified by \c val bound
/// to the location given for \c loc. /// to the location given for \c loc.
virtual StoreRef Bind(Store store, Loc loc, SVal val) = 0; 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 // FIXME: This should soon be eliminated altogether; clients should deal with
// region extents directly. // region extents directly.
virtual DefinedOrUnknownSVal getSizeInElements(const GRState *state, virtual DefinedOrUnknownSVal getSizeInElements(const ProgramState *state,
const MemRegion *region, const MemRegion *region,
QualType EleTy) { QualType EleTy) {
return UnknownVal(); return UnknownVal();
@ -130,12 +130,12 @@ public:
} }
class CastResult { class CastResult {
const GRState *state; const ProgramState *state;
const MemRegion *region; const MemRegion *region;
public: public:
const GRState *getState() const { return state; } const ProgramState *getState() const { return state; }
const MemRegion* getRegion() const { return region; } 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); const ElementRegion *GetElementZeroRegion(const MemRegion *R, QualType T);
@ -196,7 +196,7 @@ public:
/// enterStackFrame - Let the StoreManager to do something when execution /// enterStackFrame - Let the StoreManager to do something when execution
/// engine is about to execute into a callee. /// engine is about to execute into a callee.
virtual StoreRef enterStackFrame(const GRState *state, virtual StoreRef enterStackFrame(const ProgramState *state,
const StackFrameContext *frame); const StackFrameContext *frame);
virtual void print(Store store, raw_ostream &Out, virtual void print(Store store, raw_ostream &Out,
@ -271,9 +271,9 @@ public:
virtual bool iterSubRegions(const MemRegion *region, Visitor& V) const = 0; virtual bool iterSubRegions(const MemRegion *region, Visitor& V) const = 0;
}; };
// FIXME: Do we need to pass GRStateManager anymore? // FIXME: Do we need to pass ProgramStateManager anymore?
StoreManager *CreateRegionStoreManager(GRStateManager& StMgr); StoreManager *CreateRegionStoreManager(ProgramStateManager& StMgr);
StoreManager *CreateFieldsOnlyRegionStoreManager(GRStateManager& StMgr); StoreManager *CreateFieldsOnlyRegionStoreManager(ProgramStateManager& StMgr);
} // end GR namespace } // end GR namespace

View File

@ -30,8 +30,8 @@ template <typename PP> class GenericNodeBuilder;
class AnalysisManager; class AnalysisManager;
class ExplodedNodeSet; class ExplodedNodeSet;
class ExplodedNode; class ExplodedNode;
class GRState; class ProgramState;
class GRStateManager; class ProgramStateManager;
class BlockCounter; class BlockCounter;
class StmtNodeBuilder; class StmtNodeBuilder;
class BranchNodeBuilder; class BranchNodeBuilder;
@ -46,11 +46,11 @@ class SubEngine {
public: public:
virtual ~SubEngine() {} virtual ~SubEngine() {}
virtual const GRState *getInitialState(const LocationContext *InitLoc) = 0; virtual const ProgramState *getInitialState(const LocationContext *InitLoc) = 0;
virtual AnalysisManager &getAnalysisManager() = 0; virtual AnalysisManager &getAnalysisManager() = 0;
virtual GRStateManager &getStateManager() = 0; virtual ProgramStateManager &getStateManager() = 0;
/// Called by CoreEngine. Used to generate new successor /// Called by CoreEngine. Used to generate new successor
/// nodes by processing the 'effects' of a block-level statement. /// nodes by processing the 'effects' of a block-level statement.
@ -87,24 +87,24 @@ public:
/// Called by ConstraintManager. Used to call checker-specific /// Called by ConstraintManager. Used to call checker-specific
/// logic for handling assumptions on symbolic values. /// 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; 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. /// 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. /// to the store. Used to update checkers that track region values.
virtual const GRState * virtual const ProgramState *
processRegionChanges(const GRState *state, processRegionChanges(const ProgramState *state,
const StoreManager::InvalidatedSymbols *invalidated, const StoreManager::InvalidatedSymbols *invalidated,
const MemRegion* const *Begin, const MemRegion* const *Begin,
const MemRegion* const *End) = 0; const MemRegion* const *End) = 0;
inline const GRState * inline const ProgramState *
processRegionChange(const GRState *state, processRegionChange(const ProgramState *state,
const MemRegion* MR) { const MemRegion* MR) {
return processRegionChanges(state, 0, &MR, &MR+1); return processRegionChanges(state, 0, &MR, &MR+1);
} }

View File

@ -522,7 +522,7 @@ private:
class SymbolVisitor { class SymbolVisitor {
public: 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 /// The method returns \c true if symbols should continue be scanned and \c
/// false otherwise. /// false otherwise.

View File

@ -15,7 +15,7 @@
#ifndef LLVM_CLANG_GR_TRANSFERFUNCS #ifndef LLVM_CLANG_GR_TRANSFERFUNCS
#define 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/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
#include <vector> #include <vector>
@ -36,7 +36,7 @@ public:
TransferFuncs() {} TransferFuncs() {}
virtual ~TransferFuncs() {} virtual ~TransferFuncs() {}
virtual void RegisterPrinters(std::vector<GRState::Printer*>& Printers) {} virtual void RegisterPrinters(std::vector<ProgramState::Printer*>& Printers) {}
virtual void RegisterChecks(ExprEngine& Eng) {} virtual void RegisterChecks(ExprEngine& Eng) {}
@ -53,7 +53,7 @@ public:
StmtNodeBuilder& Builder, StmtNodeBuilder& Builder,
ObjCMessage msg, ObjCMessage msg,
ExplodedNode *Pred, ExplodedNode *Pred,
const GRState *state) {} const ProgramState *state) {}
// Stores. // Stores.
@ -69,7 +69,7 @@ public:
ExprEngine& Engine, ExprEngine& Engine,
StmtNodeBuilder& Builder, StmtNodeBuilder& Builder,
ExplodedNode *Pred, ExplodedNode *Pred,
const GRState *state, const ProgramState *state,
SymbolReaper& SymReaper) {} SymbolReaper& SymReaper) {}
// Return statements. // Return statements.
@ -80,7 +80,7 @@ public:
ExplodedNode *Pred) {} ExplodedNode *Pred) {}
// Assumptions. // Assumptions.
virtual const GRState *evalAssume(const GRState *state, virtual const ProgramState *evalAssume(const ProgramState *state,
SVal Cond, bool Assumption) { SVal Cond, bool Assumption) {
return state; return state;
} }

View File

@ -37,7 +37,7 @@ void AdjustedReturnValueChecker::checkPostStmt(const CallExpr *CE,
QualType expectedResultTy = CE->getType(); QualType expectedResultTy = CE->getType();
// Fetch the signature of the called function. // Fetch the signature of the called function.
const GRState *state = C.getState(); const ProgramState *state = C.getState();
SVal V = state->getSVal(CE); SVal V = state->getSVal(CE);

View File

@ -50,15 +50,15 @@ void ArrayBoundChecker::checkLocation(SVal l, bool isLoad,
if (Idx.isZeroConstant()) if (Idx.isZeroConstant())
return; return;
const GRState *state = C.getState(); const ProgramState *state = C.getState();
// Get the size of the array. // Get the size of the array.
DefinedOrUnknownSVal NumElements DefinedOrUnknownSVal NumElements
= C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(), = C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(),
ER->getValueType()); ER->getValueType());
const GRState *StInBound = state->assumeInBound(Idx, NumElements, true); const ProgramState *StInBound = state->assumeInBound(Idx, NumElements, true);
const GRState *StOutBound = state->assumeInBound(Idx, NumElements, false); const ProgramState *StOutBound = state->assumeInBound(Idx, NumElements, false);
if (StOutBound && !StInBound) { if (StOutBound && !StInBound) {
ExplodedNode *N = C.generateSink(StOutBound); ExplodedNode *N = C.generateSink(StOutBound);
if (!N) if (!N)

View File

@ -30,7 +30,7 @@ class ArrayBoundCheckerV2 :
enum OOB_Kind { OOB_Precedes, OOB_Excedes }; 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; OOB_Kind kind) const;
public: public:
@ -53,7 +53,7 @@ public:
NonLoc getByteOffset() const { return cast<NonLoc>(byteOffset); } NonLoc getByteOffset() const { return cast<NonLoc>(byteOffset); }
const SubRegion *getRegion() const { return baseRegion; } const SubRegion *getRegion() const { return baseRegion; }
static RegionRawOffsetV2 computeOffset(const GRState *state, static RegionRawOffsetV2 computeOffset(const ProgramState *state,
SValBuilder &svalBuilder, SValBuilder &svalBuilder,
SVal location); SVal location);
@ -81,7 +81,7 @@ static SVal computeExtentBegin(SValBuilder &svalBuilder,
void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad, void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
CheckerContext &checkerContext) const { 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. // some new logic here that reasons directly about memory region extents.
// Once that logic is more mature, we can bring it back to assumeInBound() // Once that logic is more mature, we can bring it back to assumeInBound()
// for all clients to use. // 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 // memory access is within the extent of the base region. Since we
// have some flexibility in defining the base region, we can achieve // have some flexibility in defining the base region, we can achieve
// various levels of conservatism in our buffer overflow checking. // various levels of conservatism in our buffer overflow checking.
const GRState *state = checkerContext.getState(); const ProgramState *state = checkerContext.getState();
const GRState *originalState = state; const ProgramState *originalState = state;
SValBuilder &svalBuilder = checkerContext.getSValBuilder(); SValBuilder &svalBuilder = checkerContext.getSValBuilder();
const RegionRawOffsetV2 &rawOffset = const RegionRawOffsetV2 &rawOffset =
@ -116,7 +116,7 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
if (!lowerBoundToCheck) if (!lowerBoundToCheck)
return; return;
const GRState *state_precedesLowerBound, *state_withinLowerBound; const ProgramState *state_precedesLowerBound, *state_withinLowerBound;
llvm::tie(state_precedesLowerBound, state_withinLowerBound) = llvm::tie(state_precedesLowerBound, state_withinLowerBound) =
state->assume(*lowerBoundToCheck); state->assume(*lowerBoundToCheck);
@ -148,7 +148,7 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
if (!upperboundToCheck) if (!upperboundToCheck)
break; break;
const GRState *state_exceedsUpperBound, *state_withinUpperBound; const ProgramState *state_exceedsUpperBound, *state_withinUpperBound;
llvm::tie(state_exceedsUpperBound, state_withinUpperBound) = llvm::tie(state_exceedsUpperBound, state_withinUpperBound) =
state->assume(*upperboundToCheck); state->assume(*upperboundToCheck);
@ -168,7 +168,7 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
} }
void ArrayBoundCheckerV2::reportOOB(CheckerContext &checkerContext, void ArrayBoundCheckerV2::reportOOB(CheckerContext &checkerContext,
const GRState *errorState, const ProgramState *errorState,
OOB_Kind kind) const { OOB_Kind kind) const {
ExplodedNode *errorNode = checkerContext.generateSink(errorState); 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 // Scale a base value by a scaling factor, and return the scaled
// value as an SVal. Used by 'computeOffset'. // 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, NonLoc baseVal, CharUnits scaling,
SValBuilder &sb) { SValBuilder &sb) {
return sb.evalBinOpNN(state, BO_Mul, baseVal, 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 // Add an SVal to another, treating unknown and undefined values as
// summing to UnknownVal. Used by 'computeOffset'. // 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) { SValBuilder &svalBuilder) {
// We treat UnknownVals and UndefinedVals the same here because we // We treat UnknownVals and UndefinedVals the same here because we
// only care about computing offsets. // 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 /// Compute a raw byte offset from a base region. Used for array bounds
/// checking. /// checking.
RegionRawOffsetV2 RegionRawOffsetV2::computeOffset(const GRState *state, RegionRawOffsetV2 RegionRawOffsetV2::computeOffset(const ProgramState *state,
SValBuilder &svalBuilder, SValBuilder &svalBuilder,
SVal location) SVal location)
{ {

View File

@ -33,7 +33,7 @@ public:
void AttrNonNullChecker::checkPreStmt(const CallExpr *CE, void AttrNonNullChecker::checkPreStmt(const CallExpr *CE,
CheckerContext &C) const { CheckerContext &C) const {
const GRState *state = C.getState(); const ProgramState *state = C.getState();
// Check if the callee has a 'nonnull' attribute. // Check if the callee has a 'nonnull' attribute.
SVal X = state->getSVal(CE->getCallee()); SVal X = state->getSVal(CE->getCallee());
@ -85,7 +85,7 @@ void AttrNonNullChecker::checkPreStmt(const CallExpr *CE,
} }
ConstraintManager &CM = C.getConstraintManager(); ConstraintManager &CM = C.getConstraintManager();
const GRState *stateNotNull, *stateNull; const ProgramState *stateNotNull, *stateNull;
llvm::tie(stateNotNull, stateNull) = CM.assumeDual(state, *DV); llvm::tie(stateNotNull, stateNull) = CM.assumeDual(state, *DV);
if (stateNull && !stateNotNull) { if (stateNull && !stateNotNull) {

View File

@ -20,7 +20,7 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.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/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/AST/DeclObjC.h" #include "clang/AST/DeclObjC.h"
@ -249,7 +249,7 @@ static const char* GetCFNumberTypeStr(uint64_t i) {
void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE, void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE,
CheckerContext &C) const { CheckerContext &C) const {
const Expr *Callee = CE->getCallee(); const Expr *Callee = CE->getCallee();
const GRState *state = C.getState(); const ProgramState *state = C.getState();
SVal CallV = state->getSVal(Callee); SVal CallV = state->getSVal(Callee);
const FunctionDecl *FD = CallV.getAsFunctionDecl(); const FunctionDecl *FD = CallV.getAsFunctionDecl();
@ -363,7 +363,7 @@ void CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE,
return; return;
// Get the function declaration of the callee. // Get the function declaration of the callee.
const GRState *state = C.getState(); const ProgramState *state = C.getState();
SVal X = state->getSVal(CE->getCallee()); SVal X = state->getSVal(CE->getCallee());
const FunctionDecl *FD = X.getAsFunctionDecl(); const FunctionDecl *FD = X.getAsFunctionDecl();
@ -400,7 +400,7 @@ void CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE,
DefinedOrUnknownSVal ArgIsNull = svalBuilder.evalEQ(state, zero, *DefArgVal); DefinedOrUnknownSVal ArgIsNull = svalBuilder.evalEQ(state, zero, *DefArgVal);
// Are they equal? // Are they equal?
const GRState *stateTrue, *stateFalse; const ProgramState *stateTrue, *stateFalse;
llvm::tie(stateTrue, stateFalse) = state->assume(ArgIsNull); llvm::tie(stateTrue, stateFalse) = state->assume(ArgIsNull);
if (stateTrue && !stateFalse) { if (stateTrue && !stateFalse) {
@ -586,7 +586,7 @@ void VariadicMethodTypeChecker::checkPreObjCMessage(ObjCMessage msg,
// Verify that all arguments have Objective-C types. // Verify that all arguments have Objective-C types.
llvm::Optional<ExplodedNode*> errorNode; llvm::Optional<ExplodedNode*> errorNode;
const GRState *state = C.getState(); const ProgramState *state = C.getState();
for (unsigned I = variadicArgsBegin; I != variadicArgsEnd; ++I) { for (unsigned I = variadicArgsBegin; I != variadicArgsEnd; ++I) {
QualType ArgTy = msg.getArgType(I); QualType ArgTy = msg.getArgType(I);

View File

@ -31,7 +31,7 @@ public:
bool BuiltinFunctionChecker::evalCall(const CallExpr *CE, bool BuiltinFunctionChecker::evalCall(const CallExpr *CE,
CheckerContext &C) const{ CheckerContext &C) const{
const GRState *state = C.getState(); const ProgramState *state = C.getState();
const Expr *Callee = CE->getCallee(); const Expr *Callee = CE->getCallee();
SVal L = state->getSVal(Callee); SVal L = state->getSVal(Callee);
const FunctionDecl *FD = L.getAsFunctionDecl(); const FunctionDecl *FD = L.getAsFunctionDecl();

View File

@ -17,7 +17,7 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.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" #include "llvm/ADT/StringSwitch.h"
using namespace clang; using namespace clang;
@ -40,14 +40,15 @@ public:
bool evalCall(const CallExpr *CE, CheckerContext &C) const; bool evalCall(const CallExpr *CE, CheckerContext &C) const;
void checkPreStmt(const DeclStmt *DS, 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; 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 ProgramState *
const StoreManager::InvalidatedSymbols *, checkRegionChanges(const ProgramState *state,
const MemRegion * const *Begin, const StoreManager::InvalidatedSymbols *,
const MemRegion * const *End) const; const MemRegion * const *Begin,
const MemRegion * const *End) const;
typedef void (CStringChecker::*FnCheck)(CheckerContext &, typedef void (CStringChecker::*FnCheck)(CheckerContext &,
const CallExpr *) const; const CallExpr *) const;
@ -57,8 +58,10 @@ public:
void evalMemmove(CheckerContext &C, const CallExpr *CE) const; void evalMemmove(CheckerContext &C, const CallExpr *CE) const;
void evalBcopy(CheckerContext &C, const CallExpr *CE) const; void evalBcopy(CheckerContext &C, const CallExpr *CE) const;
void evalCopyCommon(CheckerContext &C, const CallExpr *CE, void evalCopyCommon(CheckerContext &C, const CallExpr *CE,
const GRState *state, const ProgramState *state,
const Expr *Size, const Expr *Source, const Expr *Dest, const Expr *Size,
const Expr *Source,
const Expr *Dest,
bool Restricted = false, bool Restricted = false,
bool IsMempcpy = false) const; bool IsMempcpy = false) const;
@ -66,14 +69,18 @@ public:
void evalstrLength(CheckerContext &C, const CallExpr *CE) const; void evalstrLength(CheckerContext &C, const CallExpr *CE) const;
void evalstrnLength(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; bool IsStrnlen = false) const;
void evalStrcpy(CheckerContext &C, const CallExpr *CE) const; void evalStrcpy(CheckerContext &C, const CallExpr *CE) const;
void evalStrncpy(CheckerContext &C, const CallExpr *CE) const; void evalStrncpy(CheckerContext &C, const CallExpr *CE) const;
void evalStpcpy(CheckerContext &C, const CallExpr *CE) const; void evalStpcpy(CheckerContext &C, const CallExpr *CE) const;
void evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, bool returnEnd, void evalStrcpyCommon(CheckerContext &C,
bool isBounded, bool isAppending) const; const CallExpr *CE,
bool returnEnd,
bool isBounded,
bool isAppending) const;
void evalStrcat(CheckerContext &C, const CallExpr *CE) const; void evalStrcat(CheckerContext &C, const CallExpr *CE) const;
void evalStrncat(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 evalStrncmp(CheckerContext &C, const CallExpr *CE) const;
void evalStrcasecmp(CheckerContext &C, const CallExpr *CE) const; void evalStrcasecmp(CheckerContext &C, const CallExpr *CE) const;
void evalStrncasecmp(CheckerContext &C, const CallExpr *CE) const; void evalStrncasecmp(CheckerContext &C, const CallExpr *CE) const;
void evalStrcmpCommon(CheckerContext &C, const CallExpr *CE, void evalStrcmpCommon(CheckerContext &C,
bool isBounded = false, bool ignoreCase = false) const; const CallExpr *CE,
bool isBounded = false,
bool ignoreCase = false) const;
// Utility methods // Utility methods
std::pair<const GRState*, const GRState*> std::pair<const ProgramState*, const ProgramState*>
static assumeZero(CheckerContext &C, 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, static const ProgramState *setCStringLength(const ProgramState *state,
const MemRegion *MR, SVal strLength); const MemRegion *MR,
SVal strLength);
static SVal getCStringLengthForRegion(CheckerContext &C, static SVal getCStringLengthForRegion(CheckerContext &C,
const GRState *&state, const ProgramState *&state,
const Expr *Ex, const MemRegion *MR, const Expr *Ex,
const MemRegion *MR,
bool hypothetical); bool hypothetical);
SVal getCStringLength(CheckerContext &C, const GRState *&state, SVal getCStringLength(CheckerContext &C,
const Expr *Ex, SVal Buf, const ProgramState *&state,
const Expr *Ex,
SVal Buf,
bool hypothetical = false) const; bool hypothetical = false) const;
const StringLiteral *getCStringLiteral(CheckerContext &C, const StringLiteral *getCStringLiteral(CheckerContext &C,
const GRState *&state, const ProgramState *&state,
const Expr *expr, const Expr *expr,
SVal val) const; SVal val) const;
static const GRState *InvalidateBuffer(CheckerContext &C, static const ProgramState *InvalidateBuffer(CheckerContext &C,
const GRState *state, const ProgramState *state,
const Expr *Ex, SVal V); const Expr *Ex, SVal V);
static bool SummarizeRegion(raw_ostream &os, ASTContext &Ctx, static bool SummarizeRegion(raw_ostream &os, ASTContext &Ctx,
const MemRegion *MR); const MemRegion *MR);
// Re-usable checks // Re-usable checks
const GRState *checkNonNull(CheckerContext &C, const GRState *state, const ProgramState *checkNonNull(CheckerContext &C,
const Expr *S, SVal l) const; const ProgramState *state,
const GRState *CheckLocation(CheckerContext &C, const GRState *state, const Expr *S,
const Expr *S, SVal l, SVal l) const;
const char *message = NULL) const; const ProgramState *CheckLocation(CheckerContext &C,
const GRState *CheckBufferAccess(CheckerContext &C, const GRState *state, const ProgramState *state,
const Expr *Size, const Expr *S,
const Expr *FirstBuf, SVal l,
const Expr *SecondBuf, const char *message = NULL) const;
const char *firstMessage = NULL, const ProgramState *CheckBufferAccess(CheckerContext &C,
const char *secondMessage = NULL, const ProgramState *state,
bool WarnAboutSize = false) const; const Expr *Size,
const GRState *CheckBufferAccess(CheckerContext &C, const GRState *state, const Expr *FirstBuf,
const Expr *Size, const Expr *Buf, const Expr *SecondBuf,
const char *message = NULL, const char *firstMessage = NULL,
bool WarnAboutSize = false) const { 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. // This is a convenience override.
return CheckBufferAccess(C, state, Size, Buf, NULL, message, NULL, return CheckBufferAccess(C, state, Size, Buf, NULL, message, NULL,
WarnAboutSize); WarnAboutSize);
} }
const GRState *CheckOverlap(CheckerContext &C, const GRState *state, const ProgramState *CheckOverlap(CheckerContext &C,
const Expr *Size, const Expr *First, const ProgramState *state,
const Expr *Second) const; const Expr *Size,
void emitOverlapBug(CheckerContext &C, const GRState *state, const Expr *First,
const Stmt *First, const Stmt *Second) const; const Expr *Second) const;
const GRState *checkAdditionOverflow(CheckerContext &C, const GRState *state, void emitOverlapBug(CheckerContext &C,
NonLoc left, NonLoc right) const; 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 { class CStringLength {
@ -151,8 +179,8 @@ public:
namespace clang { namespace clang {
namespace ento { namespace ento {
template <> template <>
struct GRStateTrait<CStringLength> struct ProgramStateTrait<CStringLength>
: public GRStatePartialTrait<CStringLength::EntryMap> { : public ProgramStatePartialTrait<CStringLength::EntryMap> {
static void *GDMIndex() { return CStringChecker::getTag(); } static void *GDMIndex() { return CStringChecker::getTag(); }
}; };
} }
@ -162,26 +190,26 @@ namespace ento {
// Individual checks and utility methods. // Individual checks and utility methods.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
std::pair<const GRState*, const GRState*> std::pair<const ProgramState*, const ProgramState*>
CStringChecker::assumeZero(CheckerContext &C, const GRState *state, SVal V, CStringChecker::assumeZero(CheckerContext &C, const ProgramState *state, SVal V,
QualType Ty) { QualType Ty) {
DefinedSVal *val = dyn_cast<DefinedSVal>(&V); DefinedSVal *val = dyn_cast<DefinedSVal>(&V);
if (!val) if (!val)
return std::pair<const GRState*, const GRState *>(state, state); return std::pair<const ProgramState*, const ProgramState *>(state, state);
SValBuilder &svalBuilder = C.getSValBuilder(); SValBuilder &svalBuilder = C.getSValBuilder();
DefinedOrUnknownSVal zero = svalBuilder.makeZeroVal(Ty); DefinedOrUnknownSVal zero = svalBuilder.makeZeroVal(Ty);
return state->assume(svalBuilder.evalEQ(state, *val, zero)); return state->assume(svalBuilder.evalEQ(state, *val, zero));
} }
const GRState *CStringChecker::checkNonNull(CheckerContext &C, const ProgramState *CStringChecker::checkNonNull(CheckerContext &C,
const GRState *state, const ProgramState *state,
const Expr *S, SVal l) const { const Expr *S, SVal l) const {
// If a previous check has failed, propagate the failure. // If a previous check has failed, propagate the failure.
if (!state) if (!state)
return NULL; return NULL;
const GRState *stateNull, *stateNonNull; const ProgramState *stateNull, *stateNonNull;
llvm::tie(stateNull, stateNonNull) = assumeZero(C, state, l, S->getType()); llvm::tie(stateNull, stateNonNull) = assumeZero(C, state, l, S->getType());
if (stateNull && !stateNonNull) { if (stateNull && !stateNonNull) {
@ -214,8 +242,8 @@ const GRState *CStringChecker::checkNonNull(CheckerContext &C,
} }
// FIXME: This was originally copied from ArrayBoundChecker.cpp. Refactor? // FIXME: This was originally copied from ArrayBoundChecker.cpp. Refactor?
const GRState *CStringChecker::CheckLocation(CheckerContext &C, const ProgramState *CStringChecker::CheckLocation(CheckerContext &C,
const GRState *state, const ProgramState *state,
const Expr *S, SVal l, const Expr *S, SVal l,
const char *warningMsg) const { const char *warningMsg) const {
// If a previous check has failed, propagate the failure. // 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. // Get the index of the accessed element.
DefinedOrUnknownSVal Idx = cast<DefinedOrUnknownSVal>(ER->getIndex()); DefinedOrUnknownSVal Idx = cast<DefinedOrUnknownSVal>(ER->getIndex());
const GRState *StInBound = state->assumeInBound(Idx, Size, true); const ProgramState *StInBound = state->assumeInBound(Idx, Size, true);
const GRState *StOutBound = state->assumeInBound(Idx, Size, false); const ProgramState *StOutBound = state->assumeInBound(Idx, Size, false);
if (StOutBound && !StInBound) { if (StOutBound && !StInBound) {
ExplodedNode *N = C.generateSink(StOutBound); ExplodedNode *N = C.generateSink(StOutBound);
if (!N) if (!N)
@ -287,8 +315,8 @@ const GRState *CStringChecker::CheckLocation(CheckerContext &C,
return StInBound; return StInBound;
} }
const GRState *CStringChecker::CheckBufferAccess(CheckerContext &C, const ProgramState *CStringChecker::CheckBufferAccess(CheckerContext &C,
const GRState *state, const ProgramState *state,
const Expr *Size, const Expr *Size,
const Expr *FirstBuf, const Expr *FirstBuf,
const Expr *SecondBuf, const Expr *SecondBuf,
@ -359,8 +387,8 @@ const GRState *CStringChecker::CheckBufferAccess(CheckerContext &C,
return state; return state;
} }
const GRState *CStringChecker::CheckOverlap(CheckerContext &C, const ProgramState *CStringChecker::CheckOverlap(CheckerContext &C,
const GRState *state, const ProgramState *state,
const Expr *Size, const Expr *Size,
const Expr *First, const Expr *First,
const Expr *Second) const { const Expr *Second) const {
@ -372,7 +400,7 @@ const GRState *CStringChecker::CheckOverlap(CheckerContext &C,
if (!state) if (!state)
return NULL; return NULL;
const GRState *stateTrue, *stateFalse; const ProgramState *stateTrue, *stateFalse;
// Get the buffer values and make sure they're known locations. // Get the buffer values and make sure they're known locations.
SVal firstVal = state->getSVal(First); SVal firstVal = state->getSVal(First);
@ -470,7 +498,7 @@ const GRState *CStringChecker::CheckOverlap(CheckerContext &C,
return stateFalse; 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 { const Stmt *First, const Stmt *Second) const {
ExplodedNode *N = C.generateSink(state); ExplodedNode *N = C.generateSink(state);
if (!N) if (!N)
@ -489,8 +517,8 @@ void CStringChecker::emitOverlapBug(CheckerContext &C, const GRState *state,
C.EmitReport(report); C.EmitReport(report);
} }
const GRState *CStringChecker::checkAdditionOverflow(CheckerContext &C, const ProgramState *CStringChecker::checkAdditionOverflow(CheckerContext &C,
const GRState *state, const ProgramState *state,
NonLoc left, NonLoc left,
NonLoc right) const { NonLoc right) const {
// If a previous check has failed, propagate the failure. // 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, SVal willOverflow = svalBuilder.evalBinOpNN(state, BO_GT, left,
*maxMinusRightNL, cmpTy); *maxMinusRightNL, cmpTy);
const GRState *stateOverflow, *stateOkay; const ProgramState *stateOverflow, *stateOkay;
llvm::tie(stateOverflow, stateOkay) = llvm::tie(stateOverflow, stateOkay) =
state->assume(cast<DefinedOrUnknownSVal>(willOverflow)); state->assume(cast<DefinedOrUnknownSVal>(willOverflow));
@ -557,7 +585,7 @@ const GRState *CStringChecker::checkAdditionOverflow(CheckerContext &C,
return state; return state;
} }
const GRState *CStringChecker::setCStringLength(const GRState *state, const ProgramState *CStringChecker::setCStringLength(const ProgramState *state,
const MemRegion *MR, const MemRegion *MR,
SVal strLength) { SVal strLength) {
assert(!strLength.isUndef() && "Attempt to set an undefined string length"); 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, SVal CStringChecker::getCStringLengthForRegion(CheckerContext &C,
const GRState *&state, const ProgramState *&state,
const Expr *Ex, const Expr *Ex,
const MemRegion *MR, const MemRegion *MR,
bool hypothetical) { bool hypothetical) {
@ -622,7 +650,7 @@ SVal CStringChecker::getCStringLengthForRegion(CheckerContext &C,
return strLength; return strLength;
} }
SVal CStringChecker::getCStringLength(CheckerContext &C, const GRState *&state, SVal CStringChecker::getCStringLength(CheckerContext &C, const ProgramState *&state,
const Expr *Ex, SVal Buf, const Expr *Ex, SVal Buf,
bool hypothetical) const { bool hypothetical) const {
const MemRegion *MR = Buf.getAsRegion(); const MemRegion *MR = Buf.getAsRegion();
@ -717,7 +745,7 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, const GRState *&state,
} }
const StringLiteral *CStringChecker::getCStringLiteral(CheckerContext &C, 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. // Get the memory region pointed to by the val.
const MemRegion *bufRegion = val.getAsRegion(); const MemRegion *bufRegion = val.getAsRegion();
@ -736,8 +764,8 @@ const StringLiteral *CStringChecker::getCStringLiteral(CheckerContext &C,
return strRegion->getStringLiteral(); return strRegion->getStringLiteral();
} }
const GRState *CStringChecker::InvalidateBuffer(CheckerContext &C, const ProgramState *CStringChecker::InvalidateBuffer(CheckerContext &C,
const GRState *state, const ProgramState *state,
const Expr *E, SVal V) { const Expr *E, SVal V) {
Loc *L = dyn_cast<Loc>(&V); Loc *L = dyn_cast<Loc>(&V);
if (!L) if (!L)
@ -810,7 +838,7 @@ bool CStringChecker::SummarizeRegion(raw_ostream &os, ASTContext &Ctx,
void CStringChecker::evalCopyCommon(CheckerContext &C, void CStringChecker::evalCopyCommon(CheckerContext &C,
const CallExpr *CE, const CallExpr *CE,
const GRState *state, const ProgramState *state,
const Expr *Size, const Expr *Dest, const Expr *Size, const Expr *Dest,
const Expr *Source, bool Restricted, const Expr *Source, bool Restricted,
bool IsMempcpy) const { bool IsMempcpy) const {
@ -820,7 +848,7 @@ void CStringChecker::evalCopyCommon(CheckerContext &C,
SVal sizeVal = state->getSVal(Size); SVal sizeVal = state->getSVal(Size);
QualType sizeTy = Size->getType(); QualType sizeTy = Size->getType();
const GRState *stateZeroSize, *stateNonZeroSize; const ProgramState *stateZeroSize, *stateNonZeroSize;
llvm::tie(stateZeroSize, stateNonZeroSize) = llvm::tie(stateZeroSize, stateNonZeroSize) =
assumeZero(C, state, sizeVal, sizeTy); 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); // void *memcpy(void *restrict dst, const void *restrict src, size_t n);
// The return value is the address of the destination buffer. // The return value is the address of the destination buffer.
const Expr *Dest = CE->getArg(0); 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); 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); // 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. // The return value is a pointer to the byte following the last written byte.
const Expr *Dest = CE->getArg(0); 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); 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); // void *memmove(void *dst, const void *src, size_t n);
// The return value is the address of the destination buffer. // The return value is the address of the destination buffer.
const Expr *Dest = CE->getArg(0); 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)); 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 *Right = CE->getArg(1);
const Expr *Size = CE->getArg(2); const Expr *Size = CE->getArg(2);
const GRState *state = C.getState(); const ProgramState *state = C.getState();
SValBuilder &svalBuilder = C.getSValBuilder(); SValBuilder &svalBuilder = C.getSValBuilder();
// See if the size argument is zero. // See if the size argument is zero.
SVal sizeVal = state->getSVal(Size); SVal sizeVal = state->getSVal(Size);
QualType sizeTy = Size->getType(); QualType sizeTy = Size->getType();
const GRState *stateZeroSize, *stateNonZeroSize; const ProgramState *stateZeroSize, *stateNonZeroSize;
llvm::tie(stateZeroSize, stateNonZeroSize) = llvm::tie(stateZeroSize, stateNonZeroSize) =
assumeZero(C, state, sizeVal, sizeTy); assumeZero(C, state, sizeVal, sizeTy);
@ -979,7 +1007,7 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const {
// See if they are the same. // See if they are the same.
DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV); DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV);
const GRState *StSameBuf, *StNotSameBuf; const ProgramState *StSameBuf, *StNotSameBuf;
llvm::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf); llvm::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);
// If the two arguments might be the same buffer, we know the result is 0, // 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, void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE,
bool IsStrnlen) const { bool IsStrnlen) const {
CurrentFunctionDescription = "string length function"; CurrentFunctionDescription = "string length function";
const GRState *state = C.getState(); const ProgramState *state = C.getState();
if (IsStrnlen) { if (IsStrnlen) {
const Expr *maxlenExpr = CE->getArg(1); const Expr *maxlenExpr = CE->getArg(1);
SVal maxlenVal = state->getSVal(maxlenExpr); SVal maxlenVal = state->getSVal(maxlenExpr);
const GRState *stateZeroSize, *stateNonZeroSize; const ProgramState *stateZeroSize, *stateNonZeroSize;
llvm::tie(stateZeroSize, stateNonZeroSize) = llvm::tie(stateZeroSize, stateNonZeroSize) =
assumeZero(C, state, maxlenVal, maxlenExpr->getType()); assumeZero(C, state, maxlenVal, maxlenExpr->getType());
@ -1082,7 +1110,7 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE,
NonLoc *maxlenValNL = dyn_cast<NonLoc>(&maxlenVal); NonLoc *maxlenValNL = dyn_cast<NonLoc>(&maxlenVal);
if (strLengthNL && maxlenValNL) { if (strLengthNL && maxlenValNL) {
const GRState *stateStringTooLong, *stateStringNotTooLong; const ProgramState *stateStringTooLong, *stateStringNotTooLong;
// Check if the strLength is greater than the maxlen. // Check if the strLength is greater than the maxlen.
llvm::tie(stateStringTooLong, stateStringNotTooLong) = llvm::tie(stateStringTooLong, stateStringNotTooLong) =
@ -1189,7 +1217,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
bool returnEnd, bool isBounded, bool returnEnd, bool isBounded,
bool isAppending) const { bool isAppending) const {
CurrentFunctionDescription = "string copy function"; CurrentFunctionDescription = "string copy function";
const GRState *state = C.getState(); const ProgramState *state = C.getState();
// Check that the destination is non-null. // Check that the destination is non-null.
const Expr *Dst = CE->getArg(0); 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 // If we know both values, we might be able to figure out how much
// we're copying. // we're copying.
if (strLengthNL && lenValNL) { 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. // 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- // 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, void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE,
bool isBounded, bool ignoreCase) const { bool isBounded, bool ignoreCase) const {
CurrentFunctionDescription = "string comparison function"; CurrentFunctionDescription = "string comparison function";
const GRState *state = C.getState(); const ProgramState *state = C.getState();
// Check that the first string is non-null // Check that the first string is non-null
const Expr *s1 = CE->getArg(0); const Expr *s1 = CE->getArg(0);
@ -1547,7 +1575,7 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE,
// See if they are the same. // See if they are the same.
SValBuilder &svalBuilder = C.getSValBuilder(); SValBuilder &svalBuilder = C.getSValBuilder();
DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV); DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV);
const GRState *StSameBuf, *StNotSameBuf; const ProgramState *StSameBuf, *StNotSameBuf;
llvm::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf); llvm::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);
// If the two arguments might be the same buffer, we know the result is 0, // 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 { bool CStringChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
// Get the callee. All the functions we care about are C functions // Get the callee. All the functions we care about are C functions
// with simple identifiers. // with simple identifiers.
const GRState *state = C.getState(); const ProgramState *state = C.getState();
const Expr *Callee = CE->getCallee(); const Expr *Callee = CE->getCallee();
const FunctionDecl *FD = state->getSVal(Callee).getAsFunctionDecl(); 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 { void CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
// Record string length for char a[] = "abc"; // 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(); for (DeclStmt::const_decl_iterator I = DS->decl_begin(), E = DS->decl_end();
I != E; ++I) { I != E; ++I) {
@ -1721,13 +1749,13 @@ void CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
C.addTransition(state); C.addTransition(state);
} }
bool CStringChecker::wantsRegionChangeUpdate(const GRState *state) const { bool CStringChecker::wantsRegionChangeUpdate(const ProgramState *state) const {
CStringLength::EntryMap Entries = state->get<CStringLength>(); CStringLength::EntryMap Entries = state->get<CStringLength>();
return !Entries.isEmpty(); return !Entries.isEmpty();
} }
const GRState * const ProgramState *
CStringChecker::checkRegionChanges(const GRState *state, CStringChecker::checkRegionChanges(const ProgramState *state,
const StoreManager::InvalidatedSymbols *, const StoreManager::InvalidatedSymbols *,
const MemRegion * const *Begin, const MemRegion * const *Begin,
const MemRegion * const *End) const { const MemRegion * const *End) const {
@ -1777,7 +1805,7 @@ CStringChecker::checkRegionChanges(const GRState *state,
return state->set<CStringLength>(Entries); return state->set<CStringLength>(Entries);
} }
void CStringChecker::checkLiveSymbols(const GRState *state, void CStringChecker::checkLiveSymbols(const ProgramState *state,
SymbolReaper &SR) const { SymbolReaper &SR) const {
// Mark all symbols in our string length map as valid. // Mark all symbols in our string length map as valid.
CStringLength::EntryMap Entries = state->get<CStringLength>(); CStringLength::EntryMap Entries = state->get<CStringLength>();
@ -1797,7 +1825,7 @@ void CStringChecker::checkDeadSymbols(SymbolReaper &SR,
if (!SR.hasDeadSymbols()) if (!SR.hasDeadSymbols())
return; return;
const GRState *state = C.getState(); const ProgramState *state = C.getState();
CStringLength::EntryMap Entries = state->get<CStringLength>(); CStringLength::EntryMap Entries = state->get<CStringLength>();
if (Entries.isEmpty()) if (Entries.isEmpty())
return; return;

View File

@ -47,7 +47,8 @@ private:
void emitNilReceiverBug(CheckerContext &C, const ObjCMessage &msg, void emitNilReceiverBug(CheckerContext &C, const ObjCMessage &msg,
ExplodedNode *N) const; ExplodedNode *N) const;
void HandleNilReceiver(CheckerContext &C, const GRState *state, void HandleNilReceiver(CheckerContext &C,
const ProgramState *state,
ObjCMessage msg) const; ObjCMessage msg) const;
static void LazyInit_BT(const char *desc, llvm::OwningPtr<BugType> &BT) { 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, void CallAndMessageChecker::checkPreObjCMessage(ObjCMessage msg,
CheckerContext &C) const { CheckerContext &C) const {
const GRState *state = C.getState(); const ProgramState *state = C.getState();
// FIXME: Handle 'super'? // FIXME: Handle 'super'?
if (const Expr *receiver = msg.getInstanceReceiver()) { if (const Expr *receiver = msg.getInstanceReceiver()) {
@ -238,7 +239,7 @@ void CallAndMessageChecker::checkPreObjCMessage(ObjCMessage msg,
// Bifurcate the state into nil and non-nil ones. // Bifurcate the state into nil and non-nil ones.
DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal); DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal);
const GRState *notNilState, *nilState; const ProgramState *notNilState, *nilState;
llvm::tie(notNilState, nilState) = state->assume(receiverVal); llvm::tie(notNilState, nilState) = state->assume(receiverVal);
// Handle receiver must be nil. // Handle receiver must be nil.
@ -288,7 +289,7 @@ static bool supportsNilWithFloatRet(const llvm::Triple &triple) {
} }
void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C, void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C,
const GRState *state, const ProgramState *state,
ObjCMessage msg) const { ObjCMessage msg) const {
ASTContext &Ctx = C.getASTContext(); ASTContext &Ctx = C.getASTContext();

View File

@ -44,7 +44,7 @@ void CastSizeChecker::checkPreStmt(const CastExpr *CE,CheckerContext &C) const {
if (ToPointeeTy->isIncompleteType()) if (ToPointeeTy->isIncompleteType())
return; return;
const GRState *state = C.getState(); const ProgramState *state = C.getState();
const MemRegion *R = state->getSVal(E).getAsRegion(); const MemRegion *R = state->getSVal(E).getAsRegion();
if (R == 0) if (R == 0)
return; return;

View File

@ -16,8 +16,8 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
#include "llvm/ADT/ImmutableMap.h" #include "llvm/ADT/ImmutableMap.h"
using namespace clang; using namespace clang;
@ -62,7 +62,7 @@ private:
} // end anonymous namespace } // end anonymous namespace
bool ChrootChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { bool ChrootChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
const GRState *state = C.getState(); const ProgramState *state = C.getState();
const Expr *Callee = CE->getCallee(); const Expr *Callee = CE->getCallee();
SVal L = state->getSVal(Callee); SVal L = state->getSVal(Callee);
const FunctionDecl *FD = L.getAsFunctionDecl(); 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 { void ChrootChecker::Chroot(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState(); const ProgramState *state = C.getState();
GRStateManager &Mgr = state->getStateManager(); ProgramStateManager &Mgr = state->getStateManager();
// Once encouter a chroot(), set the enum value ROOT_CHANGED directly in // Once encouter a chroot(), set the enum value ROOT_CHANGED directly in
// the GDM. // the GDM.
@ -98,8 +98,8 @@ void ChrootChecker::Chroot(CheckerContext &C, const CallExpr *CE) const {
} }
void ChrootChecker::Chdir(CheckerContext &C, const CallExpr *CE) const { void ChrootChecker::Chdir(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState(); const ProgramState *state = C.getState();
GRStateManager &Mgr = state->getStateManager(); ProgramStateManager &Mgr = state->getStateManager();
// If there are no jail state in the GDM, just return. // If there are no jail state in the GDM, just return.
const void *k = state->FindGDM(ChrootChecker::getTag()); 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(). // Check the jail state before any function call except chroot and chdir().
void ChrootChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const { void ChrootChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const {
const GRState *state = C.getState(); const ProgramState *state = C.getState();
const Expr *Callee = CE->getCallee(); const Expr *Callee = CE->getCallee();
SVal L = state->getSVal(Callee); SVal L = state->getSVal(Callee);
const FunctionDecl *FD = L.getAsFunctionDecl(); const FunctionDecl *FD = L.getAsFunctionDecl();

View File

@ -89,8 +89,8 @@ void DereferenceChecker::checkLocation(SVal l, bool isLoad,
return; return;
const Stmt *S = C.getStmt(); const Stmt *S = C.getStmt();
const GRState *state = C.getState(); const ProgramState *state = C.getState();
const GRState *notNullState, *nullState; const ProgramState *notNullState, *nullState;
llvm::tie(notNullState, nullState) = state->assume(location); llvm::tie(notNullState, nullState) = state->assume(location);
// The explicit NULL case. // The explicit NULL case.

View File

@ -52,7 +52,7 @@ void DivZeroChecker::checkPreStmt(const BinaryOperator *B,
// Check for divide by zero. // Check for divide by zero.
ConstraintManager &CM = C.getConstraintManager(); ConstraintManager &CM = C.getConstraintManager();
const GRState *stateNotZero, *stateZero; const ProgramState *stateNotZero, *stateZero;
llvm::tie(stateNotZero, stateZero) = CM.assumeDual(C.getState(), *DV); llvm::tie(stateNotZero, stateZero) = CM.assumeDual(C.getState(), *DV);
if (stateZero && !stateNotZero) { if (stateZero && !stateNotZero) {

View File

@ -44,7 +44,7 @@ void FixedAddressChecker::checkPreStmt(const BinaryOperator *B,
if (!T->isPointerType()) if (!T->isPointerType())
return; return;
const GRState *state = C.getState(); const ProgramState *state = C.getState();
SVal RV = state->getSVal(B->getRHS()); SVal RV = state->getSVal(B->getRHS());

View File

@ -143,7 +143,7 @@ void IdempotentOperationChecker::checkPreStmt(const BinaryOperator *B,
|| containsNonLocalVarDecl(RHS); || containsNonLocalVarDecl(RHS);
} }
const GRState *state = C.getState(); const ProgramState *state = C.getState();
SVal LHSVal = state->getSVal(LHS); SVal LHSVal = state->getSVal(LHS);
SVal RHSVal = state->getSVal(RHS); SVal RHSVal = state->getSVal(RHS);

View File

@ -20,7 +20,7 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.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/DeclCXX.h"
#include "clang/AST/Decl.h" #include "clang/AST/Decl.h"
#include "clang/AST/Type.h" #include "clang/AST/Type.h"
@ -117,16 +117,28 @@ public:
CheckerContext &C) const; CheckerContext &C) const;
private: private:
const GRState *handleAssign(const GRState *state, const Expr *lexp, const ProgramState *handleAssign(const ProgramState *state,
const Expr *rexp, const LocationContext *LC) const; const Expr *lexp,
const GRState *handleAssign(const GRState *state, const MemRegion *MR, const Expr *rexp,
const Expr *rexp, const LocationContext *LC) const; const LocationContext *LC) const;
const GRState *invalidateIterators(const GRState *state, const MemRegion *MR,
const MemberExpr *ME) 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 checkExpr(CheckerContext &C, const Expr *E) const;
void checkArgs(CheckerContext &C, const CallExpr *CE) 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; const DeclRefExpr *getDeclRefExpr(const Expr *E) const;
}; };
@ -139,8 +151,8 @@ public:
namespace clang { namespace clang {
namespace ento { namespace ento {
template <> template <>
struct GRStateTrait<IteratorState> struct ProgramStateTrait<IteratorState>
: public GRStatePartialTrait<IteratorState::EntryMap> { : public ProgramStatePartialTrait<IteratorState::EntryMap> {
static void *GDMIndex() { return IteratorsChecker::getTag(); } 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 // Iterate through our map and invalidate any iterators that were
// initialized fromt the specified instance MemRegion. // 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 { const MemRegion *MR, const MemberExpr *ME) const {
IteratorState::EntryMap Map = state->get<IteratorState>(); IteratorState::EntryMap Map = state->get<IteratorState>();
if (Map.isEmpty()) 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. // 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 { const Expr *lexp, const Expr *rexp, const LocationContext *LC) const {
// Skip the cast if present. // Skip the cast if present.
if (const MaterializeTemporaryExpr *M if (const MaterializeTemporaryExpr *M
@ -259,7 +271,7 @@ const GRState *IteratorsChecker::handleAssign(const GRState *state,
} }
// handle assigning to an iterator // 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 { const MemRegion *MR, const Expr *rexp, const LocationContext *LC) const {
// Assume unknown until we find something definite. // Assume unknown until we find something definite.
state = state->set<IteratorState>(MR, RefState::getUnknown()); 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. // 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 Expr *E, const LocationContext *LC) const {
const DeclRefExpr *DRE = getDeclRefExpr(E); const DeclRefExpr *DRE = getDeclRefExpr(E);
if (!DRE) 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 // use those nodes. We also cannot create multiple nodes at one ProgramPoint
// with the same tag. // with the same tag.
void IteratorsChecker::checkExpr(CheckerContext &C, const Expr *E) const { 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, const MemRegion *MR = getRegion(state, E,
C.getPredecessor()->getLocationContext()); C.getPredecessor()->getLocationContext());
if (!MR) if (!MR)
@ -455,7 +467,7 @@ void IteratorsChecker::checkPreStmt(const CXXOperatorCallExpr *OCE,
CheckerContext &C) const CheckerContext &C) const
{ {
const LocationContext *LC = C.getPredecessor()->getLocationContext(); const LocationContext *LC = C.getPredecessor()->getLocationContext();
const GRState *state = C.getState(); const ProgramState *state = C.getState();
OverloadedOperatorKind Kind = OCE->getOperator(); OverloadedOperatorKind Kind = OCE->getOperator();
if (Kind == OO_Equal) { if (Kind == OO_Equal) {
checkExpr(C, OCE->getArg(1)); checkExpr(C, OCE->getArg(1));
@ -512,7 +524,7 @@ void IteratorsChecker::checkPreStmt(const DeclStmt *DS,
return; return;
// Get the MemRegion associated with the iterator and mark it as Undefined. // 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()); Loc VarLoc = state->getLValue(VD, C.getPredecessor()->getLocationContext());
const MemRegion *MR = VarLoc.getAsRegion(); const MemRegion *MR = VarLoc.getAsRegion();
if (!MR) if (!MR)
@ -544,8 +556,8 @@ void IteratorsChecker::checkPreStmt(const DeclStmt *DS,
namespace { struct CalledReserved {}; } namespace { struct CalledReserved {}; }
namespace clang { namespace ento { namespace clang { namespace ento {
template<> struct GRStateTrait<CalledReserved> template<> struct ProgramStateTrait<CalledReserved>
: public GRStatePartialTrait<llvm::ImmutableSet<const MemRegion*> > { : public ProgramStatePartialTrait<llvm::ImmutableSet<const MemRegion*> > {
static void *GDMIndex() { static int index = 0; return &index; } static void *GDMIndex() { static int index = 0; return &index; }
}; };
}} }}
@ -571,7 +583,7 @@ void IteratorsChecker::checkPreStmt(const CXXMemberCallExpr *MCE,
return; return;
// If we are calling a function that invalidates iterators, mark them // If we are calling a function that invalidates iterators, mark them
// appropriately by finding matching instances. // appropriately by finding matching instances.
const GRState *state = C.getState(); const ProgramState *state = C.getState();
StringRef mName = ME->getMemberDecl()->getName(); StringRef mName = ME->getMemberDecl()->getName();
if (llvm::StringSwitch<bool>(mName) if (llvm::StringSwitch<bool>(mName)
.Cases("insert", "reserve", "push_back", true) .Cases("insert", "reserve", "push_back", true)

View File

@ -17,8 +17,8 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
using namespace clang; using namespace clang;
using namespace ento; using namespace ento;
@ -90,13 +90,13 @@ private:
/// Check if RetSym evaluates to an error value in the current state. /// Check if RetSym evaluates to an error value in the current state.
bool definitelyReturnedError(SymbolRef RetSym, bool definitelyReturnedError(SymbolRef RetSym,
const GRState *State, const ProgramState *State,
SValBuilder &Builder, SValBuilder &Builder,
bool noError = false) const; bool noError = false) const;
/// Check if RetSym evaluates to a NoErr value in the current state. /// Check if RetSym evaluates to a NoErr value in the current state.
bool definitelyDidnotReturnError(SymbolRef RetSym, bool definitelyDidnotReturnError(SymbolRef RetSym,
const GRState *State, const ProgramState *State,
SValBuilder &Builder) const { SValBuilder &Builder) const {
return definitelyReturnedError(RetSym, State, Builder, true); 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 /// This is a map from the allocated content symbol to the corresponding
/// AllocationState. /// AllocationState.
typedef llvm::ImmutableMap<SymbolRef, typedef llvm::ImmutableMap<SymbolRef,
@ -112,8 +112,8 @@ typedef llvm::ImmutableMap<SymbolRef,
namespace { struct AllocatedData {}; } namespace { struct AllocatedData {}; }
namespace clang { namespace ento { namespace clang { namespace ento {
template<> struct GRStateTrait<AllocatedData> template<> struct ProgramStateTrait<AllocatedData>
: public GRStatePartialTrait<AllocatedSetTy > { : public ProgramStatePartialTrait<AllocatedSetTy > {
static void *GDMIndex() { static int index = 0; return &index; } 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. /// that value is itself an address, and return the corresponding symbol.
static SymbolRef getAsPointeeSymbol(const Expr *Expr, static SymbolRef getAsPointeeSymbol(const Expr *Expr,
CheckerContext &C) { CheckerContext &C) {
const GRState *State = C.getState(); const ProgramState *State = C.getState();
SVal ArgV = State->getSVal(Expr); SVal ArgV = State->getSVal(Expr);
if (const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(&ArgV)) { 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 (1).
// If !noError, returns true iff (2). // If !noError, returns true iff (2).
bool MacOSKeychainAPIChecker::definitelyReturnedError(SymbolRef RetSym, bool MacOSKeychainAPIChecker::definitelyReturnedError(SymbolRef RetSym,
const GRState *State, const ProgramState *State,
SValBuilder &Builder, SValBuilder &Builder,
bool noError) const { bool noError) const {
DefinedOrUnknownSVal NoErrVal = Builder.makeIntVal(NoErr, DefinedOrUnknownSVal NoErrVal = Builder.makeIntVal(NoErr,
Builder.getSymbolManager().getType(RetSym)); Builder.getSymbolManager().getType(RetSym));
DefinedOrUnknownSVal NoErr = Builder.evalEQ(State, NoErrVal, DefinedOrUnknownSVal NoErr = Builder.evalEQ(State, NoErrVal,
nonloc::SymbolVal(RetSym)); nonloc::SymbolVal(RetSym));
const GRState *ErrState = State->assume(NoErr, noError); const ProgramState *ErrState = State->assume(NoErr, noError);
if (ErrState == State) { if (ErrState == State) {
return true; return true;
} }
@ -211,7 +211,7 @@ bool MacOSKeychainAPIChecker::definitelyReturnedError(SymbolRef RetSym,
void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE, void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
CheckerContext &C) const { CheckerContext &C) const {
const GRState *State = C.getState(); const ProgramState *State = C.getState();
const Expr *Callee = CE->getCallee(); const Expr *Callee = CE->getCallee();
SVal L = State->getSVal(Callee); SVal L = State->getSVal(Callee);
unsigned idx = InvalidIdx; unsigned idx = InvalidIdx;
@ -331,7 +331,7 @@ void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
void MacOSKeychainAPIChecker::checkPostStmt(const CallExpr *CE, void MacOSKeychainAPIChecker::checkPostStmt(const CallExpr *CE,
CheckerContext &C) const { CheckerContext &C) const {
const GRState *State = C.getState(); const ProgramState *State = C.getState();
const Expr *Callee = CE->getCallee(); const Expr *Callee = CE->getCallee();
SVal L = State->getSVal(Callee); SVal L = State->getSVal(Callee);
@ -385,7 +385,7 @@ void MacOSKeychainAPIChecker::checkPreStmt(const ReturnStmt *S,
return; return;
// Check if the value is escaping through the 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(); const MemRegion *V = state->getSVal(retExpr).getAsRegion();
if (!V) if (!V)
return; return;
@ -413,7 +413,7 @@ RangedBugReport *MacOSKeychainAPIChecker::
void MacOSKeychainAPIChecker::checkDeadSymbols(SymbolReaper &SR, void MacOSKeychainAPIChecker::checkDeadSymbols(SymbolReaper &SR,
CheckerContext &C) const { CheckerContext &C) const {
const GRState *State = C.getState(); const ProgramState *State = C.getState();
AllocatedSetTy ASet = State->get<AllocatedData>(); AllocatedSetTy ASet = State->get<AllocatedData>();
if (ASet.isEmpty()) if (ASet.isEmpty())
return; return;
@ -451,7 +451,7 @@ void MacOSKeychainAPIChecker::checkDeadSymbols(SymbolReaper &SR,
// TODO: Remove this after we ensure that checkDeadSymbols are always called. // TODO: Remove this after we ensure that checkDeadSymbols are always called.
void MacOSKeychainAPIChecker::checkEndPath(EndOfFunctionNodeBuilder &B, void MacOSKeychainAPIChecker::checkEndPath(EndOfFunctionNodeBuilder &B,
ExprEngine &Eng) const { ExprEngine &Eng) const {
const GRState *state = B.getState(); const ProgramState *state = B.getState();
AllocatedSetTy AS = state->get<AllocatedData>(); AllocatedSetTy AS = state->get<AllocatedData>();
if (AS.isEmpty()) if (AS.isEmpty())
return; return;

View File

@ -20,7 +20,7 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.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 "clang/Basic/TargetInfo.h"
#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.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 // Check if the first argument is stack allocated. If so, issue a warning
// because that's likely to be bad news. // 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(); const MemRegion *R = state->getSVal(CE->getArg(0)).getAsRegion();
if (!R || !isa<StackSpaceRegion>(R->getMemorySpace())) if (!R || !isa<StackSpaceRegion>(R->getMemorySpace()))
return; return;
@ -94,7 +94,7 @@ void MacOSXAPIChecker::checkPreStmt(const CallExpr *CE,
CheckerContext &C) const { CheckerContext &C) const {
// FIXME: This sort of logic is common to several checkers, including // FIXME: This sort of logic is common to several checkers, including
// UnixAPIChecker, PthreadLockChecker, and CStringChecker. Should refactor. // UnixAPIChecker, PthreadLockChecker, and CStringChecker. Should refactor.
const GRState *state = C.getState(); const ProgramState *state = C.getState();
const Expr *Callee = CE->getCallee(); const Expr *Callee = CE->getCallee();
const FunctionDecl *Fn = state->getSVal(Callee).getAsFunctionDecl(); const FunctionDecl *Fn = state->getSVal(Callee).getAsFunctionDecl();

View File

@ -17,8 +17,8 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
#include "llvm/ADT/ImmutableMap.h" #include "llvm/ADT/ImmutableMap.h"
using namespace clang; using namespace clang;
@ -80,7 +80,7 @@ public:
void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const; void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
void checkEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng) const; void checkEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng) const;
void checkPreStmt(const ReturnStmt *S, CheckerContext &C) 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; bool Assumption) const;
void checkLocation(SVal l, bool isLoad, CheckerContext &C) const; void checkLocation(SVal l, bool isLoad, CheckerContext &C) const;
void checkBind(SVal location, SVal val, 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 MallocMem(CheckerContext &C, const CallExpr *CE);
static void MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE, static void MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE,
const OwnershipAttr* Att); 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 Expr *SizeEx, SVal Init,
const GRState *state) { const ProgramState *state) {
return MallocMemAux(C, CE, state->getSVal(SizeEx), Init, 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, SVal SizeEx, SVal Init,
const GRState *state); const ProgramState *state);
void FreeMem(CheckerContext &C, const CallExpr *CE) const; void FreeMem(CheckerContext &C, const CallExpr *CE) const;
void FreeMemAttr(CheckerContext &C, const CallExpr *CE, void FreeMemAttr(CheckerContext &C, const CallExpr *CE,
const OwnershipAttr* Att) const; const OwnershipAttr* Att) const;
const GRState *FreeMemAux(CheckerContext &C, const CallExpr *CE, const ProgramState *FreeMemAux(CheckerContext &C, const CallExpr *CE,
const GRState *state, unsigned Num, bool Hold) const; const ProgramState *state, unsigned Num, bool Hold) const;
void ReallocMem(CheckerContext &C, const CallExpr *CE) const; void ReallocMem(CheckerContext &C, const CallExpr *CE) const;
static void CallocMem(CheckerContext &C, const CallExpr *CE); static void CallocMem(CheckerContext &C, const CallExpr *CE);
@ -118,15 +118,15 @@ typedef llvm::ImmutableMap<SymbolRef, RefState> RegionStateTy;
namespace clang { namespace clang {
namespace ento { namespace ento {
template <> template <>
struct GRStateTrait<RegionState> struct ProgramStateTrait<RegionState>
: public GRStatePartialTrait<RegionStateTy> { : public ProgramStatePartialTrait<RegionStateTy> {
static void *GDMIndex() { static int x; return &x; } static void *GDMIndex() { static int x; return &x; }
}; };
} }
} }
bool MallocChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { bool MallocChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
const GRState *state = C.getState(); const ProgramState *state = C.getState();
const Expr *Callee = CE->getCallee(); const Expr *Callee = CE->getCallee();
SVal L = state->getSVal(Callee); 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) { 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.getState());
C.addTransition(state); 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(); OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
if (I != E) { if (I != E) {
const GRState *state = const ProgramState *state =
MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), C.getState()); MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), C.getState());
C.addTransition(state); C.addTransition(state);
return; return;
} }
const GRState *state = MallocMemAux(C, CE, UnknownVal(), UndefinedVal(), const ProgramState *state = MallocMemAux(C, CE, UnknownVal(), UndefinedVal(),
C.getState()); C.getState());
C.addTransition(state); C.addTransition(state);
} }
const GRState *MallocChecker::MallocMemAux(CheckerContext &C, const ProgramState *MallocChecker::MallocMemAux(CheckerContext &C,
const CallExpr *CE, const CallExpr *CE,
SVal Size, SVal Init, SVal Size, SVal Init,
const GRState *state) { const ProgramState *state) {
unsigned Count = C.getNodeBuilder().getCurrentBlockCount(); unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
SValBuilder &svalBuilder = C.getSValBuilder(); SValBuilder &svalBuilder = C.getSValBuilder();
@ -247,7 +247,7 @@ const GRState *MallocChecker::MallocMemAux(CheckerContext &C,
} }
void MallocChecker::FreeMem(CheckerContext &C, const CallExpr *CE) const { 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) if (state)
C.addTransition(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(); for (OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
I != E; ++I) { 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); Att->getOwnKind() == OwnershipAttr::Holds);
if (state) if (state)
C.addTransition(state); C.addTransition(state);
} }
} }
const GRState *MallocChecker::FreeMemAux(CheckerContext &C, const CallExpr *CE, const ProgramState *MallocChecker::FreeMemAux(CheckerContext &C, const CallExpr *CE,
const GRState *state, unsigned Num, const ProgramState *state, unsigned Num,
bool Hold) const { bool Hold) const {
const Expr *ArgExpr = CE->getArg(Num); const Expr *ArgExpr = CE->getArg(Num);
SVal ArgVal = state->getSVal(ArgExpr); 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 // FIXME: Technically using 'Assume' here can result in a path
// bifurcation. In such cases we need to return two states, not just one. // 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); llvm::tie(notNullState, nullState) = state->assume(location);
// The explicit NULL case, no operation is performed. // 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 { 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); const Expr *arg0Expr = CE->getArg(0);
DefinedOrUnknownSVal arg0Val DefinedOrUnknownSVal arg0Val
= cast<DefinedOrUnknownSVal>(state->getSVal(arg0Expr)); = 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 // If the ptr is NULL and the size is not 0, the call is equivalent to
// malloc(size). // malloc(size).
const GRState *stateEqual = state->assume(PtrEQ, true); const ProgramState *stateEqual = state->assume(PtrEQ, true);
if (stateEqual && state->assume(SizeZero, false)) { if (stateEqual && state->assume(SizeZero, false)) {
// Hack: set the NULL symbolic region to released to suppress false warning. // 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., // 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) if (Sym)
stateEqual = stateEqual->set<RegionState>(Sym, RefState::getReleased(CE)); 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); UndefinedVal(), stateEqual);
C.addTransition(stateMalloc); 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 the size is 0, free the memory.
if (const GRState *stateSizeZero = stateNotEqual->assume(SizeZero, true)) if (const ProgramState *stateSizeZero = stateNotEqual->assume(SizeZero, true))
if (const GRState *stateFree = if (const ProgramState *stateFree =
FreeMemAux(C, CE, stateSizeZero, 0, false)) { FreeMemAux(C, CE, stateSizeZero, 0, false)) {
// Add the state transition to set input pointer argument to be free. // 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. // Bind the return value to UndefinedVal because it is now free.
C.addTransition(stateFree->BindExpr(CE, UndefinedVal(), true)); C.addTransition(stateFree->BindExpr(CE, UndefinedVal(), true));
} }
if (const GRState *stateSizeNotZero = stateNotEqual->assume(SizeZero,false)) if (const ProgramState *stateSizeNotZero = stateNotEqual->assume(SizeZero,false))
if (const GRState *stateFree = FreeMemAux(C, CE, stateSizeNotZero, if (const ProgramState *stateFree = FreeMemAux(C, CE, stateSizeNotZero,
0, false)) { 0, false)) {
// FIXME: We should copy the content of the original buffer. // 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); UnknownVal(), stateFree);
C.addTransition(stateRealloc); C.addTransition(stateRealloc);
} }
@ -556,7 +556,7 @@ void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) const {
} }
void MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE) { void MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE) {
const GRState *state = C.getState(); const ProgramState *state = C.getState();
SValBuilder &svalBuilder = C.getSValBuilder(); SValBuilder &svalBuilder = C.getSValBuilder();
SVal count = state->getSVal(CE->getArg(0)); SVal count = state->getSVal(CE->getArg(0));
@ -574,7 +574,7 @@ void MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper,
if (!SymReaper.hasDeadSymbols()) if (!SymReaper.hasDeadSymbols())
return; return;
const GRState *state = C.getState(); const ProgramState *state = C.getState();
RegionStateTy RS = state->get<RegionState>(); RegionStateTy RS = state->get<RegionState>();
RegionStateTy::Factory &F = state->get_context<RegionState>(); RegionStateTy::Factory &F = state->get_context<RegionState>();
@ -607,7 +607,7 @@ void MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper,
void MallocChecker::checkEndPath(EndOfFunctionNodeBuilder &B, void MallocChecker::checkEndPath(EndOfFunctionNodeBuilder &B,
ExprEngine &Eng) const { ExprEngine &Eng) const {
const GRState *state = B.getState(); const ProgramState *state = B.getState();
RegionStateTy M = state->get<RegionState>(); RegionStateTy M = state->get<RegionState>();
for (RegionStateTy::iterator I = M.begin(), E = M.end(); I != E; ++I) { 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) if (!retExpr)
return; return;
const GRState *state = C.getState(); const ProgramState *state = C.getState();
SymbolRef Sym = state->getSVal(retExpr).getAsSymbol(); SymbolRef Sym = state->getSVal(retExpr).getAsSymbol();
if (!Sym) if (!Sym)
@ -647,7 +647,7 @@ void MallocChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const {
C.addTransition(state); C.addTransition(state);
} }
const GRState *MallocChecker::evalAssume(const GRState *state, SVal Cond, const ProgramState *MallocChecker::evalAssume(const ProgramState *state, SVal Cond,
bool Assumption) const { bool Assumption) const {
// If a symblic region is assumed to NULL, set its state to AllocateFailed. // If a symblic region is assumed to NULL, set its state to AllocateFailed.
// FIXME: should also check symbols assumed to non-null. // 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 // assignment, let it go. However, assigning to fields of a stack-storage
// structure does not transfer ownership. // structure does not transfer ownership.
const GRState *state = C.getState(); const ProgramState *state = C.getState();
DefinedOrUnknownSVal l = cast<DefinedOrUnknownSVal>(location); DefinedOrUnknownSVal l = cast<DefinedOrUnknownSVal>(location);
// Check for null dereferences. // Check for null dereferences.
@ -701,7 +701,7 @@ void MallocChecker::checkBind(SVal location, SVal val,CheckerContext &C) const {
if (Sym) { if (Sym) {
if (const RefState *RS = state->get<RegionState>(Sym)) { if (const RefState *RS = state->get<RegionState>(Sym)) {
// If ptr is NULL, no operation is performed. // If ptr is NULL, no operation is performed.
const GRState *notNullState, *nullState; const ProgramState *notNullState, *nullState;
llvm::tie(notNullState, nullState) = state->assume(l); llvm::tie(notNullState, nullState) = state->assume(l);
// Generate a transition for 'nullState' to record the assumption // Generate a transition for 'nullState' to record the assumption

View File

@ -19,7 +19,7 @@
#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.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/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/AST/DeclObjC.h" #include "clang/AST/DeclObjC.h"
#include "clang/AST/Decl.h" #include "clang/AST/Decl.h"
@ -166,18 +166,18 @@ typedef llvm::ImmutableMap<SymbolRef, unsigned> ErrorOutFlag;
namespace clang { namespace clang {
namespace ento { namespace ento {
template <> template <>
struct GRStateTrait<NSErrorOut> : public GRStatePartialTrait<ErrorOutFlag> { struct ProgramStateTrait<NSErrorOut> : public ProgramStatePartialTrait<ErrorOutFlag> {
static void *GDMIndex() { static int index = 0; return &index; } static void *GDMIndex() { static int index = 0; return &index; }
}; };
template <> template <>
struct GRStateTrait<CFErrorOut> : public GRStatePartialTrait<ErrorOutFlag> { struct ProgramStateTrait<CFErrorOut> : public ProgramStatePartialTrait<ErrorOutFlag> {
static void *GDMIndex() { static int index = 0; return &index; } static void *GDMIndex() { static int index = 0; return &index; }
}; };
} }
} }
template <typename T> 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 (SymbolRef sym = val.getAsSymbol())
if (const unsigned *attachedFlags = state->get<T>(sym)) if (const unsigned *attachedFlags = state->get<T>(sym))
return *attachedFlags; return *attachedFlags;
@ -185,7 +185,7 @@ static bool hasFlag(SVal val, const GRState *state) {
} }
template <typename T> 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. // We tag the symbol that the SVal wraps.
if (SymbolRef sym = val.getAsSymbol()) if (SymbolRef sym = val.getAsSymbol())
C.addTransition(state->set<T>(sym, true)); C.addTransition(state->set<T>(sym, true));
@ -214,7 +214,7 @@ void NSOrCFErrorDerefChecker::checkLocation(SVal loc, bool isLoad,
return; return;
ASTContext &Ctx = C.getASTContext(); 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 // If we are loading from NSError**/CFErrorRef* parameter, mark the resulting
// SVal so that we can later check it when handling the // SVal so that we can later check it when handling the
@ -247,7 +247,7 @@ void NSOrCFErrorDerefChecker::checkEvent(ImplicitNullDerefEvent event) const {
return; return;
SVal loc = event.Location; SVal loc = event.Location;
const GRState *state = event.SinkNode->getState(); const ProgramState *state = event.SinkNode->getState();
BugReporter &BR = *event.BR; BugReporter &BR = *event.BR;
bool isNSError = hasFlag<NSErrorOut>(loc, state); bool isNSError = hasFlag<NSErrorOut>(loc, state);

View File

@ -32,7 +32,7 @@ public:
void NoReturnFunctionChecker::checkPostStmt(const CallExpr *CE, void NoReturnFunctionChecker::checkPostStmt(const CallExpr *CE,
CheckerContext &C) const { CheckerContext &C) const {
const GRState *state = C.getState(); const ProgramState *state = C.getState();
const Expr *Callee = CE->getCallee(); const Expr *Callee = CE->getCallee();
bool BuildSinks = getFunctionExtInfo(Callee->getType()).getNoReturn(); bool BuildSinks = getFunctionExtInfo(Callee->getType()).getNoReturn();

View File

@ -33,7 +33,7 @@ private:
} }
bool OSAtomicChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { bool OSAtomicChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
const GRState *state = C.getState(); const ProgramState *state = C.getState();
const Expr *Callee = CE->getCallee(); const Expr *Callee = CE->getCallee();
SVal L = state->getSVal(Callee); SVal L = state->getSVal(Callee);
@ -92,7 +92,7 @@ bool OSAtomicChecker::evalOSAtomicCompareAndSwap(CheckerContext &C,
// Load 'theValue'. // Load 'theValue'.
ExprEngine &Engine = C.getEngine(); ExprEngine &Engine = C.getEngine();
const GRState *state = C.getState(); const ProgramState *state = C.getState();
ExplodedNodeSet Tmp; ExplodedNodeSet Tmp;
SVal location = state->getSVal(theValueExpr); SVal location = state->getSVal(theValueExpr);
// Here we should use the value type of the region as the load type, because // 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) { I != E; ++I) {
ExplodedNode *N = *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 // Use direct bindings from the environment since we are forcing a load
// from a location that the Environment would typically not be used // from a location that the Environment would typically not be used
@ -148,7 +148,7 @@ bool OSAtomicChecker::evalOSAtomicCompareAndSwap(CheckerContext &C,
DefinedOrUnknownSVal Cmp = DefinedOrUnknownSVal Cmp =
svalBuilder.evalEQ(stateLoad,theValueVal,oldValueVal); svalBuilder.evalEQ(stateLoad,theValueVal,oldValueVal);
const GRState *stateEqual = stateLoad->assume(Cmp, true); const ProgramState *stateEqual = stateLoad->assume(Cmp, true);
// Were they equal? // Were they equal?
if (stateEqual) { if (stateEqual) {
@ -178,7 +178,7 @@ bool OSAtomicChecker::evalOSAtomicCompareAndSwap(CheckerContext &C,
for (ExplodedNodeSet::iterator I2 = TmpStore.begin(), for (ExplodedNodeSet::iterator I2 = TmpStore.begin(),
E2 = TmpStore.end(); I2 != E2; ++I2) { E2 = TmpStore.end(); I2 != E2; ++I2) {
ExplodedNode *predNew = *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. // Check for 'void' return type if we have a bogus function prototype.
SVal Res = UnknownVal(); SVal Res = UnknownVal();
QualType T = CE->getType(); QualType T = CE->getType();
@ -189,7 +189,7 @@ bool OSAtomicChecker::evalOSAtomicCompareAndSwap(CheckerContext &C,
} }
// Were they not equal? // 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. // Check for 'void' return type if we have a bogus function prototype.
SVal Res = UnknownVal(); SVal Res = UnknownVal();
QualType T = CE->getType(); QualType T = CE->getType();

View File

@ -38,7 +38,7 @@ void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S,
CheckerContext &C) const { CheckerContext &C) const {
const Expr *Ex = S->getSynchExpr(); const Expr *Ex = S->getSynchExpr();
const GRState *state = C.getState(); const ProgramState *state = C.getState();
SVal V = state->getSVal(Ex); SVal V = state->getSVal(Ex);
// Uninitialized value used for the mutex? // Uninitialized value used for the mutex?
@ -59,7 +59,7 @@ void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S,
return; return;
// Check for null mutexes. // Check for null mutexes.
const GRState *notNullState, *nullState; const ProgramState *notNullState, *nullState;
llvm::tie(notNullState, nullState) = state->assume(cast<DefinedSVal>(V)); llvm::tie(notNullState, nullState) = state->assume(cast<DefinedSVal>(V));
if (nullState) { if (nullState) {

View File

@ -50,7 +50,7 @@
#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.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/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/AST/ParentMap.h" #include "clang/AST/ParentMap.h"
@ -109,11 +109,11 @@ namespace { struct PreCallSelfFlags {}; }
namespace clang { namespace clang {
namespace ento { namespace ento {
template<> template<>
struct GRStateTrait<SelfFlag> : public GRStatePartialTrait<SelfFlag> { struct ProgramStateTrait<SelfFlag> : public ProgramStatePartialTrait<SelfFlag> {
static void *GDMIndex() { static int index = 0; return &index; } static void *GDMIndex() { static int index = 0; return &index; }
}; };
template <> template <>
struct GRStateTrait<CalledInit> : public GRStatePartialTrait<bool> { struct ProgramStateTrait<CalledInit> : public ProgramStatePartialTrait<bool> {
static void *GDMIndex() { static int index = 0; return &index; } 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' /// object before the call so we can assign them to the new object that 'self'
/// points to after the call. /// points to after the call.
template <> template <>
struct GRStateTrait<PreCallSelfFlags> : public GRStatePartialTrait<unsigned> { struct ProgramStateTrait<PreCallSelfFlags> : public ProgramStatePartialTrait<unsigned> {
static void *GDMIndex() { static int index = 0; return &index; } 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 (SymbolRef sym = val.getAsSymbol())
if (const unsigned *attachedFlags = state->get<SelfFlag>(sym)) if (const unsigned *attachedFlags = state->get<SelfFlag>(sym))
return (SelfFlagEnum)*attachedFlags; return (SelfFlagEnum)*attachedFlags;
@ -139,7 +139,7 @@ static SelfFlagEnum getSelfFlags(SVal val, CheckerContext &C) {
return getSelfFlags(val, C.getState()); 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) { SelfFlagEnum flag, CheckerContext &C) {
// We tag the symbol that the SVal wraps. // We tag the symbol that the SVal wraps.
if (SymbolRef sym = val.getAsSymbol()) if (SymbolRef sym = val.getAsSymbol())
@ -197,7 +197,7 @@ void ObjCSelfInitChecker::checkPostObjCMessage(ObjCMessage msg,
if (isInitMessage(msg)) { if (isInitMessage(msg)) {
// Tag the return value as the result of an initializer. // 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 // FIXME this really should be context sensitive, where we record
// the current stack frame (for IPA). Also, we need to clean this // 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, void ObjCSelfInitChecker::checkPreStmt(const CallExpr *CE,
CheckerContext &C) const { CheckerContext &C) const {
const GRState *state = C.getState(); const ProgramState *state = C.getState();
for (CallExpr::const_arg_iterator for (CallExpr::const_arg_iterator
I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) { I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) {
SVal argV = state->getSVal(*I); SVal argV = state->getSVal(*I);
@ -275,7 +275,7 @@ void ObjCSelfInitChecker::checkPreStmt(const CallExpr *CE,
void ObjCSelfInitChecker::checkPostStmt(const CallExpr *CE, void ObjCSelfInitChecker::checkPostStmt(const CallExpr *CE,
CheckerContext &C) const { CheckerContext &C) const {
const GRState *state = C.getState(); const ProgramState *state = C.getState();
for (CallExpr::const_arg_iterator for (CallExpr::const_arg_iterator
I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) { I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) {
SVal argV = state->getSVal(*I); SVal argV = state->getSVal(*I);
@ -297,7 +297,7 @@ void ObjCSelfInitChecker::checkLocation(SVal location, bool isLoad,
CheckerContext &C) const { CheckerContext &C) const {
// Tag the result of a load from 'self' so that we can easily know that the // Tag the result of a load from 'self' so that we can easily know that the
// value is the object that 'self' points to. // value is the object that 'self' points to.
const GRState *state = C.getState(); const ProgramState *state = C.getState();
if (isSelfVar(location, C)) if (isSelfVar(location, C))
addSelfFlag(state, state->getSVal(cast<Loc>(location)), SelfFlag_Self, C); addSelfFlag(state, state->getSVal(cast<Loc>(location)), SelfFlag_Self, C);
} }

View File

@ -36,7 +36,7 @@ void PointerArithChecker::checkPreStmt(const BinaryOperator *B,
if (B->getOpcode() != BO_Sub && B->getOpcode() != BO_Add) if (B->getOpcode() != BO_Sub && B->getOpcode() != BO_Add)
return; return;
const GRState *state = C.getState(); const ProgramState *state = C.getState();
SVal LV = state->getSVal(B->getLHS()); SVal LV = state->getSVal(B->getLHS());
SVal RV = state->getSVal(B->getRHS()); SVal RV = state->getSVal(B->getRHS());

View File

@ -39,7 +39,7 @@ void PointerSubChecker::checkPreStmt(const BinaryOperator *B,
if (B->getOpcode() != BO_Sub) if (B->getOpcode() != BO_Sub)
return; return;
const GRState *state = C.getState(); const ProgramState *state = C.getState();
SVal LV = state->getSVal(B->getLHS()); SVal LV = state->getSVal(B->getLHS());
SVal RV = state->getSVal(B->getRHS()); SVal RV = state->getSVal(B->getRHS());

View File

@ -17,7 +17,7 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.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" #include "llvm/ADT/ImmutableList.h"
using namespace clang; using namespace clang;
@ -46,8 +46,8 @@ public:
namespace { class LockSet {}; } namespace { class LockSet {}; }
namespace clang { namespace clang {
namespace ento { namespace ento {
template <> struct GRStateTrait<LockSet> : template <> struct ProgramStateTrait<LockSet> :
public GRStatePartialTrait<llvm::ImmutableList<const MemRegion*> > { public ProgramStatePartialTrait<llvm::ImmutableList<const MemRegion*> > {
static void *GDMIndex() { static int x = 0; return &x; } static void *GDMIndex() { static int x = 0; return &x; }
}; };
} // end GR namespace } // end GR namespace
@ -56,7 +56,7 @@ template <> struct GRStateTrait<LockSet> :
void PthreadLockChecker::checkPostStmt(const CallExpr *CE, void PthreadLockChecker::checkPostStmt(const CallExpr *CE,
CheckerContext &C) const { CheckerContext &C) const {
const GRState *state = C.getState(); const ProgramState *state = C.getState();
const Expr *Callee = CE->getCallee(); const Expr *Callee = CE->getCallee();
const FunctionDecl *FD = state->getSVal(Callee).getAsFunctionDecl(); const FunctionDecl *FD = state->getSVal(Callee).getAsFunctionDecl();
@ -103,7 +103,7 @@ void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE,
if (!lockR) if (!lockR)
return; return;
const GRState *state = C.getState(); const ProgramState *state = C.getState();
SVal X = state->getSVal(CE); SVal X = state->getSVal(CE);
if (X.isUnknownOrUndef()) if (X.isUnknownOrUndef())
@ -125,10 +125,10 @@ void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE,
return; return;
} }
const GRState *lockSucc = state; const ProgramState *lockSucc = state;
if (isTryLock) { if (isTryLock) {
// Bifurcate the state, and allow a mode where the lock acquisition fails. // Bifurcate the state, and allow a mode where the lock acquisition fails.
const GRState *lockFail; const ProgramState *lockFail;
switch (semantics) { switch (semantics) {
case PthreadSemantics: case PthreadSemantics:
llvm::tie(lockFail, lockSucc) = state->assume(retVal); llvm::tie(lockFail, lockSucc) = state->assume(retVal);
@ -166,7 +166,7 @@ void PthreadLockChecker::ReleaseLock(CheckerContext &C, const CallExpr *CE,
if (!lockR) if (!lockR)
return; return;
const GRState *state = C.getState(); const ProgramState *state = C.getState();
llvm::ImmutableList<const MemRegion*> LS = state->get<LockSet>(); llvm::ImmutableList<const MemRegion*> LS = state->get<LockSet>();
// FIXME: Better analysis requires IPA for wrappers. // FIXME: Better analysis requires IPA for wrappers.

View File

@ -33,7 +33,7 @@ public:
void ReturnPointerRangeChecker::checkPreStmt(const ReturnStmt *RS, void ReturnPointerRangeChecker::checkPreStmt(const ReturnStmt *RS,
CheckerContext &C) const { CheckerContext &C) const {
const GRState *state = C.getState(); const ProgramState *state = C.getState();
const Expr *RetE = RS->getRetValue(); const Expr *RetE = RS->getRetValue();
if (!RetE) if (!RetE)
@ -58,8 +58,8 @@ void ReturnPointerRangeChecker::checkPreStmt(const ReturnStmt *RS,
= C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(), = C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(),
ER->getValueType()); ER->getValueType());
const GRState *StInBound = state->assumeInBound(Idx, NumElements, true); const ProgramState *StInBound = state->assumeInBound(Idx, NumElements, true);
const GRState *StOutBound = state->assumeInBound(Idx, NumElements, false); const ProgramState *StOutBound = state->assumeInBound(Idx, NumElements, false);
if (StOutBound && !StInBound) { if (StOutBound && !StInBound) {
ExplodedNode *N = C.generateSink(StOutBound); ExplodedNode *N = C.generateSink(StOutBound);

View File

@ -17,7 +17,7 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.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 "clang/Basic/SourceManager.h"
#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallString.h"
using namespace clang; using namespace clang;
@ -134,7 +134,7 @@ void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS,
void StackAddrEscapeChecker::checkEndPath(EndOfFunctionNodeBuilder &B, void StackAddrEscapeChecker::checkEndPath(EndOfFunctionNodeBuilder &B,
ExprEngine &Eng) const { 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 // Iterate over all bindings to global variables and see if it contains
// a memory region in the stack space. // a memory region in the stack space.

View File

@ -16,8 +16,8 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
#include "llvm/ADT/ImmutableMap.h" #include "llvm/ADT/ImmutableMap.h"
@ -96,9 +96,9 @@ private:
void OpenFileAux(CheckerContext &C, const CallExpr *CE) const; 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; CheckerContext &C) const;
const GRState *CheckDoubleClose(const CallExpr *CE, const GRState *state, const ProgramState *CheckDoubleClose(const CallExpr *CE, const ProgramState *state,
CheckerContext &C) const; CheckerContext &C) const;
}; };
@ -107,15 +107,15 @@ private:
namespace clang { namespace clang {
namespace ento { namespace ento {
template <> template <>
struct GRStateTrait<StreamState> struct ProgramStateTrait<StreamState>
: public GRStatePartialTrait<llvm::ImmutableMap<SymbolRef, StreamState> > { : public ProgramStatePartialTrait<llvm::ImmutableMap<SymbolRef, StreamState> > {
static void *GDMIndex() { static int x; return &x; } static void *GDMIndex() { static int x; return &x; }
}; };
} }
} }
bool StreamChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { bool StreamChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
const GRState *state = C.getState(); const ProgramState *state = C.getState();
const Expr *Callee = CE->getCallee(); const Expr *Callee = CE->getCallee();
SVal L = state->getSVal(Callee); SVal L = state->getSVal(Callee);
const FunctionDecl *FD = L.getAsFunctionDecl(); 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 { void StreamChecker::OpenFileAux(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState(); const ProgramState *state = C.getState();
unsigned Count = C.getNodeBuilder().getCurrentBlockCount(); unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
SValBuilder &svalBuilder = C.getSValBuilder(); SValBuilder &svalBuilder = C.getSValBuilder();
DefinedSVal RetVal = DefinedSVal RetVal =
@ -231,7 +231,7 @@ void StreamChecker::OpenFileAux(CheckerContext &C, const CallExpr *CE) const {
ConstraintManager &CM = C.getConstraintManager(); ConstraintManager &CM = C.getConstraintManager();
// Bifurcate the state into two: one with a valid FILE* pointer, the other // Bifurcate the state into two: one with a valid FILE* pointer, the other
// with a NULL. // with a NULL.
const GRState *stateNotNull, *stateNull; const ProgramState *stateNotNull, *stateNull;
llvm::tie(stateNotNull, stateNull) = CM.assumeDual(state, RetVal); llvm::tie(stateNotNull, stateNull) = CM.assumeDual(state, RetVal);
if (SymbolRef Sym = RetVal.getAsSymbol()) { 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 { 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) if (state)
C.addTransition(state); C.addTransition(state);
} }
void StreamChecker::Fread(CheckerContext &C, const CallExpr *CE) const { 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)) if (!CheckNullStream(state->getSVal(CE->getArg(3)), state, C))
return; return;
} }
void StreamChecker::Fwrite(CheckerContext &C, const CallExpr *CE) const { 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)) if (!CheckNullStream(state->getSVal(CE->getArg(3)), state, C))
return; return;
} }
void StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) const { 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))) if (!(state = CheckNullStream(state->getSVal(CE->getArg(0)), state, C)))
return; return;
// Check the legality of the 'whence' argument of 'fseek'. // 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 { 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)) if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
return; return;
} }
void StreamChecker::Rewind(CheckerContext &C, const CallExpr *CE) const { 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)) if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
return; return;
} }
void StreamChecker::Fgetpos(CheckerContext &C, const CallExpr *CE) const { 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)) if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
return; return;
} }
void StreamChecker::Fsetpos(CheckerContext &C, const CallExpr *CE) const { 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)) if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
return; return;
} }
void StreamChecker::Clearerr(CheckerContext &C, const CallExpr *CE) const { 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)) if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
return; return;
} }
void StreamChecker::Feof(CheckerContext &C, const CallExpr *CE) const { 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)) if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
return; return;
} }
void StreamChecker::Ferror(CheckerContext &C, const CallExpr *CE) const { 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)) if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
return; return;
} }
void StreamChecker::Fileno(CheckerContext &C, const CallExpr *CE) const { 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)) if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
return; return;
} }
const GRState *StreamChecker::CheckNullStream(SVal SV, const GRState *state, const ProgramState *StreamChecker::CheckNullStream(SVal SV, const ProgramState *state,
CheckerContext &C) const { CheckerContext &C) const {
const DefinedSVal *DV = dyn_cast<DefinedSVal>(&SV); const DefinedSVal *DV = dyn_cast<DefinedSVal>(&SV);
if (!DV) if (!DV)
return 0; return 0;
ConstraintManager &CM = C.getConstraintManager(); ConstraintManager &CM = C.getConstraintManager();
const GRState *stateNotNull, *stateNull; const ProgramState *stateNotNull, *stateNull;
llvm::tie(stateNotNull, stateNull) = CM.assumeDual(state, *DV); llvm::tie(stateNotNull, stateNull) = CM.assumeDual(state, *DV);
if (!stateNotNull && stateNull) { if (!stateNotNull && stateNull) {
@ -361,8 +361,8 @@ const GRState *StreamChecker::CheckNullStream(SVal SV, const GRState *state,
return stateNotNull; return stateNotNull;
} }
const GRState *StreamChecker::CheckDoubleClose(const CallExpr *CE, const ProgramState *StreamChecker::CheckDoubleClose(const CallExpr *CE,
const GRState *state, const ProgramState *state,
CheckerContext &C) const { CheckerContext &C) const {
SymbolRef Sym = state->getSVal(CE->getArg(0)).getAsSymbol(); SymbolRef Sym = state->getSVal(CE->getArg(0)).getAsSymbol();
if (!Sym) if (!Sym)
@ -399,7 +399,7 @@ void StreamChecker::checkDeadSymbols(SymbolReaper &SymReaper,
for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(), for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
E = SymReaper.dead_end(); I != E; ++I) { E = SymReaper.dead_end(); I != E; ++I) {
SymbolRef Sym = *I; SymbolRef Sym = *I;
const GRState *state = C.getState(); const ProgramState *state = C.getState();
const StreamState *SS = state->get<StreamState>(Sym); const StreamState *SS = state->get<StreamState>(Sym);
if (!SS) if (!SS)
return; return;
@ -420,7 +420,7 @@ void StreamChecker::checkDeadSymbols(SymbolReaper &SymReaper,
void StreamChecker::checkEndPath(EndOfFunctionNodeBuilder &B, void StreamChecker::checkEndPath(EndOfFunctionNodeBuilder &B,
ExprEngine &Eng) const { ExprEngine &Eng) const {
const GRState *state = B.getState(); const ProgramState *state = B.getState();
typedef llvm::ImmutableMap<SymbolRef, StreamState> SymMap; typedef llvm::ImmutableMap<SymbolRef, StreamState> SymMap;
SymMap M = state->get<StreamState>(); SymMap M = state->get<StreamState>();
@ -445,7 +445,7 @@ void StreamChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const {
if (!RetE) if (!RetE)
return; return;
const GRState *state = C.getState(); const ProgramState *state = C.getState();
SymbolRef Sym = state->getSVal(RetE).getAsSymbol(); SymbolRef Sym = state->getSVal(RetE).getAsSymbol();
if (!Sym) if (!Sym)

View File

@ -27,10 +27,10 @@ class UndefBranchChecker : public Checker<check::BranchCondition> {
mutable llvm::OwningPtr<BuiltinBug> BT; mutable llvm::OwningPtr<BuiltinBug> BT;
struct FindUndefExpr { struct FindUndefExpr {
GRStateManager& VM; ProgramStateManager& VM;
const GRState *St; 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) { const Expr *FindExpr(const Expr *Ex) {
if (!MatchesCriteria(Ex)) if (!MatchesCriteria(Ex))
@ -59,7 +59,7 @@ public:
void UndefBranchChecker::checkBranchCondition(const Stmt *Condition, void UndefBranchChecker::checkBranchCondition(const Stmt *Condition,
BranchNodeBuilder &Builder, BranchNodeBuilder &Builder,
ExprEngine &Eng) const { ExprEngine &Eng) const {
const GRState *state = Builder.getState(); const ProgramState *state = Builder.getState();
SVal X = state->getSVal(Condition); SVal X = state->getSVal(Condition);
if (X.isUndef()) { if (X.isUndef()) {
ExplodedNode *N = Builder.generateNode(state, true); ExplodedNode *N = Builder.generateNode(state, true);
@ -89,7 +89,7 @@ void UndefBranchChecker::checkBranchCondition(const Stmt *Condition,
// had to already be undefined. // had to already be undefined.
ExplodedNode *PrevN = *N->pred_begin(); ExplodedNode *PrevN = *N->pred_begin();
ProgramPoint P = PrevN->getLocation(); ProgramPoint P = PrevN->getLocation();
const GRState *St = N->getState(); const ProgramState *St = N->getState();
if (PostStmt *PS = dyn_cast<PostStmt>(&P)) if (PostStmt *PS = dyn_cast<PostStmt>(&P))
if (PS->getStmt() == Ex) if (PS->getStmt() == Ex)

View File

@ -55,7 +55,7 @@ UndefCapturedBlockVarChecker::checkPostStmt(const BlockExpr *BE,
if (!BE->getBlockDecl()->hasCaptures()) if (!BE->getBlockDecl()->hasCaptures())
return; return;
const GRState *state = C.getState(); const ProgramState *state = C.getState();
const BlockDataRegion *R = const BlockDataRegion *R =
cast<BlockDataRegion>(state->getSVal(BE).getAsRegion()); cast<BlockDataRegion>(state->getSVal(BE).getAsRegion());

View File

@ -35,7 +35,7 @@ public:
void UndefResultChecker::checkPostStmt(const BinaryOperator *B, void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
CheckerContext &C) const { CheckerContext &C) const {
const GRState *state = C.getState(); const ProgramState *state = C.getState();
if (state->getSVal(B).isUndef()) { if (state->getSVal(B).isUndef()) {
// Generate an error node. // Generate an error node.
ExplodedNode *N = C.generateSink(); ExplodedNode *N = C.generateSink();

View File

@ -53,7 +53,7 @@ void UndefinedAssignmentChecker::checkBind(SVal location, SVal val,
while (StoreE) { while (StoreE) {
if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) { if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) {
if (B->isCompoundAssignmentOp()) { if (B->isCompoundAssignmentOp()) {
const GRState *state = C.getState(); const ProgramState *state = C.getState();
if (state->getSVal(B->getLHS()).isUndef()) { if (state->getSVal(B->getLHS()).isUndef()) {
str = "The left expression of the compound assignment is an " str = "The left expression of the compound assignment is an "
"uninitialized value. The computed value will also be garbage"; "uninitialized value. The computed value will also be garbage";

View File

@ -73,7 +73,7 @@ void UnixAPIChecker::CheckOpen(CheckerContext &C, const CallExpr *CE) const {
} }
// Look at the 'oflags' argument for the O_CREAT flag. // Look at the 'oflags' argument for the O_CREAT flag.
const GRState *state = C.getState(); const ProgramState *state = C.getState();
if (CE->getNumArgs() < 2) { if (CE->getNumArgs() < 2) {
// The frontend should issue a warning for this case, so this is a sanity // 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); DefinedSVal maskedFlags = cast<DefinedSVal>(maskedFlagsUC);
// Check if maskedFlags is non-zero. // Check if maskedFlags is non-zero.
const GRState *trueState, *falseState; const ProgramState *trueState, *falseState;
llvm::tie(trueState, falseState) = state->assume(maskedFlags); llvm::tie(trueState, falseState) = state->assume(maskedFlags);
// Only emit an error if the value of 'maskedFlags' is properly // 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 // Check if the first argument is stack allocated. If so, issue a warning
// because that's likely to be bad news. // 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(); const MemRegion *R = state->getSVal(CE->getArg(0)).getAsRegion();
if (!R || !isa<StackSpaceRegion>(R->getMemorySpace())) if (!R || !isa<StackSpaceRegion>(R->getMemorySpace()))
return; return;
@ -182,13 +182,13 @@ void UnixAPIChecker::CheckMallocZero(CheckerContext &C,
return; return;
// Check if the allocation size is 0. // Check if the allocation size is 0.
const GRState *state = C.getState(); const ProgramState *state = C.getState();
SVal argVal = state->getSVal(CE->getArg(0)); SVal argVal = state->getSVal(CE->getArg(0));
if (argVal.isUnknownOrUndef()) if (argVal.isUnknownOrUndef())
return; return;
const GRState *trueState, *falseState; const ProgramState *trueState, *falseState;
llvm::tie(trueState, falseState) = state->assume(cast<DefinedSVal>(argVal)); llvm::tie(trueState, falseState) = state->assume(cast<DefinedSVal>(argVal));
// Is the value perfectly constrained to zero? // 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 { void UnixAPIChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const {
// Get the callee. All the functions we care about are C functions // Get the callee. All the functions we care about are C functions
// with simple identifiers. // with simple identifiers.
const GRState *state = C.getState(); const ProgramState *state = C.getState();
const Expr *Callee = CE->getCallee(); const Expr *Callee = CE->getCallee();
const FunctionDecl *Fn = state->getSVal(Callee).getAsFunctionDecl(); const FunctionDecl *Fn = state->getSVal(Callee).getAsFunctionDecl();

View File

@ -49,7 +49,7 @@ void VLASizeChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
// FIXME: Handle multi-dimensional VLAs. // FIXME: Handle multi-dimensional VLAs.
const Expr *SE = VLA->getSizeExpr(); const Expr *SE = VLA->getSizeExpr();
const GRState *state = C.getState(); const ProgramState *state = C.getState();
SVal sizeV = state->getSVal(SE); SVal sizeV = state->getSVal(SE);
if (sizeV.isUndef()) { if (sizeV.isUndef()) {
@ -78,7 +78,7 @@ void VLASizeChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
// Check if the size is zero. // Check if the size is zero.
DefinedSVal sizeD = cast<DefinedSVal>(sizeV); DefinedSVal sizeD = cast<DefinedSVal>(sizeV);
const GRState *stateNotZero, *stateZero; const ProgramState *stateNotZero, *stateZero;
llvm::tie(stateNotZero, stateZero) = state->assume(sizeD); llvm::tie(stateNotZero, stateZero) = state->assume(sizeD);
if (stateZero && !stateNotZero) { if (stateZero && !stateNotZero) {

View File

@ -8,13 +8,13 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// //
// This file defines BasicConstraintManager, a class that tracks simple // 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 "SimpleConstraintManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.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/TransferFuncs.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
@ -25,7 +25,7 @@ using namespace ento;
namespace { class ConstNotEq {}; } namespace { class ConstNotEq {}; }
namespace { class ConstEq {}; } 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; typedef llvm::ImmutableMap<SymbolRef,const llvm::APSInt*> ConstEqTy;
static int ConstEqIndex = 0; static int ConstEqIndex = 0;
@ -34,12 +34,13 @@ static int ConstNotEqIndex = 0;
namespace clang { namespace clang {
namespace ento { namespace ento {
template<> template<>
struct GRStateTrait<ConstNotEq> : public GRStatePartialTrait<ConstNotEqTy> { struct ProgramStateTrait<ConstNotEq> :
public ProgramStatePartialTrait<ConstNotEqTy> {
static inline void *GDMIndex() { return &ConstNotEqIndex; } static inline void *GDMIndex() { return &ConstNotEqIndex; }
}; };
template<> template<>
struct GRStateTrait<ConstEq> : public GRStatePartialTrait<ConstEqTy> { struct ProgramStateTrait<ConstEq> : public ProgramStatePartialTrait<ConstEqTy> {
static inline void *GDMIndex() { return &ConstEqIndex; } static inline void *GDMIndex() { return &ConstEqIndex; }
}; };
} }
@ -50,62 +51,81 @@ namespace {
// constants and integer variables. // constants and integer variables.
class BasicConstraintManager class BasicConstraintManager
: public SimpleConstraintManager { : public SimpleConstraintManager {
GRState::IntSetTy::Factory ISetFactory; ProgramState::IntSetTy::Factory ISetFactory;
public: public:
BasicConstraintManager(GRStateManager &statemgr, SubEngine &subengine) BasicConstraintManager(ProgramStateManager &statemgr, SubEngine &subengine)
: SimpleConstraintManager(subengine), : SimpleConstraintManager(subengine),
ISetFactory(statemgr.getAllocator()) {} ISetFactory(statemgr.getAllocator()) {}
const GRState *assumeSymNE(const GRState *state, SymbolRef sym, const ProgramState *assumeSymNE(const ProgramState *state,
const llvm::APSInt& V, SymbolRef sym,
const llvm::APSInt& Adjustment); const llvm::APSInt& V,
const llvm::APSInt& Adjustment);
const GRState *assumeSymEQ(const GRState *state, SymbolRef sym, const ProgramState *assumeSymEQ(const ProgramState *state,
const llvm::APSInt& V, SymbolRef sym,
const llvm::APSInt& Adjustment); const llvm::APSInt& V,
const llvm::APSInt& Adjustment);
const GRState *assumeSymLT(const GRState *state, SymbolRef sym, const ProgramState *assumeSymLT(const ProgramState *state,
const llvm::APSInt& V, SymbolRef sym,
const llvm::APSInt& Adjustment); const llvm::APSInt& V,
const llvm::APSInt& Adjustment);
const GRState *assumeSymGT(const GRState *state, SymbolRef sym, const ProgramState *assumeSymGT(const ProgramState *state,
const llvm::APSInt& V, SymbolRef sym,
const llvm::APSInt& Adjustment); const llvm::APSInt& V,
const llvm::APSInt& Adjustment);
const GRState *assumeSymGE(const GRState *state, SymbolRef sym, const ProgramState *assumeSymGE(const ProgramState *state,
const llvm::APSInt& V, SymbolRef sym,
const llvm::APSInt& Adjustment); const llvm::APSInt& V,
const llvm::APSInt& Adjustment);
const GRState *assumeSymLE(const GRState *state, SymbolRef sym, const ProgramState *assumeSymLE(const ProgramState *state,
const llvm::APSInt& V, SymbolRef sym,
const llvm::APSInt& Adjustment); 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; const llvm::APSInt* getSymVal(const ProgramState *state,
bool isNotEqual(const GRState *state, SymbolRef sym, const llvm::APSInt& V) SymbolRef sym) const;
const;
bool isEqual(const GRState *state, SymbolRef sym, const llvm::APSInt& V)
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, bool isEqual(const ProgramState *state,
const char* nl, const char *sep); 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 } // end anonymous namespace
ConstraintManager* ento::CreateBasicConstraintManager(GRStateManager& statemgr, ConstraintManager*
SubEngine &subengine) { ento::CreateBasicConstraintManager(ProgramStateManager& statemgr,
SubEngine &subengine) {
return new BasicConstraintManager(statemgr, subengine); return new BasicConstraintManager(statemgr, subengine);
} }
const ProgramState*
const GRState* BasicConstraintManager::assumeSymNE(const ProgramState *state,
BasicConstraintManager::assumeSymNE(const GRState *state, SymbolRef sym, SymbolRef sym,
const llvm::APSInt &V, const llvm::APSInt &V,
const llvm::APSInt &Adjustment) { const llvm::APSInt &Adjustment) {
// First, determine if sym == X, where X+Adjustment != V. // 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); return AddNE(state, sym, Adjusted);
} }
const GRState* const ProgramState*
BasicConstraintManager::assumeSymEQ(const GRState *state, SymbolRef sym, BasicConstraintManager::assumeSymEQ(const ProgramState *state,
SymbolRef sym,
const llvm::APSInt &V, const llvm::APSInt &V,
const llvm::APSInt &Adjustment) { const llvm::APSInt &Adjustment) {
// First, determine if sym == X, where X+Adjustment != V. // 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. // The logic for these will be handled in another ConstraintManager.
const GRState* const ProgramState*
BasicConstraintManager::assumeSymLT(const GRState *state, SymbolRef sym, BasicConstraintManager::assumeSymLT(const ProgramState *state,
SymbolRef sym,
const llvm::APSInt &V, const llvm::APSInt &V,
const llvm::APSInt &Adjustment) { const llvm::APSInt &Adjustment) {
// Is 'V' the smallest possible value? // Is 'V' the smallest possible value?
@ -159,8 +181,9 @@ BasicConstraintManager::assumeSymLT(const GRState *state, SymbolRef sym,
return assumeSymNE(state, sym, V, Adjustment); return assumeSymNE(state, sym, V, Adjustment);
} }
const GRState* const ProgramState*
BasicConstraintManager::assumeSymGT(const GRState *state, SymbolRef sym, BasicConstraintManager::assumeSymGT(const ProgramState *state,
SymbolRef sym,
const llvm::APSInt &V, const llvm::APSInt &V,
const llvm::APSInt &Adjustment) { const llvm::APSInt &Adjustment) {
// Is 'V' the largest possible value? // Is 'V' the largest possible value?
@ -173,8 +196,9 @@ BasicConstraintManager::assumeSymGT(const GRState *state, SymbolRef sym,
return assumeSymNE(state, sym, V, Adjustment); return assumeSymNE(state, sym, V, Adjustment);
} }
const GRState* const ProgramState*
BasicConstraintManager::assumeSymGE(const GRState *state, SymbolRef sym, BasicConstraintManager::assumeSymGE(const ProgramState *state,
SymbolRef sym,
const llvm::APSInt &V, const llvm::APSInt &V,
const llvm::APSInt &Adjustment) { const llvm::APSInt &Adjustment) {
// Reject a path if the value of sym is a constant X and !(X+Adj >= V). // 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; return state;
} }
const GRState* const ProgramState*
BasicConstraintManager::assumeSymLE(const GRState *state, SymbolRef sym, BasicConstraintManager::assumeSymLE(const ProgramState *state,
SymbolRef sym,
const llvm::APSInt &V, const llvm::APSInt &V,
const llvm::APSInt &Adjustment) { const llvm::APSInt &Adjustment) {
// Reject a path if the value of sym is a constant X and !(X+Adj <= V). // 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; return state;
} }
const GRState *BasicConstraintManager::AddEQ(const GRState *state, SymbolRef sym, const ProgramState *BasicConstraintManager::AddEQ(const ProgramState *state,
SymbolRef sym,
const llvm::APSInt& V) { const llvm::APSInt& V) {
// Create a new state with the old binding replaced. // Create a new state with the old binding replaced.
return state->set<ConstEq>(sym, &state->getBasicVals().getValue(V)); return state->set<ConstEq>(sym, &state->getBasicVals().getValue(V));
} }
const GRState *BasicConstraintManager::AddNE(const GRState *state, SymbolRef sym, const ProgramState *BasicConstraintManager::AddNE(const ProgramState *state,
const llvm::APSInt& V) { SymbolRef sym,
const llvm::APSInt& V) {
// First, retrieve the NE-set associated with the given symbol. // First, retrieve the NE-set associated with the given symbol.
ConstNotEqTy::data_type* T = state->get<ConstNotEq>(sym); 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. // Now add V to the NE set.
S = ISetFactory.add(S, &state->getBasicVals().getValue(V)); 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); 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 { SymbolRef sym) const {
const ConstEqTy::data_type* T = state->get<ConstEq>(sym); const ConstEqTy::data_type* T = state->get<ConstEq>(sym);
return T ? *T : NULL; 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 { const llvm::APSInt& V) const {
// Retrieve the NE-set associated with the given symbol. // 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; 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 { const llvm::APSInt& V) const {
// Retrieve the EQ-set associated with the given symbol. // Retrieve the EQ-set associated with the given symbol.
const ConstEqTy::data_type* T = state->get<ConstEq>(sym); 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 /// Scan all symbols referenced by the constraints. If the symbol is not alive
/// as marked in LSymbols, mark it as dead in DSymbols. /// as marked in LSymbols, mark it as dead in DSymbols.
const GRState* const ProgramState*
BasicConstraintManager::removeDeadBindings(const GRState *state, BasicConstraintManager::removeDeadBindings(const ProgramState *state,
SymbolReaper& SymReaper) { SymbolReaper& SymReaper) {
ConstEqTy CE = state->get<ConstEq>(); ConstEqTy CE = state->get<ConstEq>();
@ -301,7 +330,8 @@ BasicConstraintManager::removeDeadBindings(const GRState *state,
return state->set<ConstNotEq>(CNE); 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) { const char* nl, const char *sep) {
// Print equality constraints. // Print equality constraints.
@ -324,7 +354,7 @@ void BasicConstraintManager::print(const GRState *state, raw_ostream &Out,
Out << nl << " $" << I.getKey() << " : "; Out << nl << " $" << I.getKey() << " : ";
bool isFirst = true; bool isFirst = true;
GRState::IntSetTy::iterator J = I.getData().begin(), ProgramState::IntSetTy::iterator J = I.getData().begin(),
EJ = I.getData().end(); EJ = I.getData().end();
for ( ; J != EJ; ++J) { for ( ; J != EJ; ++J) {

View File

@ -346,9 +346,9 @@ PathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) {
// ScanNotableSymbols: closure-like callback for scanning Store bindings. // ScanNotableSymbols: closure-like callback for scanning Store bindings.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
static const VarDecl* static const VarDecl* GetMostRecentVarDeclBinding(const ExplodedNode *N,
GetMostRecentVarDeclBinding(const ExplodedNode *N, ProgramStateManager& VMgr,
GRStateManager& VMgr, SVal X) { SVal X) {
for ( ; N ; N = N->pred_empty() ? 0 : *N->pred_begin()) { for ( ; N ; N = N->pred_empty() ? 0 : *N->pred_begin()) {
@ -383,19 +383,29 @@ class NotableSymbolHandler
: public StoreManager::BindingsHandler { : public StoreManager::BindingsHandler {
SymbolRef Sym; SymbolRef Sym;
const GRState *PrevSt; const ProgramState *PrevSt;
const Stmt *S; const Stmt *S;
GRStateManager& VMgr; ProgramStateManager& VMgr;
const ExplodedNode *Pred; const ExplodedNode *Pred;
PathDiagnostic& PD; PathDiagnostic& PD;
BugReporter& BR; BugReporter& BR;
public: public:
NotableSymbolHandler(SymbolRef sym, const GRState *prevst, const Stmt *s, NotableSymbolHandler(SymbolRef sym,
GRStateManager& vmgr, const ExplodedNode *pred, const ProgramState *prevst,
PathDiagnostic& pd, BugReporter& br) const Stmt *s,
: Sym(sym), PrevSt(prevst), S(s), VMgr(vmgr), Pred(pred), PD(pd), BR(br) {} 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, bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R,
SVal V) { SVal V) {
@ -466,14 +476,14 @@ static void HandleNotableSymbol(const ExplodedNode *N,
PathDiagnostic& PD) { PathDiagnostic& PD) {
const ExplodedNode *Pred = N->pred_empty() ? 0 : *N->pred_begin(); 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) if (!PrevSt)
return; return;
// Look at the region bindings of the current state that map to the // Look at the region bindings of the current state that map to the
// specified symbol. Are any of them not in the previous state? // 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); NotableSymbolHandler H(Sym, PrevSt, S, VMgr, Pred, PD, BR);
cast<GRBugReporter>(BR).getStateManager().iterBindings(N->getState(), H); cast<GRBugReporter>(BR).getStateManager().iterBindings(N->getState(), H);
} }
@ -1314,7 +1324,7 @@ BugReporterData::~BugReporterData() {}
ExplodedGraph &GRBugReporter::getGraph() { return Eng.getGraph(); } ExplodedGraph &GRBugReporter::getGraph() { return Eng.getGraph(); }
GRStateManager& ProgramStateManager&
GRBugReporter::getStateManager() { return Eng.getStateManager(); } GRBugReporter::getStateManager() { return Eng.getStateManager(); }
BugReporter::~BugReporter() { FlushReports(); } BugReporter::~BugReporter() { FlushReports(); }

View File

@ -17,7 +17,7 @@
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.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 clang;
using namespace ento; using namespace ento;
@ -311,7 +311,7 @@ void bugreporter::registerTrackNullOrUndefValue(BugReporterContext &BRC,
if (!S) if (!S)
return; return;
GRStateManager &StateMgr = BRC.getStateManager(); ProgramStateManager &StateMgr = BRC.getStateManager();
// Walk through nodes until we get one that matches the statement // Walk through nodes until we get one that matches the statement
// exactly. // exactly.
@ -327,7 +327,7 @@ void bugreporter::registerTrackNullOrUndefValue(BugReporterContext &BRC,
if (!N) if (!N)
return; return;
const GRState *state = N->getState(); const ProgramState *state = N->getState();
// Walk through lvalue-to-rvalue conversions. // Walk through lvalue-to-rvalue conversions.
if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S)) { if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S)) {
@ -374,7 +374,7 @@ void bugreporter::registerFindLastStore(BugReporterContext &BRC,
if (!R) if (!R)
return; return;
const GRState *state = N->getState(); const ProgramState *state = N->getState();
SVal V = state->getSVal(R); SVal V = state->getSVal(R);
if (V.isUnknown()) if (V.isUnknown())
@ -407,7 +407,7 @@ public:
const Expr *Receiver = ME->getInstanceReceiver(); const Expr *Receiver = ME->getInstanceReceiver();
if (!Receiver) if (!Receiver)
return 0; return 0;
const GRState *state = N->getState(); const ProgramState *state = N->getState();
const SVal &V = state->getSVal(Receiver); const SVal &V = state->getSVal(Receiver);
const DefinedOrUnknownSVal *DV = dyn_cast<DefinedOrUnknownSVal>(&V); const DefinedOrUnknownSVal *DV = dyn_cast<DefinedOrUnknownSVal>(&V);
if (!DV) if (!DV)
@ -446,8 +446,8 @@ void bugreporter::registerVarDeclsLastStore(BugReporterContext &BRC,
const Stmt *Head = WorkList.front(); const Stmt *Head = WorkList.front();
WorkList.pop_front(); WorkList.pop_front();
GRStateManager &StateMgr = BRC.getStateManager(); ProgramStateManager &StateMgr = BRC.getStateManager();
const GRState *state = N->getState(); const ProgramState *state = N->getState();
if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Head)) { if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Head)) {
if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
@ -486,8 +486,8 @@ public:
BugReporterContext &BRC); BugReporterContext &BRC);
PathDiagnosticPiece *VisitTerminator(const Stmt *Term, PathDiagnosticPiece *VisitTerminator(const Stmt *Term,
const GRState *CurrentState, const ProgramState *CurrentState,
const GRState *PrevState, const ProgramState *PrevState,
const CFGBlock *srcBlk, const CFGBlock *srcBlk,
const CFGBlock *dstBlk, const CFGBlock *dstBlk,
BugReporterContext &BRC); BugReporterContext &BRC);
@ -516,8 +516,8 @@ PathDiagnosticPiece *ConditionVisitor::VisitNode(const ExplodedNode *N,
const CFGBlock *srcBlk = BE->getSrc(); const CFGBlock *srcBlk = BE->getSrc();
if (const Stmt *term = srcBlk->getTerminator()) { if (const Stmt *term = srcBlk->getTerminator()) {
const GRState *CurrentState = N->getState(); const ProgramState *CurrentState = N->getState();
const GRState *PrevState = Prev->getState(); const ProgramState *PrevState = Prev->getState();
if (CurrentState != PrevState) if (CurrentState != PrevState)
return VisitTerminator(term, CurrentState, PrevState, return VisitTerminator(term, CurrentState, PrevState,
srcBlk, BE->getDst(), srcBlk, BE->getDst(),
@ -532,8 +532,8 @@ PathDiagnosticPiece *ConditionVisitor::VisitNode(const ExplodedNode *N,
PathDiagnosticPiece * PathDiagnosticPiece *
ConditionVisitor::VisitTerminator(const Stmt *Term, ConditionVisitor::VisitTerminator(const Stmt *Term,
const GRState *CurrentState, const ProgramState *CurrentState,
const GRState *PrevState, const ProgramState *PrevState,
const CFGBlock *srcBlk, const CFGBlock *srcBlk,
const CFGBlock *dstBlk, const CFGBlock *dstBlk,
BugReporterContext &BRC) { BugReporterContext &BRC) {

View File

@ -25,7 +25,7 @@
#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h" #include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
#include "clang/Analysis/DomainSpecific/CocoaConventions.h" #include "clang/Analysis/DomainSpecific/CocoaConventions.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngineBuilders.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/TransferFuncs.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
@ -56,7 +56,7 @@ public:
return isValid(); return isValid();
} }
SVal getSValAsScalarOrLoc(const GRState *state) { SVal getSValAsScalarOrLoc(const ProgramState *state) {
assert(isValid()); assert(isValid());
// We have an expression for the receiver? Fetch the value // We have an expression for the receiver? Fetch the value
// of that expression. // of that expression.
@ -98,7 +98,7 @@ public:
GenericNodeBuilderRefCount(EndOfFunctionNodeBuilder &enb) GenericNodeBuilderRefCount(EndOfFunctionNodeBuilder &enb)
: SNB(0), S(0), tag(0), ENB(&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) if (SNB)
return SNB->generateNode(PostStmt(S, Pred->getLocationContext(), tag), return SNB->generateNode(PostStmt(S, Pred->getLocationContext(), tag),
state, Pred); state, Pred);
@ -396,13 +396,14 @@ typedef llvm::ImmutableMap<SymbolRef, RefVal> RefBindings;
namespace clang { namespace clang {
namespace ento { namespace ento {
template<> template<>
struct GRStateTrait<RefBindings> : public GRStatePartialTrait<RefBindings> { struct ProgramStateTrait<RefBindings>
static void *GDMIndex() { : public ProgramStatePartialTrait<RefBindings> {
static int RefBIndex = 0; static void *GDMIndex() {
return &RefBIndex; static int RefBIndex = 0;
} return &RefBIndex;
}; }
};
} }
} }
@ -814,7 +815,7 @@ public:
RetainSummary* getSummary(const FunctionDecl *FD); RetainSummary* getSummary(const FunctionDecl *FD);
RetainSummary *getInstanceMethodSummary(const ObjCMessage &msg, RetainSummary *getInstanceMethodSummary(const ObjCMessage &msg,
const GRState *state, const ProgramState *state,
const LocationContext *LC); const LocationContext *LC);
RetainSummary* getInstanceMethodSummary(const ObjCMessage &msg, RetainSummary* getInstanceMethodSummary(const ObjCMessage &msg,
@ -1358,7 +1359,7 @@ RetainSummaryManager::getCommonMethodSummary(const ObjCMethodDecl *MD,
RetainSummary* RetainSummary*
RetainSummaryManager::getInstanceMethodSummary(const ObjCMessage &msg, RetainSummaryManager::getInstanceMethodSummary(const ObjCMessage &msg,
const GRState *state, const ProgramState *state,
const LocationContext *LC) { const LocationContext *LC) {
// We need the type-information of the tracked receiver object // We need the type-information of the tracked receiver object
@ -1609,26 +1610,27 @@ namespace { class AutoreleaseStack {}; }
namespace clang { namespace clang {
namespace ento { namespace ento {
template<> struct GRStateTrait<AutoreleaseStack> template<> struct ProgramStateTrait<AutoreleaseStack>
: public GRStatePartialTrait<ARStack> { : public ProgramStatePartialTrait<ARStack> {
static inline void *GDMIndex() { return &AutoRBIndex; } static inline void *GDMIndex() { return &AutoRBIndex; }
}; };
template<> struct GRStateTrait<AutoreleasePoolContents> template<> struct ProgramStateTrait<AutoreleasePoolContents>
: public GRStatePartialTrait<ARPoolContents> { : public ProgramStatePartialTrait<ARPoolContents> {
static inline void *GDMIndex() { return &AutoRCIndex; } static inline void *GDMIndex() { return &AutoRCIndex; }
}; };
} // end GR namespace } // end GR namespace
} // end clang namespace } // end clang namespace
static SymbolRef GetCurrentAutoreleasePool(const GRState *state) { static SymbolRef GetCurrentAutoreleasePool(const ProgramState *state) {
ARStack stack = state->get<AutoreleaseStack>(); ARStack stack = state->get<AutoreleaseStack>();
return stack.isEmpty() ? SymbolRef() : stack.getHead(); return stack.isEmpty() ? SymbolRef() : stack.getHead();
} }
static const GRState * SendAutorelease(const GRState *state, static const ProgramState *
ARCounts::Factory &F, SymbolRef sym) { SendAutorelease(const ProgramState *state,
ARCounts::Factory &F,
SymbolRef sym) {
SymbolRef pool = GetCurrentAutoreleasePool(state); SymbolRef pool = GetCurrentAutoreleasePool(state);
const ARCounts *cnts = state->get<AutoreleasePoolContents>(pool); const ARCounts *cnts = state->get<AutoreleasePoolContents>(pool);
ARCounts newCnts(0); ARCounts newCnts(0);
@ -1651,10 +1653,12 @@ namespace {
class CFRefCount : public TransferFuncs { class CFRefCount : public TransferFuncs {
public: public:
class BindingsPrinter : public GRState::Printer { class BindingsPrinter : public ProgramState::Printer {
public: public:
virtual void Print(raw_ostream &Out, const GRState *state, virtual void Print(raw_ostream &Out,
const char* nl, const char* sep); const ProgramState *state,
const char* nl,
const char* sep);
}; };
typedef llvm::DenseMap<const ExplodedNode*, const RetainSummary*> typedef llvm::DenseMap<const ExplodedNode*, const RetainSummary*>
@ -1674,24 +1678,31 @@ public:
llvm::DenseMap<SymbolRef, const SimpleProgramPointTag*> DeadSymbolTags; llvm::DenseMap<SymbolRef, const SimpleProgramPointTag*> DeadSymbolTags;
const GRState * Update(const GRState * state, SymbolRef sym, RefVal V, const ProgramState *Update(const ProgramState * state,
ArgEffect E, RefVal::Kind& hasErr); SymbolRef sym,
RefVal V,
ArgEffect E,
RefVal::Kind& hasErr);
void ProcessNonLeakError(ExplodedNodeSet &Dst, void ProcessNonLeakError(ExplodedNodeSet &Dst,
StmtNodeBuilder& Builder, StmtNodeBuilder& Builder,
const Expr *NodeExpr, SourceRange ErrorRange, const Expr *NodeExpr,
SourceRange ErrorRange,
ExplodedNode *Pred, ExplodedNode *Pred,
const GRState *St, const ProgramState *St,
RefVal::Kind hasErr, SymbolRef Sym); RefVal::Kind hasErr,
SymbolRef Sym);
const GRState * HandleSymbolDeath(const GRState * state, SymbolRef sid, RefVal V, const ProgramState *HandleSymbolDeath(const ProgramState * state,
SmallVectorImpl<SymbolRef> &Leaked); SymbolRef sid,
RefVal V,
SmallVectorImpl<SymbolRef> &Leaked);
ExplodedNode *ProcessLeaks(const GRState * state, ExplodedNode *ProcessLeaks(const ProgramState * state,
SmallVectorImpl<SymbolRef> &Leaked, SmallVectorImpl<SymbolRef> &Leaked,
GenericNodeBuilderRefCount &Builder, GenericNodeBuilderRefCount &Builder,
ExprEngine &Eng, ExprEngine &Eng,
ExplodedNode *Pred = 0); ExplodedNode *Pred = 0);
public: public:
CFRefCount(ASTContext &Ctx, bool gcenabled, const LangOptions& lopts) CFRefCount(ASTContext &Ctx, bool gcenabled, const LangOptions& lopts)
@ -1709,7 +1720,7 @@ public:
void RegisterChecks(ExprEngine &Eng); 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()); Printers.push_back(new BindingsPrinter());
} }
@ -1733,7 +1744,7 @@ public:
InstanceReceiver Receiver, InstanceReceiver Receiver,
const RetainSummary& Summ, const RetainSummary& Summ,
const MemRegion *Callee, const MemRegion *Callee,
ExplodedNode *Pred, const GRState *state); ExplodedNode *Pred, const ProgramState *state);
virtual void evalCall(ExplodedNodeSet &Dst, virtual void evalCall(ExplodedNodeSet &Dst,
ExprEngine& Eng, ExprEngine& Eng,
@ -1747,7 +1758,7 @@ public:
StmtNodeBuilder& Builder, StmtNodeBuilder& Builder,
ObjCMessage msg, ObjCMessage msg,
ExplodedNode *Pred, ExplodedNode *Pred,
const GRState *state); const ProgramState *state);
// Stores. // Stores.
virtual void evalBind(StmtNodeBuilderRef& B, SVal location, SVal val); virtual void evalBind(StmtNodeBuilderRef& B, SVal location, SVal val);
@ -1760,15 +1771,19 @@ public:
ExprEngine& Engine, ExprEngine& Engine,
StmtNodeBuilder& Builder, StmtNodeBuilder& Builder,
ExplodedNode *Pred, ExplodedNode *Pred,
const GRState *state, const ProgramState *state,
SymbolReaper& SymReaper); SymbolReaper& SymReaper);
const ProgramPointTag *getDeadSymbolTag(SymbolRef sym); const ProgramPointTag *getDeadSymbolTag(SymbolRef sym);
std::pair<ExplodedNode*, const GRState *> std::pair<ExplodedNode*, const ProgramState *>
HandleAutoreleaseCounts(const GRState * state, GenericNodeBuilderRefCount Bd, HandleAutoreleaseCounts(const ProgramState * state,
ExplodedNode *Pred, ExprEngine &Eng, GenericNodeBuilderRefCount Bd,
SymbolRef Sym, RefVal V, bool &stop); ExplodedNode *Pred,
ExprEngine &Eng,
SymbolRef Sym,
RefVal V,
bool &stop);
// Return statements. // Return statements.
virtual void evalReturn(ExplodedNodeSet &Dst, virtual void evalReturn(ExplodedNodeSet &Dst,
@ -1783,19 +1798,21 @@ public:
const ReturnStmt *S, const ReturnStmt *S,
ExplodedNode *Pred, ExplodedNode *Pred,
RetEffect RE, RefVal X, RetEffect RE, RefVal X,
SymbolRef Sym, const GRState *state); SymbolRef Sym, const ProgramState *state);
// Assumptions. // Assumptions.
virtual const GRState *evalAssume(const GRState *state, SVal condition, virtual const ProgramState *evalAssume(const ProgramState *state,
bool assumption); SVal condition,
bool assumption);
}; };
} // end anonymous namespace } // end anonymous namespace
static void PrintPool(raw_ostream &Out, SymbolRef Sym, static void PrintPool(raw_ostream &Out,
const GRState *state) { SymbolRef Sym,
const ProgramState *state) {
Out << ' '; Out << ' ';
if (Sym) if (Sym)
Out << Sym->getSymbolID(); Out << Sym->getSymbolID();
@ -1812,7 +1829,7 @@ static void PrintPool(raw_ostream &Out, SymbolRef Sym,
} }
void CFRefCount::BindingsPrinter::Print(raw_ostream &Out, void CFRefCount::BindingsPrinter::Print(raw_ostream &Out,
const GRState *state, const ProgramState *state,
const char* nl, const char* sep) { const char* nl, const char* sep) {
RefBindings B = state->get<RefBindings>(); RefBindings B = state->get<RefBindings>();
@ -2060,8 +2077,8 @@ PathDiagnosticPiece *CFRefReport::VisitNode(const ExplodedNode *N,
return NULL; return NULL;
// Check if the type state has changed. // Check if the type state has changed.
const GRState *PrevSt = PrevN->getState(); const ProgramState *PrevSt = PrevN->getState();
const GRState *CurrSt = N->getState(); const ProgramState *CurrSt = N->getState();
const RefVal* CurrT = CurrSt->get<RefBindings>(Sym); const RefVal* CurrT = CurrSt->get<RefBindings>(Sym);
if (!CurrT) return NULL; if (!CurrT) return NULL;
@ -2329,7 +2346,7 @@ namespace {
} }
static std::pair<const ExplodedNode*,const MemRegion*> static std::pair<const ExplodedNode*,const MemRegion*>
GetAllocationSite(GRStateManager& StateMgr, const ExplodedNode *N, GetAllocationSite(ProgramStateManager& StateMgr, const ExplodedNode *N,
SymbolRef Sym) { SymbolRef Sym) {
// Find both first node that referred to the tracked symbol and the // 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; const MemRegion* FirstBinding = 0;
while (N) { while (N) {
const GRState *St = N->getState(); const ProgramState *St = N->getState();
RefBindings B = St->get<RefBindings>(); RefBindings B = St->get<RefBindings>();
if (!B.lookup(Sym)) if (!B.lookup(Sym))
@ -2555,7 +2572,8 @@ void CFRefCount::evalSummary(ExplodedNodeSet &Dst,
InstanceReceiver Receiver, InstanceReceiver Receiver,
const RetainSummary& Summ, const RetainSummary& Summ,
const MemRegion *Callee, const MemRegion *Callee,
ExplodedNode *Pred, const GRState *state) { ExplodedNode *Pred,
const ProgramState *state) {
// Evaluate the effect of the arguments. // Evaluate the effect of the arguments.
RefVal::Kind hasErr = (RefVal::Kind) 0; RefVal::Kind hasErr = (RefVal::Kind) 0;
@ -2850,7 +2868,7 @@ void CFRefCount::evalObjCMessage(ExplodedNodeSet &Dst,
StmtNodeBuilder& Builder, StmtNodeBuilder& Builder,
ObjCMessage msg, ObjCMessage msg,
ExplodedNode *Pred, ExplodedNode *Pred,
const GRState *state) { const ProgramState *state) {
RetainSummary *Summ = RetainSummary *Summ =
msg.isInstanceMessage() msg.isInstanceMessage()
? Summaries.getInstanceMethodSummary(msg, state,Pred->getLocationContext()) ? Summaries.getInstanceMethodSummary(msg, state,Pred->getLocationContext())
@ -2865,10 +2883,10 @@ void CFRefCount::evalObjCMessage(ExplodedNodeSet &Dst,
namespace { namespace {
class StopTrackingCallback : public SymbolVisitor { class StopTrackingCallback : public SymbolVisitor {
const GRState *state; const ProgramState *state;
public: public:
StopTrackingCallback(const GRState *st) : state(st) {} StopTrackingCallback(const ProgramState *st) : state(st) {}
const GRState *getState() const { return state; } const ProgramState *getState() const { return state; }
bool VisitSymbol(SymbolRef sym) { bool VisitSymbol(SymbolRef sym) {
state = state->remove<RefBindings>(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 // (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 // (3) we are binding to a memregion with stack storage that the store
// does not understand. // does not understand.
const GRState *state = B.getState(); const ProgramState *state = B.getState();
if (!isa<loc::MemRegionVal>(location)) if (!isa<loc::MemRegionVal>(location))
escapes = true; escapes = true;
@ -2927,7 +2945,7 @@ void CFRefCount::evalReturn(ExplodedNodeSet &Dst,
if (!RetE) if (!RetE)
return; return;
const GRState *state = Pred->getState(); const ProgramState *state = Pred->getState();
SymbolRef Sym = state->getSValAsScalarOrLoc(RetE).getAsLocSymbol(); SymbolRef Sym = state->getSValAsScalarOrLoc(RetE).getAsLocSymbol();
if (!Sym) if (!Sym)
@ -3016,7 +3034,8 @@ void CFRefCount::evalReturnWithRetEffect(ExplodedNodeSet &Dst,
const ReturnStmt *S, const ReturnStmt *S,
ExplodedNode *Pred, ExplodedNode *Pred,
RetEffect RE, RefVal X, RetEffect RE, RefVal X,
SymbolRef Sym, const GRState *state) { SymbolRef Sym,
const ProgramState *state) {
// Any leaks or other errors? // Any leaks or other errors?
if (X.isReturnedOwned() && X.getCount() == 0) { if (X.isReturnedOwned() && X.getCount() == 0) {
if (RE.getKind() != RetEffect::NoRet) { if (RE.getKind() != RetEffect::NoRet) {
@ -3078,8 +3097,9 @@ void CFRefCount::evalReturnWithRetEffect(ExplodedNodeSet &Dst,
// Assumptions. // Assumptions.
const GRState *CFRefCount::evalAssume(const GRState *state, const ProgramState *CFRefCount::evalAssume(const ProgramState *state,
SVal Cond, bool Assumption) { SVal Cond,
bool Assumption) {
// FIXME: We may add to the interface of evalAssume the list of symbols // FIXME: We may add to the interface of evalAssume the list of symbols
// whose assumptions have changed. For now we just iterate through the // whose assumptions have changed. For now we just iterate through the
@ -3110,9 +3130,11 @@ const GRState *CFRefCount::evalAssume(const GRState *state,
return state; return state;
} }
const GRState * CFRefCount::Update(const GRState * state, SymbolRef sym, const ProgramState * CFRefCount::Update(const ProgramState * state,
RefVal V, ArgEffect E, SymbolRef sym,
RefVal::Kind& hasErr) { RefVal V,
ArgEffect E,
RefVal::Kind& hasErr) {
// In GC mode [... release] and [... retain] do nothing. // In GC mode [... release] and [... retain] do nothing.
switch (E) { switch (E) {
@ -3250,12 +3272,14 @@ const GRState * CFRefCount::Update(const GRState * state, SymbolRef sym,
// Handle dead symbols and end-of-path. // Handle dead symbols and end-of-path.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
std::pair<ExplodedNode*, const GRState *> std::pair<ExplodedNode*, const ProgramState *>
CFRefCount::HandleAutoreleaseCounts(const GRState * state, CFRefCount::HandleAutoreleaseCounts(const ProgramState *state,
GenericNodeBuilderRefCount Bd, GenericNodeBuilderRefCount Bd,
ExplodedNode *Pred, ExplodedNode *Pred,
ExprEngine &Eng, ExprEngine &Eng,
SymbolRef Sym, RefVal V, bool &stop) { SymbolRef Sym,
RefVal V,
bool &stop) {
unsigned ACnt = V.getAutoreleaseCount(); unsigned ACnt = V.getAutoreleaseCount();
stop = false; stop = false;
@ -3315,8 +3339,10 @@ CFRefCount::HandleAutoreleaseCounts(const GRState * state,
return std::make_pair((ExplodedNode*)0, state); return std::make_pair((ExplodedNode*)0, state);
} }
const GRState * const ProgramState *
CFRefCount::HandleSymbolDeath(const GRState * state, SymbolRef sid, RefVal V, CFRefCount::HandleSymbolDeath(const ProgramState *state,
SymbolRef sid,
RefVal V,
SmallVectorImpl<SymbolRef> &Leaked) { SmallVectorImpl<SymbolRef> &Leaked) {
bool hasLeak = V.isOwned() || bool hasLeak = V.isOwned() ||
@ -3330,7 +3356,7 @@ CFRefCount::HandleSymbolDeath(const GRState * state, SymbolRef sid, RefVal V,
} }
ExplodedNode* ExplodedNode*
CFRefCount::ProcessLeaks(const GRState * state, CFRefCount::ProcessLeaks(const ProgramState * state,
SmallVectorImpl<SymbolRef> &Leaked, SmallVectorImpl<SymbolRef> &Leaked,
GenericNodeBuilderRefCount &Builder, GenericNodeBuilderRefCount &Builder,
ExprEngine& Eng, ExprEngine& Eng,
@ -3360,7 +3386,7 @@ CFRefCount::ProcessLeaks(const GRState * state,
void CFRefCount::evalEndPath(ExprEngine& Eng, void CFRefCount::evalEndPath(ExprEngine& Eng,
EndOfFunctionNodeBuilder& Builder) { EndOfFunctionNodeBuilder& Builder) {
const GRState *state = Builder.getState(); const ProgramState *state = Builder.getState();
GenericNodeBuilderRefCount Bd(Builder); GenericNodeBuilderRefCount Bd(Builder);
RefBindings B = state->get<RefBindings>(); RefBindings B = state->get<RefBindings>();
ExplodedNode *Pred = 0; ExplodedNode *Pred = 0;
@ -3399,7 +3425,7 @@ void CFRefCount::evalDeadSymbols(ExplodedNodeSet &Dst,
ExprEngine& Eng, ExprEngine& Eng,
StmtNodeBuilder& Builder, StmtNodeBuilder& Builder,
ExplodedNode *Pred, ExplodedNode *Pred,
const GRState *state, const ProgramState *state,
SymbolReaper& SymReaper) { SymbolReaper& SymReaper) {
const Stmt *S = Builder.getStmt(); const Stmt *S = Builder.getStmt();
RefBindings B = state->get<RefBindings>(); RefBindings B = state->get<RefBindings>();
@ -3454,7 +3480,7 @@ void CFRefCount::ProcessNonLeakError(ExplodedNodeSet &Dst,
const Expr *NodeExpr, const Expr *NodeExpr,
SourceRange ErrorRange, SourceRange ErrorRange,
ExplodedNode *Pred, ExplodedNode *Pred,
const GRState *St, const ProgramState *St,
RefVal::Kind hasErr, SymbolRef Sym) { RefVal::Kind hasErr, SymbolRef Sym) {
Builder.BuildSinks = true; Builder.BuildSinks = true;
ExplodedNode *N = Builder.MakeNode(Dst, NodeExpr, Pred, St); ExplodedNode *N = Builder.MakeNode(Dst, NodeExpr, Pred, St);
@ -3508,19 +3534,19 @@ public:
void checkPostStmt(const CastExpr *CE, CheckerContext &C) const; 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 StoreManager::InvalidatedSymbols *invalidated,
const MemRegion * const *begin, const MemRegion * const *begin,
const MemRegion * const *end) const; const MemRegion * const *end) const;
bool wantsRegionChangeUpdate(const GRState *state) const { bool wantsRegionChangeUpdate(const ProgramState *state) const {
return wantsRegionUpdate; return wantsRegionUpdate;
} }
}; };
} // end anonymous namespace } // end anonymous namespace
const GRState * const ProgramState *
RetainReleaseChecker::checkRegionChanges(const GRState *state, RetainReleaseChecker::checkRegionChanges(const ProgramState *state,
const StoreManager::InvalidatedSymbols *invalidated, const StoreManager::InvalidatedSymbols *invalidated,
const MemRegion * const *begin, const MemRegion * const *begin,
const MemRegion * const *end) const { const MemRegion * const *end) const {
@ -3546,7 +3572,7 @@ void RetainReleaseChecker::checkPostStmt(const BlockExpr *BE,
if (!BE->getBlockDecl()->hasCaptures()) if (!BE->getBlockDecl()->hasCaptures())
return; return;
const GRState *state = C.getState(); const ProgramState *state = C.getState();
const BlockDataRegion *R = const BlockDataRegion *R =
cast<BlockDataRegion>(state->getSVal(BE).getAsRegion()); cast<BlockDataRegion>(state->getSVal(BE).getAsRegion());
@ -3597,7 +3623,7 @@ void RetainReleaseChecker::checkPostStmt(const CastExpr *CE,
break; break;
} }
const GRState *state = C.getState(); const ProgramState *state = C.getState();
SymbolRef Sym = state->getSVal(CE).getAsLocSymbol(); SymbolRef Sym = state->getSVal(CE).getAsLocSymbol();
if (!Sym) if (!Sym)
return; return;

View File

@ -20,12 +20,12 @@ add_clang_library(clangStaticAnalyzerCore
Environment.cpp Environment.cpp
ExplodedGraph.cpp ExplodedGraph.cpp
ExprEngine.cpp ExprEngine.cpp
GRState.cpp
HTMLDiagnostics.cpp HTMLDiagnostics.cpp
MemRegion.cpp MemRegion.cpp
ObjCMessage.cpp ObjCMessage.cpp
PathDiagnostic.cpp PathDiagnostic.cpp
PlistDiagnostics.cpp PlistDiagnostics.cpp
ProgramState.cpp
RangeConstraintManager.cpp RangeConstraintManager.cpp
RegionStore.cpp RegionStore.cpp
SValBuilder.cpp SValBuilder.cpp

View File

@ -109,7 +109,7 @@ void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
ExplodedNodeSet Tmp; ExplodedNodeSet Tmp;
Visit(ME->GetTemporaryExpr(), Pred, Tmp); Visit(ME->GetTemporaryExpr(), Pred, Tmp);
for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) { 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 // Bind the temporary object to the value of the expression. Then bind
// the expression to the location of the object. // the expression to the location of the object.
@ -187,7 +187,7 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(), for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(),
NE = argsEvaluated.end(); NI != NE; ++NI) { 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 // Setup 'this' region, so that the ctor is evaluated on the object pointed
// by 'Dest'. // by 'Dest'.
state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest)); state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
@ -216,7 +216,7 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
i != e; ++i) i != e; ++i)
{ {
ExplodedNode *Pred = *i; ExplodedNode *Pred = *i;
const GRState *state = Pred->getState(); const ProgramState *state = Pred->getState();
// Accumulate list of regions that are invalidated. // Accumulate list of regions that are invalidated.
for (CXXConstructExpr::const_arg_iterator for (CXXConstructExpr::const_arg_iterator
@ -259,7 +259,7 @@ void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
CallEnter PP(S, SFC, Pred->getLocationContext()); 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)); state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
ExplodedNode *N = Builder->generateNode(PP, state, Pred); ExplodedNode *N = Builder->generateNode(PP, state, Pred);
if (N) if (N)
@ -280,7 +280,7 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
if (CNE->isArray()) { if (CNE->isArray()) {
// FIXME: allocating an array requires simulating the constructors. // FIXME: allocating an array requires simulating the constructors.
// For now, just return a symbolicated region. // For now, just return a symbolicated region.
const GRState *state = Pred->getState(); const ProgramState *state = Pred->getState();
state = state->BindExpr(CNE, loc::MemRegionVal(EleReg)); state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
MakeNode(Dst, CNE, Pred, state); MakeNode(Dst, CNE, Pred, state);
return; return;
@ -299,7 +299,7 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
for (ExplodedNodeSet::iterator I = argsEvaluated.begin(), for (ExplodedNodeSet::iterator I = argsEvaluated.begin(),
E = argsEvaluated.end(); I != E; ++I) { E = argsEvaluated.end(); I != E; ++I) {
const GRState *state = (*I)->getState(); const ProgramState *state = (*I)->getState();
// Accumulate list of regions that are invalidated. // Accumulate list of regions that are invalidated.
// FIXME: Eventually we should unify the logic for constructor // FIXME: Eventually we should unify the logic for constructor
@ -352,7 +352,7 @@ void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
Visit(CDE->getArgument(), Pred, Argevaluated); Visit(CDE->getArgument(), Pred, Argevaluated);
for (ExplodedNodeSet::iterator I = Argevaluated.begin(), for (ExplodedNodeSet::iterator I = Argevaluated.begin(),
E = Argevaluated.end(); I != E; ++I) { E = Argevaluated.end(); I != E; ++I) {
const GRState *state = (*I)->getState(); const ProgramState *state = (*I)->getState();
MakeNode(Dst, CDE, *I, state); MakeNode(Dst, CDE, *I, state);
} }
} }
@ -365,7 +365,7 @@ void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
getContext().getCanonicalType(TE->getType()), getContext().getCanonicalType(TE->getType()),
Pred->getLocationContext()); Pred->getLocationContext());
const GRState *state = Pred->getState(); const ProgramState *state = Pred->getState();
SVal V = state->getSVal(loc::MemRegionVal(R)); SVal V = state->getSVal(loc::MemRegionVal(R));
MakeNode(Dst, TE, Pred, state->BindExpr(TE, V)); MakeNode(Dst, TE, Pred, state->BindExpr(TE, V));
} }

View File

@ -294,7 +294,7 @@ void CheckerManager::runCheckersForBranchCondition(const Stmt *condition,
} }
/// \brief Run checkers for live symbols. /// \brief Run checkers for live symbols.
void CheckerManager::runCheckersForLiveSymbols(const GRState *state, void CheckerManager::runCheckersForLiveSymbols(const ProgramState *state,
SymbolReaper &SymReaper) { SymbolReaper &SymReaper) {
for (unsigned i = 0, e = LiveSymbolsCheckers.size(); i != e; ++i) for (unsigned i = 0, e = LiveSymbolsCheckers.size(); i != e; ++i)
LiveSymbolsCheckers[i](state, SymReaper); 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. /// \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) for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i)
if (RegionChangesCheckers[i].WantUpdateFn(state)) if (RegionChangesCheckers[i].WantUpdateFn(state))
return true; return true;
@ -344,8 +344,8 @@ bool CheckerManager::wantsRegionChangeUpdate(const GRState *state) {
} }
/// \brief Run checkers for region changes. /// \brief Run checkers for region changes.
const GRState * const ProgramState *
CheckerManager::runCheckersForRegionChanges(const GRState *state, CheckerManager::runCheckersForRegionChanges(const ProgramState *state,
const StoreManager::InvalidatedSymbols *invalidated, const StoreManager::InvalidatedSymbols *invalidated,
const MemRegion * const *Begin, const MemRegion * const *Begin,
const MemRegion * const *End) { const MemRegion * const *End) {
@ -360,8 +360,8 @@ CheckerManager::runCheckersForRegionChanges(const GRState *state,
} }
/// \brief Run checkers for handling assumptions on symbolic values. /// \brief Run checkers for handling assumptions on symbolic values.
const GRState * const ProgramState *
CheckerManager::runCheckersForEvalAssume(const GRState *state, CheckerManager::runCheckersForEvalAssume(const ProgramState *state,
SVal Cond, bool Assumption) { SVal Cond, bool Assumption) {
for (unsigned i = 0, e = EvalAssumeCheckers.size(); i != e; ++i) { for (unsigned i = 0, e = EvalAssumeCheckers.size(); i != e; ++i) {
// If any checker declares the state infeasible (or if it starts that way), // If any checker declares the state infeasible (or if it starts that way),

View File

@ -159,7 +159,7 @@ WorkList* WorkList::makeBFSBlockDFSContents() {
/// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps. /// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps.
bool CoreEngine::ExecuteWorkList(const LocationContext *L, unsigned 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 if (G->num_roots() == 0) { // Initialize the analysis by constructing
// the root if none exists. // the root if none exists.
@ -243,9 +243,9 @@ bool CoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps,
} }
void CoreEngine::ExecuteWorkListWithInitialState(const LocationContext *L, void CoreEngine::ExecuteWorkListWithInitialState(const LocationContext *L,
unsigned Steps, unsigned Steps,
const GRState *InitState, const ProgramState *InitState,
ExplodedNodeSet &Dst) { ExplodedNodeSet &Dst) {
ExecuteWorkList(L, Steps, InitState); ExecuteWorkList(L, Steps, InitState);
for (SmallVectorImpl<ExplodedNode*>::iterator I = G->EndNodes.begin(), for (SmallVectorImpl<ExplodedNode*>::iterator I = G->EndNodes.begin(),
E = G->EndNodes.end(); I != E; ++I) { 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, /// generateNode - Utility method to generate nodes, hook up successors,
/// and add nodes to the worklist. /// and add nodes to the worklist.
void CoreEngine::generateNode(const ProgramPoint &Loc, void CoreEngine::generateNode(const ProgramPoint &Loc,
const GRState *State, ExplodedNode *Pred) { const ProgramState *State,
ExplodedNode *Pred) {
bool IsNew; bool IsNew;
ExplodedNode *Node = G->getNode(Loc, State, &IsNew); ExplodedNode *Node = G->getNode(Loc, State, &IsNew);
@ -460,7 +461,7 @@ void CoreEngine::generateNode(const ProgramPoint &Loc,
} }
ExplodedNode * ExplodedNode *
GenericNodeBuilderImpl::generateNodeImpl(const GRState *state, GenericNodeBuilderImpl::generateNodeImpl(const ProgramState *state,
ExplodedNode *pred, ExplodedNode *pred,
ProgramPoint programPoint, ProgramPoint programPoint,
bool asSink) { bool asSink) {
@ -480,9 +481,11 @@ GenericNodeBuilderImpl::generateNodeImpl(const GRState *state,
return 0; return 0;
} }
StmtNodeBuilder::StmtNodeBuilder(const CFGBlock *b, unsigned idx, StmtNodeBuilder::StmtNodeBuilder(const CFGBlock *b,
ExplodedNode *N, CoreEngine* e, unsigned idx,
GRStateManager &mgr) ExplodedNode *N,
CoreEngine* e,
ProgramStateManager &mgr)
: Eng(*e), B(*b), Idx(idx), Pred(N), Mgr(mgr), : Eng(*e), B(*b), Idx(idx), Pred(N), Mgr(mgr),
PurgingDeadSymbols(false), BuildSinks(false), hasGeneratedNode(false), PurgingDeadSymbols(false), BuildSinks(false), hasGeneratedNode(false),
PointKind(ProgramPoint::PostStmtKind), Tag(0) { PointKind(ProgramPoint::PostStmtKind), Tag(0) {
@ -529,9 +532,11 @@ void StmtNodeBuilder::GenerateAutoTransition(ExplodedNode *N) {
Eng.WList->enqueue(Succ, &B, Idx+1); Eng.WList->enqueue(Succ, &B, Idx+1);
} }
ExplodedNode *StmtNodeBuilder::MakeNode(ExplodedNodeSet &Dst, const Stmt *S, ExplodedNode *StmtNodeBuilder::MakeNode(ExplodedNodeSet &Dst,
ExplodedNode *Pred, const GRState *St, const Stmt *S,
ProgramPoint::Kind K) { ExplodedNode *Pred,
const ProgramState *St,
ProgramPoint::Kind K) {
ExplodedNode *N = generateNode(S, St, Pred, K); ExplodedNode *N = generateNode(S, St, Pred, K);
@ -571,7 +576,8 @@ static ProgramPoint GetProgramPoint(const Stmt *S, ProgramPoint::Kind K,
} }
ExplodedNode* ExplodedNode*
StmtNodeBuilder::generateNodeInternal(const Stmt *S, const GRState *state, StmtNodeBuilder::generateNodeInternal(const Stmt *S,
const ProgramState *state,
ExplodedNode *Pred, ExplodedNode *Pred,
ProgramPoint::Kind K, ProgramPoint::Kind K,
const ProgramPointTag *tag) { const ProgramPointTag *tag) {
@ -583,8 +589,8 @@ StmtNodeBuilder::generateNodeInternal(const Stmt *S, const GRState *state,
ExplodedNode* ExplodedNode*
StmtNodeBuilder::generateNodeInternal(const ProgramPoint &Loc, StmtNodeBuilder::generateNodeInternal(const ProgramPoint &Loc,
const GRState *State, const ProgramState *State,
ExplodedNode *Pred) { ExplodedNode *Pred) {
bool IsNew; bool IsNew;
ExplodedNode *N = Eng.G->getNode(Loc, State, &IsNew); ExplodedNode *N = Eng.G->getNode(Loc, State, &IsNew);
N->addPredecessor(Pred, *Eng.G); 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). // This function generate a new ExplodedNode but not a new branch(block edge).
ExplodedNode *BranchNodeBuilder::generateNode(const Stmt *Condition, ExplodedNode *BranchNodeBuilder::generateNode(const Stmt *Condition,
const GRState *State) { const ProgramState *State) {
bool IsNew; bool IsNew;
ExplodedNode *Succ ExplodedNode *Succ
@ -617,8 +623,8 @@ ExplodedNode *BranchNodeBuilder::generateNode(const Stmt *Condition,
return NULL; return NULL;
} }
ExplodedNode *BranchNodeBuilder::generateNode(const GRState *State, ExplodedNode *BranchNodeBuilder::generateNode(const ProgramState *State,
bool branch) { bool branch) {
// If the branch has been marked infeasible we should not generate a node. // If the branch has been marked infeasible we should not generate a node.
if (!isFeasible(branch)) if (!isFeasible(branch))
@ -655,8 +661,9 @@ BranchNodeBuilder::~BranchNodeBuilder() {
ExplodedNode* ExplodedNode*
IndirectGotoNodeBuilder::generateNode(const iterator &I, const GRState *St, IndirectGotoNodeBuilder::generateNode(const iterator &I,
bool isSink) { const ProgramState *St,
bool isSink) {
bool IsNew; bool IsNew;
ExplodedNode *Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(), ExplodedNode *Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(),
@ -679,26 +686,25 @@ IndirectGotoNodeBuilder::generateNode(const iterator &I, const GRState *St,
ExplodedNode* ExplodedNode*
SwitchNodeBuilder::generateCaseStmtNode(const iterator &I, const GRState *St){ SwitchNodeBuilder::generateCaseStmtNode(const iterator &I,
const ProgramState *St) {
bool IsNew; bool IsNew;
ExplodedNode *Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(), ExplodedNode *Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(),
Pred->getLocationContext()), St, &IsNew); Pred->getLocationContext()),
St, &IsNew);
Succ->addPredecessor(Pred, *Eng.G); Succ->addPredecessor(Pred, *Eng.G);
if (IsNew) { if (IsNew) {
Eng.WList->enqueue(Succ); Eng.WList->enqueue(Succ);
return Succ; return Succ;
} }
return NULL; return NULL;
} }
ExplodedNode* ExplodedNode*
SwitchNodeBuilder::generateDefaultCaseNode(const GRState *St, bool isSink) { SwitchNodeBuilder::generateDefaultCaseNode(const ProgramState *St,
bool isSink) {
// Get the block for the default case. // Get the block for the default case.
assert (Src->succ_rbegin() != Src->succ_rend()); assert (Src->succ_rbegin() != Src->succ_rend());
CFGBlock *DefaultBlock = *Src->succ_rbegin(); CFGBlock *DefaultBlock = *Src->succ_rbegin();
@ -733,7 +739,7 @@ EndOfFunctionNodeBuilder::~EndOfFunctionNodeBuilder() {
} }
ExplodedNode* ExplodedNode*
EndOfFunctionNodeBuilder::generateNode(const GRState *State, EndOfFunctionNodeBuilder::generateNode(const ProgramState *State,
ExplodedNode *P, ExplodedNode *P,
const ProgramPointTag *tag) { const ProgramPointTag *tag) {
hasGeneratedNode = true; hasGeneratedNode = true;
@ -753,7 +759,7 @@ EndOfFunctionNodeBuilder::generateNode(const GRState *State,
return NULL; return NULL;
} }
void EndOfFunctionNodeBuilder::GenerateCallExitNode(const GRState *state) { void EndOfFunctionNodeBuilder::GenerateCallExitNode(const ProgramState *state) {
hasGeneratedNode = true; hasGeneratedNode = true;
// Create a CallExit node and enqueue it. // Create a CallExit node and enqueue it.
const StackFrameContext *LocCtx 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. // Check if the callee is in the same translation unit.
if (CalleeCtx->getTranslationUnit() != if (CalleeCtx->getTranslationUnit() !=
Pred->getLocationContext()->getTranslationUnit()) { Pred->getLocationContext()->getTranslationUnit()) {
@ -824,8 +830,8 @@ void CallEnterNodeBuilder::generateNode(const GRState *state) {
OldLocCtx->getIndex()); OldLocCtx->getIndex());
// Now create an initial state for the new engine. // Now create an initial state for the new engine.
const GRState *NewState = NewEng.getStateManager().MarshalState(state, const ProgramState *NewState =
NewLocCtx); NewEng.getStateManager().MarshalState(state, NewLocCtx);
ExplodedNodeSet ReturnNodes; ExplodedNodeSet ReturnNodes;
NewEng.ExecuteWorkListWithInitialState(NewLocCtx, AMgr.getMaxNodes(), NewEng.ExecuteWorkListWithInitialState(NewLocCtx, AMgr.getMaxNodes(),
NewState, ReturnNodes); NewState, ReturnNodes);
@ -851,7 +857,7 @@ void CallEnterNodeBuilder::generateNode(const GRState *state) {
Eng.WList->enqueue(Node); Eng.WList->enqueue(Node);
} }
void CallExitNodeBuilder::generateNode(const GRState *state) { void CallExitNodeBuilder::generateNode(const ProgramState *state) {
// Get the callee's location context. // Get the callee's location context.
const StackFrameContext *LocCtx const StackFrameContext *LocCtx
= cast<StackFrameContext>(Pred->getLocationContext()); = cast<StackFrameContext>(Pred->getLocationContext());

View File

@ -13,7 +13,7 @@
#include "clang/Analysis/AnalysisContext.h" #include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.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 clang;
using namespace ento; using namespace ento;
@ -143,7 +143,7 @@ static inline bool IsLocation(const Stmt *S) {
Environment Environment
EnvironmentManager::removeDeadBindings(Environment Env, EnvironmentManager::removeDeadBindings(Environment Env,
SymbolReaper &SymReaper, SymbolReaper &SymReaper,
const GRState *ST) { const ProgramState *ST) {
// We construct a new Environment object entirely, as this is cheaper than // We construct a new Environment object entirely, as this is cheaper than
// individually removing all the subexpression bindings (which will greatly // individually removing all the subexpression bindings (which will greatly

View File

@ -13,7 +13,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" #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 "clang/AST/Stmt.h"
#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
@ -103,8 +103,8 @@ void ExplodedGraph::reclaimRecentlyAllocatedNodes() {
continue; continue;
// Conditions 5, 6, and 7. // Conditions 5, 6, and 7.
const GRState *state = node->getState(); const ProgramState *state = node->getState();
const GRState *pred_state = pred->getState(); const ProgramState *pred_state = pred->getState();
if (state->store != pred_state->store || state->GDM != pred_state->GDM || if (state->store != pred_state->store || state->GDM != pred_state->GDM ||
progPoint.getLocationContext() != pred->getLocationContext()) progPoint.getLocationContext() != pred->getLocationContext())
continue; continue;
@ -216,7 +216,7 @@ ExplodedNode** ExplodedNode::NodeGroup::end() const {
} }
ExplodedNode *ExplodedGraph::getNode(const ProgramPoint &L, 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. // Profile 'State' to determine if we already have an existing node.
llvm::FoldingSetNodeID profile; llvm::FoldingSetNodeID profile;
void *InsertPos = 0; void *InsertPos = 0;

View File

@ -93,8 +93,8 @@ ExprEngine::~ExprEngine() {
// Utility methods. // Utility methods.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
const GRState *ExprEngine::getInitialState(const LocationContext *InitLoc) { const ProgramState *ExprEngine::getInitialState(const LocationContext *InitLoc) {
const GRState *state = StateMgr.getInitialState(InitLoc); const ProgramState *state = StateMgr.getInitialState(InitLoc);
// Preconditions. // Preconditions.
@ -129,7 +129,7 @@ const GRState *ExprEngine::getInitialState(const LocationContext *InitLoc) {
if (!Constraint) if (!Constraint)
break; break;
if (const GRState *newState = state->assume(*Constraint, true)) if (const ProgramState *newState = state->assume(*Constraint, true))
state = newState; state = newState;
break; break;
@ -180,7 +180,7 @@ ExprEngine::doesInvalidateGlobals(const CallOrObjCMessage &callOrMessage) const
/// evalAssume - Called by ConstraintManager. Used to call checker-specific /// evalAssume - Called by ConstraintManager. Used to call checker-specific
/// logic for handling assumptions on symbolic values. /// 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) { bool assumption) {
state = getCheckerManager().runCheckersForEvalAssume(state, cond, 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); return TF->evalAssume(state, cond, assumption);
} }
bool ExprEngine::wantsRegionChangeUpdate(const GRState *state) { bool ExprEngine::wantsRegionChangeUpdate(const ProgramState *state) {
return getCheckerManager().wantsRegionChangeUpdate(state); return getCheckerManager().wantsRegionChangeUpdate(state);
} }
const GRState * const ProgramState *
ExprEngine::processRegionChanges(const GRState *state, ExprEngine::processRegionChanges(const ProgramState *state,
const StoreManager::InvalidatedSymbols *invalidated, const StoreManager::InvalidatedSymbols *invalidated,
const MemRegion * const *Begin, const MemRegion * const *Begin,
const MemRegion * const *End) { const MemRegion * const *End) {
@ -234,7 +234,7 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) {
// Reclaim any unnecessary nodes in the ExplodedGraph. // Reclaim any unnecessary nodes in the ExplodedGraph.
G.reclaimRecentlyAllocatedNodes(); G.reclaimRecentlyAllocatedNodes();
// Recycle any unused states in the GRStateManager. // Recycle any unused states in the ProgramStateManager.
StateMgr.recycleUnusedStates(); StateMgr.recycleUnusedStates();
currentStmt = S.getStmt(); currentStmt = S.getStmt();
@ -247,7 +247,7 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) {
Builder = &builder; Builder = &builder;
EntryNode = builder.getPredecessor(); EntryNode = builder.getPredecessor();
const GRState *EntryState = EntryNode->getState(); const ProgramState *EntryState = EntryNode->getState();
CleanedState = EntryState; CleanedState = EntryState;
ExplodedNode *CleanedNode = 0; ExplodedNode *CleanedNode = 0;
@ -299,7 +299,7 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) {
// states as the predecessors. // states as the predecessors.
for (ExplodedNodeSet::const_iterator I = Tmp3.begin(), E = Tmp3.end(); for (ExplodedNodeSet::const_iterator I = Tmp3.begin(), E = Tmp3.end();
I != E; ++I) { 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. // The constraint manager has not been cleaned up yet, so clean up now.
CheckerState = getConstraintManager().removeDeadBindings(CheckerState, 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 // Create a state based on CleanedState with CheckerState GDM and
// generate a transition to that state. // generate a transition to that state.
const GRState *CleanedCheckerSt = const ProgramState *CleanedCheckerSt =
StateMgr.getPersistentStateWithGDM(CleanedState, CheckerState); StateMgr.getPersistentStateWithGDM(CleanedState, CheckerState);
ExplodedNode *CleanedNode = Builder->generateNode(currentStmt, ExplodedNode *CleanedNode = Builder->generateNode(currentStmt,
CleanedCheckerSt, *I, CleanedCheckerSt, *I,
@ -358,7 +358,7 @@ void ExprEngine::ProcessInitializer(const CFGInitializer Init,
for (ExplodedNodeSet::iterator I = Dst.begin(), E = Dst.end(); I != E; ++I){ for (ExplodedNodeSet::iterator I = Dst.begin(), E = Dst.end(); I != E; ++I){
ExplodedNode *Pred = *I; ExplodedNode *Pred = *I;
const GRState *state = Pred->getState(); const ProgramState *state = Pred->getState();
const FieldDecl *FD = BMI->getAnyMember(); const FieldDecl *FD = BMI->getAnyMember();
@ -415,7 +415,7 @@ void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D,
void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor dtor, void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor dtor,
StmtNodeBuilder &builder) { StmtNodeBuilder &builder) {
ExplodedNode *pred = builder.getPredecessor(); ExplodedNode *pred = builder.getPredecessor();
const GRState *state = pred->getState(); const ProgramState *state = pred->getState();
const VarDecl *varDecl = dtor.getVarDecl(); const VarDecl *varDecl = dtor.getVarDecl();
QualType varType = varDecl->getType(); QualType varType = varDecl->getType();
@ -535,7 +535,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::GNUNullExprClass: { case Stmt::GNUNullExprClass: {
// GNU __null is a pointer-width integer, not an actual pointer. // 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)); state = state->BindExpr(S, svalBuilder.makeIntValWithPtrWidth(0, false));
MakeNode(Dst, S, Pred, state); MakeNode(Dst, S, Pred, state);
break; break;
@ -550,7 +550,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
break; break;
case Stmt::ImplicitValueInitExprClass: { case Stmt::ImplicitValueInitExprClass: {
const GRState *state = Pred->getState(); const ProgramState *state = Pred->getState();
QualType ty = cast<ImplicitValueInitExpr>(S)->getType(); QualType ty = cast<ImplicitValueInitExpr>(S)->getType();
SVal val = svalBuilder.makeZeroVal(ty); SVal val = svalBuilder.makeZeroVal(ty);
MakeNode(Dst, S, Pred, state->BindExpr(S, val)); MakeNode(Dst, S, Pred, state->BindExpr(S, val));
@ -621,7 +621,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
break; break;
} }
else if (B->getOpcode() == BO_Comma) { 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()))); MakeNode(Dst, B, Pred, state->BindExpr(B, state->getSVal(B->getRHS())));
break; break;
} }
@ -791,7 +791,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
} }
if (Expr *LastExpr = dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) { 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))); MakeNode(Dst, SE, Pred, state->BindExpr(SE, state->getSVal(LastExpr)));
} }
else else
@ -801,7 +801,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
} }
case Stmt::StringLiteralClass: { case Stmt::StringLiteralClass: {
const GRState *state = Pred->getState(); const ProgramState *state = Pred->getState();
SVal V = state->getLValue(cast<StringLiteral>(S)); SVal V = state->getLValue(cast<StringLiteral>(S));
MakeNode(Dst, S, Pred, state->BindExpr(S, V)); MakeNode(Dst, S, Pred, state->BindExpr(S, V));
return; return;
@ -845,7 +845,7 @@ void ExprEngine::processCFGBlockEntrance(ExplodedNodeSet &dstNodes,
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
ExplodedNode *ExprEngine::MakeNode(ExplodedNodeSet &Dst, const Stmt *S, ExplodedNode *ExprEngine::MakeNode(ExplodedNodeSet &Dst, const Stmt *S,
ExplodedNode *Pred, const GRState *St, ExplodedNode *Pred, const ProgramState *St,
ProgramPoint::Kind K, ProgramPoint::Kind K,
const ProgramPointTag *tag) { const ProgramPointTag *tag) {
assert (Builder && "StmtNodeBuilder not present."); assert (Builder && "StmtNodeBuilder not present.");
@ -858,7 +858,7 @@ ExplodedNode *ExprEngine::MakeNode(ExplodedNodeSet &Dst, const Stmt *S,
// Branch processing. // Branch processing.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
const GRState *ExprEngine::MarkBranch(const GRState *state, const ProgramState *ExprEngine::MarkBranch(const ProgramState *state,
const Stmt *Terminator, const Stmt *Terminator,
bool branchTaken) { bool branchTaken) {
@ -919,7 +919,7 @@ const GRState *ExprEngine::MarkBranch(const GRState *state,
/// integers that promote their values (which are currently not tracked well). /// integers that promote their values (which are currently not tracked well).
/// This function returns the SVal bound to Condition->IgnoreCasts if all the /// This function returns the SVal bound to Condition->IgnoreCasts if all the
// cast(s) did was sign-extend the original value. // 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 Stmt *Condition, ASTContext &Ctx) {
const Expr *Ex = dyn_cast<Expr>(Condition); 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)) if (!builder.isFeasible(true) && !builder.isFeasible(false))
return; return;
const GRState *PrevState = builder.getState(); const ProgramState *PrevState = builder.getState();
SVal X = PrevState->getSVal(Condition); SVal X = PrevState->getSVal(Condition);
if (X.isUnknownOrUndef()) { if (X.isUnknownOrUndef()) {
@ -1004,7 +1004,7 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
// Process the true branch. // Process the true branch.
if (builder.isFeasible(true)) { 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); builder.generateNode(MarkBranch(state, Term, true), true);
else else
builder.markInfeasible(true); builder.markInfeasible(true);
@ -1012,7 +1012,7 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
// Process the false branch. // Process the false branch.
if (builder.isFeasible(false)) { 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); builder.generateNode(MarkBranch(state, Term, false), false);
else else
builder.markInfeasible(false); 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. /// nodes by processing the 'effects' of a computed goto jump.
void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) { void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) {
const GRState *state = builder.getState(); const ProgramState *state = builder.getState();
SVal V = state->getSVal(builder.getTarget()); SVal V = state->getSVal(builder.getTarget());
// Three possibilities: // Three possibilities:
@ -1072,7 +1072,7 @@ void ExprEngine::VisitGuardedExpr(const Expr *Ex, const Expr *L,
assert(Ex == currentStmt && assert(Ex == currentStmt &&
Pred->getLocationContext()->getCFG()->isBlkExpr(Ex)); Pred->getLocationContext()->getCFG()->isBlkExpr(Ex));
const GRState *state = Pred->getState(); const ProgramState *state = Pred->getState();
SVal X = state->getSVal(Ex); SVal X = state->getSVal(Ex);
assert (X.isUndef()); assert (X.isUndef());
@ -1097,7 +1097,7 @@ void ExprEngine::processEndOfFunction(EndOfFunctionNodeBuilder& builder) {
/// nodes by processing the 'effects' of a switch statement. /// nodes by processing the 'effects' of a switch statement.
void ExprEngine::processSwitch(SwitchNodeBuilder& builder) { void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
typedef SwitchNodeBuilder::iterator iterator; typedef SwitchNodeBuilder::iterator iterator;
const GRState *state = builder.getState(); const ProgramState *state = builder.getState();
const Expr *CondE = builder.getCondition(); const Expr *CondE = builder.getCondition();
SVal CondV_untested = state->getSVal(CondE); SVal CondV_untested = state->getSVal(CondE);
@ -1110,7 +1110,7 @@ void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
} }
DefinedOrUnknownSVal CondV = cast<DefinedOrUnknownSVal>(CondV_untested); DefinedOrUnknownSVal CondV = cast<DefinedOrUnknownSVal>(CondV_untested);
const GRState *DefaultSt = state; const ProgramState *DefaultSt = state;
iterator I = builder.begin(), EI = builder.end(); iterator I = builder.begin(), EI = builder.end();
bool defaultIsFeasible = I == EI; bool defaultIsFeasible = I == EI;
@ -1155,7 +1155,7 @@ void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
CondV, CaseVal); CondV, CaseVal);
// Now "assume" that the case matches. // 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); builder.generateCaseStmtNode(I, stateNew);
// If CondV evaluates to a constant, then we know that this // 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 // Now "assume" that the case doesn't match. Add this state
// to the default state (if it is feasible). // to the default state (if it is feasible).
if (DefaultSt) { if (DefaultSt) {
if (const GRState *stateNew = DefaultSt->assume(Res, false)) { if (const ProgramState *stateNew = DefaultSt->assume(Res, false)) {
defaultIsFeasible = true; defaultIsFeasible = true;
DefaultSt = stateNew; DefaultSt = stateNew;
} }
@ -1209,12 +1209,12 @@ void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
} }
void ExprEngine::processCallEnter(CallEnterNodeBuilder &B) { void ExprEngine::processCallEnter(CallEnterNodeBuilder &B) {
const GRState *state = B.getState()->enterStackFrame(B.getCalleeContext()); const ProgramState *state = B.getState()->enterStackFrame(B.getCalleeContext());
B.generateNode(state); B.generateNode(state);
} }
void ExprEngine::processCallExit(CallExitNodeBuilder &B) { void ExprEngine::processCallExit(CallExitNodeBuilder &B) {
const GRState *state = B.getState(); const ProgramState *state = B.getState();
const ExplodedNode *Pred = B.getPredecessor(); const ExplodedNode *Pred = B.getPredecessor();
const StackFrameContext *calleeCtx = const StackFrameContext *calleeCtx =
cast<StackFrameContext>(Pred->getLocationContext()); cast<StackFrameContext>(Pred->getLocationContext());
@ -1254,7 +1254,7 @@ void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred,
assert(B==currentStmt && Pred->getLocationContext()->getCFG()->isBlkExpr(B)); assert(B==currentStmt && Pred->getLocationContext()->getCFG()->isBlkExpr(B));
const GRState *state = Pred->getState(); const ProgramState *state = Pred->getState();
SVal X = state->getSVal(B); SVal X = state->getSVal(B);
assert(X.isUndef()); 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 // 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, // 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. // 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, MakeNode(Dst, B, Pred,
newState->BindExpr(B, svalBuilder.makeIntVal(1U, B->getType()))); 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, MakeNode(Dst, B, Pred,
newState->BindExpr(B, svalBuilder.makeIntVal(0U, B->getType()))); 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, void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
ExplodedNode *Pred, ExplodedNode *Pred,
ExplodedNodeSet &Dst) { ExplodedNodeSet &Dst) {
const GRState *state = Pred->getState(); const ProgramState *state = Pred->getState();
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
assert(Ex->isLValue()); assert(Ex->isLValue());
@ -1368,7 +1368,7 @@ void ExprEngine::VisitLvalArraySubscriptExpr(const ArraySubscriptExpr *A,
for (ExplodedNodeSet::iterator it = checkerPreStmt.begin(), for (ExplodedNodeSet::iterator it = checkerPreStmt.begin(),
ei = checkerPreStmt.end(); it != ei; ++it) { 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), SVal V = state->getLValue(A->getType(), state->getSVal(Idx),
state->getSVal(Base)); state->getSVal(Base));
assert(A->isLValue()); assert(A->isLValue());
@ -1385,7 +1385,7 @@ void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
return; return;
Expr *baseExpr = M->getBase()->IgnoreParens(); Expr *baseExpr = M->getBase()->IgnoreParens();
const GRState *state = Pred->getState(); const ProgramState *state = Pred->getState();
SVal baseExprVal = state->getSVal(baseExpr); SVal baseExprVal = state->getSVal(baseExpr);
if (isa<nonloc::LazyCompoundVal>(baseExprVal) || if (isa<nonloc::LazyCompoundVal>(baseExprVal) ||
isa<nonloc::CompoundVal>(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. /// evalBind - Handle the semantics of binding a value to a specific location.
/// This method is used by evalStore and (soon) VisitDeclStmt, and others. /// This method is used by evalStore and (soon) VisitDeclStmt, and others.
void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE, void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
ExplodedNode *Pred, const GRState *state, ExplodedNode *Pred, const ProgramState *state,
SVal location, SVal Val, bool atDeclInit) { SVal location, SVal Val, bool atDeclInit) {
@ -1428,7 +1428,7 @@ void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
if (Pred != *I) if (Pred != *I)
state = (*I)->getState(); state = (*I)->getState();
const GRState *newState = 0; const ProgramState *newState = 0;
if (atDeclInit) { if (atDeclInit) {
const VarRegion *VR = const VarRegion *VR =
@ -1475,7 +1475,7 @@ void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
void ExprEngine::evalStore(ExplodedNodeSet &Dst, const Expr *AssignE, void ExprEngine::evalStore(ExplodedNodeSet &Dst, const Expr *AssignE,
const Expr *LocationE, const Expr *LocationE,
ExplodedNode *Pred, ExplodedNode *Pred,
const GRState *state, SVal location, SVal Val, const ProgramState *state, SVal location, SVal Val,
const ProgramPointTag *tag) { const ProgramPointTag *tag) {
assert(Builder && "StmtNodeBuilder must be defined."); 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, void ExprEngine::evalLoad(ExplodedNodeSet &Dst, const Expr *Ex,
ExplodedNode *Pred, ExplodedNode *Pred,
const GRState *state, SVal location, const ProgramState *state, SVal location,
const ProgramPointTag *tag, QualType LoadTy) { const ProgramPointTag *tag, QualType LoadTy) {
assert(!isa<NonLoc>(location) && "location cannot be a NonLoc."); 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, void ExprEngine::evalLoadCommon(ExplodedNodeSet &Dst, const Expr *Ex,
ExplodedNode *Pred, ExplodedNode *Pred,
const GRState *state, SVal location, const ProgramState *state, SVal location,
const ProgramPointTag *tag, QualType LoadTy) { const ProgramPointTag *tag, QualType LoadTy) {
// Evaluate the location (checks for bad dereferences). // 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, void ExprEngine::evalLocation(ExplodedNodeSet &Dst, const Stmt *S,
ExplodedNode *Pred, ExplodedNode *Pred,
const GRState *state, SVal location, const ProgramState *state, SVal location,
const ProgramPointTag *tag, bool isLoad) { const ProgramPointTag *tag, bool isLoad) {
// Early checks for performance reason. // Early checks for performance reason.
if (location.isUnknown()) { if (location.isUnknown()) {
@ -1626,7 +1626,7 @@ bool ExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE,
// cases as well. // cases as well.
#if 0 #if 0
const GRState *state = Pred->getState(); const ProgramState *state = Pred->getState();
const Expr *Callee = CE->getCallee(); const Expr *Callee = CE->getCallee();
SVal L = state->getSVal(Callee); 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. // Dispatch to transfer function logic to handle the call itself.
const Expr *Callee = CE->getCallee()->IgnoreParens(); const Expr *Callee = CE->getCallee()->IgnoreParens();
const GRState *state = Pred->getState(); const ProgramState *state = Pred->getState();
SVal L = state->getSVal(Callee); SVal L = state->getSVal(Callee);
Eng.getTF().evalCall(Dst, Eng, Builder, CE, L, Pred); Eng.getTF().evalCall(Dst, Eng, Builder, CE, L, Pred);
@ -1778,11 +1778,11 @@ void ExprEngine::evalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
continue; continue;
} }
const GRState *state = Pred->getState(); const ProgramState *state = Pred->getState();
SVal V = state->getSVal(Ex); SVal V = state->getSVal(Ex);
if (nonloc::SymExprVal *SEV = dyn_cast<nonloc::SymExprVal>(&V)) { if (nonloc::SymExprVal *SEV = dyn_cast<nonloc::SymExprVal>(&V)) {
// First assume that the condition is true. // 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, stateTrue = stateTrue->BindExpr(Ex,
svalBuilder.makeIntVal(1U, Ex->getType())); svalBuilder.makeIntVal(1U, Ex->getType()));
Dst.Add(Builder->generateNode(PostStmtCustom(Ex, Dst.Add(Builder->generateNode(PostStmtCustom(Ex,
@ -1791,7 +1791,7 @@ void ExprEngine::evalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
} }
// Next, assume that the condition is false. // 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, stateFalse = stateFalse->BindExpr(Ex,
svalBuilder.makeIntVal(0U, Ex->getType())); svalBuilder.makeIntVal(0U, Ex->getType()));
Dst.Add(Builder->generateNode(PostStmtCustom(Ex, &EagerlyAssumeTag, Dst.Add(Builder->generateNode(PostStmtCustom(Ex, &EagerlyAssumeTag,
@ -1822,7 +1822,7 @@ void ExprEngine::VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *Ex,
ExplodedNode *Pred, ExplodedNode *Pred,
ExplodedNodeSet &Dst) { ExplodedNodeSet &Dst) {
const GRState *state = Pred->getState(); const ProgramState *state = Pred->getState();
SVal baseVal = state->getSVal(Ex->getBase()); SVal baseVal = state->getSVal(Ex->getBase());
SVal location = state->getLValue(Ex->getDecl(), baseVal); SVal location = state->getLValue(Ex->getDecl(), baseVal);
@ -1867,7 +1867,7 @@ void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
// result in state splitting. // result in state splitting.
const Stmt *elem = S->getElement(); const Stmt *elem = S->getElement();
const GRState *state = Pred->getState(); const ProgramState *state = Pred->getState();
SVal elementV; SVal elementV;
if (const DeclStmt *DS = dyn_cast<DeclStmt>(elem)) { if (const DeclStmt *DS = dyn_cast<DeclStmt>(elem)) {
@ -1888,15 +1888,15 @@ void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
for (ExplodedNodeSet::iterator NI = dstLocation.begin(), for (ExplodedNodeSet::iterator NI = dstLocation.begin(),
NE = dstLocation.end(); NI!=NE; ++NI) { NE = dstLocation.end(); NI!=NE; ++NI) {
Pred = *NI; Pred = *NI;
const GRState *state = Pred->getState(); const ProgramState *state = Pred->getState();
// Handle the case where the container still has elements. // Handle the case where the container still has elements.
SVal TrueV = svalBuilder.makeTruthVal(1); 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. // Handle the case where the container has no elements.
SVal FalseV = svalBuilder.makeTruthVal(0); 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 (loc::MemRegionVal *MV = dyn_cast<loc::MemRegionVal>(&elementV))
if (const TypedValueRegion *R = if (const TypedValueRegion *R =
@ -1947,13 +1947,13 @@ void ExprEngine::VisitObjCMessage(const ObjCMessage &msg,
SaveOr OldHasGen(Builder->hasGeneratedNode); SaveOr OldHasGen(Builder->hasGeneratedNode);
if (const Expr *Receiver = msg.getInstanceReceiver()) { if (const Expr *Receiver = msg.getInstanceReceiver()) {
const GRState *state = Pred->getState(); const ProgramState *state = Pred->getState();
SVal recVal = state->getSVal(Receiver); SVal recVal = state->getSVal(Receiver);
if (!recVal.isUndef()) { if (!recVal.isUndef()) {
// Bifurcate the state into nil and non-nil ones. // Bifurcate the state into nil and non-nil ones.
DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal); DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal);
const GRState *notNilState, *nilState; const ProgramState *notNilState, *nilState;
llvm::tie(notNilState, nilState) = state->assume(receiverVal); llvm::tie(notNilState, nilState) = state->assume(receiverVal);
// There are three cases: can be nil or non-nil, must be nil, must be // 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(); for (ExplodedNodeSet::iterator I = dstPreStmt.begin(), E = dstPreStmt.end();
I!=E; ++I) { I!=E; ++I) {
ExplodedNode *subExprNode = *I; ExplodedNode *subExprNode = *I;
const GRState *state = subExprNode->getState(); const ProgramState *state = subExprNode->getState();
evalLoad(Dst, CastE, subExprNode, state, state->getSVal(Ex)); evalLoad(Dst, CastE, subExprNode, state, state->getSVal(Ex));
} }
return; return;
@ -2088,7 +2088,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
case CK_NoOp: case CK_NoOp:
case CK_FunctionToPointerDecay: { case CK_FunctionToPointerDecay: {
// Copy the SVal of Ex to CastE. // Copy the SVal of Ex to CastE.
const GRState *state = Pred->getState(); const ProgramState *state = Pred->getState();
SVal V = state->getSVal(Ex); SVal V = state->getSVal(Ex);
state = state->BindExpr(CastE, V); state = state->BindExpr(CastE, V);
MakeNode(Dst, CastE, Pred, state); MakeNode(Dst, CastE, Pred, state);
@ -2122,7 +2122,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
case CK_AnyPointerToBlockPointerCast: case CK_AnyPointerToBlockPointerCast:
case CK_ObjCObjectLValueCast: { case CK_ObjCObjectLValueCast: {
// Delegate to SValBuilder to process. // Delegate to SValBuilder to process.
const GRState *state = Pred->getState(); const ProgramState *state = Pred->getState();
SVal V = state->getSVal(Ex); SVal V = state->getSVal(Ex);
V = svalBuilder.evalCast(V, T, ExTy); V = svalBuilder.evalCast(V, T, ExTy);
state = state->BindExpr(CastE, V); state = state->BindExpr(CastE, V);
@ -2132,7 +2132,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
case CK_DerivedToBase: case CK_DerivedToBase:
case CK_UncheckedDerivedToBase: { case CK_UncheckedDerivedToBase: {
// For DerivedToBase cast, delegate to the store manager. // For DerivedToBase cast, delegate to the store manager.
const GRState *state = Pred->getState(); const ProgramState *state = Pred->getState();
SVal val = state->getSVal(Ex); SVal val = state->getSVal(Ex);
val = getStoreManager().evalDerivedToBase(val, T); val = getStoreManager().evalDerivedToBase(val, T);
state = state->BindExpr(CastE, val); state = state->BindExpr(CastE, val);
@ -2159,7 +2159,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
svalBuilder.getConjuredSymbolVal(NULL, CastE, resultType, svalBuilder.getConjuredSymbolVal(NULL, CastE, resultType,
Builder->getCurrentBlockCount()); Builder->getCurrentBlockCount());
const GRState *state = Pred->getState()->BindExpr(CastE, result); const ProgramState *state = Pred->getState()->BindExpr(CastE, result);
MakeNode(Dst, CastE, Pred, state); MakeNode(Dst, CastE, Pred, state);
continue; continue;
} }
@ -2173,7 +2173,7 @@ void ExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL,
const InitListExpr *ILE const InitListExpr *ILE
= cast<InitListExpr>(CL->getInitializer()->IgnoreParens()); = cast<InitListExpr>(CL->getInitializer()->IgnoreParens());
const GRState *state = Pred->getState(); const ProgramState *state = Pred->getState();
SVal ILV = state->getSVal(ILE); SVal ILV = state->getSVal(ILE);
const LocationContext *LC = Pred->getLocationContext(); const LocationContext *LC = Pred->getLocationContext();
@ -2209,7 +2209,7 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
I!=E; ++I) I!=E; ++I)
{ {
ExplodedNode *N = *I; ExplodedNode *N = *I;
const GRState *state = N->getState(); const ProgramState *state = N->getState();
// Decls without InitExpr are not initialized explicitly. // Decls without InitExpr are not initialized explicitly.
const LocationContext *LC = N->getLocationContext(); 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, void ExprEngine::VisitInitListExpr(const InitListExpr *IE, ExplodedNode *Pred,
ExplodedNodeSet &Dst) { ExplodedNodeSet &Dst) {
const GRState *state = Pred->getState(); const ProgramState *state = Pred->getState();
QualType T = getContext().getCanonicalType(IE->getType()); QualType T = getContext().getCanonicalType(IE->getType());
unsigned NumInitElements = IE->getNumInits(); unsigned NumInitElements = IE->getNumInits();
@ -2302,7 +2302,7 @@ void ExprEngine::VisitUnaryExprOrTypeTraitExpr(
// Get the size by getting the extent of the sub-expression. // Get the size by getting the extent of the sub-expression.
// First, visit the sub-expression to find its region. // First, visit the sub-expression to find its region.
const Expr *Arg = Ex->getArgumentExpr(); const Expr *Arg = Ex->getArgumentExpr();
const GRState *state = Pred->getState(); const ProgramState *state = Pred->getState();
const MemRegion *MR = state->getSVal(Arg).getAsRegion(); const MemRegion *MR = state->getSVal(Arg).getAsRegion();
// If the subexpression can't be resolved to a region, we don't know // 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. // For all other types, UO_Real is an identity operation.
assert (U->getType() == Ex->getType()); 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))); 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. // For all other types, UO_Imag returns 0.
const GRState *state = (*I)->getState(); const ProgramState *state = (*I)->getState();
SVal X = svalBuilder.makeZeroVal(Ex->getType()); SVal X = svalBuilder.makeZeroVal(Ex->getType());
MakeNode(Dst, U, *I, state->BindExpr(U, X)); MakeNode(Dst, U, *I, state->BindExpr(U, X));
} }
@ -2424,7 +2424,7 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
Visit(Ex, Pred, Tmp); Visit(Ex, Pred, Tmp);
for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { 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))); MakeNode(Dst, U, *I, state->BindExpr(U, state->getSVal(Ex)));
} }
@ -2440,7 +2440,7 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
Visit(Ex, Pred, Tmp); Visit(Ex, Pred, Tmp);
for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { 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. // Get the value of the subexpression.
SVal V = state->getSVal(Ex); 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) { 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); SVal loc = state->getSVal(Ex);
// Perform a load. // Perform a load.
@ -2626,7 +2626,7 @@ void ExprEngine::VisitAsmStmtHelperInputs(const AsmStmt *A,
// which interprets the inline asm and stores proper results in the // which interprets the inline asm and stores proper results in the
// outputs. // outputs.
const GRState *state = Pred->getState(); const ProgramState *state = Pred->getState();
for (AsmStmt::const_outputs_iterator OI = A->begin_outputs(), for (AsmStmt::const_outputs_iterator OI = A->begin_outputs(),
OE = A->end_outputs(); OI != OE; ++OI) { 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. // processCallExit to bind the return value to the call expr.
{ {
static SimpleProgramPointTag tag("ExprEngine: ReturnStmt"); static SimpleProgramPointTag tag("ExprEngine: ReturnStmt");
const GRState *state = Pred->getState(); const ProgramState *state = Pred->getState();
state = state->set<ReturnExpr>(RetE); state = state->set<ReturnExpr>(RetE);
Pred = Builder->generateNode(RetE, state, Pred, &tag); 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(); for (ExplodedNodeSet::iterator I2=CheckedSet.begin(), E2=CheckedSet.end();
I2 != E2; ++I2) { I2 != E2; ++I2) {
const GRState *state = (*I2)->getState(); const ProgramState *state = (*I2)->getState();
SVal RightV = state->getSVal(RHS); SVal RightV = state->getSVal(RHS);
BinaryOperator::Opcode Op = B->getOpcode(); 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 Out << "\\|StateID: " << (void*) state
<< " NodeID: " << (void*) N << "\\|"; << " NodeID: " << (void*) N << "\\|";
state->printDOT(Out, *N->getLocationContext()->getCFG()); state->printDOT(Out, *N->getLocationContext()->getCFG());

View File

@ -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;
}

View File

@ -8,13 +8,13 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// //
// This file defines RangeConstraintManager, a class that tracks simple // 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 "SimpleConstraintManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.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/TransferFuncs.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/FoldingSet.h"
@ -196,8 +196,8 @@ typedef llvm::ImmutableMap<SymbolRef,RangeSet> ConstraintRangeTy;
namespace clang { namespace clang {
namespace ento { namespace ento {
template<> template<>
struct GRStateTrait<ConstraintRange> struct ProgramStateTrait<ConstraintRange>
: public GRStatePartialTrait<ConstraintRangeTy> { : public ProgramStatePartialTrait<ConstraintRangeTy> {
static inline void *GDMIndex() { return &ConstraintRangeIndex; } static inline void *GDMIndex() { return &ConstraintRangeIndex; }
}; };
} }
@ -205,46 +205,46 @@ struct GRStateTrait<ConstraintRange>
namespace { namespace {
class RangeConstraintManager : public SimpleConstraintManager{ class RangeConstraintManager : public SimpleConstraintManager{
RangeSet GetRange(const GRState *state, SymbolRef sym); RangeSet GetRange(const ProgramState *state, SymbolRef sym);
public: public:
RangeConstraintManager(SubEngine &subengine) RangeConstraintManager(SubEngine &subengine)
: SimpleConstraintManager(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& Int,
const llvm::APSInt& Adjustment); 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& Int,
const llvm::APSInt& Adjustment); 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& Int,
const llvm::APSInt& Adjustment); 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& Int,
const llvm::APSInt& Adjustment); 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& Int,
const llvm::APSInt& Adjustment); 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& Int,
const llvm::APSInt& Adjustment); 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? // 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); const llvm::APSInt *i = getSymVal(St, sym);
return i ? *i == V : false; 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); const char* nl, const char *sep);
private: private:
@ -253,12 +253,12 @@ private:
} // end anonymous namespace } // end anonymous namespace
ConstraintManager* ento::CreateRangeConstraintManager(GRStateManager&, ConstraintManager* ento::CreateRangeConstraintManager(ProgramStateManager&,
SubEngine &subeng) { SubEngine &subeng) {
return new RangeConstraintManager(subeng); return new RangeConstraintManager(subeng);
} }
const llvm::APSInt* RangeConstraintManager::getSymVal(const GRState *St, const llvm::APSInt* RangeConstraintManager::getSymVal(const ProgramState *St,
SymbolRef sym) const { SymbolRef sym) const {
const ConstraintRangeTy::data_type *T = St->get<ConstraintRange>(sym); const ConstraintRangeTy::data_type *T = St->get<ConstraintRange>(sym);
return T ? T->getConcreteValue() : NULL; 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 /// Scan all symbols referenced by the constraints. If the symbol is not alive
/// as marked in LSymbols, mark it as dead in DSymbols. /// as marked in LSymbols, mark it as dead in DSymbols.
const GRState* const ProgramState*
RangeConstraintManager::removeDeadBindings(const GRState *state, RangeConstraintManager::removeDeadBindings(const ProgramState *state,
SymbolReaper& SymReaper) { SymbolReaper& SymReaper) {
ConstraintRangeTy CR = state->get<ConstraintRange>(); ConstraintRangeTy CR = state->get<ConstraintRange>();
@ -283,7 +283,7 @@ RangeConstraintManager::removeDeadBindings(const GRState *state,
} }
RangeSet RangeSet
RangeConstraintManager::GetRange(const GRState *state, SymbolRef sym) { RangeConstraintManager::GetRange(const ProgramState *state, SymbolRef sym) {
if (ConstraintRangeTy::data_type* V = state->get<ConstraintRange>(sym)) if (ConstraintRangeTy::data_type* V = state->get<ConstraintRange>(sym))
return *V; 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, // As an example, the range [UINT_MAX-1, 3) contains five values: UINT_MAX-1,
// UINT_MAX, 0, 1, and 2. // UINT_MAX, 0, 1, and 2.
const GRState* const ProgramState*
RangeConstraintManager::assumeSymNE(const GRState *state, SymbolRef sym, RangeConstraintManager::assumeSymNE(const ProgramState *state, SymbolRef sym,
const llvm::APSInt& Int, const llvm::APSInt& Int,
const llvm::APSInt& Adjustment) { const llvm::APSInt& Adjustment) {
BasicValueFactory &BV = state->getBasicVals(); BasicValueFactory &BV = state->getBasicVals();
@ -323,8 +323,8 @@ RangeConstraintManager::assumeSymNE(const GRState *state, SymbolRef sym,
return New.isEmpty() ? NULL : state->set<ConstraintRange>(sym, New); return New.isEmpty() ? NULL : state->set<ConstraintRange>(sym, New);
} }
const GRState* const ProgramState*
RangeConstraintManager::assumeSymEQ(const GRState *state, SymbolRef sym, RangeConstraintManager::assumeSymEQ(const ProgramState *state, SymbolRef sym,
const llvm::APSInt& Int, const llvm::APSInt& Int,
const llvm::APSInt& Adjustment) { const llvm::APSInt& Adjustment) {
// [Int-Adjustment, Int-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); return New.isEmpty() ? NULL : state->set<ConstraintRange>(sym, New);
} }
const GRState* const ProgramState*
RangeConstraintManager::assumeSymLT(const GRState *state, SymbolRef sym, RangeConstraintManager::assumeSymLT(const ProgramState *state, SymbolRef sym,
const llvm::APSInt& Int, const llvm::APSInt& Int,
const llvm::APSInt& Adjustment) { const llvm::APSInt& Adjustment) {
BasicValueFactory &BV = state->getBasicVals(); BasicValueFactory &BV = state->getBasicVals();
@ -355,8 +355,8 @@ RangeConstraintManager::assumeSymLT(const GRState *state, SymbolRef sym,
return New.isEmpty() ? NULL : state->set<ConstraintRange>(sym, New); return New.isEmpty() ? NULL : state->set<ConstraintRange>(sym, New);
} }
const GRState* const ProgramState*
RangeConstraintManager::assumeSymGT(const GRState *state, SymbolRef sym, RangeConstraintManager::assumeSymGT(const ProgramState *state, SymbolRef sym,
const llvm::APSInt& Int, const llvm::APSInt& Int,
const llvm::APSInt& Adjustment) { const llvm::APSInt& Adjustment) {
BasicValueFactory &BV = state->getBasicVals(); BasicValueFactory &BV = state->getBasicVals();
@ -376,8 +376,8 @@ RangeConstraintManager::assumeSymGT(const GRState *state, SymbolRef sym,
return New.isEmpty() ? NULL : state->set<ConstraintRange>(sym, New); return New.isEmpty() ? NULL : state->set<ConstraintRange>(sym, New);
} }
const GRState* const ProgramState*
RangeConstraintManager::assumeSymGE(const GRState *state, SymbolRef sym, RangeConstraintManager::assumeSymGE(const ProgramState *state, SymbolRef sym,
const llvm::APSInt& Int, const llvm::APSInt& Int,
const llvm::APSInt& Adjustment) { const llvm::APSInt& Adjustment) {
BasicValueFactory &BV = state->getBasicVals(); BasicValueFactory &BV = state->getBasicVals();
@ -398,8 +398,8 @@ RangeConstraintManager::assumeSymGE(const GRState *state, SymbolRef sym,
return New.isEmpty() ? NULL : state->set<ConstraintRange>(sym, New); return New.isEmpty() ? NULL : state->set<ConstraintRange>(sym, New);
} }
const GRState* const ProgramState*
RangeConstraintManager::assumeSymLE(const GRState *state, SymbolRef sym, RangeConstraintManager::assumeSymLE(const ProgramState *state, SymbolRef sym,
const llvm::APSInt& Int, const llvm::APSInt& Int,
const llvm::APSInt& Adjustment) { const llvm::APSInt& Adjustment) {
BasicValueFactory &BV = state->getBasicVals(); BasicValueFactory &BV = state->getBasicVals();
@ -424,7 +424,7 @@ RangeConstraintManager::assumeSymLE(const GRState *state, SymbolRef sym,
// Pretty-printing. // 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) { const char* nl, const char *sep) {
ConstraintRangeTy Ranges = St->get<ConstraintRange>(); ConstraintRangeTy Ranges = St->get<ConstraintRange>();

View File

@ -20,8 +20,8 @@
#include "clang/Analysis/Analyses/LiveVariables.h" #include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/AnalysisContext.h" #include "clang/Analysis/AnalysisContext.h"
#include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetInfo.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "llvm/ADT/ImmutableList.h" #include "llvm/ADT/ImmutableList.h"
#include "llvm/ADT/ImmutableMap.h" #include "llvm/ADT/ImmutableMap.h"
@ -196,7 +196,7 @@ class RegionStoreManager : public StoreManager {
RegionBindings::Factory RBFactory; RegionBindings::Factory RBFactory;
public: public:
RegionStoreManager(GRStateManager& mgr, const RegionStoreFeatures &f) RegionStoreManager(ProgramStateManager& mgr, const RegionStoreFeatures &f)
: StoreManager(mgr), : StoreManager(mgr),
Features(f), Features(f),
RBFactory(mgr.getAllocator()) {} RBFactory(mgr.getAllocator()) {}
@ -376,7 +376,7 @@ public: // Part of public interface to class.
StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx, StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx,
SymbolReaper& SymReaper); SymbolReaper& SymReaper);
StoreRef enterStackFrame(const GRState *state, StoreRef enterStackFrame(const ProgramState *state,
const StackFrameContext *frame); 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. // 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); const MemRegion* R, QualType EleTy);
//===------------------------------------------------------------------===// //===------------------------------------------------------------------===//
@ -419,12 +419,12 @@ public: // Part of public interface to class.
// RegionStore creation. // RegionStore creation.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
StoreManager *ento::CreateRegionStoreManager(GRStateManager& StMgr) { StoreManager *ento::CreateRegionStoreManager(ProgramStateManager& StMgr) {
RegionStoreFeatures F = maximal_features_tag(); RegionStoreFeatures F = maximal_features_tag();
return new RegionStoreManager(StMgr, F); return new RegionStoreManager(StMgr, F);
} }
StoreManager *ento::CreateFieldsOnlyRegionStoreManager(GRStateManager &StMgr) { StoreManager *ento::CreateFieldsOnlyRegionStoreManager(ProgramStateManager &StMgr) {
RegionStoreFeatures F = minimal_features_tag(); RegionStoreFeatures F = minimal_features_tag();
F.enableFields(true); F.enableFields(true);
return new RegionStoreManager(StMgr, F); return new RegionStoreManager(StMgr, F);
@ -480,7 +480,7 @@ protected:
const bool includeGlobals; const bool includeGlobals;
public: public:
ClusterAnalysis(RegionStoreManager &rm, GRStateManager &StateMgr, ClusterAnalysis(RegionStoreManager &rm, ProgramStateManager &StateMgr,
RegionBindings b, const bool includeGlobals) RegionBindings b, const bool includeGlobals)
: RM(rm), Ctx(StateMgr.getContext()), : RM(rm), Ctx(StateMgr.getContext()),
svalBuilder(StateMgr.getSValBuilder()), svalBuilder(StateMgr.getSValBuilder()),
@ -593,7 +593,7 @@ class invalidateRegionsWorker : public ClusterAnalysis<invalidateRegionsWorker>
StoreManager::InvalidatedRegions *Regions; StoreManager::InvalidatedRegions *Regions;
public: public:
invalidateRegionsWorker(RegionStoreManager &rm, invalidateRegionsWorker(RegionStoreManager &rm,
GRStateManager &stateMgr, ProgramStateManager &stateMgr,
RegionBindings b, RegionBindings b,
const Expr *ex, unsigned count, const Expr *ex, unsigned count,
StoreManager::InvalidatedSymbols &is, StoreManager::InvalidatedSymbols &is,
@ -766,7 +766,7 @@ StoreRef RegionStoreManager::invalidateRegions(Store store,
// Extents for regions. // Extents for regions.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state, DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const ProgramState *state,
const MemRegion *R, const MemRegion *R,
QualType EleTy) { QualType EleTy) {
SVal Size = cast<SubRegion>(R)->getExtent(svalBuilder); SVal Size = cast<SubRegion>(R)->getExtent(svalBuilder);
@ -1644,7 +1644,7 @@ class removeDeadBindingsWorker :
const StackFrameContext *CurrentLCtx; const StackFrameContext *CurrentLCtx;
public: public:
removeDeadBindingsWorker(RegionStoreManager &rm, GRStateManager &stateMgr, removeDeadBindingsWorker(RegionStoreManager &rm, ProgramStateManager &stateMgr,
RegionBindings b, SymbolReaper &symReaper, RegionBindings b, SymbolReaper &symReaper,
const StackFrameContext *LCtx) const StackFrameContext *LCtx)
: ClusterAnalysis<removeDeadBindingsWorker>(rm, stateMgr, b, : 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) { const StackFrameContext *frame) {
FunctionDecl const *FD = cast<FunctionDecl>(frame->getDecl()); FunctionDecl const *FD = cast<FunctionDecl>(frame->getDecl());
FunctionDecl::param_const_iterator PI = FD->param_begin(), FunctionDecl::param_const_iterator PI = FD->param_begin(),

View File

@ -15,7 +15,7 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.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" #include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
using namespace clang; 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) { SVal lhs, SVal rhs, QualType type) {
if (lhs.isUndef() || rhs.isUndef()) 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); 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 lhs,
DefinedOrUnknownSVal rhs) { DefinedOrUnknownSVal rhs) {
return cast<DefinedOrUnknownSVal>(evalBinOp(state, BO_EQ, lhs, rhs, return cast<DefinedOrUnknownSVal>(evalBinOp(state, BO_EQ, lhs, rhs,

View File

@ -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/AST/ExprObjC.h"
#include "clang/Basic/IdentifierTable.h" #include "clang/Basic/IdentifierTable.h"
using namespace clang; using namespace clang;

View File

@ -14,7 +14,7 @@
#include "SimpleConstraintManager.h" #include "SimpleConstraintManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
namespace clang { namespace clang {
@ -56,7 +56,7 @@ bool SimpleConstraintManager::canReasonAbout(SVal X) const {
return true; return true;
} }
const GRState *SimpleConstraintManager::assume(const GRState *state, const ProgramState *SimpleConstraintManager::assume(const ProgramState *state,
DefinedSVal Cond, DefinedSVal Cond,
bool Assumption) { bool Assumption) {
if (isa<NonLoc>(Cond)) if (isa<NonLoc>(Cond))
@ -65,13 +65,13 @@ const GRState *SimpleConstraintManager::assume(const GRState *state,
return assume(state, cast<Loc>(Cond), Assumption); 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) { bool assumption) {
state = assumeAux(state, cond, assumption); state = assumeAux(state, cond, assumption);
return SU.processAssume(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) { Loc Cond, bool Assumption) {
BasicValueFactory &BasicVals = state->getBasicVals(); BasicValueFactory &BasicVals = state->getBasicVals();
@ -113,7 +113,7 @@ const GRState *SimpleConstraintManager::assumeAux(const GRState *state,
} // end switch } // end switch
} }
const GRState *SimpleConstraintManager::assume(const GRState *state, const ProgramState *SimpleConstraintManager::assume(const ProgramState *state,
NonLoc cond, NonLoc cond,
bool assumption) { bool assumption) {
state = assumeAux(state, cond, 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, NonLoc Cond,
bool Assumption) { bool Assumption) {
@ -202,7 +202,7 @@ const GRState *SimpleConstraintManager::assumeAux(const GRState *state,
} // end switch } // end switch
} }
const GRState *SimpleConstraintManager::assumeSymRel(const GRState *state, const ProgramState *SimpleConstraintManager::assumeSymRel(const ProgramState *state,
const SymExpr *LHS, const SymExpr *LHS,
BinaryOperator::Opcode op, BinaryOperator::Opcode op,
const llvm::APSInt& Int) { 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 // 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 // comparisons should be performed using the Int's type, then mapped back to
// the symbol's range of values. // the symbol's range of values.
GRStateManager &StateMgr = state->getStateManager(); ProgramStateManager &StateMgr = state->getStateManager();
ASTContext &Ctx = StateMgr.getContext(); ASTContext &Ctx = StateMgr.getContext();
QualType T = Sym->getType(Ctx); QualType T = Sym->getType(Ctx);

View File

@ -15,7 +15,7 @@
#define LLVM_CLANG_GR_SIMPLE_CONSTRAINT_MANAGER_H #define LLVM_CLANG_GR_SIMPLE_CONSTRAINT_MANAGER_H
#include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
namespace clang { namespace clang {
@ -33,14 +33,14 @@ public:
bool canReasonAbout(SVal X) const; bool canReasonAbout(SVal X) const;
const GRState *assume(const GRState *state, DefinedSVal Cond, const ProgramState *assume(const ProgramState *state, DefinedSVal Cond,
bool Assumption); 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, const SymExpr *LHS,
BinaryOperator::Opcode op, BinaryOperator::Opcode op,
const llvm::APSInt& Int); const llvm::APSInt& Int);
@ -53,27 +53,27 @@ protected:
// Each of these is of the form "$sym+Adj <> V", where "<>" is the comparison // Each of these is of the form "$sym+Adj <> V", where "<>" is the comparison
// operation for the method being invoked. // 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& V,
const llvm::APSInt& Adjustment) = 0; 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& V,
const llvm::APSInt& Adjustment) = 0; 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& V,
const llvm::APSInt& Adjustment) = 0; 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& V,
const llvm::APSInt& Adjustment) = 0; 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& V,
const llvm::APSInt& Adjustment) = 0; 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& V,
const llvm::APSInt& Adjustment) = 0; const llvm::APSInt& Adjustment) = 0;
@ -81,9 +81,9 @@ protected:
// Internal implementation. // 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 } // end GR namespace

View File

@ -12,7 +12,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" #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 clang;
using namespace ento; using namespace ento;
@ -25,22 +25,22 @@ protected:
public: public:
SimpleSValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context, SimpleSValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context,
GRStateManager &stateMgr) ProgramStateManager &stateMgr)
: SValBuilder(alloc, context, stateMgr) {} : SValBuilder(alloc, context, stateMgr) {}
virtual ~SimpleSValBuilder() {} virtual ~SimpleSValBuilder() {}
virtual SVal evalMinus(NonLoc val); virtual SVal evalMinus(NonLoc val);
virtual SVal evalComplement(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); 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); 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); Loc lhs, NonLoc rhs, QualType resultTy);
/// getKnownValue - evaluates a given SVal. If the SVal has only one possible /// getKnownValue - evaluates a given SVal. If the SVal has only one possible
/// (integer) value, that value is returned. Otherwise, returns NULL. /// (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, SVal MakeSymIntVal(const SymExpr *LHS, BinaryOperator::Opcode op,
const llvm::APSInt &RHS, QualType resultTy); const llvm::APSInt &RHS, QualType resultTy);
@ -49,7 +49,7 @@ public:
SValBuilder *ento::createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc, SValBuilder *ento::createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc,
ASTContext &context, ASTContext &context,
GRStateManager &stateMgr) { ProgramStateManager &stateMgr) {
return new SimpleSValBuilder(alloc, context, stateMgr); return new SimpleSValBuilder(alloc, context, stateMgr);
} }
@ -270,7 +270,7 @@ SVal SimpleSValBuilder::MakeSymIntVal(const SymExpr *LHS,
return makeNonLoc(LHS, op, RHS, resultTy); return makeNonLoc(LHS, op, RHS, resultTy);
} }
SVal SimpleSValBuilder::evalBinOpNN(const GRState *state, SVal SimpleSValBuilder::evalBinOpNN(const ProgramState *state,
BinaryOperator::Opcode op, BinaryOperator::Opcode op,
NonLoc lhs, NonLoc rhs, NonLoc lhs, NonLoc rhs,
QualType resultTy) { QualType resultTy) {
@ -539,7 +539,7 @@ SVal SimpleSValBuilder::evalBinOpNN(const GRState *state,
} }
// FIXME: all this logic will change if/when we have MemRegion::getLocation(). // 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, BinaryOperator::Opcode op,
Loc lhs, Loc rhs, Loc lhs, Loc rhs,
QualType resultTy) { 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, BinaryOperator::Opcode op,
Loc lhs, NonLoc rhs, QualType resultTy) { Loc lhs, NonLoc rhs, QualType resultTy) {
@ -930,7 +930,7 @@ SVal SimpleSValBuilder::evalBinOpLN(const GRState *state,
return UnknownVal(); return UnknownVal();
} }
const llvm::APSInt *SimpleSValBuilder::getKnownValue(const GRState *state, const llvm::APSInt *SimpleSValBuilder::getKnownValue(const ProgramState *state,
SVal V) { SVal V) {
if (V.isUnknownOrUndef()) if (V.isUnknownOrUndef())
return NULL; return NULL;

View File

@ -12,17 +12,17 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" #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" #include "clang/AST/CharUnits.h"
using namespace clang; using namespace clang;
using namespace ento; using namespace ento;
StoreManager::StoreManager(GRStateManager &stateMgr) StoreManager::StoreManager(ProgramStateManager &stateMgr)
: svalBuilder(stateMgr.getSValBuilder()), StateMgr(stateMgr), : svalBuilder(stateMgr.getSValBuilder()), StateMgr(stateMgr),
MRMgr(svalBuilder.getRegionManager()), Ctx(stateMgr.getContext()) {} MRMgr(svalBuilder.getRegionManager()), Ctx(stateMgr.getContext()) {}
StoreRef StoreManager::enterStackFrame(const GRState *state, StoreRef StoreManager::enterStackFrame(const ProgramState *state,
const StackFrameContext *frame) { const StackFrameContext *frame) {
return StoreRef(state->getStore(), *this); return StoreRef(state->getStore(), *this);
} }

View File

@ -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 In a nutshell, the analyzer is basically a source code simulator that
traces out possible paths of execution. The state of the program traces out possible paths of execution. The state of the program
(values of variables and expressions) is encapsulated by the state (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 (ProgramPoint), and the combination of state and program point is a
node in an exploded graph (ExplodedGraph). The term "exploded" comes node in an exploded graph (ExplodedGraph). The term "exploded" comes
from exploding the control-flow edges in the control-flow graph (CFG). 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 branch are assumed to be true and on the false branch the conditions
of the branch are assumed to be false. Such "assumptions" create of the branch are assumed to be false. Such "assumptions" create
constraints on the values of the program, and those constraints are 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 ConstraintManager). If assuming the conditions of a branch would
cause the constraints to be unsatisfiable, the branch is considered cause the constraints to be unsatisfiable, the branch is considered
infeasible and that path is not taken. This is how we get 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 existing node. Thus the ExplodedGraph is not a DAG; it can contain
cycles as paths loop back onto each other and cache out. cycles as paths loop back onto each other and cache out.
GRState and ExplodedNodes are basically immutable once created. Once ProgramState and ExplodedNodes are basically immutable once created. Once
one creates a GRState, you need to create a new one to get a new one creates a ProgramState, you need to create a new one to get a new
GRState. This immutability is key since the ExplodedGraph represents ProgramState. This immutability is key since the ExplodedGraph represents
the behavior of the analyzed program from the entry point. To the behavior of the analyzed program from the entry point. To
represent these efficiently, we use functional data structures (e.g., represent these efficiently, we use functional data structures (e.g.,
ImmutableMaps) which share data between instances. 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 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 checker is asked to check for any preconditions that might not be
satisfied. The checker can do nothing, or it can generate a new 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, 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 providing it an ExplodedNode which is the last node in the path that
triggered the problem. triggered the problem.