[cfe-commits] r86798 - in /cfe/trunk: include/clang/Analysis/PathSensitive/Checker.h include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h include/clang/Analysis/PathSensitive/GRExprEngine.h include/clang/Analysis/ProgramPoint.h lib/Analysis/DereferenceChecker.cpp lib/Analysis/GRCoreEngine.cpp lib/Analysis/GRExprEngine.cpp lib/Analysis/GRExprEngineInternalChecks.cpp lib/Analysis/GRExprEngineInternalChecks.h lib/Analysis/NSErrorChecker.cpp
Ted Kremenek
kremenek at apple.com
Tue Nov 10 19:26:35 PST 2009
Author: kremenek
Date: Tue Nov 10 21:26:34 2009
New Revision: 86798
URL: http://llvm.org/viewvc/llvm-project?rev=86798&view=rev
Log:
Refactor DereferenceChecker to use only the new Checker API instead of
the old builder API. This percolated a bunch of changes up to the
Checker class (where CheckLocation has been renamed VisitLocation) and
GRExprEngine. ProgramPoint now has the notion of a "LocationCheck"
point (with PreLoad and PreStore respectively), and a bunch of the old
ProgramPoints that are no longer used have been removed.
Modified:
cfe/trunk/include/clang/Analysis/PathSensitive/Checker.h
cfe/trunk/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h
cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
cfe/trunk/include/clang/Analysis/ProgramPoint.h
cfe/trunk/lib/Analysis/DereferenceChecker.cpp
cfe/trunk/lib/Analysis/GRCoreEngine.cpp
cfe/trunk/lib/Analysis/GRExprEngine.cpp
cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp
cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.h
cfe/trunk/lib/Analysis/NSErrorChecker.cpp
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/Checker.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/Checker.h?rev=86798&r1=86797&r2=86798&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/Checker.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/Checker.h Tue Nov 10 21:26:34 2009
@@ -39,22 +39,19 @@
SaveAndRestore<const void*> OldTag;
SaveAndRestore<ProgramPoint::Kind> OldPointKind;
SaveOr OldHasGen;
+ const GRState *state;
public:
- CheckerContext(ExplodedNodeSet &dst,
- GRStmtNodeBuilder &builder,
- GRExprEngine &eng,
- ExplodedNode *pred,
- const void *tag, bool preVisit)
+ CheckerContext(ExplodedNodeSet &dst, GRStmtNodeBuilder &builder,
+ GRExprEngine &eng, ExplodedNode *pred,
+ const void *tag, ProgramPoint::Kind K,
+ const GRState *st = 0)
: Dst(dst), B(builder), Eng(eng), Pred(pred),
- OldSink(B.BuildSinks), OldTag(B.Tag),
- OldPointKind(B.PointKind), OldHasGen(B.HasGeneratedNode) {
- //assert(Dst.empty()); // This is a fake assertion.
- // See GRExprEngine::CheckerVisit(), CurrSet is repeatedly used.
- B.Tag = tag;
- if (preVisit)
- B.PointKind = ProgramPoint::PreStmtKind;
- }
+ OldSink(B.BuildSinks),
+ OldTag(B.Tag, tag),
+ OldPointKind(B.PointKind, K),
+ OldHasGen(B.HasGeneratedNode),
+ state(st) {}
~CheckerContext() {
if (!B.BuildSinks && !B.HasGeneratedNode)
@@ -72,7 +69,7 @@
ExplodedNodeSet &getNodeSet() { return Dst; }
GRStmtNodeBuilder &getNodeBuilder() { return B; }
ExplodedNode *&getPredecessor() { return Pred; }
- const GRState *getState() { return B.GetState(Pred); }
+ const GRState *getState() { return state ? state : B.GetState(Pred); }
ASTContext &getASTContext() {
return Eng.getContext();
@@ -113,43 +110,54 @@
private:
friend class GRExprEngine;
+ // FIXME: Remove the 'tag' option.
void GR_Visit(ExplodedNodeSet &Dst,
GRStmtNodeBuilder &Builder,
GRExprEngine &Eng,
- const Stmt *stmt,
+ const Stmt *S,
ExplodedNode *Pred, void *tag, bool isPrevisit) {
- CheckerContext C(Dst, Builder, Eng, Pred, tag, isPrevisit);
+ CheckerContext C(Dst, Builder, Eng, Pred, tag,
+ isPrevisit ? ProgramPoint::PreStmtKind :
+ ProgramPoint::PostStmtKind);
assert(isPrevisit && "Only previsit supported for now.");
- _PreVisit(C, stmt);
+ _PreVisit(C, S);
}
+ // 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) {
- CheckerContext C(Dst, Builder, Eng, Pred, tag, isPrevisit);
+ CheckerContext C(Dst, Builder, Eng, Pred, tag,
+ isPrevisit ? ProgramPoint::PreStmtKind :
+ ProgramPoint::PostStmtKind);
assert(isPrevisit && "Only previsit supported for now.");
PreVisitBind(C, AssignE, StoreE, location, val);
}
+
+ // FIXME: Remove the 'tag' option.
+ void GR_VisitLocation(ExplodedNodeSet &Dst,
+ GRStmtNodeBuilder &Builder,
+ GRExprEngine &Eng,
+ const Stmt *S,
+ ExplodedNode *Pred, const GRState *state,
+ SVal location,
+ void *tag, bool isLoad) {
+ CheckerContext C(Dst, Builder, Eng, Pred, tag,
+ isLoad ? ProgramPoint::PreLoadKind :
+ ProgramPoint::PreStoreKind, state);
+ VisitLocation(C, S, location);
+ }
public:
virtual ~Checker() {}
virtual void _PreVisit(CheckerContext &C, const Stmt *ST) {}
-
- // This is a previsit which takes a node returns a node.
- virtual ExplodedNode *CheckLocation(const Stmt *S, ExplodedNode *Pred,
- const GRState *state, SVal V,
- GRExprEngine &Eng) {
- return Pred;
- }
-
- virtual void PreVisitBind(CheckerContext &C,
- const Stmt *AssignE, const Stmt *StoreE,
- SVal location, SVal val) {}
+ 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) {}
};
-
} // end clang namespace
#endif
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h?rev=86798&r1=86797&r2=86798&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h Tue Nov 10 21:26:34 2009
@@ -16,38 +16,16 @@
#ifndef LLVM_CLANG_DEREFCHECKER
#define LLVM_CLANG_DEREFCHECKER
-#include "clang/Analysis/PathSensitive/Checker.h"
-#include "clang/Analysis/PathSensitive/BugType.h"
+#include <utility>
namespace clang {
+class GRExprEngine;
class ExplodedNode;
-class NullDerefChecker : public Checker {
- BuiltinBug *BT;
- llvm::SmallVector<ExplodedNode*, 2> ImplicitNullDerefNodes;
-
-public:
- NullDerefChecker() : BT(0) {}
- ExplodedNode *CheckLocation(const Stmt *S, ExplodedNode *Pred,
- const GRState *state, SVal V,GRExprEngine &Eng);
-
- static void *getTag();
- typedef llvm::SmallVectorImpl<ExplodedNode*>::iterator iterator;
- iterator implicit_nodes_begin() { return ImplicitNullDerefNodes.begin(); }
- iterator implicit_nodes_end() { return ImplicitNullDerefNodes.end(); }
-};
-
-class UndefDerefChecker : public Checker {
- BuiltinBug *BT;
-public:
- UndefDerefChecker() : BT(0) {}
-
- ExplodedNode *CheckLocation(const Stmt *S, ExplodedNode *Pred,
- const GRState *state, SVal V, GRExprEngine &Eng);
-
- static void *getTag();
-};
+std::pair<ExplodedNode * const *, ExplodedNode * const *>
+GetImplicitNullDereferences(GRExprEngine &Eng);
} // end clang namespace
+
#endif
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h?rev=86798&r1=86797&r2=86798&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h Tue Nov 10 21:26:34 2009
@@ -556,16 +556,21 @@
bool atDeclInit = false);
public:
+ // FIXME: 'tag' should be removed, and a LocationContext should be used
+ // instead.
void EvalLoad(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred,
const GRState* St, SVal location, const void *tag = 0);
- ExplodedNode* EvalLocation(Stmt* Ex, ExplodedNode* Pred,
+ // FIXME: 'tag' should be removed, and a LocationContext should be used
+ // instead.
+ void EvalLocation(ExplodedNodeSet &Dst, Stmt *S, ExplodedNode* Pred,
const GRState* St, SVal location,
- const void *tag = 0);
+ const void *tag, bool isLoad);
+ // FIXME: 'tag' should be removed, and a LocationContext should be used
+ // instead.
void EvalStore(ExplodedNodeSet& Dst, Expr* AssignE, Expr* StoreE,
- ExplodedNode* Pred,
- const GRState* St, SVal TargetLV, SVal Val,
+ ExplodedNode* Pred, const GRState* St, SVal TargetLV, SVal Val,
const void *tag = 0);
};
Modified: cfe/trunk/include/clang/Analysis/ProgramPoint.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/ProgramPoint.h?rev=86798&r1=86797&r2=86798&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/ProgramPoint.h (original)
+++ cfe/trunk/include/clang/Analysis/ProgramPoint.h Tue Nov 10 21:26:34 2009
@@ -33,13 +33,10 @@
BlockEntranceKind,
BlockExitKind,
PreStmtKind,
- // Keep the following together and in this order.
PostStmtKind,
- PostLocationChecksSucceedKind,
- PostOutOfBoundsCheckFailedKind,
- PostNullCheckFailedKind,
- PostUndefLocationCheckFailedKind,
+ PreLoadKind,
PostLoadKind,
+ PreStoreKind,
PostStoreKind,
PostPurgeDeadSymbolsKind,
PostStmtCustomKind,
@@ -194,17 +191,6 @@
}
};
-class PostLocationChecksSucceed : public PostStmt {
-public:
- PostLocationChecksSucceed(const Stmt* S, const LocationContext *L,
- const void *tag = 0)
- : PostStmt(S, PostLocationChecksSucceedKind, L, tag) {}
-
- static bool classof(const ProgramPoint* Location) {
- return Location->getKind() == PostLocationChecksSucceedKind;
- }
-};
-
class PostStmtCustom : public PostStmt {
public:
PostStmtCustom(const Stmt* S,
@@ -226,36 +212,36 @@
}
};
-class PostOutOfBoundsCheckFailed : public PostStmt {
-public:
- PostOutOfBoundsCheckFailed(const Stmt* S, const LocationContext *L,
- const void *tag = 0)
- : PostStmt(S, PostOutOfBoundsCheckFailedKind, L, tag) {}
-
- static bool classof(const ProgramPoint* Location) {
- return Location->getKind() == PostOutOfBoundsCheckFailedKind;
+
+class LocationCheck : public StmtPoint {
+protected:
+ LocationCheck(const Stmt *S, const LocationContext *L,
+ ProgramPoint::Kind K, const void *tag)
+ : StmtPoint(S, NULL, K, L, tag) {}
+
+ static bool classof(const ProgramPoint *location) {
+ unsigned k = location->getKind();
+ return k == PreLoadKind || PreStoreKind;
}
};
-
-class PostUndefLocationCheckFailed : public PostStmt {
+
+class PreLoad : public LocationCheck {
public:
- PostUndefLocationCheckFailed(const Stmt* S, const LocationContext *L,
- const void *tag = 0)
- : PostStmt(S, PostUndefLocationCheckFailedKind, L, tag) {}
-
- static bool classof(const ProgramPoint* Location) {
- return Location->getKind() == PostUndefLocationCheckFailedKind;
+ PreLoad(const Stmt *S, const LocationContext *L, const void *tag = 0)
+ : LocationCheck(S, L, PreLoadKind, tag) {}
+
+ static bool classof(const ProgramPoint *location) {
+ return location->getKind() == PreLoadKind;
}
};
-class PostNullCheckFailed : public PostStmt {
+class PreStore : public LocationCheck {
public:
- PostNullCheckFailed(const Stmt* S, const LocationContext *L,
- const void *tag = 0)
- : PostStmt(S, PostNullCheckFailedKind, L, tag) {}
-
- static bool classof(const ProgramPoint* Location) {
- return Location->getKind() == PostNullCheckFailedKind;
+ PreStore(const Stmt *S, const LocationContext *L, const void *tag = 0)
+ : LocationCheck(S, L, PreStoreKind, tag) {}
+
+ static bool classof(const ProgramPoint *location) {
+ return location->getKind() == PreStoreKind;
}
};
Modified: cfe/trunk/lib/Analysis/DereferenceChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/DereferenceChecker.cpp?rev=86798&r1=86797&r2=86798&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/DereferenceChecker.cpp (original)
+++ cfe/trunk/lib/Analysis/DereferenceChecker.cpp Tue Nov 10 21:26:34 2009
@@ -13,99 +13,103 @@
//===----------------------------------------------------------------------===//
#include "clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h"
+#include "clang/Analysis/PathSensitive/Checker.h"
#include "clang/Analysis/PathSensitive/GRExprEngine.h"
#include "clang/Analysis/PathSensitive/BugReporter.h"
+#include "GRExprEngineInternalChecks.h"
using namespace clang;
-void *NullDerefChecker::getTag() {
- static int x = 0;
- return &x;
-}
-
-ExplodedNode *NullDerefChecker::CheckLocation(const Stmt *S, ExplodedNode *Pred,
- const GRState *state, SVal V,
- GRExprEngine &Eng) {
- Loc *LV = dyn_cast<Loc>(&V);
-
- // If the value is not a location, don't touch the node.
- if (!LV)
- return Pred;
-
- const GRState *NotNullState = state->Assume(*LV, true);
- const GRState *NullState = state->Assume(*LV, false);
-
- GRStmtNodeBuilder &Builder = Eng.getBuilder();
- BugReporter &BR = Eng.getBugReporter();
-
- // The explicit NULL case.
- if (NullState) {
- // Use the GDM to mark in the state what lval was null.
- const SVal *PersistentLV = Eng.getBasicVals().getPersistentSVal(*LV);
- NullState = NullState->set<GRState::NullDerefTag>(PersistentLV);
-
- ExplodedNode *N = Builder.generateNode(S, NullState, Pred,
- ProgramPoint::PostNullCheckFailedKind);
- if (N) {
- N->markAsSink();
-
- if (!NotNullState) { // Explicit null case.
- if (!BT)
- BT = new BuiltinBug("Null dereference","Dereference of null pointer");
-
- EnhancedBugReport *R =
- new EnhancedBugReport(*BT, BT->getDescription().c_str(), N);
-
- R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
- bugreporter::GetDerefExpr(N));
-
- BR.EmitReport(R);
-
- return 0;
- } else // Implicit null case.
- ImplicitNullDerefNodes.push_back(N);
- }
- }
+namespace {
+class VISIBILITY_HIDDEN DereferenceChecker : public Checker {
+ BuiltinBug *BT_null;
+ BuiltinBug *BT_undef;
+ llvm::SmallVector<ExplodedNode*, 2> ImplicitNullDerefNodes;
+public:
+ DereferenceChecker() : BT_null(0), BT_undef(0) {}
+ static void *getTag() { static int tag = 0; return &tag; }
+ void VisitLocation(CheckerContext &C, const Stmt *S, SVal location);
- if (!NotNullState)
- return 0;
+ std::pair<ExplodedNode * const*, ExplodedNode * const*>
+ getImplicitNodes() const {
+ return std::make_pair(ImplicitNullDerefNodes.data(),
+ ImplicitNullDerefNodes.data() +
+ ImplicitNullDerefNodes.size());
+ }
+};
+} // end anonymous namespace
- return Builder.generateNode(S, NotNullState, Pred,
- ProgramPoint::PostLocationChecksSucceedKind);
+void clang::RegisterDereferenceChecker(GRExprEngine &Eng) {
+ Eng.registerCheck(new DereferenceChecker());
}
-
-void *UndefDerefChecker::getTag() {
- static int x = 0;
- return &x;
+std::pair<ExplodedNode * const *, ExplodedNode * const *>
+clang::GetImplicitNullDereferences(GRExprEngine &Eng) {
+ DereferenceChecker *checker = Eng.getChecker<DereferenceChecker>();
+ if (!checker)
+ return std::make_pair((ExplodedNode * const *) 0,
+ (ExplodedNode * const *) 0);
+ return checker->getImplicitNodes();
}
-ExplodedNode *UndefDerefChecker::CheckLocation(const Stmt *S,
- ExplodedNode *Pred,
- const GRState *state, SVal V,
- GRExprEngine &Eng) {
- GRStmtNodeBuilder &Builder = Eng.getBuilder();
- BugReporter &BR = Eng.getBugReporter();
-
- if (V.isUndef()) {
- ExplodedNode *N = Builder.generateNode(S, state, Pred,
- ProgramPoint::PostUndefLocationCheckFailedKind);
+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) {
- N->markAsSink();
-
- if (!BT)
- BT = new BuiltinBug(0, "Undefined dereference",
- "Dereference of undefined pointer value");
-
- EnhancedBugReport *R =
- new EnhancedBugReport(*BT, BT->getDescription().c_str(), N);
- R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
- bugreporter::GetDerefExpr(N));
- BR.EmitReport(R);
+ if (!BT_undef)
+ BT_undef = new BuiltinBug("Dereference of undefined pointer value");
+
+ EnhancedBugReport *report =
+ new EnhancedBugReport(*BT_undef, BT_undef->getDescription().c_str(), N);
+ report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+ bugreporter::GetDerefExpr(N));
+ C.EmitReport(report);
}
- return 0;
+ return;
}
-
- return Pred;
+
+ DefinedOrUnknownSVal location = cast<DefinedOrUnknownSVal>(l);
+
+ // Check for null dereferences.
+ if (!isa<Loc>(location))
+ return;
+
+ const GRState *state = C.getState();
+ const GRState *notNullState, *nullState;
+ llvm::tie(notNullState, nullState) = state->Assume(location);
+
+ // The explicit NULL case.
+ if (nullState) {
+ // Generate an error node.
+ ExplodedNode *N = C.GenerateNode(S, nullState, true);
+ if (N) {
+ if (!notNullState) {
+ // We know that 'location' cannot be non-null. This is what
+ // we call an "explicit" null dereference.
+ if (!BT_null)
+ BT_null = new BuiltinBug("Null pointer dereference",
+ "Dereference of null pointer");
+
+ EnhancedBugReport *report =
+ new EnhancedBugReport(*BT_null, BT_null->getDescription().c_str(), N);
+ report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+ bugreporter::GetDerefExpr(N));
+
+ C.EmitReport(report);
+ return;
+ }
+
+ // Otherwise, we have the case where the location could either be
+ // null or not-null. Record the error node as an "implicit" null
+ // dereference.
+ 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());
}
-
Modified: cfe/trunk/lib/Analysis/GRCoreEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRCoreEngine.cpp?rev=86798&r1=86797&r2=86798&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRCoreEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRCoreEngine.cpp Tue Nov 10 21:26:34 2009
@@ -418,51 +418,38 @@
Eng.WList->Enqueue(Succ, B, Idx+1);
}
-static inline PostStmt GetPostLoc(const Stmt* S, ProgramPoint::Kind K,
- const LocationContext *L, const void *tag) {
+static ProgramPoint GetProgramPoint(const Stmt *S, ProgramPoint::Kind K,
+ const LocationContext *LC, const void *tag){
switch (K) {
default:
- assert(false && "Invalid PostXXXKind.");
-
+ assert(false && "Unhandled ProgramPoint kind");
+ case ProgramPoint::PreStmtKind:
+ return PreStmt(S, LC, tag);
case ProgramPoint::PostStmtKind:
- return PostStmt(S, L, tag);
-
+ return PostStmt(S, LC, tag);
+ case ProgramPoint::PreLoadKind:
+ return PreLoad(S, LC, tag);
case ProgramPoint::PostLoadKind:
- return PostLoad(S, L, tag);
-
- case ProgramPoint::PostUndefLocationCheckFailedKind:
- return PostUndefLocationCheckFailed(S, L, tag);
-
- case ProgramPoint::PostLocationChecksSucceedKind:
- return PostLocationChecksSucceed(S, L, tag);
-
- case ProgramPoint::PostOutOfBoundsCheckFailedKind:
- return PostOutOfBoundsCheckFailed(S, L, tag);
-
- case ProgramPoint::PostNullCheckFailedKind:
- return PostNullCheckFailed(S, L, tag);
-
+ return PostLoad(S, LC, tag);
+ case ProgramPoint::PreStoreKind:
+ return PreStore(S, LC, tag);
case ProgramPoint::PostStoreKind:
- return PostStore(S, L, tag);
-
+ return PostStore(S, LC, tag);
case ProgramPoint::PostLValueKind:
- return PostLValue(S, L, tag);
-
+ return PostLValue(S, LC, tag);
case ProgramPoint::PostPurgeDeadSymbolsKind:
- return PostPurgeDeadSymbols(S, L, tag);
+ return PostPurgeDeadSymbols(S, LC, tag);
}
}
ExplodedNode*
-GRStmtNodeBuilder::generateNodeInternal(const Stmt* S, const GRState* State,
+GRStmtNodeBuilder::generateNodeInternal(const Stmt* S, const GRState* state,
ExplodedNode* Pred,
ProgramPoint::Kind K,
const void *tag) {
- return K == ProgramPoint::PreStmtKind
- ? generateNodeInternal(PreStmt(S, Pred->getLocationContext(),tag),
- State, Pred)
- : generateNodeInternal(GetPostLoc(S, K, Pred->getLocationContext(), tag),
- State, Pred);
+
+ const ProgramPoint &L = GetProgramPoint(S, K, Pred->getLocationContext(),tag);
+ return generateNodeInternal(L, state, Pred);
}
ExplodedNode*
Modified: cfe/trunk/lib/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngine.cpp?rev=86798&r1=86797&r2=86798&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Tue Nov 10 21:26:34 2009
@@ -1190,68 +1190,87 @@
assert(Builder && "GRStmtNodeBuilder must be defined.");
// Evaluate the location (checks for bad dereferences).
- Pred = EvalLocation(StoreE, Pred, state, location, tag);
+ ExplodedNodeSet Tmp;
+ EvalLocation(Tmp, StoreE, Pred, state, location, tag, false);
- if (!Pred)
+ if (Tmp.empty())
return;
- assert (!location.isUndef());
- state = GetState(Pred);
+ assert(!location.isUndef());
+ SaveAndRestore<ProgramPoint::Kind> OldSPointKind(Builder->PointKind,
+ ProgramPoint::PostStoreKind);
+ SaveAndRestore<const void*> OldTag(Builder->Tag, tag);
+
// Proceed with the store.
- SaveAndRestore<ProgramPoint::Kind> OldSPointKind(Builder->PointKind);
- SaveAndRestore<const void*> OldTag(Builder->Tag);
- Builder->PointKind = ProgramPoint::PostStoreKind;
- Builder->Tag = tag;
- EvalBind(Dst, AssignE, StoreE, Pred, state, location, Val);
+ for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI)
+ EvalBind(Dst, AssignE, StoreE, *NI, GetState(*NI), location, Val);
}
-void GRExprEngine::EvalLoad(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred,
+void GRExprEngine::EvalLoad(ExplodedNodeSet& Dst, Expr *Ex, ExplodedNode* Pred,
const GRState* state, SVal location,
const void *tag) {
// Evaluate the location (checks for bad dereferences).
- Pred = EvalLocation(Ex, Pred, state, location, tag);
+ ExplodedNodeSet Tmp;
+ EvalLocation(Tmp, Ex, Pred, state, location, tag, true);
- if (!Pred)
+ if (Tmp.empty())
return;
-
- state = GetState(Pred);
+
+ assert(!location.isUndef());
+
+ SaveAndRestore<ProgramPoint::Kind> OldSPointKind(Builder->PointKind);
+ SaveAndRestore<const void*> OldTag(Builder->Tag);
// Proceed with the load.
- ProgramPoint::Kind K = ProgramPoint::PostLoadKind;
-
- if (location.isUnknown()) {
- // This is important. We must nuke the old binding.
- MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, UnknownVal()),
- K, tag);
- }
- else {
- SVal V = state->getSVal(cast<Loc>(location), Ex->getType());
- MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, V), K, tag);
+ for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI) {
+ state = GetState(*NI);
+ if (location.isUnknown()) {
+ // This is important. We must nuke the old binding.
+ MakeNode(Dst, Ex, *NI, state->BindExpr(Ex, UnknownVal()),
+ ProgramPoint::PostLoadKind, tag);
+ }
+ else {
+ SVal V = state->getSVal(cast<Loc>(location), Ex->getType());
+ MakeNode(Dst, Ex, *NI, state->BindExpr(Ex, V), ProgramPoint::PostLoadKind,
+ tag);
+ }
}
}
-ExplodedNode* GRExprEngine::EvalLocation(Stmt* Ex, ExplodedNode* Pred,
- const GRState* state, SVal location,
- const void *tag) {
-
- SaveAndRestore<const void*> OldTag(Builder->Tag);
- Builder->Tag = tag;
-
- if (location.isUnknown() || Checkers.empty())
- return Pred;
+void GRExprEngine::EvalLocation(ExplodedNodeSet &Dst, Stmt *S,
+ ExplodedNode* Pred,
+ const GRState* state, SVal location,
+ const void *tag, bool isLoad) {
+ if (location.isUnknown() || Checkers.empty()) {
+ Dst.Add(Pred);
+ return;
+ }
- for (CheckersOrdered::iterator I=Checkers.begin(), E=Checkers.end(); I!=E;++I)
+ ExplodedNodeSet Src, Tmp;
+ Src.Add(Pred);
+ ExplodedNodeSet *PrevSet = &Src;
+
+ for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E; ++I)
{
- Pred = I->second->CheckLocation(Ex, Pred, state, location, *this);
- if (!Pred)
- break;
+ ExplodedNodeSet *CurrSet = (I+1 == E) ? &Dst
+ : (PrevSet == &Tmp) ? &Src : &Tmp;
+
+ CurrSet->clear();
+ void *tag = I->first;
+ 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,
+ location, tag, isLoad);
+
+ // Update which NodeSet is the current one.
+ PrevSet = CurrSet;
}
- return Pred;
-
// FIXME: Temporarily disable out-of-bounds checking until we make
// the logic reflect recent changes to CastRegion and friends.
#if 0
@@ -1746,46 +1765,47 @@
ExplodedNode* Pred, ExplodedNodeSet& Dst,
SVal ElementV) {
-
-
- // Get the current state. Use 'EvalLocation' to determine if it is a null
- // pointer, etc.
+ // Check if the location we are writing back to is a null pointer.
Stmt* elem = S->getElement();
-
- Pred = EvalLocation(elem, Pred, GetState(Pred), ElementV);
- if (!Pred)
+ ExplodedNodeSet Tmp;
+ EvalLocation(Tmp, elem, Pred, GetState(Pred), ElementV, NULL, false);
+
+ if (Tmp.empty())
return;
-
- const GRState *state = GetState(Pred);
-
- // Handle the case where the container still has elements.
- SVal TrueV = ValMgr.makeTruthVal(1);
- const GRState *hasElems = state->BindExpr(S, TrueV);
-
- // Handle the case where the container has no elements.
- SVal FalseV = ValMgr.makeTruthVal(0);
- const GRState *noElems = state->BindExpr(S, FalseV);
-
- if (loc::MemRegionVal* MV = dyn_cast<loc::MemRegionVal>(&ElementV))
- if (const TypedRegion* R = dyn_cast<TypedRegion>(MV->getRegion())) {
- // FIXME: The proper thing to do is to really iterate over the
- // container. We will do this with dispatch logic to the store.
- // For now, just 'conjure' up a symbolic value.
- QualType T = R->getValueType(getContext());
- assert (Loc::IsLocType(T));
- unsigned Count = Builder->getCurrentBlockCount();
- SymbolRef Sym = SymMgr.getConjuredSymbol(elem, T, Count);
- SVal V = ValMgr.makeLoc(Sym);
- hasElems = hasElems->bindLoc(ElementV, V);
-
- // Bind the location to 'nil' on the false branch.
- SVal nilV = ValMgr.makeIntVal(0, T);
- noElems = noElems->bindLoc(ElementV, nilV);
- }
-
- // Create the new nodes.
- MakeNode(Dst, S, Pred, hasElems);
- MakeNode(Dst, S, Pred, noElems);
+
+ for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI) {
+ Pred = *NI;
+ const GRState *state = GetState(Pred);
+
+ // Handle the case where the container still has elements.
+ SVal TrueV = ValMgr.makeTruthVal(1);
+ const GRState *hasElems = state->BindExpr(S, TrueV);
+
+ // Handle the case where the container has no elements.
+ SVal FalseV = ValMgr.makeTruthVal(0);
+ const GRState *noElems = state->BindExpr(S, FalseV);
+
+ if (loc::MemRegionVal* MV = dyn_cast<loc::MemRegionVal>(&ElementV))
+ if (const TypedRegion* R = dyn_cast<TypedRegion>(MV->getRegion())) {
+ // FIXME: The proper thing to do is to really iterate over the
+ // container. We will do this with dispatch logic to the store.
+ // For now, just 'conjure' up a symbolic value.
+ QualType T = R->getValueType(getContext());
+ assert(Loc::IsLocType(T));
+ unsigned Count = Builder->getCurrentBlockCount();
+ SymbolRef Sym = SymMgr.getConjuredSymbol(elem, T, Count);
+ SVal V = ValMgr.makeLoc(Sym);
+ hasElems = hasElems->bindLoc(ElementV, V);
+
+ // Bind the location to 'nil' on the false branch.
+ SVal nilV = ValMgr.makeIntVal(0, T);
+ noElems = noElems->bindLoc(ElementV, nilV);
+ }
+
+ // Create the new nodes.
+ MakeNode(Dst, S, Pred, hasElems);
+ MakeNode(Dst, S, Pred, noElems);
+ }
}
//===----------------------------------------------------------------------===//
@@ -2920,10 +2940,6 @@
Out << "\\lPostStore\\l";
else if (isa<PostLValue>(Loc))
Out << "\\lPostLValue\\l";
- else if (isa<PostLocationChecksSucceed>(Loc))
- Out << "\\lPostLocationChecksSucceed\\l";
- else if (isa<PostNullCheckFailed>(Loc))
- Out << "\\lPostNullCheckFailed\\l";
if (GraphPrintCheckerState->isImplicitNullDeref(N))
Out << "\\|Implicit-Null Dereference.\\l";
Modified: cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp?rev=86798&r1=86797&r2=86798&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp Tue Nov 10 21:26:34 2009
@@ -16,7 +16,6 @@
#include "clang/Analysis/PathSensitive/BugReporter.h"
#include "clang/Analysis/PathSensitive/GRExprEngine.h"
#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
-#include "clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h"
#include "clang/Analysis/PathSensitive/Checkers/BadCallChecker.h"
#include "clang/Analysis/PathSensitive/Checkers/UndefinedArgChecker.h"
#include "clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h"
@@ -405,9 +404,8 @@
registerCheck(new UndefinedArgChecker());
registerCheck(new UndefinedAssignmentChecker());
registerCheck(new BadCallChecker());
- registerCheck(new UndefDerefChecker());
- registerCheck(new NullDerefChecker());
+ RegisterDereferenceChecker(*this);
RegisterVLASizeChecker(*this);
RegisterDivZeroChecker(*this);
RegisterReturnStackAddressChecker(*this);
Modified: cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.h?rev=86798&r1=86797&r2=86798&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.h (original)
+++ cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.h Tue Nov 10 21:26:34 2009
@@ -19,6 +19,7 @@
class GRExprEngine;
+void RegisterDereferenceChecker(GRExprEngine &Eng);
void RegisterDivZeroChecker(GRExprEngine &Eng);
void RegisterReturnPointerRangeChecker(GRExprEngine &Eng);
void RegisterReturnStackAddressChecker(GRExprEngine &Eng);
@@ -28,5 +29,6 @@
void RegisterPointerArithChecker(GRExprEngine &Eng);
void RegisterFixedAddressChecker(GRExprEngine &Eng);
void RegisterCastToStructChecker(GRExprEngine &Eng);
+
} // end clang namespace
#endif
Modified: cfe/trunk/lib/Analysis/NSErrorChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/NSErrorChecker.cpp?rev=86798&r1=86797&r2=86798&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/NSErrorChecker.cpp (original)
+++ cfe/trunk/lib/Analysis/NSErrorChecker.cpp Tue Nov 10 21:26:34 2009
@@ -209,15 +209,12 @@
return;
// Iterate over the implicit-null dereferences.
- NullDerefChecker *Checker = Eng.getChecker<NullDerefChecker>();
- assert(Checker && "NullDerefChecker not exist.");
- for (NullDerefChecker::iterator I = Checker->implicit_nodes_begin(),
- E = Checker->implicit_nodes_end(); I != E; ++I) {
-
+ ExplodedNode *const* I, *const* E;
+ llvm::tie(I, E) = GetImplicitNullDereferences(Eng);
+ for ( ; I != E; ++I) {
const GRState *state = (*I)->getState();
- const SVal* X = state->get<GRState::NullDerefTag>();
-
- if (!X || X->getAsSymbol() != ParamSym)
+ SVal location = state->getSVal((*I)->getLocationAs<StmtPoint>()->getStmt());
+ if (location.getAsSymbol() != ParamSym)
continue;
// Emit an error.
More information about the cfe-commits
mailing list