blob: f9cf97e5083574e308454f2aacc0080437283838 [file] [log] [blame]
Aleksei Sidorin29afb192016-09-01 13:55:38 +00001//===- 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"
Artem Dergacheve941dae2018-01-18 00:53:50 +000018#include "clang/AST/ExprCXX.h"
Reka Kovacs38679fd2018-08-02 22:31:03 +000019#include "clang/Analysis/CFGStmtMap.h"
Aleksei Sidorin29afb192016-09-01 13:55:38 +000020#include "clang/StaticAnalyzer/Core/Checker.h"
21#include "clang/StaticAnalyzer/Core/CheckerManager.h"
Artem Dergacheve941dae2018-01-18 00:53:50 +000022#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
Aleksei Sidorin29afb192016-09-01 13:55:38 +000023#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
24
25using namespace clang;
26using namespace ento;
27
28namespace {
29
Artem Dergachev647804a2017-03-28 15:43:26 +000030class AnalysisOrderChecker
31 : public Checker<check::PreStmt<CastExpr>,
32 check::PostStmt<CastExpr>,
33 check::PreStmt<ArraySubscriptExpr>,
34 check::PostStmt<ArraySubscriptExpr>,
Artem Dergacheve941dae2018-01-18 00:53:50 +000035 check::PreStmt<CXXNewExpr>,
36 check::PostStmt<CXXNewExpr>,
Artem Dergachev4b0d1602018-02-10 00:55:49 +000037 check::PreStmt<OffsetOfExpr>,
38 check::PostStmt<OffsetOfExpr>,
Artem Dergacheve941dae2018-01-18 00:53:50 +000039 check::PreCall,
40 check::PostCall,
Reka Kovacs38679fd2018-08-02 22:31:03 +000041 check::EndFunction,
Artem Dergacheve941dae2018-01-18 00:53:50 +000042 check::NewAllocator,
Artem Dergachev647804a2017-03-28 15:43:26 +000043 check::Bind,
George Karpenkovfb4acff2018-02-02 02:19:43 +000044 check::RegionChanges,
45 check::LiveSymbols> {
46
Artem Dergachev647804a2017-03-28 15:43:26 +000047 bool isCallbackEnabled(AnalyzerOptions &Opts, StringRef CallbackName) const {
Kristof Umann0a1f91c2018-11-05 03:50:37 +000048 return Opts.getCheckerBooleanOption("*", false, this) ||
49 Opts.getCheckerBooleanOption(CallbackName, false, this);
Aleksei Sidorin29afb192016-09-01 13:55:38 +000050 }
51
Artem Dergachev647804a2017-03-28 15:43:26 +000052 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
Aleksei Sidorin29afb192016-09-01 13:55:38 +000063public:
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 }
Anna Zaksfb859a92016-10-04 20:49:31 +000075
Artem Dergachev647804a2017-03-28 15:43:26 +000076 void checkPreStmt(const ArraySubscriptExpr *SubExpr,
77 CheckerContext &C) const {
Anna Zaksfb859a92016-10-04 20:49:31 +000078 if (isCallbackEnabled(C, "PreStmtArraySubscriptExpr"))
79 llvm::errs() << "PreStmt<ArraySubscriptExpr>\n";
80 }
81
Artem Dergachev647804a2017-03-28 15:43:26 +000082 void checkPostStmt(const ArraySubscriptExpr *SubExpr,
83 CheckerContext &C) const {
Anna Zaksfb859a92016-10-04 20:49:31 +000084 if (isCallbackEnabled(C, "PostStmtArraySubscriptExpr"))
85 llvm::errs() << "PostStmt<ArraySubscriptExpr>\n";
86 }
Artem Dergachev647804a2017-03-28 15:43:26 +000087
Artem Dergacheve941dae2018-01-18 00:53:50 +000088 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
Artem Dergachev4b0d1602018-02-10 00:55:49 +000098 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
Artem Dergacheve941dae2018-01-18 00:53:50 +0000108 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
Reka Kovacs38679fd2018-08-02 22:31:03 +0000126 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
Artem Dergacheve941dae2018-01-18 00:53:50 +0000143 void checkNewAllocator(const CXXNewExpr *CNE, SVal Target,
144 CheckerContext &C) const {
145 if (isCallbackEnabled(C, "NewAllocator"))
146 llvm::errs() << "NewAllocator\n";
147 }
148
Artem Dergachev647804a2017-03-28 15:43:26 +0000149 void checkBind(SVal Loc, SVal Val, const Stmt *S, CheckerContext &C) const {
150 if (isCallbackEnabled(C, "Bind"))
151 llvm::errs() << "Bind\n";
152 }
153
George Karpenkovfb4acff2018-02-02 02:19:43 +0000154 void checkLiveSymbols(ProgramStateRef State, SymbolReaper &SymReaper) const {
155 if (isCallbackEnabled(State, "LiveSymbols"))
156 llvm::errs() << "LiveSymbols\n";
157 }
158
Artem Dergachev647804a2017-03-28 15:43:26 +0000159 ProgramStateRef
160 checkRegionChanges(ProgramStateRef State,
161 const InvalidatedSymbols *Invalidated,
162 ArrayRef<const MemRegion *> ExplicitRegions,
163 ArrayRef<const MemRegion *> Regions,
164 const LocationContext *LCtx, const CallEvent *Call) const {
165 if (isCallbackEnabled(State, "RegionChanges"))
166 llvm::errs() << "RegionChanges\n";
167 return State;
168 }
Aleksei Sidorin29afb192016-09-01 13:55:38 +0000169};
Artem Dergachev647804a2017-03-28 15:43:26 +0000170} // end anonymous namespace
Aleksei Sidorin29afb192016-09-01 13:55:38 +0000171
172//===----------------------------------------------------------------------===//
173// Registration.
174//===----------------------------------------------------------------------===//
175
176void ento::registerAnalysisOrderChecker(CheckerManager &mgr) {
177 mgr.registerChecker<AnalysisOrderChecker>();
178}