/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- AnalysisOrderChecker - Print callbacks called ------------*- C++ -*-===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // This checker prints callbacks that are called during analysis. |
10 | | // This is required to ensure that callbacks are fired in order |
11 | | // and do not duplicate or get lost. |
12 | | // Feel free to extend this checker with any callback you need to check. |
13 | | // |
14 | | //===----------------------------------------------------------------------===// |
15 | | |
16 | | #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" |
17 | | #include "clang/AST/ExprCXX.h" |
18 | | #include "clang/Analysis/CFGStmtMap.h" |
19 | | #include "clang/StaticAnalyzer/Core/Checker.h" |
20 | | #include "clang/StaticAnalyzer/Core/CheckerManager.h" |
21 | | #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" |
22 | | #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" |
23 | | |
24 | | using namespace clang; |
25 | | using namespace ento; |
26 | | |
27 | | namespace { |
28 | | |
29 | | class AnalysisOrderChecker |
30 | | : public Checker<check::PreStmt<CastExpr>, |
31 | | check::PostStmt<CastExpr>, |
32 | | check::PreStmt<ArraySubscriptExpr>, |
33 | | check::PostStmt<ArraySubscriptExpr>, |
34 | | check::PreStmt<CXXNewExpr>, |
35 | | check::PostStmt<CXXNewExpr>, |
36 | | check::PreStmt<OffsetOfExpr>, |
37 | | check::PostStmt<OffsetOfExpr>, |
38 | | check::PreCall, |
39 | | check::PostCall, |
40 | | check::EndFunction, |
41 | | check::NewAllocator, |
42 | | check::Bind, |
43 | | check::RegionChanges, |
44 | | check::LiveSymbols> { |
45 | | |
46 | 151 | bool isCallbackEnabled(AnalyzerOptions &Opts, StringRef CallbackName) const { |
47 | 151 | return Opts.getCheckerBooleanOption(this, "*") || |
48 | 151 | Opts.getCheckerBooleanOption(this, CallbackName); |
49 | 151 | } |
50 | | |
51 | 86 | bool isCallbackEnabled(CheckerContext &C, StringRef CallbackName) const { |
52 | 86 | AnalyzerOptions &Opts = C.getAnalysisManager().getAnalyzerOptions(); |
53 | 86 | return isCallbackEnabled(Opts, CallbackName); |
54 | 86 | } |
55 | | |
56 | 65 | bool isCallbackEnabled(ProgramStateRef State, StringRef CallbackName) const { |
57 | 65 | AnalyzerOptions &Opts = State->getStateManager().getOwningEngine() |
58 | 65 | .getAnalysisManager().getAnalyzerOptions(); |
59 | 65 | return isCallbackEnabled(Opts, CallbackName); |
60 | 65 | } |
61 | | |
62 | | public: |
63 | 12 | void checkPreStmt(const CastExpr *CE, CheckerContext &C) const { |
64 | 12 | if (isCallbackEnabled(C, "PreStmtCastExpr")) |
65 | 2 | llvm::errs() << "PreStmt<CastExpr> (Kind : " << CE->getCastKindName() |
66 | 2 | << ")\n"; |
67 | 12 | } |
68 | | |
69 | 12 | void checkPostStmt(const CastExpr *CE, CheckerContext &C) const { |
70 | 12 | if (isCallbackEnabled(C, "PostStmtCastExpr")) |
71 | 2 | llvm::errs() << "PostStmt<CastExpr> (Kind : " << CE->getCastKindName() |
72 | 2 | << ")\n"; |
73 | 12 | } |
74 | | |
75 | | void checkPreStmt(const ArraySubscriptExpr *SubExpr, |
76 | 0 | CheckerContext &C) const { |
77 | 0 | if (isCallbackEnabled(C, "PreStmtArraySubscriptExpr")) |
78 | 0 | llvm::errs() << "PreStmt<ArraySubscriptExpr>\n"; |
79 | 0 | } |
80 | | |
81 | | void checkPostStmt(const ArraySubscriptExpr *SubExpr, |
82 | 0 | CheckerContext &C) const { |
83 | 0 | if (isCallbackEnabled(C, "PostStmtArraySubscriptExpr")) |
84 | 0 | llvm::errs() << "PostStmt<ArraySubscriptExpr>\n"; |
85 | 0 | } |
86 | | |
87 | 2 | void checkPreStmt(const CXXNewExpr *NE, CheckerContext &C) const { |
88 | 2 | if (isCallbackEnabled(C, "PreStmtCXXNewExpr")) |
89 | 2 | llvm::errs() << "PreStmt<CXXNewExpr>\n"; |
90 | 2 | } |
91 | | |
92 | 2 | void checkPostStmt(const CXXNewExpr *NE, CheckerContext &C) const { |
93 | 2 | if (isCallbackEnabled(C, "PostStmtCXXNewExpr")) |
94 | 2 | llvm::errs() << "PostStmt<CXXNewExpr>\n"; |
95 | 2 | } |
96 | | |
97 | 1 | void checkPreStmt(const OffsetOfExpr *OOE, CheckerContext &C) const { |
98 | 1 | if (isCallbackEnabled(C, "PreStmtOffsetOfExpr")) |
99 | 1 | llvm::errs() << "PreStmt<OffsetOfExpr>\n"; |
100 | 1 | } |
101 | | |
102 | 1 | void checkPostStmt(const OffsetOfExpr *OOE, CheckerContext &C) const { |
103 | 1 | if (isCallbackEnabled(C, "PostStmtOffsetOfExpr")) |
104 | 1 | llvm::errs() << "PostStmt<OffsetOfExpr>\n"; |
105 | 1 | } |
106 | | |
107 | 15 | void checkPreCall(const CallEvent &Call, CheckerContext &C) const { |
108 | 15 | if (isCallbackEnabled(C, "PreCall")) { |
109 | 9 | llvm::errs() << "PreCall"; |
110 | 9 | if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Call.getDecl())) |
111 | 9 | llvm::errs() << " (" << ND->getQualifiedNameAsString() << ')'; |
112 | 9 | llvm::errs() << '\n'; |
113 | 9 | } |
114 | 15 | } |
115 | | |
116 | 15 | void checkPostCall(const CallEvent &Call, CheckerContext &C) const { |
117 | 15 | if (isCallbackEnabled(C, "PostCall")) { |
118 | 9 | llvm::errs() << "PostCall"; |
119 | 9 | if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Call.getDecl())) |
120 | 9 | llvm::errs() << " (" << ND->getQualifiedNameAsString() << ')'; |
121 | 9 | llvm::errs() << '\n'; |
122 | 9 | } |
123 | 15 | } |
124 | | |
125 | 20 | void checkEndFunction(const ReturnStmt *S, CheckerContext &C) const { |
126 | 20 | if (isCallbackEnabled(C, "EndFunction")) { |
127 | 3 | llvm::errs() << "EndFunction\nReturnStmt: " << (S ? "yes"2 : "no"1 ) << "\n"; |
128 | 3 | if (!S) |
129 | 1 | return; |
130 | 2 | |
131 | 2 | llvm::errs() << "CFGElement: "; |
132 | 2 | CFGStmtMap *Map = C.getCurrentAnalysisDeclContext()->getCFGStmtMap(); |
133 | 2 | CFGElement LastElement = Map->getBlock(S)->back(); |
134 | 2 | |
135 | 2 | if (LastElement.getAs<CFGStmt>()) |
136 | 1 | llvm::errs() << "CFGStmt\n"; |
137 | 1 | else if (LastElement.getAs<CFGAutomaticObjDtor>()) |
138 | 1 | llvm::errs() << "CFGAutomaticObjDtor\n"; |
139 | 2 | } |
140 | 20 | } |
141 | | |
142 | | void checkNewAllocator(const CXXNewExpr *CNE, SVal Target, |
143 | 1 | CheckerContext &C) const { |
144 | 1 | if (isCallbackEnabled(C, "NewAllocator")) |
145 | 1 | llvm::errs() << "NewAllocator\n"; |
146 | 1 | } |
147 | | |
148 | 5 | void checkBind(SVal Loc, SVal Val, const Stmt *S, CheckerContext &C) const { |
149 | 5 | if (isCallbackEnabled(C, "Bind")) |
150 | 1 | llvm::errs() << "Bind\n"; |
151 | 5 | } |
152 | | |
153 | 49 | void checkLiveSymbols(ProgramStateRef State, SymbolReaper &SymReaper) const { |
154 | 49 | if (isCallbackEnabled(State, "LiveSymbols")) |
155 | 10 | llvm::errs() << "LiveSymbols\n"; |
156 | 49 | } |
157 | | |
158 | | ProgramStateRef |
159 | | checkRegionChanges(ProgramStateRef State, |
160 | | const InvalidatedSymbols *Invalidated, |
161 | | ArrayRef<const MemRegion *> ExplicitRegions, |
162 | | ArrayRef<const MemRegion *> Regions, |
163 | 16 | const LocationContext *LCtx, const CallEvent *Call) const { |
164 | 16 | if (isCallbackEnabled(State, "RegionChanges")) |
165 | 2 | llvm::errs() << "RegionChanges\n"; |
166 | 16 | return State; |
167 | 16 | } |
168 | | }; |
169 | | } // end anonymous namespace |
170 | | |
171 | | //===----------------------------------------------------------------------===// |
172 | | // Registration. |
173 | | //===----------------------------------------------------------------------===// |
174 | | |
175 | 8 | void ento::registerAnalysisOrderChecker(CheckerManager &mgr) { |
176 | 8 | mgr.registerChecker<AnalysisOrderChecker>(); |
177 | 8 | } |
178 | | |
179 | 8 | bool ento::shouldRegisterAnalysisOrderChecker(const LangOptions &LO) { |
180 | 8 | return true; |
181 | 8 | } |