1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H |
14 | #define LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H |
15 | |
16 | #include "clang/Analysis/ProgramPoint.h" |
17 | #include "clang/Basic/LangOptions.h" |
18 | #include "clang/StaticAnalyzer/Core/CheckerManager.h" |
19 | #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" |
20 | #include "llvm/Support/Casting.h" |
21 | |
22 | namespace clang { |
23 | namespace ento { |
24 | class BugReporter; |
25 | |
26 | namespace check { |
27 | |
28 | template <typename DECL> |
29 | class ASTDecl { |
30 | template <typename CHECKER> |
31 | static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr, |
32 | BugReporter &BR) { |
33 | ((const CHECKER *)checker)->checkASTDecl(cast<DECL>(D), mgr, BR); |
34 | } |
35 | |
36 | static bool _handlesDecl(const Decl *D) { |
37 | return isa<DECL>(D); |
38 | } |
39 | public: |
40 | template <typename CHECKER> |
41 | static void _register(CHECKER *checker, CheckerManager &mgr) { |
42 | mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker, |
43 | _checkDecl<CHECKER>), |
44 | _handlesDecl); |
45 | } |
46 | }; |
47 | |
48 | class ASTCodeBody { |
49 | template <typename CHECKER> |
50 | static void _checkBody(void *checker, const Decl *D, AnalysisManager& mgr, |
51 | BugReporter &BR) { |
52 | ((const CHECKER *)checker)->checkASTCodeBody(D, mgr, BR); |
53 | } |
54 | |
55 | public: |
56 | template <typename CHECKER> |
57 | static void _register(CHECKER *checker, CheckerManager &mgr) { |
58 | mgr._registerForBody(CheckerManager::CheckDeclFunc(checker, |
59 | _checkBody<CHECKER>)); |
60 | } |
61 | }; |
62 | |
63 | class EndOfTranslationUnit { |
64 | template <typename CHECKER> |
65 | static void _checkEndOfTranslationUnit(void *checker, |
66 | const TranslationUnitDecl *TU, |
67 | AnalysisManager& mgr, |
68 | BugReporter &BR) { |
69 | ((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR); |
70 | } |
71 | |
72 | public: |
73 | template <typename CHECKER> |
74 | static void _register(CHECKER *checker, CheckerManager &mgr){ |
75 | mgr._registerForEndOfTranslationUnit( |
76 | CheckerManager::CheckEndOfTranslationUnit(checker, |
77 | _checkEndOfTranslationUnit<CHECKER>)); |
78 | } |
79 | }; |
80 | |
81 | template <typename STMT> |
82 | class PreStmt { |
83 | template <typename CHECKER> |
84 | static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) { |
85 | ((const CHECKER *)checker)->checkPreStmt(cast<STMT>(S), C); |
86 | } |
87 | |
88 | static bool _handlesStmt(const Stmt *S) { |
89 | return isa<STMT>(S); |
90 | } |
91 | public: |
92 | template <typename CHECKER> |
93 | static void _register(CHECKER *checker, CheckerManager &mgr) { |
94 | mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker, |
95 | _checkStmt<CHECKER>), |
96 | _handlesStmt); |
97 | } |
98 | }; |
99 | |
100 | template <typename STMT> |
101 | class PostStmt { |
102 | template <typename CHECKER> |
103 | static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) { |
104 | ((const CHECKER *)checker)->checkPostStmt(cast<STMT>(S), C); |
105 | } |
106 | |
107 | static bool _handlesStmt(const Stmt *S) { |
108 | return isa<STMT>(S); |
109 | } |
110 | public: |
111 | template <typename CHECKER> |
112 | static void _register(CHECKER *checker, CheckerManager &mgr) { |
113 | mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker, |
114 | _checkStmt<CHECKER>), |
115 | _handlesStmt); |
116 | } |
117 | }; |
118 | |
119 | class PreObjCMessage { |
120 | template <typename CHECKER> |
121 | static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg, |
122 | CheckerContext &C) { |
123 | ((const CHECKER *)checker)->checkPreObjCMessage(msg, C); |
124 | } |
125 | |
126 | public: |
127 | template <typename CHECKER> |
128 | static void _register(CHECKER *checker, CheckerManager &mgr) { |
129 | mgr._registerForPreObjCMessage( |
130 | CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); |
131 | } |
132 | }; |
133 | |
134 | class ObjCMessageNil { |
135 | template <typename CHECKER> |
136 | static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg, |
137 | CheckerContext &C) { |
138 | ((const CHECKER *)checker)->checkObjCMessageNil(msg, C); |
139 | } |
140 | |
141 | public: |
142 | template <typename CHECKER> |
143 | static void _register(CHECKER *checker, CheckerManager &mgr) { |
144 | mgr._registerForObjCMessageNil( |
145 | CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); |
146 | } |
147 | }; |
148 | |
149 | class PostObjCMessage { |
150 | template <typename CHECKER> |
151 | static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg, |
152 | CheckerContext &C) { |
153 | ((const CHECKER *)checker)->checkPostObjCMessage(msg, C); |
154 | } |
155 | |
156 | public: |
157 | template <typename CHECKER> |
158 | static void _register(CHECKER *checker, CheckerManager &mgr) { |
159 | mgr._registerForPostObjCMessage( |
160 | CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); |
161 | } |
162 | }; |
163 | |
164 | class PreCall { |
165 | template <typename CHECKER> |
166 | static void _checkCall(void *checker, const CallEvent &msg, |
167 | CheckerContext &C) { |
168 | ((const CHECKER *)checker)->checkPreCall(msg, C); |
169 | } |
170 | |
171 | public: |
172 | template <typename CHECKER> |
173 | static void _register(CHECKER *checker, CheckerManager &mgr) { |
174 | mgr._registerForPreCall( |
175 | CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>)); |
176 | } |
177 | }; |
178 | |
179 | class PostCall { |
180 | template <typename CHECKER> |
181 | static void _checkCall(void *checker, const CallEvent &msg, |
182 | CheckerContext &C) { |
183 | ((const CHECKER *)checker)->checkPostCall(msg, C); |
184 | } |
185 | |
186 | public: |
187 | template <typename CHECKER> |
188 | static void _register(CHECKER *checker, CheckerManager &mgr) { |
189 | mgr._registerForPostCall( |
190 | CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>)); |
191 | } |
192 | }; |
193 | |
194 | class Location { |
195 | template <typename CHECKER> |
196 | static void _checkLocation(void *checker, |
197 | const SVal &location, bool isLoad, const Stmt *S, |
198 | CheckerContext &C) { |
199 | ((const CHECKER *)checker)->checkLocation(location, isLoad, S, C); |
200 | } |
201 | |
202 | public: |
203 | template <typename CHECKER> |
204 | static void _register(CHECKER *checker, CheckerManager &mgr) { |
205 | mgr._registerForLocation( |
206 | CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>)); |
207 | } |
208 | }; |
209 | |
210 | class Bind { |
211 | template <typename CHECKER> |
212 | static void _checkBind(void *checker, |
213 | const SVal &location, const SVal &val, const Stmt *S, |
214 | CheckerContext &C) { |
215 | ((const CHECKER *)checker)->checkBind(location, val, S, C); |
216 | } |
217 | |
218 | public: |
219 | template <typename CHECKER> |
220 | static void _register(CHECKER *checker, CheckerManager &mgr) { |
221 | mgr._registerForBind( |
222 | CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>)); |
223 | } |
224 | }; |
225 | |
226 | class EndAnalysis { |
227 | template <typename CHECKER> |
228 | static void _checkEndAnalysis(void *checker, ExplodedGraph &G, |
229 | BugReporter &BR, ExprEngine &Eng) { |
230 | ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng); |
231 | } |
232 | |
233 | public: |
234 | template <typename CHECKER> |
235 | static void _register(CHECKER *checker, CheckerManager &mgr) { |
236 | mgr._registerForEndAnalysis( |
237 | CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>)); |
238 | } |
239 | }; |
240 | |
241 | class BeginFunction { |
242 | template <typename CHECKER> |
243 | static void _checkBeginFunction(void *checker, CheckerContext &C) { |
244 | ((const CHECKER *)checker)->checkBeginFunction(C); |
245 | } |
246 | |
247 | public: |
248 | template <typename CHECKER> |
249 | static void _register(CHECKER *checker, CheckerManager &mgr) { |
250 | mgr._registerForBeginFunction(CheckerManager::CheckBeginFunctionFunc( |
251 | checker, _checkBeginFunction<CHECKER>)); |
252 | } |
253 | }; |
254 | |
255 | class EndFunction { |
256 | template <typename CHECKER> |
257 | static void _checkEndFunction(void *checker, const ReturnStmt *RS, |
258 | CheckerContext &C) { |
259 | ((const CHECKER *)checker)->checkEndFunction(RS, C); |
260 | } |
261 | |
262 | public: |
263 | template <typename CHECKER> |
264 | static void _register(CHECKER *checker, CheckerManager &mgr) { |
265 | mgr._registerForEndFunction( |
266 | CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>)); |
267 | } |
268 | }; |
269 | |
270 | class BranchCondition { |
271 | template <typename CHECKER> |
272 | static void _checkBranchCondition(void *checker, const Stmt *Condition, |
273 | CheckerContext & C) { |
274 | ((const CHECKER *)checker)->checkBranchCondition(Condition, C); |
275 | } |
276 | |
277 | public: |
278 | template <typename CHECKER> |
279 | static void _register(CHECKER *checker, CheckerManager &mgr) { |
280 | mgr._registerForBranchCondition( |
281 | CheckerManager::CheckBranchConditionFunc(checker, |
282 | _checkBranchCondition<CHECKER>)); |
283 | } |
284 | }; |
285 | |
286 | class NewAllocator { |
287 | template <typename CHECKER> |
288 | static void _checkNewAllocator(void *checker, const CXXNewExpr *NE, |
289 | SVal Target, CheckerContext &C) { |
290 | ((const CHECKER *)checker)->checkNewAllocator(NE, Target, C); |
291 | } |
292 | |
293 | public: |
294 | template <typename CHECKER> |
295 | static void _register(CHECKER *checker, CheckerManager &mgr) { |
296 | mgr._registerForNewAllocator( |
297 | CheckerManager::CheckNewAllocatorFunc(checker, |
298 | _checkNewAllocator<CHECKER>)); |
299 | } |
300 | }; |
301 | |
302 | class LiveSymbols { |
303 | template <typename CHECKER> |
304 | static void _checkLiveSymbols(void *checker, ProgramStateRef state, |
305 | SymbolReaper &SR) { |
306 | ((const CHECKER *)checker)->checkLiveSymbols(state, SR); |
307 | } |
308 | |
309 | public: |
310 | template <typename CHECKER> |
311 | static void _register(CHECKER *checker, CheckerManager &mgr) { |
312 | mgr._registerForLiveSymbols( |
313 | CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>)); |
314 | } |
315 | }; |
316 | |
317 | class DeadSymbols { |
318 | template <typename CHECKER> |
319 | static void _checkDeadSymbols(void *checker, |
320 | SymbolReaper &SR, CheckerContext &C) { |
321 | ((const CHECKER *)checker)->checkDeadSymbols(SR, C); |
322 | } |
323 | |
324 | public: |
325 | template <typename CHECKER> |
326 | static void _register(CHECKER *checker, CheckerManager &mgr) { |
327 | mgr._registerForDeadSymbols( |
328 | CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>)); |
329 | } |
330 | }; |
331 | |
332 | class RegionChanges { |
333 | template <typename CHECKER> |
334 | static ProgramStateRef |
335 | _checkRegionChanges(void *checker, |
336 | ProgramStateRef state, |
337 | const InvalidatedSymbols *invalidated, |
338 | ArrayRef<const MemRegion *> Explicits, |
339 | ArrayRef<const MemRegion *> Regions, |
340 | const LocationContext *LCtx, |
341 | const CallEvent *Call) { |
342 | return ((const CHECKER *) checker)->checkRegionChanges(state, invalidated, |
343 | Explicits, Regions, |
344 | LCtx, Call); |
345 | } |
346 | |
347 | public: |
348 | template <typename CHECKER> |
349 | static void _register(CHECKER *checker, CheckerManager &mgr) { |
350 | mgr._registerForRegionChanges( |
351 | CheckerManager::CheckRegionChangesFunc(checker, |
352 | _checkRegionChanges<CHECKER>)); |
353 | } |
354 | }; |
355 | |
356 | class PointerEscape { |
357 | template <typename CHECKER> |
358 | static ProgramStateRef |
359 | _checkPointerEscape(void *Checker, |
360 | ProgramStateRef State, |
361 | const InvalidatedSymbols &Escaped, |
362 | const CallEvent *Call, |
363 | PointerEscapeKind Kind, |
364 | RegionAndSymbolInvalidationTraits *ETraits) { |
365 | |
366 | if (!ETraits) |
367 | return ((const CHECKER *)Checker)->checkPointerEscape(State, |
368 | Escaped, |
369 | Call, |
370 | Kind); |
371 | |
372 | InvalidatedSymbols RegularEscape; |
373 | for (InvalidatedSymbols::const_iterator I = Escaped.begin(), |
374 | E = Escaped.end(); I != E; ++I) |
375 | if (!ETraits->hasTrait(*I, |
376 | RegionAndSymbolInvalidationTraits::TK_PreserveContents) && |
377 | !ETraits->hasTrait(*I, |
378 | RegionAndSymbolInvalidationTraits::TK_SuppressEscape)) |
379 | RegularEscape.insert(*I); |
380 | |
381 | if (RegularEscape.empty()) |
382 | return State; |
383 | |
384 | return ((const CHECKER *)Checker)->checkPointerEscape(State, |
385 | RegularEscape, |
386 | Call, |
387 | Kind); |
388 | } |
389 | |
390 | public: |
391 | template <typename CHECKER> |
392 | static void _register(CHECKER *checker, CheckerManager &mgr) { |
393 | mgr._registerForPointerEscape( |
394 | CheckerManager::CheckPointerEscapeFunc(checker, |
395 | _checkPointerEscape<CHECKER>)); |
396 | } |
397 | }; |
398 | |
399 | class ConstPointerEscape { |
400 | template <typename CHECKER> |
401 | static ProgramStateRef |
402 | _checkConstPointerEscape(void *Checker, |
403 | ProgramStateRef State, |
404 | const InvalidatedSymbols &Escaped, |
405 | const CallEvent *Call, |
406 | PointerEscapeKind Kind, |
407 | RegionAndSymbolInvalidationTraits *ETraits) { |
408 | |
409 | if (!ETraits) |
410 | return State; |
411 | |
412 | InvalidatedSymbols ConstEscape; |
413 | for (InvalidatedSymbols::const_iterator I = Escaped.begin(), |
414 | E = Escaped.end(); I != E; ++I) |
415 | if (ETraits->hasTrait(*I, |
416 | RegionAndSymbolInvalidationTraits::TK_PreserveContents) && |
417 | !ETraits->hasTrait(*I, |
418 | RegionAndSymbolInvalidationTraits::TK_SuppressEscape)) |
419 | ConstEscape.insert(*I); |
420 | |
421 | if (ConstEscape.empty()) |
422 | return State; |
423 | |
424 | return ((const CHECKER *)Checker)->checkConstPointerEscape(State, |
425 | ConstEscape, |
426 | Call, |
427 | Kind); |
428 | } |
429 | |
430 | public: |
431 | template <typename CHECKER> |
432 | static void _register(CHECKER *checker, CheckerManager &mgr) { |
433 | mgr._registerForPointerEscape( |
434 | CheckerManager::CheckPointerEscapeFunc(checker, |
435 | _checkConstPointerEscape<CHECKER>)); |
436 | } |
437 | }; |
438 | |
439 | |
440 | template <typename EVENT> |
441 | class Event { |
442 | template <typename CHECKER> |
443 | static void _checkEvent(void *checker, const void *event) { |
444 | ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event); |
445 | } |
446 | public: |
447 | template <typename CHECKER> |
448 | static void _register(CHECKER *checker, CheckerManager &mgr) { |
449 | mgr._registerListenerForEvent<EVENT>( |
450 | CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>)); |
451 | } |
452 | }; |
453 | |
454 | } |
455 | |
456 | namespace eval { |
457 | |
458 | class Assume { |
459 | template <typename CHECKER> |
460 | static ProgramStateRef _evalAssume(void *checker, |
461 | ProgramStateRef state, |
462 | const SVal &cond, |
463 | bool assumption) { |
464 | return ((const CHECKER *)checker)->evalAssume(state, cond, assumption); |
465 | } |
466 | |
467 | public: |
468 | template <typename CHECKER> |
469 | static void _register(CHECKER *checker, CheckerManager &mgr) { |
470 | mgr._registerForEvalAssume( |
471 | CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>)); |
472 | } |
473 | }; |
474 | |
475 | class Call { |
476 | template <typename CHECKER> |
477 | static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) { |
478 | return ((const CHECKER *)checker)->evalCall(CE, C); |
479 | } |
480 | |
481 | public: |
482 | template <typename CHECKER> |
483 | static void _register(CHECKER *checker, CheckerManager &mgr) { |
484 | mgr._registerForEvalCall( |
485 | CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>)); |
486 | } |
487 | }; |
488 | |
489 | } |
490 | |
491 | class CheckerBase : public ProgramPointTag { |
492 | CheckName Name; |
493 | friend class ::clang::ento::CheckerManager; |
494 | |
495 | public: |
496 | StringRef getTagDescription() const override; |
497 | CheckName getCheckName() const; |
498 | |
499 | |
500 | virtual void printState(raw_ostream &Out, ProgramStateRef State, |
501 | const char *NL, const char *Sep) const { } |
502 | }; |
503 | |
504 | |
505 | raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker); |
506 | |
507 | |
508 | |
509 | class CheckerProgramPointTag : public SimpleProgramPointTag { |
510 | public: |
511 | CheckerProgramPointTag(StringRef CheckerName, StringRef Msg); |
512 | CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg); |
513 | }; |
514 | |
515 | template <typename CHECK1, typename... CHECKs> |
516 | class Checker : public CHECK1, public CHECKs..., public CheckerBase { |
517 | public: |
518 | template <typename CHECKER> |
519 | static void _register(CHECKER *checker, CheckerManager &mgr) { |
520 | CHECK1::_register(checker, mgr); |
521 | Checker<CHECKs...>::_register(checker, mgr); |
522 | } |
523 | }; |
524 | |
525 | template <typename CHECK1> |
526 | class Checker<CHECK1> : public CHECK1, public CheckerBase { |
527 | public: |
528 | template <typename CHECKER> |
529 | static void _register(CHECKER *checker, CheckerManager &mgr) { |
530 | CHECK1::_register(checker, mgr); |
531 | } |
532 | }; |
533 | |
534 | template <typename EVENT> |
535 | class EventDispatcher { |
536 | CheckerManager *Mgr; |
537 | public: |
538 | EventDispatcher() : Mgr(nullptr) { } |
539 | |
540 | template <typename CHECKER> |
541 | static void _register(CHECKER *checker, CheckerManager &mgr) { |
542 | mgr._registerDispatcherForEvent<EVENT>(); |
543 | static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr; |
544 | } |
545 | |
546 | void dispatchEvent(const EVENT &event) const { |
547 | Mgr->_dispatchEvent(event); |
548 | } |
549 | }; |
550 | |
551 | |
552 | struct ImplicitNullDerefEvent { |
553 | SVal Location; |
554 | bool IsLoad; |
555 | ExplodedNode *SinkNode; |
556 | BugReporter *BR; |
557 | |
558 | |
559 | |
560 | bool IsDirectDereference; |
561 | |
562 | static int Tag; |
563 | }; |
564 | |
565 | |
566 | |
567 | |
568 | |
569 | struct DefaultBool { |
570 | bool val; |
571 | DefaultBool() : val(false) {} |
572 | operator bool&() { return val; } |
573 | operator const bool&() const { return val; } |
574 | DefaultBool &operator=(bool b) { val = b; return *this; } |
575 | }; |
576 | |
577 | } |
578 | |
579 | } |
580 | |
581 | #endif |
582 | |