For GRExprEngine::EvalBind() (and called visitors), unifiy StoreE and AssignE. Now StoreE (const Stmt*) represents the expression where the store took place, which is the assignment expression if it takes place in an assignment. This removes some conceptual dissidence as well as removes an extra parameter from the Checker::PreVisitBind() visitor. It also improves ranges and source location information in analyzer diagnostics.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112789 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Checker/PathSensitive/Checker.h b/include/clang/Checker/PathSensitive/Checker.h
index af28fc3..136a29d 100644
--- a/include/clang/Checker/PathSensitive/Checker.h
+++ b/include/clang/Checker/PathSensitive/Checker.h
@@ -226,7 +226,6 @@
// FIXME: Remove the 'tag' option.
void GR_VisitBind(ExplodedNodeSet &Dst,
GRStmtNodeBuilder &Builder, GRExprEngine &Eng,
- const Stmt *AssignE,
const Stmt *StoreE, ExplodedNode *Pred, void *tag,
SVal location, SVal val,
bool isPrevisit) {
@@ -234,7 +233,7 @@
isPrevisit ? ProgramPoint::PreStmtKind :
ProgramPoint::PostStmtKind, 0, StoreE);
assert(isPrevisit && "Only previsit supported for now.");
- PreVisitBind(C, AssignE, StoreE, location, val);
+ PreVisitBind(C, StoreE, location, val);
}
// FIXME: Remove the 'tag' option.
@@ -264,8 +263,8 @@
virtual void _PreVisit(CheckerContext &C, const Stmt *S) {}
virtual void _PostVisit(CheckerContext &C, const Stmt *S) {}
virtual void VisitLocation(CheckerContext &C, const Stmt *S, SVal location) {}
- virtual void PreVisitBind(CheckerContext &C, const Stmt *AssignE,
- const Stmt *StoreE, SVal location, SVal val) {}
+ virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE,
+ SVal location, SVal val) {}
virtual void EvalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper) {}
virtual void EvalEndPath(GREndPathNodeBuilder &B, void *tag,
GRExprEngine &Eng) {}
diff --git a/include/clang/Checker/PathSensitive/GRExprEngine.h b/include/clang/Checker/PathSensitive/GRExprEngine.h
index 55dab2a..5ba0b36 100644
--- a/include/clang/Checker/PathSensitive/GRExprEngine.h
+++ b/include/clang/Checker/PathSensitive/GRExprEngine.h
@@ -295,10 +295,9 @@
const GRState *state,
ExplodedNode *Pred);
- void CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE,
- ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
- SVal location, SVal val, bool isPrevisit);
-
+ void CheckerVisitBind(const Stmt *StoreE, ExplodedNodeSet &Dst,
+ ExplodedNodeSet &Src, SVal location, SVal val,
+ bool isPrevisit);
/// Visit - Transfer function logic for all statements. Dispatches to
/// other functions that handle specific kinds of statements.
@@ -494,8 +493,7 @@
/// EvalBind - Handle the semantics of binding a value to a specific location.
/// This method is used by EvalStore, VisitDeclStmt, and others.
- void EvalBind(ExplodedNodeSet& Dst, const Stmt *AssignE,
- const Stmt* StoreE, ExplodedNode* Pred,
+ void EvalBind(ExplodedNodeSet& Dst, const Stmt* StoreE, ExplodedNode* Pred,
const GRState* St, SVal location, SVal Val,
bool atDeclInit = false);
diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp
index c9173aa..12974e9 100644
--- a/lib/Checker/GRExprEngine.cpp
+++ b/lib/Checker/GRExprEngine.cpp
@@ -306,10 +306,9 @@
// FIXME: This is largely copy-paste from CheckerVisit(). Need to
// unify.
-void GRExprEngine::CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE,
- ExplodedNodeSet &Dst,
- ExplodedNodeSet &Src,
- SVal location, SVal val, bool isPrevisit) {
+void GRExprEngine::CheckerVisitBind(const Stmt *StoreE, ExplodedNodeSet &Dst,
+ ExplodedNodeSet &Src, SVal location,
+ SVal val, bool isPrevisit) {
if (Checkers.empty()) {
Dst.insert(Src);
@@ -334,7 +333,7 @@
for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
NI != NE; ++NI)
- checker->GR_VisitBind(*CurrSet, *Builder, *this, AssignE, StoreE,
+ checker->GR_VisitBind(*CurrSet, *Builder, *this, StoreE,
*NI, tag, location, val, isPrevisit);
// Update which NodeSet is the current one.
@@ -1816,16 +1815,15 @@
/// EvalBind - Handle the semantics of binding a value to a specific location.
/// This method is used by EvalStore and (soon) VisitDeclStmt, and others.
-void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, const Stmt *AssignE,
- const Stmt* StoreE, ExplodedNode* Pred,
- const GRState* state, SVal location, SVal Val,
- bool atDeclInit) {
+void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, const Stmt* StoreE,
+ ExplodedNode* Pred, const GRState* state,
+ SVal location, SVal Val, bool atDeclInit) {
// Do a previsit of the bind.
ExplodedNodeSet CheckedSet, Src;
Src.Add(Pred);
- CheckerVisitBind(AssignE, StoreE, CheckedSet, Src, location, Val, true);
+ CheckerVisitBind(StoreE, CheckedSet, Src, location, Val, true);
for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
I!=E; ++I) {
@@ -1858,6 +1856,10 @@
// The next thing to do is check if the GRTransferFuncs object wants to
// update the state based on the new binding. If the GRTransferFunc object
// doesn't do anything, just auto-propagate the current state.
+
+ // NOTE: We use 'AssignE' for the location of the PostStore if 'AssignE'
+ // is non-NULL. Checkers typically care about
+
GRStmtNodeBuilderRef BuilderRef(Dst, *Builder, *this, *I, newState, StoreE,
newState != state);
@@ -1872,7 +1874,7 @@
/// @param location The location to store the value
/// @param Val The value to be stored
void GRExprEngine::EvalStore(ExplodedNodeSet& Dst, const Expr *AssignE,
- const Expr* StoreE,
+ const Expr* LocationE,
ExplodedNode* Pred,
const GRState* state, SVal location, SVal Val,
const void *tag) {
@@ -1881,7 +1883,7 @@
// Evaluate the location (checks for bad dereferences).
ExplodedNodeSet Tmp;
- EvalLocation(Tmp, StoreE, Pred, state, location, tag, false);
+ EvalLocation(Tmp, LocationE, Pred, state, location, tag, false);
if (Tmp.empty())
return;
@@ -1892,9 +1894,12 @@
ProgramPoint::PostStoreKind);
SaveAndRestore<const void*> OldTag(Builder->Tag, tag);
- // Proceed with the store.
+ // Proceed with the store. We use AssignE as the anchor for the PostStore
+ // ProgramPoint if it is non-NULL, and LocationE otherwise.
+ const Expr *StoreE = AssignE ? AssignE : LocationE;
+
for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI)
- EvalBind(Dst, AssignE, StoreE, *NI, GetState(*NI), location, Val);
+ EvalBind(Dst, StoreE, *NI, GetState(*NI), location, Val);
}
void GRExprEngine::EvalLoad(ExplodedNodeSet& Dst, const Expr *Ex,
@@ -2701,7 +2706,7 @@
Builder->getCurrentBlockCount());
}
- EvalBind(Dst, DS, DS, *I, state,
+ EvalBind(Dst, DS, *I, state,
loc::MemRegionVal(state->getRegion(VD, LC)), InitVal, true);
}
else {
@@ -2733,7 +2738,7 @@
Builder->getCurrentBlockCount());
}
- EvalBind(Dst, S, S, N, state,
+ EvalBind(Dst, S, N, state,
loc::MemRegionVal(state->getRegion(VD, LC)), InitVal, true);
}
}
diff --git a/lib/Checker/MallocChecker.cpp b/lib/Checker/MallocChecker.cpp
index 3224f7b..ac98c89 100644
--- a/lib/Checker/MallocChecker.cpp
+++ b/lib/Checker/MallocChecker.cpp
@@ -82,9 +82,8 @@
const GRState *EvalAssume(const GRState *state, SVal Cond, bool Assumption,
bool *respondsToCallback);
void VisitLocation(CheckerContext &C, const Stmt *S, SVal l);
- virtual void PreVisitBind(CheckerContext &C, const Stmt *AssignE,
- const Stmt *StoreE, SVal location,
- SVal val);
+ virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE,
+ SVal location, SVal val);
private:
void MallocMem(CheckerContext &C, const CallExpr *CE);
@@ -676,7 +675,6 @@
}
void MallocChecker::PreVisitBind(CheckerContext &C,
- const Stmt *AssignE,
const Stmt *StoreE,
SVal location,
SVal val) {
diff --git a/lib/Checker/UndefinedAssignmentChecker.cpp b/lib/Checker/UndefinedAssignmentChecker.cpp
index 6cef60e..ccc9748 100644
--- a/lib/Checker/UndefinedAssignmentChecker.cpp
+++ b/lib/Checker/UndefinedAssignmentChecker.cpp
@@ -25,9 +25,8 @@
public:
UndefinedAssignmentChecker() : BT(0) {}
static void *getTag();
- virtual void PreVisitBind(CheckerContext &C, const Stmt *AssignE,
- const Stmt *StoreE, SVal location,
- SVal val);
+ virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE,
+ SVal location, SVal val);
};
}
@@ -41,7 +40,6 @@
}
void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C,
- const Stmt *AssignE,
const Stmt *StoreE,
SVal location,
SVal val) {
@@ -61,8 +59,8 @@
// Generate a report for this bug.
const Expr *ex = 0;
- while (AssignE) {
- if (const BinaryOperator *B = dyn_cast<BinaryOperator>(AssignE)) {
+ while (StoreE) {
+ if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) {
if (B->isCompoundAssignmentOp()) {
const GRState *state = C.getState();
if (state->getSVal(B->getLHS()).isUndef()) {
@@ -77,7 +75,7 @@
break;
}
- if (const DeclStmt *DS = dyn_cast<DeclStmt>(AssignE)) {
+ if (const DeclStmt *DS = dyn_cast<DeclStmt>(StoreE)) {
const VarDecl* VD = dyn_cast<VarDecl>(DS->getSingleDecl());
ex = VD->getInit();
}
diff --git a/test/Analysis/plist-output.m b/test/Analysis/plist-output.m
index aa866de..95faa06 100644
--- a/test/Analysis/plist-output.m
+++ b/test/Analysis/plist-output.m
@@ -205,7 +205,7 @@
// CHECK: </dict>
// CHECK: <dict>
// CHECK: <key>line</key><integer>10</integer>
-// CHECK: <key>col</key><integer>3</integer>
+// CHECK: <key>col</key><integer>7</integer>
// CHECK: <key>file</key><integer>0</integer>
// CHECK: </dict>
// CHECK: </array>