Home | History | Annotate | Download | only in PathSensitive
      1 //== CheckerContext.h - Context info for path-sensitive checkers--*- C++ -*--=//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 //  This file defines CheckerContext that provides contextual info for
     11 // path-sensitive checkers.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #ifndef LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT
     16 #define LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT
     17 
     18 #include "clang/Analysis/Support/SaveAndRestore.h"
     19 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
     20 
     21 namespace clang {
     22 
     23 namespace ento {
     24 
     25 class CheckerContext {
     26   ExplodedNodeSet &Dst;
     27   StmtNodeBuilder &B;
     28   ExprEngine &Eng;
     29   ExplodedNode *Pred;
     30   SaveAndRestore<bool> OldSink;
     31   const void *checkerTag;
     32   SaveAndRestore<ProgramPoint::Kind> OldPointKind;
     33   SaveOr OldHasGen;
     34   const GRState *ST;
     35   const Stmt *statement;
     36   const unsigned size;
     37 public:
     38   bool *respondsToCallback;
     39 public:
     40   CheckerContext(ExplodedNodeSet &dst, StmtNodeBuilder &builder,
     41                  ExprEngine &eng, ExplodedNode *pred,
     42                  const void *tag, ProgramPoint::Kind K,
     43                  bool *respondsToCB = 0,
     44                  const Stmt *stmt = 0, const GRState *st = 0)
     45     : Dst(dst), B(builder), Eng(eng), Pred(pred),
     46       OldSink(B.BuildSinks),
     47       checkerTag(tag),
     48       OldPointKind(B.PointKind, K),
     49       OldHasGen(B.hasGeneratedNode),
     50       ST(st), statement(stmt), size(Dst.size()),
     51       respondsToCallback(respondsToCB) {}
     52 
     53   ~CheckerContext();
     54 
     55   ExprEngine &getEngine() {
     56     return Eng;
     57   }
     58 
     59   AnalysisManager &getAnalysisManager() {
     60     return Eng.getAnalysisManager();
     61   }
     62 
     63   ConstraintManager &getConstraintManager() {
     64     return Eng.getConstraintManager();
     65   }
     66 
     67   StoreManager &getStoreManager() {
     68     return Eng.getStoreManager();
     69   }
     70 
     71   ExplodedNodeSet &getNodeSet() { return Dst; }
     72   StmtNodeBuilder &getNodeBuilder() { return B; }
     73   ExplodedNode *&getPredecessor() { return Pred; }
     74   const GRState *getState() { return ST ? ST : B.GetState(Pred); }
     75   const Stmt *getStmt() const { return statement; }
     76 
     77   ASTContext &getASTContext() {
     78     return Eng.getContext();
     79   }
     80 
     81   BugReporter &getBugReporter() {
     82     return Eng.getBugReporter();
     83   }
     84 
     85   SourceManager &getSourceManager() {
     86     return getBugReporter().getSourceManager();
     87   }
     88 
     89   SValBuilder &getSValBuilder() {
     90     return Eng.getSValBuilder();
     91   }
     92 
     93   ExplodedNode *generateNode(bool autoTransition = true) {
     94     assert(statement && "Only transitions with statements currently supported");
     95     ExplodedNode *N = generateNodeImpl(statement, getState(), false,
     96                                        checkerTag);
     97     if (N && autoTransition)
     98       Dst.Add(N);
     99     return N;
    100   }
    101 
    102   ExplodedNode *generateNode(const Stmt *stmt, const GRState *state,
    103                              bool autoTransition = true, const void *tag = 0) {
    104     assert(state);
    105     ExplodedNode *N = generateNodeImpl(stmt, state, false,
    106                                        tag ? tag : checkerTag);
    107     if (N && autoTransition)
    108       addTransition(N);
    109     return N;
    110   }
    111 
    112   ExplodedNode *generateNode(const GRState *state, ExplodedNode *pred,
    113                              bool autoTransition = true) {
    114    assert(statement && "Only transitions with statements currently supported");
    115     ExplodedNode *N = generateNodeImpl(statement, state, pred, false);
    116     if (N && autoTransition)
    117       addTransition(N);
    118     return N;
    119   }
    120 
    121   ExplodedNode *generateNode(const GRState *state, bool autoTransition = true,
    122                              const void *tag = 0) {
    123     assert(statement && "Only transitions with statements currently supported");
    124     ExplodedNode *N = generateNodeImpl(statement, state, false,
    125                                        tag ? tag : checkerTag);
    126     if (N && autoTransition)
    127       addTransition(N);
    128     return N;
    129   }
    130 
    131   ExplodedNode *generateSink(const Stmt *stmt, const GRState *state = 0) {
    132     return generateNodeImpl(stmt, state ? state : getState(), true,
    133                             checkerTag);
    134   }
    135 
    136   ExplodedNode *generateSink(const GRState *state = 0) {
    137     assert(statement && "Only transitions with statements currently supported");
    138     return generateNodeImpl(statement, state ? state : getState(), true,
    139                             checkerTag);
    140   }
    141 
    142   void addTransition(ExplodedNode *node) {
    143     Dst.Add(node);
    144   }
    145 
    146   void addTransition(const GRState *state, const void *tag = 0) {
    147     assert(state);
    148     // If the 'state' is not new, we need to check if the cached state 'ST'
    149     // is new.
    150     if (state != getState() || (ST && ST != B.GetState(Pred)))
    151       // state is new or equals to ST.
    152       generateNode(state, true, tag);
    153     else
    154       Dst.Add(Pred);
    155   }
    156 
    157   void EmitReport(BugReport *R) {
    158     Eng.getBugReporter().EmitReport(R);
    159   }
    160 
    161   AnalysisContext *getCurrentAnalysisContext() const {
    162     return Pred->getLocationContext()->getAnalysisContext();
    163   }
    164 
    165 private:
    166   ExplodedNode *generateNodeImpl(const Stmt* stmt, const GRState *state,
    167                              bool markAsSink, const void *tag) {
    168     ExplodedNode *node = B.generateNode(stmt, state, Pred, tag);
    169     if (markAsSink && node)
    170       node->markAsSink();
    171     return node;
    172   }
    173 
    174   ExplodedNode *generateNodeImpl(const Stmt* stmt, const GRState *state,
    175                                  ExplodedNode *pred, bool markAsSink) {
    176    ExplodedNode *node = B.generateNode(stmt, state, pred, checkerTag);
    177     if (markAsSink && node)
    178       node->markAsSink();
    179     return node;
    180   }
    181 };
    182 
    183 } // end GR namespace
    184 
    185 } // end clang namespace
    186 
    187 #endif
    188