clang  8.0.0svn
AnalysisOrderChecker.cpp
Go to the documentation of this file.
1 //===- AnalysisOrderChecker - Print callbacks called ------------*- 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 checker prints callbacks that are called during analysis.
11 // This is required to ensure that callbacks are fired in order
12 // and do not duplicate or get lost.
13 // Feel free to extend this checker with any callback you need to check.
14 //
15 //===----------------------------------------------------------------------===//
16 
17 #include "ClangSACheckers.h"
18 #include "clang/AST/ExprCXX.h"
24 
25 using namespace clang;
26 using namespace ento;
27 
28 namespace {
29 
30 class AnalysisOrderChecker
31  : public Checker<check::PreStmt<CastExpr>,
32  check::PostStmt<CastExpr>,
33  check::PreStmt<ArraySubscriptExpr>,
34  check::PostStmt<ArraySubscriptExpr>,
35  check::PreStmt<CXXNewExpr>,
36  check::PostStmt<CXXNewExpr>,
37  check::PreStmt<OffsetOfExpr>,
38  check::PostStmt<OffsetOfExpr>,
39  check::PreCall,
40  check::PostCall,
41  check::EndFunction,
42  check::NewAllocator,
43  check::Bind,
44  check::RegionChanges,
45  check::LiveSymbols> {
46 
47  bool isCallbackEnabled(AnalyzerOptions &Opts, StringRef CallbackName) const {
48  return Opts.getBooleanOption("*", false, this) ||
49  Opts.getBooleanOption(CallbackName, false, this);
50  }
51 
52  bool isCallbackEnabled(CheckerContext &C, StringRef CallbackName) const {
53  AnalyzerOptions &Opts = C.getAnalysisManager().getAnalyzerOptions();
54  return isCallbackEnabled(Opts, CallbackName);
55  }
56 
57  bool isCallbackEnabled(ProgramStateRef State, StringRef CallbackName) const {
58  AnalyzerOptions &Opts = State->getStateManager().getOwningEngine()
59  ->getAnalysisManager().getAnalyzerOptions();
60  return isCallbackEnabled(Opts, CallbackName);
61  }
62 
63 public:
64  void checkPreStmt(const CastExpr *CE, CheckerContext &C) const {
65  if (isCallbackEnabled(C, "PreStmtCastExpr"))
66  llvm::errs() << "PreStmt<CastExpr> (Kind : " << CE->getCastKindName()
67  << ")\n";
68  }
69 
70  void checkPostStmt(const CastExpr *CE, CheckerContext &C) const {
71  if (isCallbackEnabled(C, "PostStmtCastExpr"))
72  llvm::errs() << "PostStmt<CastExpr> (Kind : " << CE->getCastKindName()
73  << ")\n";
74  }
75 
76  void checkPreStmt(const ArraySubscriptExpr *SubExpr,
77  CheckerContext &C) const {
78  if (isCallbackEnabled(C, "PreStmtArraySubscriptExpr"))
79  llvm::errs() << "PreStmt<ArraySubscriptExpr>\n";
80  }
81 
82  void checkPostStmt(const ArraySubscriptExpr *SubExpr,
83  CheckerContext &C) const {
84  if (isCallbackEnabled(C, "PostStmtArraySubscriptExpr"))
85  llvm::errs() << "PostStmt<ArraySubscriptExpr>\n";
86  }
87 
88  void checkPreStmt(const CXXNewExpr *NE, CheckerContext &C) const {
89  if (isCallbackEnabled(C, "PreStmtCXXNewExpr"))
90  llvm::errs() << "PreStmt<CXXNewExpr>\n";
91  }
92 
93  void checkPostStmt(const CXXNewExpr *NE, CheckerContext &C) const {
94  if (isCallbackEnabled(C, "PostStmtCXXNewExpr"))
95  llvm::errs() << "PostStmt<CXXNewExpr>\n";
96  }
97 
98  void checkPreStmt(const OffsetOfExpr *OOE, CheckerContext &C) const {
99  if (isCallbackEnabled(C, "PreStmtOffsetOfExpr"))
100  llvm::errs() << "PreStmt<OffsetOfExpr>\n";
101  }
102 
103  void checkPostStmt(const OffsetOfExpr *OOE, CheckerContext &C) const {
104  if (isCallbackEnabled(C, "PostStmtOffsetOfExpr"))
105  llvm::errs() << "PostStmt<OffsetOfExpr>\n";
106  }
107 
108  void checkPreCall(const CallEvent &Call, CheckerContext &C) const {
109  if (isCallbackEnabled(C, "PreCall")) {
110  llvm::errs() << "PreCall";
111  if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Call.getDecl()))
112  llvm::errs() << " (" << ND->getQualifiedNameAsString() << ')';
113  llvm::errs() << '\n';
114  }
115  }
116 
117  void checkPostCall(const CallEvent &Call, CheckerContext &C) const {
118  if (isCallbackEnabled(C, "PostCall")) {
119  llvm::errs() << "PostCall";
120  if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Call.getDecl()))
121  llvm::errs() << " (" << ND->getQualifiedNameAsString() << ')';
122  llvm::errs() << '\n';
123  }
124  }
125 
126  void checkEndFunction(const ReturnStmt *S, CheckerContext &C) const {
127  if (isCallbackEnabled(C, "EndFunction")) {
128  llvm::errs() << "EndFunction\nReturnStmt: " << (S ? "yes" : "no") << "\n";
129  if (!S)
130  return;
131 
132  llvm::errs() << "CFGElement: ";
133  CFGStmtMap *Map = C.getCurrentAnalysisDeclContext()->getCFGStmtMap();
134  CFGElement LastElement = Map->getBlock(S)->back();
135 
136  if (LastElement.getAs<CFGStmt>())
137  llvm::errs() << "CFGStmt\n";
138  else if (LastElement.getAs<CFGAutomaticObjDtor>())
139  llvm::errs() << "CFGAutomaticObjDtor\n";
140  }
141  }
142 
143  void checkNewAllocator(const CXXNewExpr *CNE, SVal Target,
144  CheckerContext &C) const {
145  if (isCallbackEnabled(C, "NewAllocator"))
146  llvm::errs() << "NewAllocator\n";
147  }
148 
149  void checkBind(SVal Loc, SVal Val, const Stmt *S, CheckerContext &C) const {
150  if (isCallbackEnabled(C, "Bind"))
151  llvm::errs() << "Bind\n";
152  }
153 
154  void checkLiveSymbols(ProgramStateRef State, SymbolReaper &SymReaper) const {
155  if (isCallbackEnabled(State, "LiveSymbols"))
156  llvm::errs() << "LiveSymbols\n";
157  }
158 
160  checkRegionChanges(ProgramStateRef State,
161  const InvalidatedSymbols *Invalidated,
162  ArrayRef<const MemRegion *> ExplicitRegions,
164  const LocationContext *LCtx, const CallEvent *Call) const {
165  if (isCallbackEnabled(State, "RegionChanges"))
166  llvm::errs() << "RegionChanges\n";
167  return State;
168  }
169 };
170 } // end anonymous namespace
171 
172 //===----------------------------------------------------------------------===//
173 // Registration.
174 //===----------------------------------------------------------------------===//
175 
176 void ento::registerAnalysisOrderChecker(CheckerManager &mgr) {
177  mgr.registerChecker<AnalysisOrderChecker>();
178 }
llvm::DenseSet< SymbolRef > InvalidatedSymbols
Definition: Store.h:52
Stmt - This represents one statement.
Definition: Stmt.h:66
bool getBooleanOption(StringRef Name, bool DefaultVal, const ento::CheckerBase *C=nullptr, bool SearchInParents=false)
Interprets an option&#39;s string value as a boolean.
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
Defines the clang::Expr interface and subclasses for C++ expressions.
LineState State
Represents C++ object destructor implicitly generated for automatic object or temporary bound to cons...
Definition: CFG.h:384
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition: Expr.h:2790
CFGBlock * getBlock(Stmt *S)
Returns the CFGBlock the specified Stmt* appears in.
Definition: CFGStmtMap.cpp:27
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
Definition: Stmt.h:1444
CFGElement back() const
Definition: CFG.h:701
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)"...
Definition: ExprCXX.h:1873
Optional< T > getAs() const
Convert to the specified CFGElement type, returning None if this CFGElement is not of the desired typ...
Definition: CFG.h:110
Dataflow Directional Tag Classes.
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition: Expr.h:2197
static const char * getCastKindName(CastKind CK)
Definition: Expr.cpp:1672
Represents a top-level expression in a basic block.
Definition: CFG.h:56
This represents a decl that may have a name.
Definition: Decl.h:248
OffsetOfExpr - [C99 7.17] - This represents an expression of the form offsetof(record-type, member-designator).
Definition: Expr.h:2002