CheckerContext.h revision 3f5e8d87dbf449d8b39fe96068415428594d370e
16bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis//== CheckerContext.h - Context info for path-sensitive checkers--*- C++ -*--=//
26bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis//
36bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis//                     The LLVM Compiler Infrastructure
46bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis//
56bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis// This file is distributed under the University of Illinois Open Source
66bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis// License. See LICENSE.TXT for details.
76bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis//
86bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
96bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis//
106bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis//  This file defines CheckerContext that provides contextual info for
116bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis// path-sensitive checkers.
126bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis//
136bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
146bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
156bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis#ifndef LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT
166bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis#define LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT
176bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
186bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis#include "clang/Analysis/Support/SaveAndRestore.h"
196bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
206bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
216bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidisnamespace clang {
226bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
236bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidisnamespace ento {
246bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
256bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidisclass CheckerContext {
266bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  ExplodedNodeSet &Dst;
276bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  StmtNodeBuilder &B;
286bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  ExprEngine &Eng;
296bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  ExplodedNode *Pred;
306bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  SaveAndRestore<bool> OldSink;
316bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  SaveOr OldHasGen;
323f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks  const ProgramPoint Location;
3318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek  const ProgramState *ST;
346bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  const unsigned size;
356bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidispublic:
366bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  bool *respondsToCallback;
376bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidispublic:
3818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek  CheckerContext(ExplodedNodeSet &dst,
3918c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek                 StmtNodeBuilder &builder,
4018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek                 ExprEngine &eng,
4118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek                 ExplodedNode *pred,
423f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks                 const ProgramPoint &loc,
436bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis                 bool *respondsToCB = 0,
4418c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek                 const ProgramState *st = 0)
4518c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek    : Dst(dst),
4618c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek      B(builder),
4718c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek      Eng(eng),
4818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek      Pred(pred),
496bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis      OldSink(B.BuildSinks),
506bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis      OldHasGen(B.hasGeneratedNode),
513f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks      Location(loc),
5218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek      ST(st),
5318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek      size(Dst.size()),
546bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis      respondsToCallback(respondsToCB) {}
556bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
566bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  ~CheckerContext();
576bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
586bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  ExprEngine &getEngine() {
596bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return Eng;
606bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
616bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
626bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  AnalysisManager &getAnalysisManager() {
636bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return Eng.getAnalysisManager();
646bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
656bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
666bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  ConstraintManager &getConstraintManager() {
676bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return Eng.getConstraintManager();
686bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
696bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
706bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  StoreManager &getStoreManager() {
716bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return Eng.getStoreManager();
726bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
736bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
746bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  ExplodedNodeSet &getNodeSet() { return Dst; }
756bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  ExplodedNode *&getPredecessor() { return Pred; }
7618c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek  const ProgramState *getState() { return ST ? ST : Pred->getState(); }
776bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
785d0ea6d62e076c776ddad028c4eb615783be1323Anna Zaks  /// \brief Returns the number of times the current block has been visited
795d0ea6d62e076c776ddad028c4eb615783be1323Anna Zaks  /// along the analyzed path.
805d0ea6d62e076c776ddad028c4eb615783be1323Anna Zaks  unsigned getCurrentBlockCount() {return B.getCurrentBlockCount();}
815d0ea6d62e076c776ddad028c4eb615783be1323Anna Zaks
826bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  ASTContext &getASTContext() {
836bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return Eng.getContext();
846bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
856bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
866bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  BugReporter &getBugReporter() {
876bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return Eng.getBugReporter();
886bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
896bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
906bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  SourceManager &getSourceManager() {
916bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return getBugReporter().getSourceManager();
926bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
936bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
946bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  SValBuilder &getSValBuilder() {
956bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return Eng.getSValBuilder();
966bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
976bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
983f10e32b15e54f507aed90cb72d73c7acaa500bbAnna Zaks  SymbolManager &getSymbolManager() {
993f10e32b15e54f507aed90cb72d73c7acaa500bbAnna Zaks    return getSValBuilder().getSymbolManager();
1003f10e32b15e54f507aed90cb72d73c7acaa500bbAnna Zaks  }
1013f10e32b15e54f507aed90cb72d73c7acaa500bbAnna Zaks
10217a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose  bool isObjCGCEnabled() {
10317a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose    return Eng.isObjCGCEnabled();
10417a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose  }
10517a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose
1068ba721428af297e540fb40b176eeeea0ee010c1fAnna Zaks  /// \brief Generate a default checker node (containing checker tag but no
1078ba721428af297e540fb40b176eeeea0ee010c1fAnna Zaks  /// checker state changes).
1086bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  ExplodedNode *generateNode(bool autoTransition = true) {
10950f3cade2a87bda005ae08d42b51c5b960b07779Anna Zaks    return generateNode(getState(), autoTransition);
1106bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
1116bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
1128ba721428af297e540fb40b176eeeea0ee010c1fAnna Zaks  /// \brief Generate a new checker node with the given predecessor.
1138ba721428af297e540fb40b176eeeea0ee010c1fAnna Zaks  /// Allows checkers to generate a chain of nodes.
11418c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek  ExplodedNode *generateNode(const ProgramState *state,
11518c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek                             ExplodedNode *pred,
116cbb7add8d7e3f868a6695a601e45fc13257bd9f5Anna Zaks                             const ProgramPointTag *tag = 0,
1176bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis                             bool autoTransition = true) {
118cbb7add8d7e3f868a6695a601e45fc13257bd9f5Anna Zaks    ExplodedNode *N = generateNodeImpl(state, false, pred, tag);
1196bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    if (N && autoTransition)
1206bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis      addTransition(N);
1216bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return N;
1226bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
1236bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
1248ba721428af297e540fb40b176eeeea0ee010c1fAnna Zaks  /// \brief Generate a new checker node.
12518c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek  ExplodedNode *generateNode(const ProgramState *state,
12618c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek                             bool autoTransition = true,
127ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek                             const ProgramPointTag *tag = 0) {
12850f3cade2a87bda005ae08d42b51c5b960b07779Anna Zaks    ExplodedNode *N = generateNodeImpl(state, false, 0, tag);
1296bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    if (N && autoTransition)
1306bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis      addTransition(N);
1316bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return N;
1326bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
1336bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
1348ba721428af297e540fb40b176eeeea0ee010c1fAnna Zaks  /// \brief Generate a sink node. Generating sink stops exploration of the
1358ba721428af297e540fb40b176eeeea0ee010c1fAnna Zaks  /// given path.
13618c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek  ExplodedNode *generateSink(const ProgramState *state = 0) {
13750f3cade2a87bda005ae08d42b51c5b960b07779Anna Zaks    return generateNodeImpl(state ? state : getState(), true);
1386bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
1396bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
1406bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  void addTransition(ExplodedNode *node) {
1416bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    Dst.Add(node);
1426bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
1436bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
14418c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek  void addTransition(const ProgramState *state,
14518c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek                     const ProgramPointTag *tag = 0) {
1466bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    assert(state);
1476bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    // If the 'state' is not new, we need to check if the cached state 'ST'
1486bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    // is new.
1490e89061a399bae32f0eca5b85658ad66a58c504dAnna Zaks    if (state != getState() || (ST && ST != Pred->getState()))
1506bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis      // state is new or equals to ST.
1516bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis      generateNode(state, true, tag);
1526bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    else
1536bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis      Dst.Add(Pred);
1546bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
1556bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
1566bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  void EmitReport(BugReport *R) {
1576bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    Eng.getBugReporter().EmitReport(R);
1586bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
1596bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
1606bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  AnalysisContext *getCurrentAnalysisContext() const {
1616bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return Pred->getLocationContext()->getAnalysisContext();
1626bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
1636bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
1646bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidisprivate:
16550f3cade2a87bda005ae08d42b51c5b960b07779Anna Zaks  ExplodedNode *generateNodeImpl(const ProgramState *state,
16618c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek                                 bool markAsSink,
16750f3cade2a87bda005ae08d42b51c5b960b07779Anna Zaks                                 ExplodedNode *pred = 0,
16850f3cade2a87bda005ae08d42b51c5b960b07779Anna Zaks                                 const ProgramPointTag *tag = 0) {
1693f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks
1703f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks    ExplodedNode *node = B.generateNode(tag ? Location.withTag(tag) : Location,
1713f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks                                        state,
1723f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks                                        pred ? pred : Pred);
1736bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    if (markAsSink && node)
1746bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis      node->markAsSink();
1756bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis    return node;
1766bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis  }
1776bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis};
1786bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
1796bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis} // end GR namespace
1806bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
1816bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis} // end clang namespace
1826bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis
1836bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis#endif
184