summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Analysis/PathSensitive/Checker.h79
-rw-r--r--clang/lib/Analysis/ArrayBoundChecker.cpp4
-rw-r--r--clang/lib/Analysis/AttrNonNullChecker.cpp6
-rw-r--r--clang/lib/Analysis/BasicObjCFoundationChecks.cpp5
-rw-r--r--clang/lib/Analysis/CastToStructChecker.cpp2
-rw-r--r--clang/lib/Analysis/Checker.cpp17
-rw-r--r--clang/lib/Analysis/DereferenceChecker.cpp11
-rw-r--r--clang/lib/Analysis/DivZeroChecker.cpp5
-rw-r--r--clang/lib/Analysis/FixedAddressChecker.cpp2
-rw-r--r--clang/lib/Analysis/GRExprEngine.cpp8
-rw-r--r--clang/lib/Analysis/MallocChecker.cpp14
-rw-r--r--clang/lib/Analysis/PointerArithChecker.cpp2
-rw-r--r--clang/lib/Analysis/PointerSubChecker.cpp2
-rw-r--r--clang/lib/Analysis/ReturnPointerRangeChecker.cpp3
-rw-r--r--clang/lib/Analysis/ReturnStackAddressChecker.cpp2
-rw-r--r--clang/lib/Analysis/ReturnUndefChecker.cpp2
-rw-r--r--clang/lib/Analysis/UndefinedArgChecker.cpp8
-rw-r--r--clang/lib/Analysis/UndefinedArraySubscriptChecker.cpp2
-rw-r--r--clang/lib/Analysis/UndefinedAssignmentChecker.cpp2
-rw-r--r--clang/lib/Analysis/VLASizeChecker.cpp7
20 files changed, 113 insertions, 70 deletions
diff --git a/clang/include/clang/Analysis/PathSensitive/Checker.h b/clang/include/clang/Analysis/PathSensitive/Checker.h
index 1fb92a61dea..e94096ba4f2 100644
--- a/clang/include/clang/Analysis/PathSensitive/Checker.h
+++ b/clang/include/clang/Analysis/PathSensitive/Checker.h
@@ -40,24 +40,22 @@ class CheckerContext {
SaveAndRestore<ProgramPoint::Kind> OldPointKind;
SaveOr OldHasGen;
const GRState *state;
-
+ const Stmt *statement;
+ const unsigned size;
public:
CheckerContext(ExplodedNodeSet &dst, GRStmtNodeBuilder &builder,
GRExprEngine &eng, ExplodedNode *pred,
const void *tag, ProgramPoint::Kind K,
- const GRState *st = 0)
+ const Stmt *stmt = 0, const GRState *st = 0)
: Dst(dst), B(builder), Eng(eng), Pred(pred),
OldSink(B.BuildSinks),
OldTag(B.Tag, tag),
OldPointKind(B.PointKind, K),
OldHasGen(B.HasGeneratedNode),
- state(st) {}
-
- ~CheckerContext() {
- if (!B.BuildSinks && !B.HasGeneratedNode)
- Dst.Add(Pred);
- }
+ state(st), statement(stmt), size(Dst.size()) {}
+ ~CheckerContext();
+
ConstraintManager &getConstraintManager() {
return Eng.getConstraintManager();
}
@@ -83,27 +81,66 @@ public:
return getBugReporter().getSourceManager();
}
- ExplodedNode *GenerateNode(const Stmt *S, bool markAsSink = false) {
- return GenerateNode(S, getState(), markAsSink);
+ ExplodedNode *GenerateNode(bool autoTransition = true) {
+ assert(statement && "Only transitions with statements currently supported");
+ ExplodedNode *N = GenerateNodeImpl(statement, getState(), false);
+ if (N && autoTransition)
+ Dst.Add(N);
+ return N;
+ }
+
+ ExplodedNode *GenerateNode(const Stmt *stmt, const GRState *state,
+ bool autoTransition = true) {
+ assert(state);
+ ExplodedNode *N = GenerateNodeImpl(stmt, state, false);
+ if (N && autoTransition)
+ addTransition(N);
+ return N;
}
- ExplodedNode *GenerateNode(const Stmt* S, const GRState *state,
- bool markAsSink = false) {
- ExplodedNode *node = B.generateNode(S, state, Pred);
-
- if (markAsSink && node)
- node->markAsSink();
+ ExplodedNode *GenerateNode(const GRState *state, bool autoTransition = true) {
+ assert(statement && "Only transitions with statements currently supported");
+ ExplodedNode *N = GenerateNodeImpl(statement, state, false);
+ if (N && autoTransition)
+ addTransition(N);
+ return N;
+ }
- return node;
+ ExplodedNode *GenerateSink(const Stmt *stmt, const GRState *state = 0) {
+ return GenerateNodeImpl(stmt, state ? state : getState(), true);
+ }
+
+ ExplodedNode *GenerateSink(const GRState *state = 0) {
+ assert(statement && "Only transitions with statements currently supported");
+ return GenerateNodeImpl(statement, state ? state : getState(), true);
}
void addTransition(ExplodedNode *node) {
Dst.Add(node);
}
+
+ void addTransition(const GRState *state) {
+ assert(state);
+ if (state != getState() ||
+ (state && state != B.GetState(Pred)))
+ GenerateNode(state, true);
+ else
+ Dst.Add(Pred);
+ }
void EmitReport(BugReport *R) {
Eng.getBugReporter().EmitReport(R);
}
+
+private:
+ ExplodedNode *GenerateNodeImpl(const Stmt* stmt, const GRState *state,
+ bool markAsSink) {
+ ExplodedNode *node = B.generateNode(stmt, state, Pred);
+ if (markAsSink && node)
+ node->markAsSink();
+ return node;
+ }
+
};
class Checker {
@@ -118,7 +155,7 @@ private:
ExplodedNode *Pred, void *tag, bool isPrevisit) {
CheckerContext C(Dst, Builder, Eng, Pred, tag,
isPrevisit ? ProgramPoint::PreStmtKind :
- ProgramPoint::PostStmtKind);
+ ProgramPoint::PostStmtKind, S);
if (isPrevisit)
_PreVisit(C, S);
else
@@ -134,7 +171,7 @@ private:
bool isPrevisit) {
CheckerContext C(Dst, Builder, Eng, Pred, tag,
isPrevisit ? ProgramPoint::PreStmtKind :
- ProgramPoint::PostStmtKind);
+ ProgramPoint::PostStmtKind, StoreE);
assert(isPrevisit && "Only previsit supported for now.");
PreVisitBind(C, AssignE, StoreE, location, val);
}
@@ -149,7 +186,7 @@ private:
void *tag, bool isLoad) {
CheckerContext C(Dst, Builder, Eng, Pred, tag,
isLoad ? ProgramPoint::PreLoadKind :
- ProgramPoint::PreStoreKind, state);
+ ProgramPoint::PreStoreKind, S, state);
VisitLocation(C, S, location);
}
@@ -157,7 +194,7 @@ private:
GRExprEngine &Eng, const Stmt *S, ExplodedNode *Pred,
SymbolReaper &SymReaper, void *tag) {
CheckerContext C(Dst, Builder, Eng, Pred, tag,
- ProgramPoint::PostPurgeDeadSymbolsKind);
+ ProgramPoint::PostPurgeDeadSymbolsKind, S);
EvalDeadSymbols(C, S, SymReaper);
}
diff --git a/clang/lib/Analysis/ArrayBoundChecker.cpp b/clang/lib/Analysis/ArrayBoundChecker.cpp
index 549a22bec17..3d8b3b3d1b1 100644
--- a/clang/lib/Analysis/ArrayBoundChecker.cpp
+++ b/clang/lib/Analysis/ArrayBoundChecker.cpp
@@ -62,8 +62,7 @@ void ArrayBoundChecker::VisitLocation(CheckerContext &C, const Stmt *S, SVal l){
const GRState *StInBound = state->AssumeInBound(Idx, NumElements, true);
const GRState *StOutBound = state->AssumeInBound(Idx, NumElements, false);
if (StOutBound && !StInBound) {
- ExplodedNode *N = C.GenerateNode(S, StOutBound, true);
-
+ ExplodedNode *N = C.GenerateSink(StOutBound);
if (!N)
return;
@@ -80,7 +79,6 @@ void ArrayBoundChecker::VisitLocation(CheckerContext &C, const Stmt *S, SVal l){
new RangedBugReport(*BT, BT->getDescription(), N);
report->addRange(S->getSourceRange());
-
C.EmitReport(report);
}
}
diff --git a/clang/lib/Analysis/AttrNonNullChecker.cpp b/clang/lib/Analysis/AttrNonNullChecker.cpp
index 01e1a1fcf69..8668c75c754 100644
--- a/clang/lib/Analysis/AttrNonNullChecker.cpp
+++ b/clang/lib/Analysis/AttrNonNullChecker.cpp
@@ -39,7 +39,6 @@ void clang::RegisterAttrNonNullChecker(GRExprEngine &Eng) {
void AttrNonNullChecker::PreVisitCallExpr(CheckerContext &C,
const CallExpr *CE) {
const GRState *state = C.getState();
- const GRState *originalState = state;
// Check if the callee has a 'nonnull' attribute.
SVal X = state->getSVal(CE->getCallee());
@@ -74,7 +73,7 @@ void AttrNonNullChecker::PreVisitCallExpr(CheckerContext &C,
if (stateNull && !stateNotNull) {
// Generate an error node. Check for a null node in case
// we cache out.
- if (ExplodedNode *errorNode = C.GenerateNode(CE, stateNull, true)) {
+ if (ExplodedNode *errorNode = C.GenerateSink(stateNull)) {
// Lazily allocate the BugType object if it hasn't already been
// created. Ownership is transferred to the BugReporter object once
@@ -109,6 +108,5 @@ void AttrNonNullChecker::PreVisitCallExpr(CheckerContext &C,
// If we reach here all of the arguments passed the nonnull check.
// If 'state' has been updated generated a new node.
- if (state != originalState)
- C.addTransition(C.GenerateNode(CE, state));
+ C.addTransition(state);
}
diff --git a/clang/lib/Analysis/BasicObjCFoundationChecks.cpp b/clang/lib/Analysis/BasicObjCFoundationChecks.cpp
index 5a88a7af935..424a0b3b254 100644
--- a/clang/lib/Analysis/BasicObjCFoundationChecks.cpp
+++ b/clang/lib/Analysis/BasicObjCFoundationChecks.cpp
@@ -563,12 +563,11 @@ void ClassReleaseChecker::PreVisitObjCMessageExpr(CheckerContext &C,
BT = new APIMisuse("message incorrectly sent to class instead of class "
"instance");
- ExplodedNode *N = C.GenerateNode(ME, C.getState(), false);
+ ExplodedNode *N = C.GenerateNode();
+
if (!N)
return;
- C.addTransition(N);
-
llvm::SmallString<200> buf;
llvm::raw_svector_ostream os(buf);
diff --git a/clang/lib/Analysis/CastToStructChecker.cpp b/clang/lib/Analysis/CastToStructChecker.cpp
index ccd4a3333e2..7c6fc7ed3f4 100644
--- a/clang/lib/Analysis/CastToStructChecker.cpp
+++ b/clang/lib/Analysis/CastToStructChecker.cpp
@@ -59,7 +59,7 @@ void CastToStructChecker::PreVisitCastExpr(CheckerContext &C,
// Now the cast-to-type is struct pointer, the original type is not void*.
if (!OrigPointeeTy->isRecordType()) {
- if (ExplodedNode *N = C.GenerateNode(CE)) {
+ if (ExplodedNode *N = C.GenerateNode()) {
if (!BT)
BT = new BuiltinBug("Cast from non-struct type to struct type",
"Casting a non-structure type to a structure type "
diff --git a/clang/lib/Analysis/Checker.cpp b/clang/lib/Analysis/Checker.cpp
index 985b1e0a1d7..0d907e50168 100644
--- a/clang/lib/Analysis/Checker.cpp
+++ b/clang/lib/Analysis/Checker.cpp
@@ -16,3 +16,20 @@
using namespace clang;
Checker::~Checker() {}
+
+CheckerContext::~CheckerContext() {
+ // Do we need to autotransition? 'Dst' can get populated in a variety of
+ // ways, including 'addTransition()' adding the predecessor node to Dst
+ // without actually generated a new node. We also shouldn't autotransition
+ // if we are building sinks or we generated a node and decided to not
+ // add it as a transition.
+ if (Dst.size() == size && !B.BuildSinks && !B.HasGeneratedNode) {
+ if (state && state != B.GetState(Pred)) {
+ static int autoTransitionTag = 0;
+ B.Tag = &autoTransitionTag;
+ addTransition(state);
+ }
+ else
+ Dst.Add(Pred);
+ }
+}
diff --git a/clang/lib/Analysis/DereferenceChecker.cpp b/clang/lib/Analysis/DereferenceChecker.cpp
index a8f5af34a72..4c4091cbc28 100644
--- a/clang/lib/Analysis/DereferenceChecker.cpp
+++ b/clang/lib/Analysis/DereferenceChecker.cpp
@@ -56,8 +56,7 @@ void DereferenceChecker::VisitLocation(CheckerContext &C, const Stmt *S,
SVal l) {
// Check for dereference of an undefined value.
if (l.isUndef()) {
- ExplodedNode *N = C.GenerateNode(S, true);
- if (N) {
+ if (ExplodedNode *N = C.GenerateSink()) {
if (!BT_undef)
BT_undef = new BuiltinBug("Dereference of undefined pointer value");
@@ -84,7 +83,7 @@ void DereferenceChecker::VisitLocation(CheckerContext &C, const Stmt *S,
if (nullState) {
if (!notNullState) {
// Generate an error node.
- ExplodedNode *N = C.GenerateNode(S, nullState, true);
+ ExplodedNode *N = C.GenerateSink(nullState);
if (!N)
return;
@@ -106,13 +105,11 @@ void DereferenceChecker::VisitLocation(CheckerContext &C, const Stmt *S,
// Otherwise, we have the case where the location could either be
// null or not-null. Record the error node as an "implicit" null
// dereference.
- if (ExplodedNode *N = C.GenerateNode(S, nullState, true))
+ if (ExplodedNode *N = C.GenerateSink(nullState))
ImplicitNullDerefNodes.push_back(N);
}
}
// From this point forward, we know that the location is not null.
- assert(notNullState);
- C.addTransition(state != nullState ? C.GenerateNode(S, notNullState) :
- C.getPredecessor());
+ C.addTransition(notNullState);
}
diff --git a/clang/lib/Analysis/DivZeroChecker.cpp b/clang/lib/Analysis/DivZeroChecker.cpp
index a8630f10088..4052637043f 100644
--- a/clang/lib/Analysis/DivZeroChecker.cpp
+++ b/clang/lib/Analysis/DivZeroChecker.cpp
@@ -63,7 +63,7 @@ void DivZeroChecker::PreVisitBinaryOperator(CheckerContext &C,
llvm::tie(stateNotZero, stateZero) = CM.AssumeDual(C.getState(), *DV);
if (stateZero && !stateNotZero) {
- if (ExplodedNode *N = C.GenerateNode(B, stateZero, true)) {
+ if (ExplodedNode *N = C.GenerateSink(stateZero)) {
if (!BT)
BT = new BuiltinBug("Division by zero");
@@ -80,6 +80,5 @@ void DivZeroChecker::PreVisitBinaryOperator(CheckerContext &C,
// If we get here, then the denom should not be zero. We abandon the implicit
// zero denom case for now.
- if (stateNotZero != C.getState())
- C.addTransition(C.GenerateNode(B, stateNotZero));
+ C.addTransition(stateNotZero);
}
diff --git a/clang/lib/Analysis/FixedAddressChecker.cpp b/clang/lib/Analysis/FixedAddressChecker.cpp
index 80096dcb70d..d8adaafa605 100644
--- a/clang/lib/Analysis/FixedAddressChecker.cpp
+++ b/clang/lib/Analysis/FixedAddressChecker.cpp
@@ -53,7 +53,7 @@ void FixedAddressChecker::PreVisitBinaryOperator(CheckerContext &C,
if (!RV.isConstant() || RV.isZeroConstant())
return;
- if (ExplodedNode *N = C.GenerateNode(B)) {
+ if (ExplodedNode *N = C.GenerateNode()) {
if (!BT)
BT = new BuiltinBug("Use fixed address",
"Using a fixed address is not portable because that "
diff --git a/clang/lib/Analysis/GRExprEngine.cpp b/clang/lib/Analysis/GRExprEngine.cpp
index 4f3440d88a0..f657aebdf6d 100644
--- a/clang/lib/Analysis/GRExprEngine.cpp
+++ b/clang/lib/Analysis/GRExprEngine.cpp
@@ -1292,9 +1292,13 @@ void GRExprEngine::EvalLocation(ExplodedNodeSet &Dst, Stmt *S,
Checker *checker = I->second;
for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
- NI != NE; ++NI)
- checker->GR_VisitLocation(*CurrSet, *Builder, *this, S, *NI, state,
+ NI != NE; ++NI) {
+ // Use the 'state' argument only when the predecessor node is the
+ // same as Pred. This allows us to catch updates to the state.
+ checker->GR_VisitLocation(*CurrSet, *Builder, *this, S, *NI,
+ *NI == Pred ? state : GetState(*NI),
location, tag, isLoad);
+ }
// Update which NodeSet is the current one.
PrevSet = CurrSet;
diff --git a/clang/lib/Analysis/MallocChecker.cpp b/clang/lib/Analysis/MallocChecker.cpp
index 995720b1f8f..a16125df77e 100644
--- a/clang/lib/Analysis/MallocChecker.cpp
+++ b/clang/lib/Analysis/MallocChecker.cpp
@@ -112,9 +112,7 @@ void MallocChecker::MallocMem(CheckerContext &C, const CallExpr *CE) {
SymbolRef Sym = CallVal.getAsLocSymbol();
assert(Sym);
// Set the symbol's state to Allocated.
- const GRState *AllocState
- = state->set<RegionState>(Sym, RefState::getAllocated(CE));
- C.addTransition(C.GenerateNode(CE, AllocState));
+ C.addTransition(state->set<RegionState>(Sym, RefState::getAllocated(CE)));
}
void MallocChecker::FreeMem(CheckerContext &C, const CallExpr *CE) {
@@ -128,7 +126,7 @@ void MallocChecker::FreeMem(CheckerContext &C, const CallExpr *CE) {
// Check double free.
if (RS->isReleased()) {
- ExplodedNode *N = C.GenerateNode(CE, true);
+ ExplodedNode *N = C.GenerateSink();
if (N) {
if (!BT_DoubleFree)
BT_DoubleFree = new BuiltinBug("Double free",
@@ -144,7 +142,7 @@ void MallocChecker::FreeMem(CheckerContext &C, const CallExpr *CE) {
// Normal free.
const GRState *FreedState
= state->set<RegionState>(Sym, RefState::getReleased(CE));
- C.addTransition(C.GenerateNode(CE, FreedState));
+ C.addTransition(FreedState);
}
void MallocChecker::EvalDeadSymbols(CheckerContext &C, const Stmt *S,
@@ -158,7 +156,7 @@ void MallocChecker::EvalDeadSymbols(CheckerContext &C, const Stmt *S,
return;
if (RS->isAllocated()) {
- ExplodedNode *N = C.GenerateNode(S, true);
+ ExplodedNode *N = C.GenerateSink();
if (N) {
if (!BT_Leak)
BT_Leak = new BuiltinBug("Memory leak",
@@ -213,7 +211,5 @@ void MallocChecker::PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S) {
if (RS->isAllocated())
state = state->set<RegionState>(Sym, RefState::getEscaped(S));
- ExplodedNode *N = C.GenerateNode(S, state);
- if (N)
- C.addTransition(N);
+ C.addTransition(state);
}
diff --git a/clang/lib/Analysis/PointerArithChecker.cpp b/clang/lib/Analysis/PointerArithChecker.cpp
index 93823484e1d..6bf1a3fc5da 100644
--- a/clang/lib/Analysis/PointerArithChecker.cpp
+++ b/clang/lib/Analysis/PointerArithChecker.cpp
@@ -53,7 +53,7 @@ void PointerArithChecker::PreVisitBinaryOperator(CheckerContext &C,
if (isa<VarRegion>(LR) || isa<CodeTextRegion>(LR) ||
isa<CompoundLiteralRegion>(LR)) {
- if (ExplodedNode *N = C.GenerateNode(B)) {
+ if (ExplodedNode *N = C.GenerateNode()) {
if (!BT)
BT = new BuiltinBug("Dangerous pointer arithmetic",
"Pointer arithmetic done on non-array variables "
diff --git a/clang/lib/Analysis/PointerSubChecker.cpp b/clang/lib/Analysis/PointerSubChecker.cpp
index 4c7906f4beb..50f502507db 100644
--- a/clang/lib/Analysis/PointerSubChecker.cpp
+++ b/clang/lib/Analysis/PointerSubChecker.cpp
@@ -61,7 +61,7 @@ void PointerSubChecker::PreVisitBinaryOperator(CheckerContext &C,
if (isa<SymbolicRegion>(BaseLR) || isa<SymbolicRegion>(BaseRR))
return;
- if (ExplodedNode *N = C.GenerateNode(B)) {
+ if (ExplodedNode *N = C.GenerateNode()) {
if (!BT)
BT = new BuiltinBug("Pointer subtraction",
"Subtraction of two pointers that do not point to "
diff --git a/clang/lib/Analysis/ReturnPointerRangeChecker.cpp b/clang/lib/Analysis/ReturnPointerRangeChecker.cpp
index 44887b2625d..8a1929464e9 100644
--- a/clang/lib/Analysis/ReturnPointerRangeChecker.cpp
+++ b/clang/lib/Analysis/ReturnPointerRangeChecker.cpp
@@ -70,7 +70,7 @@ void ReturnPointerRangeChecker::PreVisitReturnStmt(CheckerContext &C,
const GRState *StInBound = state->AssumeInBound(Idx, NumElements, true);
const GRState *StOutBound = state->AssumeInBound(Idx, NumElements, false);
if (StOutBound && !StInBound) {
- ExplodedNode *N = C.GenerateNode(RS, StOutBound, true);
+ ExplodedNode *N = C.GenerateSink(StOutBound);
if (!N)
return;
@@ -91,7 +91,6 @@ void ReturnPointerRangeChecker::PreVisitReturnStmt(CheckerContext &C,
new RangedBugReport(*BT, BT->getDescription(), N);
report->addRange(RetE->getSourceRange());
-
C.EmitReport(report);
}
}
diff --git a/clang/lib/Analysis/ReturnStackAddressChecker.cpp b/clang/lib/Analysis/ReturnStackAddressChecker.cpp
index e4be8712d09..e8a014af291 100644
--- a/clang/lib/Analysis/ReturnStackAddressChecker.cpp
+++ b/clang/lib/Analysis/ReturnStackAddressChecker.cpp
@@ -53,7 +53,7 @@ void ReturnStackAddressChecker::PreVisitReturnStmt(CheckerContext &C,
if (!R || !R->hasStackStorage())
return;
- ExplodedNode *N = C.GenerateNode(RS, C.getState(), true);
+ ExplodedNode *N = C.GenerateSink();
if (!N)
return;
diff --git a/clang/lib/Analysis/ReturnUndefChecker.cpp b/clang/lib/Analysis/ReturnUndefChecker.cpp
index 796c7608c86..48163b4d86e 100644
--- a/clang/lib/Analysis/ReturnUndefChecker.cpp
+++ b/clang/lib/Analysis/ReturnUndefChecker.cpp
@@ -50,7 +50,7 @@ void ReturnUndefChecker::PreVisitReturnStmt(CheckerContext &C,
if (!C.getState()->getSVal(RetE).isUndef())
return;
- ExplodedNode *N = C.GenerateNode(RS, C.getState(), true);
+ ExplodedNode *N = C.GenerateSink();
if (!N)
return;
diff --git a/clang/lib/Analysis/UndefinedArgChecker.cpp b/clang/lib/Analysis/UndefinedArgChecker.cpp
index ea7d971fdb8..e717f6bfe21 100644
--- a/clang/lib/Analysis/UndefinedArgChecker.cpp
+++ b/clang/lib/Analysis/UndefinedArgChecker.cpp
@@ -47,7 +47,7 @@ void clang::RegisterUndefinedArgChecker(GRExprEngine &Eng) {
void UndefinedArgChecker::EmitBadCall(BugType *BT, CheckerContext &C,
const CallExpr *CE) {
- ExplodedNode *N = C.GenerateNode(CE, true);
+ ExplodedNode *N = C.GenerateSink();
if (!N)
return;
@@ -81,7 +81,7 @@ void UndefinedArgChecker::PreVisitCallExpr(CheckerContext &C,
for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end();
I != E; ++I) {
if (C.getState()->getSVal(*I).isUndef()) {
- if (ExplodedNode *N = C.GenerateNode(CE, true)) {
+ if (ExplodedNode *N = C.GenerateSink()) {
if (!BT_call_arg)
BT_call_arg = new BuiltinBug("Pass-by-value argument in function call"
" is undefined");
@@ -104,7 +104,7 @@ void UndefinedArgChecker::PreVisitObjCMessageExpr(CheckerContext &C,
if (const Expr *receiver = ME->getReceiver())
if (state->getSVal(receiver).isUndef()) {
- if (ExplodedNode *N = C.GenerateNode(ME, true)) {
+ if (ExplodedNode *N = C.GenerateSink()) {
if (!BT_msg_undef)
BT_msg_undef =
new BuiltinBug("Receiver in message expression is a garbage value");
@@ -122,7 +122,7 @@ void UndefinedArgChecker::PreVisitObjCMessageExpr(CheckerContext &C,
for (ObjCMessageExpr::const_arg_iterator I = ME->arg_begin(), E = ME->arg_end();
I != E; ++I) {
if (state->getSVal(*I).isUndef()) {
- if (ExplodedNode *N = C.GenerateNode(ME, true)) {
+ if (ExplodedNode *N = C.GenerateSink()) {
if (!BT_msg_arg)
BT_msg_arg =
new BuiltinBug("Pass-by-value argument in message expression"
diff --git a/clang/lib/Analysis/UndefinedArraySubscriptChecker.cpp b/clang/lib/Analysis/UndefinedArraySubscriptChecker.cpp
index 887c7755fe4..3ae0c579e91 100644
--- a/clang/lib/Analysis/UndefinedArraySubscriptChecker.cpp
+++ b/clang/lib/Analysis/UndefinedArraySubscriptChecker.cpp
@@ -41,7 +41,7 @@ void
UndefinedArraySubscriptChecker::PreVisitArraySubscriptExpr(CheckerContext &C,
const ArraySubscriptExpr *A) {
if (C.getState()->getSVal(A->getIdx()).isUndef()) {
- if (ExplodedNode *N = C.GenerateNode(A, true)) {
+ if (ExplodedNode *N = C.GenerateSink()) {
if (!BT)
BT = new BuiltinBug("Array subscript is undefined");
diff --git a/clang/lib/Analysis/UndefinedAssignmentChecker.cpp b/clang/lib/Analysis/UndefinedAssignmentChecker.cpp
index 0e911ffab08..1c5b25cd8e1 100644
--- a/clang/lib/Analysis/UndefinedAssignmentChecker.cpp
+++ b/clang/lib/Analysis/UndefinedAssignmentChecker.cpp
@@ -48,7 +48,7 @@ void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C,
if (!val.isUndef())
return;
- ExplodedNode *N = C.GenerateNode(StoreE, true);
+ ExplodedNode *N = C.GenerateSink();
if (!N)
return;
diff --git a/clang/lib/Analysis/VLASizeChecker.cpp b/clang/lib/Analysis/VLASizeChecker.cpp
index 799a73e293c..9a3436c4c96 100644
--- a/clang/lib/Analysis/VLASizeChecker.cpp
+++ b/clang/lib/Analysis/VLASizeChecker.cpp
@@ -55,7 +55,7 @@ void VLASizeChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) {
if (sizeV.isUndef()) {
// Generate an error node.
- ExplodedNode *N = C.GenerateNode(DS, true);
+ ExplodedNode *N = C.GenerateSink();
if (!N)
return;
@@ -78,7 +78,7 @@ void VLASizeChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) {
llvm::tie(stateNotZero, stateZero) = state->Assume(sizeD);
if (stateZero && !stateNotZero) {
- ExplodedNode* N = C.GenerateNode(DS, stateZero, true);
+ ExplodedNode* N = C.GenerateSink(stateZero);
if (!BT_zero)
BT_zero = new BuiltinBug("Declared variable-length array (VLA) has zero "
"size");
@@ -92,6 +92,5 @@ void VLASizeChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) {
}
// From this point on, assume that the size is not zero.
- if (state != stateNotZero)
- C.addTransition(C.GenerateNode(DS, stateNotZero));
+ C.addTransition(stateNotZero);
}
OpenPOWER on IntegriCloud