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   ExprEngine &Eng;
     28   ExplodedNode *Pred;
     29   const ProgramPoint Location;
     30   const ProgramState *ST;
     31   const unsigned size;
     32   // TODO: Use global context.
     33   NodeBuilderContext Ctx;
     34   NodeBuilder &NB;
     35 public:
     36   bool *respondsToCallback;
     37 public:
     38   CheckerContext(ExplodedNodeSet &dst,
     39                  NodeBuilder &builder,
     40                  ExprEngine &eng,
     41                  ExplodedNode *pred,
     42                  const ProgramPoint &loc,
     43                  bool *respondsToCB = 0,
     44                  const ProgramState *st = 0)
     45     : Dst(dst),
     46       Eng(eng),
     47       Pred(pred),
     48       Location(loc),
     49       ST(st),
     50       size(Dst.size()),
     51       Ctx(builder.C.Eng, builder.getBlock(), pred),
     52       NB(builder),
     53       respondsToCallback(respondsToCB) {
     54     assert(!(ST && ST != Pred->getState()));
     55   }
     56 
     57   ~CheckerContext();
     58 
     59   ExprEngine &getEngine() {
     60     return Eng;
     61   }
     62 
     63   AnalysisManager &getAnalysisManager() {
     64     return Eng.getAnalysisManager();
     65   }
     66 
     67   ConstraintManager &getConstraintManager() {
     68     return Eng.getConstraintManager();
     69   }
     70 
     71   StoreManager &getStoreManager() {
     72     return Eng.getStoreManager();
     73   }
     74 
     75   ExplodedNode *&getPredecessor() { return Pred; }
     76   const ProgramState *getState() { return ST ? ST : Pred->getState(); }
     77 
     78   /// \brief Returns the number of times the current block has been visited
     79   /// along the analyzed path.
     80   unsigned getCurrentBlockCount() {return NB.getCurrentBlockCount();}
     81 
     82   ASTContext &getASTContext() {
     83     return Eng.getContext();
     84   }
     85 
     86   BugReporter &getBugReporter() {
     87     return Eng.getBugReporter();
     88   }
     89 
     90   SourceManager &getSourceManager() {
     91     return getBugReporter().getSourceManager();
     92   }
     93 
     94   SValBuilder &getSValBuilder() {
     95     return Eng.getSValBuilder();
     96   }
     97 
     98   SymbolManager &getSymbolManager() {
     99     return getSValBuilder().getSymbolManager();
    100   }
    101 
    102   bool isObjCGCEnabled() {
    103     return Eng.isObjCGCEnabled();
    104   }
    105 
    106   /// \brief Generate a default checker node (containing checker tag but no
    107   /// checker state changes).
    108   ExplodedNode *generateNode(bool autoTransition = true) {
    109     return generateNode(getState(), autoTransition);
    110   }
    111 
    112   /// \brief Generate a new checker node with the given predecessor.
    113   /// Allows checkers to generate a chain of nodes.
    114   ExplodedNode *generateNode(const ProgramState *state,
    115                              ExplodedNode *pred,
    116                              const ProgramPointTag *tag = 0,
    117                              bool autoTransition = true,
    118                              bool isSink = false) {
    119     ExplodedNode *N = generateNodeImpl(state, isSink, pred, tag);
    120     return N;
    121   }
    122 
    123   /// \brief Generate a new checker node.
    124   ExplodedNode *generateNode(const ProgramState *state,
    125                              bool autoTransition = true,
    126                              const ProgramPointTag *tag = 0) {
    127     ExplodedNode *N = generateNodeImpl(state, false, 0, tag);
    128     return N;
    129   }
    130 
    131   /// \brief Generate a sink node. Generating sink stops exploration of the
    132   /// given path.
    133   ExplodedNode *generateSink(const ProgramState *state = 0) {
    134     return generateNodeImpl(state ? state : getState(), true);
    135   }
    136 
    137   void addTransition(const ProgramState *state,
    138                      const ProgramPointTag *tag = 0) {
    139     assert(state);
    140     // If the 'state' is not new, we need to check if the cached state 'ST'
    141     // is new.
    142     if (state != getState())
    143       generateNode(state, true, tag);
    144   }
    145 
    146   void EmitReport(BugReport *R) {
    147     Eng.getBugReporter().EmitReport(R);
    148   }
    149 
    150   AnalysisContext *getCurrentAnalysisContext() const {
    151     return Pred->getLocationContext()->getAnalysisContext();
    152   }
    153 
    154 private:
    155   ExplodedNode *generateNodeImpl(const ProgramState *state,
    156                                  bool markAsSink,
    157                                  ExplodedNode *pred = 0,
    158                                  const ProgramPointTag *tag = 0) {
    159 
    160     ExplodedNode *node = NB.generateNode(tag ? Location.withTag(tag) : Location,
    161                                         state,
    162                                         pred ? pred : Pred, markAsSink);
    163     return node;
    164   }
    165 };
    166 
    167 } // end GR namespace
    168 
    169 } // end clang namespace
    170 
    171 #endif
    172