23 #include "llvm/Support/ErrorHandling.h"
25 using namespace clang;
30 class AnalysisOrderChecker
32 check::PreStmt<CastExpr>, check::PostStmt<CastExpr>,
33 check::PreStmt<ArraySubscriptExpr>,
34 check::PostStmt<ArraySubscriptExpr>, check::PreStmt<CXXNewExpr>,
35 check::PostStmt<CXXNewExpr>, check::PreStmt<CXXDeleteExpr>,
36 check::PostStmt<CXXDeleteExpr>, check::PreStmt<CXXConstructExpr>,
37 check::PostStmt<CXXConstructExpr>, check::PreStmt<OffsetOfExpr>,
38 check::PostStmt<OffsetOfExpr>, check::PreCall, check::PostCall,
39 check::EndFunction, check::EndAnalysis, check::NewAllocator,
40 check::Bind, check::PointerEscape, check::RegionChanges,
41 check::LiveSymbols, eval::Call> {
44 StringRef CallbackName)
const {
49 bool isCallbackEnabled(CheckerContext &C, StringRef CallbackName)
const {
51 return isCallbackEnabled(Opts, CallbackName);
56 .getAnalysisManager().getAnalyzerOptions();
57 return isCallbackEnabled(Opts, CallbackName);
61 void checkPreStmt(
const CastExpr *CE, CheckerContext &C)
const {
62 if (isCallbackEnabled(C,
"PreStmtCastExpr"))
67 void checkPostStmt(
const CastExpr *CE, CheckerContext &C)
const {
68 if (isCallbackEnabled(C,
"PostStmtCastExpr"))
74 CheckerContext &C)
const {
75 if (isCallbackEnabled(C,
"PreStmtArraySubscriptExpr"))
76 llvm::errs() <<
"PreStmt<ArraySubscriptExpr>\n";
80 CheckerContext &C)
const {
81 if (isCallbackEnabled(C,
"PostStmtArraySubscriptExpr"))
82 llvm::errs() <<
"PostStmt<ArraySubscriptExpr>\n";
85 void checkPreStmt(
const CXXNewExpr *
NE, CheckerContext &C)
const {
86 if (isCallbackEnabled(C,
"PreStmtCXXNewExpr"))
87 llvm::errs() <<
"PreStmt<CXXNewExpr>\n";
90 void checkPostStmt(
const CXXNewExpr *
NE, CheckerContext &C)
const {
91 if (isCallbackEnabled(C,
"PostStmtCXXNewExpr"))
92 llvm::errs() <<
"PostStmt<CXXNewExpr>\n";
96 if (isCallbackEnabled(C,
"PreStmtCXXDeleteExpr"))
97 llvm::errs() <<
"PreStmt<CXXDeleteExpr>\n";
101 if (isCallbackEnabled(C,
"PostStmtCXXDeleteExpr"))
102 llvm::errs() <<
"PostStmt<CXXDeleteExpr>\n";
106 if (isCallbackEnabled(C,
"PreStmtCXXConstructExpr"))
107 llvm::errs() <<
"PreStmt<CXXConstructExpr>\n";
111 if (isCallbackEnabled(C,
"PostStmtCXXConstructExpr"))
112 llvm::errs() <<
"PostStmt<CXXConstructExpr>\n";
115 void checkPreStmt(
const OffsetOfExpr *OOE, CheckerContext &C)
const {
116 if (isCallbackEnabled(C,
"PreStmtOffsetOfExpr"))
117 llvm::errs() <<
"PreStmt<OffsetOfExpr>\n";
120 void checkPostStmt(
const OffsetOfExpr *OOE, CheckerContext &C)
const {
121 if (isCallbackEnabled(C,
"PostStmtOffsetOfExpr"))
122 llvm::errs() <<
"PostStmt<OffsetOfExpr>\n";
125 bool evalCall(
const CallEvent &Call, CheckerContext &C)
const {
126 if (isCallbackEnabled(C,
"EvalCall")) {
127 llvm::errs() <<
"EvalCall";
128 if (
const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(
Call.getDecl()))
129 llvm::errs() <<
" (" << ND->getQualifiedNameAsString() <<
')';
130 llvm::errs() <<
" {argno: " <<
Call.getNumArgs() <<
'}';
131 llvm::errs() <<
" [" <<
Call.getKindAsString() <<
']';
132 llvm::errs() <<
'\n';
138 void checkPreCall(
const CallEvent &Call, CheckerContext &C)
const {
139 if (isCallbackEnabled(C,
"PreCall")) {
140 llvm::errs() <<
"PreCall";
141 if (
const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(
Call.getDecl()))
142 llvm::errs() <<
" (" << ND->getQualifiedNameAsString() <<
')';
143 llvm::errs() <<
" [" <<
Call.getKindAsString() <<
']';
144 llvm::errs() <<
'\n';
148 void checkPostCall(
const CallEvent &Call, CheckerContext &C)
const {
149 if (isCallbackEnabled(C,
"PostCall")) {
150 llvm::errs() <<
"PostCall";
151 if (
const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(
Call.getDecl()))
152 llvm::errs() <<
" (" << ND->getQualifiedNameAsString() <<
')';
153 llvm::errs() <<
" [" <<
Call.getKindAsString() <<
']';
154 llvm::errs() <<
'\n';
158 void checkEndFunction(
const ReturnStmt *S, CheckerContext &C)
const {
159 if (isCallbackEnabled(C,
"EndFunction")) {
160 llvm::errs() <<
"EndFunction\nReturnStmt: " << (S ?
"yes" :
"no") <<
"\n";
164 llvm::errs() <<
"CFGElement: ";
165 CFGStmtMap *Map =
C.getCurrentAnalysisDeclContext()->getCFGStmtMap();
169 llvm::errs() <<
"CFGStmt\n";
171 llvm::errs() <<
"CFGAutomaticObjDtor\n";
175 void checkEndAnalysis(ExplodedGraph &G, BugReporter &BR,
176 ExprEngine &Eng)
const {
177 if (isCallbackEnabled(BR.getAnalyzerOptions(),
"EndAnalysis"))
178 llvm::errs() <<
"EndAnalysis\n";
181 void checkNewAllocator(
const CXXAllocatorCall &Call,
182 CheckerContext &C)
const {
183 if (isCallbackEnabled(C,
"NewAllocator"))
184 llvm::errs() <<
"NewAllocator\n";
187 void checkBind(SVal Loc, SVal Val,
const Stmt *S, CheckerContext &C)
const {
188 if (isCallbackEnabled(C,
"Bind"))
189 llvm::errs() <<
"Bind\n";
193 if (isCallbackEnabled(
State,
"LiveSymbols"))
194 llvm::errs() <<
"LiveSymbols\n";
203 if (isCallbackEnabled(
State,
"RegionChanges"))
204 llvm::errs() <<
"RegionChanges\n";
210 const CallEvent *Call,
212 if (isCallbackEnabled(
State,
"PointerEscape"))
213 llvm::errs() <<
"PointerEscape\n";
223 void ento::registerAnalysisOrderChecker(CheckerManager &mgr) {
224 mgr.registerChecker<AnalysisOrderChecker>();
227 bool ento::shouldRegisterAnalysisOrderChecker(
const CheckerManager &mgr) {