diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2010-02-16 09:31:36 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2010-02-16 09:31:36 +0000 |
commit | fd035e6496665b1f1197868e21cb0a4594e8db6e (patch) | |
tree | 53010172e19c77ea447bcd89e117cda052ab52e0 /include/clang/Checker/PathSensitive/Checker.h | |
parent | 2fce988e86bc01829142e4362d4eff1af0925147 (diff) | |
download | FreeBSD-src-fd035e6496665b1f1197868e21cb0a4594e8db6e.zip FreeBSD-src-fd035e6496665b1f1197868e21cb0a4594e8db6e.tar.gz |
Update clang to r96341.
Diffstat (limited to 'include/clang/Checker/PathSensitive/Checker.h')
-rw-r--r-- | include/clang/Checker/PathSensitive/Checker.h | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/include/clang/Checker/PathSensitive/Checker.h b/include/clang/Checker/PathSensitive/Checker.h new file mode 100644 index 0000000..d498044 --- /dev/null +++ b/include/clang/Checker/PathSensitive/Checker.h @@ -0,0 +1,281 @@ +//== Checker.h - Abstract interface for checkers -----------------*- 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 Checker and CheckerVisitor, classes used for creating +// domain-specific checks. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_CHECKER +#define LLVM_CLANG_ANALYSIS_CHECKER +#include "clang/Analysis/Support/SaveAndRestore.h" +#include "clang/Checker/PathSensitive/GRCoreEngine.h" +#include "clang/Checker/PathSensitive/GRState.h" +#include "clang/Checker/PathSensitive/GRExprEngine.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/StmtObjC.h" + +//===----------------------------------------------------------------------===// +// Checker interface. +//===----------------------------------------------------------------------===// + +namespace clang { + class GRExprEngine; + +class CheckerContext { + ExplodedNodeSet &Dst; + GRStmtNodeBuilder &B; + GRExprEngine &Eng; + ExplodedNode *Pred; + SaveAndRestore<bool> OldSink; + SaveAndRestore<const void*> OldTag; + SaveAndRestore<ProgramPoint::Kind> OldPointKind; + SaveOr OldHasGen; + const GRState *ST; + const Stmt *statement; + const unsigned size; + bool DoneEvaluating; // FIXME: This is not a permanent API change. +public: + CheckerContext(ExplodedNodeSet &dst, GRStmtNodeBuilder &builder, + GRExprEngine &eng, ExplodedNode *pred, + const void *tag, ProgramPoint::Kind K, + 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), + ST(st), statement(stmt), size(Dst.size()) {} + + ~CheckerContext(); + + GRExprEngine &getEngine() { + return Eng; + } + + AnalysisManager &getAnalysisManager() { + return Eng.getAnalysisManager(); + } + + ConstraintManager &getConstraintManager() { + return Eng.getConstraintManager(); + } + + StoreManager &getStoreManager() { + return Eng.getStoreManager(); + } + + ExplodedNodeSet &getNodeSet() { return Dst; } + GRStmtNodeBuilder &getNodeBuilder() { return B; } + ExplodedNode *&getPredecessor() { return Pred; } + const GRState *getState() { return ST ? ST : B.GetState(Pred); } + + ASTContext &getASTContext() { + return Eng.getContext(); + } + + BugReporter &getBugReporter() { + return Eng.getBugReporter(); + } + + SourceManager &getSourceManager() { + return getBugReporter().getSourceManager(); + } + + ValueManager &getValueManager() { + return Eng.getValueManager(); + } + + SValuator &getSValuator() { + return Eng.getSValuator(); + } + + 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 GRState *state, ExplodedNode *pred, + bool autoTransition = true) { + assert(statement && "Only transitions with statements currently supported"); + ExplodedNode *N = GenerateNodeImpl(statement, state, pred, false); + if (N && autoTransition) + addTransition(N); + return N; + } + + 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; + } + + 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() || (ST && ST != 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; + } + + ExplodedNode *GenerateNodeImpl(const Stmt* stmt, const GRState *state, + ExplodedNode *pred, bool markAsSink) { + ExplodedNode *node = B.generateNode(stmt, state, pred); + if (markAsSink && node) + node->markAsSink(); + return node; + } +}; + +class Checker { +private: + friend class GRExprEngine; + + // FIXME: Remove the 'tag' option. + void GR_Visit(ExplodedNodeSet &Dst, + GRStmtNodeBuilder &Builder, + GRExprEngine &Eng, + const Stmt *S, + ExplodedNode *Pred, void *tag, bool isPrevisit) { + CheckerContext C(Dst, Builder, Eng, Pred, tag, + isPrevisit ? ProgramPoint::PreStmtKind : + ProgramPoint::PostStmtKind, S); + if (isPrevisit) + _PreVisit(C, S); + else + _PostVisit(C, S); + } + + bool GR_EvalNilReceiver(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder, + GRExprEngine &Eng, const ObjCMessageExpr *ME, + ExplodedNode *Pred, const GRState *state, void *tag) { + CheckerContext C(Dst, Builder, Eng, Pred, tag, ProgramPoint::PostStmtKind, + ME, state); + return EvalNilReceiver(C, ME); + } + + bool GR_EvalCallExpr(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder, + GRExprEngine &Eng, const CallExpr *CE, + ExplodedNode *Pred, void *tag) { + CheckerContext C(Dst, Builder, Eng, Pred, tag, ProgramPoint::PostStmtKind, + CE); + return EvalCallExpr(C, CE); + } + + // 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 ? ProgramPoint::PreStmtKind : + ProgramPoint::PostStmtKind, StoreE); + 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, S, state); + VisitLocation(C, S, location); + } + + void GR_EvalDeadSymbols(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder, + GRExprEngine &Eng, const Stmt *S, ExplodedNode *Pred, + SymbolReaper &SymReaper, void *tag) { + CheckerContext C(Dst, Builder, Eng, Pred, tag, + ProgramPoint::PostPurgeDeadSymbolsKind, S); + EvalDeadSymbols(C, S, SymReaper); + } + +public: + virtual ~Checker(); + 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 EvalDeadSymbols(CheckerContext &C, const Stmt *S, + SymbolReaper &SymReaper) {} + virtual void EvalEndPath(GREndPathNodeBuilder &B, void *tag, + GRExprEngine &Eng) {} + + virtual void VisitBranchCondition(GRBranchNodeBuilder &Builder, + GRExprEngine &Eng, + Stmt *Condition, void *tag) {} + + virtual bool EvalNilReceiver(CheckerContext &C, const ObjCMessageExpr *ME) { + return false; + } + + virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE) { + return false; + } + + virtual const GRState *EvalAssume(const GRState *state, SVal Cond, + bool Assumption) { + return state; + } +}; +} // end clang namespace + +#endif + |