diff options
author | Ted Kremenek <kremenek@apple.com> | 2009-11-12 04:35:08 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2009-11-12 04:35:08 +0000 |
commit | 31a241a0bbb281040b02ced04d1ad6c45c586d73 (patch) | |
tree | 30e197ab38c6a84b9378f5d973dbea9efd0749f0 | |
parent | 7422db3eb6753370ece0443c23f636b233f5ec9b (diff) |
Enhance Checker class (and GRExprEngine) to support PostVisitation for CallExprs. No clients (yet).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86949 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Analysis/PathSensitive/Checker.h | 9 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/CheckerVisitor.def | 9 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/CheckerVisitor.h | 27 | ||||
-rw-r--r-- | lib/Analysis/GRExprEngine.cpp | 20 |
4 files changed, 48 insertions, 17 deletions
diff --git a/include/clang/Analysis/PathSensitive/Checker.h b/include/clang/Analysis/PathSensitive/Checker.h index 5503a9099b..37ae2e8ed4 100644 --- a/include/clang/Analysis/PathSensitive/Checker.h +++ b/include/clang/Analysis/PathSensitive/Checker.h @@ -119,8 +119,10 @@ private: CheckerContext C(Dst, Builder, Eng, Pred, tag, isPrevisit ? ProgramPoint::PreStmtKind : ProgramPoint::PostStmtKind); - assert(isPrevisit && "Only previsit supported for now."); - _PreVisit(C, S); + if (isPrevisit) + _PreVisit(C, S); + else + _PostVisit(C, S); } // FIXME: Remove the 'tag' option. @@ -153,7 +155,8 @@ private: public: virtual ~Checker() {} - virtual void _PreVisit(CheckerContext &C, const Stmt *ST) {} + 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) {} diff --git a/include/clang/Analysis/PathSensitive/CheckerVisitor.def b/include/clang/Analysis/PathSensitive/CheckerVisitor.def index 44c6f18f0d..090a5d3975 100644 --- a/include/clang/Analysis/PathSensitive/CheckerVisitor.def +++ b/include/clang/Analysis/PathSensitive/CheckerVisitor.def @@ -11,6 +11,7 @@ // //===---------------------------------------------------------------------===// +#ifdef PREVISIT PREVISIT(ArraySubscriptExpr) PREVISIT(BinaryOperator) PREVISIT(CallExpr) @@ -18,5 +19,11 @@ PREVISIT(CastExpr) PREVISIT(DeclStmt) PREVISIT(ObjCMessageExpr) PREVISIT(ReturnStmt) - #undef PREVISIT +#endif + +#ifdef POSTVISIT +POSTVISIT(CallExpr) +#undef POSTVISIT +#endif + diff --git a/include/clang/Analysis/PathSensitive/CheckerVisitor.h b/include/clang/Analysis/PathSensitive/CheckerVisitor.h index f2e8f29aa6..7cef17eb65 100644 --- a/include/clang/Analysis/PathSensitive/CheckerVisitor.h +++ b/include/clang/Analysis/PathSensitive/CheckerVisitor.h @@ -27,8 +27,12 @@ namespace clang { template<typename ImplClass> class CheckerVisitor : public Checker { public: - virtual void _PreVisit(CheckerContext &C, const Stmt *stmt) { - PreVisit(C, stmt); + virtual void _PreVisit(CheckerContext &C, const Stmt *S) { + PreVisit(C, S); + } + + virtual void _PostVisit(CheckerContext &C, const Stmt *S) { + PostVisit(C, S); } void PreVisit(CheckerContext &C, const Stmt *S) { @@ -56,13 +60,30 @@ break; #include "clang/Analysis/PathSensitive/CheckerVisitor.def" } } + + void PostVisit(CheckerContext &C, const Stmt *S) { + switch (S->getStmtClass()) { + default: + assert(false && "Unsupport statement."); + return; +#define POSTVISIT(NAME) \ +case Stmt::NAME ## Class:\ +static_cast<ImplClass*>(this)->\ +PostVisit ## NAME(C,static_cast<const NAME*>(S));\ +break; +#include "clang/Analysis/PathSensitive/CheckerVisitor.def" + } + } #define PREVISIT(NAME) \ void PreVisit ## NAME(CheckerContext &C, const NAME* S) {} #include "clang/Analysis/PathSensitive/CheckerVisitor.def" + +#define POSTVISIT(NAME) \ +void PostVisit ## NAME(CheckerContext &C, const NAME* S) {} +#include "clang/Analysis/PathSensitive/CheckerVisitor.def" }; } // end clang namespace #endif - diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index 08151e7d61..50d53df2b7 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -1575,25 +1575,25 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, ExplodedNode* Pred, continue; // Dispatch to the plug-in transfer function. - - unsigned size = Dst.size(); SaveOr OldHasGen(Builder->HasGeneratedNode); + Pred = *DI; // Dispatch to transfer function logic to handle the call itself. + // FIXME: Allow us to chain together transfer functions. assert(Builder && "GRStmtNodeBuilder must be defined."); + ExplodedNodeSet DstTmp; - // FIXME: Allow us to chain together transfer functions. - Pred = *DI; - - if (!EvalOSAtomic(Dst, *this, *Builder, CE, L, Pred)) - getTF().EvalCall(Dst, *this, *Builder, CE, L, Pred); + if (!EvalOSAtomic(DstTmp, *this, *Builder, CE, L, Pred)) + getTF().EvalCall(DstTmp, *this, *Builder, CE, L, Pred); // Handle the case where no nodes where generated. Auto-generate that // contains the updated state if we aren't generating sinks. - - if (!Builder->BuildSinks && Dst.size() == size && + if (!Builder->BuildSinks && DstTmp.empty() && !Builder->HasGeneratedNode) - MakeNode(Dst, CE, Pred, state); + MakeNode(DstTmp, CE, Pred, state); + + // Perform the post-condition check of the CallExpr. + CheckerVisit(CE, Dst, DstTmp, false); } } |