1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H |
14 | #define LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H |
15 | |
16 | #include "clang/Analysis/ProgramPoint.h" |
17 | #include "clang/Basic/LangOptions.h" |
18 | #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" |
19 | #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" |
20 | #include "llvm/ADT/ArrayRef.h" |
21 | #include "llvm/ADT/DenseMap.h" |
22 | #include "llvm/ADT/SmallVector.h" |
23 | #include "llvm/ADT/StringRef.h" |
24 | #include <vector> |
25 | |
26 | namespace clang { |
27 | |
28 | class AnalyzerOptions; |
29 | class CallExpr; |
30 | class CXXNewExpr; |
31 | class Decl; |
32 | class LocationContext; |
33 | class Stmt; |
34 | class TranslationUnitDecl; |
35 | |
36 | namespace ento { |
37 | |
38 | class AnalysisManager; |
39 | class BugReporter; |
40 | class CallEvent; |
41 | class CheckerBase; |
42 | class CheckerContext; |
43 | class CheckerRegistry; |
44 | class ExplodedGraph; |
45 | class ExplodedNode; |
46 | class ExplodedNodeSet; |
47 | class ExprEngine; |
48 | class MemRegion; |
49 | struct NodeBuilderContext; |
50 | class ObjCMethodCall; |
51 | class RegionAndSymbolInvalidationTraits; |
52 | class SVal; |
53 | class SymbolReaper; |
54 | |
55 | template <typename T> class CheckerFn; |
56 | |
57 | template <typename RET, typename... Ps> |
58 | class CheckerFn<RET(Ps...)> { |
59 | using Func = RET (*)(void *, Ps...); |
60 | |
61 | Func Fn; |
62 | |
63 | public: |
64 | CheckerBase *Checker; |
65 | |
66 | CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) {} |
67 | |
68 | RET operator()(Ps... ps) const { |
69 | return Fn(Checker, ps...); |
70 | } |
71 | }; |
72 | |
73 | |
74 | |
75 | enum PointerEscapeKind { |
76 | |
77 | |
78 | PSK_EscapeOnBind, |
79 | |
80 | |
81 | PSK_DirectEscapeOnCall, |
82 | |
83 | |
84 | |
85 | |
86 | PSK_IndirectEscapeOnCall, |
87 | |
88 | |
89 | |
90 | PSK_EscapeOther |
91 | }; |
92 | |
93 | |
94 | |
95 | |
96 | |
97 | class CheckName { |
98 | friend class ::clang::ento::CheckerRegistry; |
99 | |
100 | StringRef Name; |
101 | |
102 | explicit CheckName(StringRef Name) : Name(Name) {} |
103 | |
104 | public: |
105 | CheckName() = default; |
106 | |
107 | StringRef getName() const { return Name; } |
108 | }; |
109 | |
110 | enum class ObjCMessageVisitKind { |
111 | Pre, |
112 | Post, |
113 | MessageNil |
114 | }; |
115 | |
116 | class CheckerManager { |
117 | ASTContext &Context; |
118 | const LangOptions LangOpts; |
119 | AnalyzerOptions &AOptions; |
120 | CheckName CurrentCheckName; |
121 | |
122 | public: |
123 | CheckerManager(ASTContext &Context, AnalyzerOptions &AOptions) |
124 | : Context(Context), LangOpts(Context.getLangOpts()), AOptions(AOptions) {} |
125 | |
126 | ~CheckerManager(); |
127 | |
128 | void setCurrentCheckName(CheckName name) { CurrentCheckName = name; } |
129 | CheckName getCurrentCheckName() const { return CurrentCheckName; } |
130 | |
131 | bool hasPathSensitiveCheckers() const; |
132 | |
133 | void finishedCheckerRegistration(); |
134 | |
135 | const LangOptions &getLangOpts() const { return LangOpts; } |
136 | AnalyzerOptions &getAnalyzerOptions() { return AOptions; } |
137 | ASTContext &getASTContext() { return Context; } |
138 | |
139 | |
140 | |
141 | void reportInvalidCheckerOptionValue(const CheckerBase *C, |
142 | StringRef OptionName, |
143 | StringRef ExpectedValueDesc); |
144 | |
145 | using CheckerRef = CheckerBase *; |
146 | using CheckerTag = const void *; |
147 | using CheckerDtor = CheckerFn<void ()>; |
148 | |
149 | |
150 | |
151 | |
152 | |
153 | |
154 | |
155 | |
156 | |
157 | |
158 | template <typename CHECKER, typename... AT> |
159 | CHECKER *registerChecker(AT &&... Args) { |
160 | CheckerTag tag = getTag<CHECKER>(); |
161 | CheckerRef &ref = CheckerTags[tag]; |
162 | (0) . __assert_fail ("!ref && \"Checker already registered, use getChecker!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h", 162, __PRETTY_FUNCTION__))" file_link="../../../../../include/assert.h.html#88" macro="true">assert(!ref && "Checker already registered, use getChecker!"); |
163 | |
164 | CHECKER *checker = new CHECKER(std::forward<AT>(Args)...); |
165 | checker->Name = CurrentCheckName; |
166 | CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>)); |
167 | CHECKER::_register(checker, *this); |
168 | ref = checker; |
169 | return checker; |
170 | } |
171 | |
172 | template <typename CHECKER> |
173 | CHECKER *getChecker() { |
174 | CheckerTag tag = getTag<CHECKER>(); |
175 | (0) . __assert_fail ("CheckerTags.count(tag) != 0 && \"Requested checker is not registered! Maybe you should add it as a \" \"dependency in Checkers.td?\"", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h", 177, __PRETTY_FUNCTION__))" file_link="../../../../../include/assert.h.html#88" macro="true">assert(CheckerTags.count(tag) != 0 && |
176 | (0) . __assert_fail ("CheckerTags.count(tag) != 0 && \"Requested checker is not registered! Maybe you should add it as a \" \"dependency in Checkers.td?\"", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h", 177, __PRETTY_FUNCTION__))" file_link="../../../../../include/assert.h.html#88" macro="true"> "Requested checker is not registered! Maybe you should add it as a " |
177 | (0) . __assert_fail ("CheckerTags.count(tag) != 0 && \"Requested checker is not registered! Maybe you should add it as a \" \"dependency in Checkers.td?\"", "/home/seafit/code_projects/clang_source/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h", 177, __PRETTY_FUNCTION__))" file_link="../../../../../include/assert.h.html#88" macro="true"> "dependency in Checkers.td?"); |
178 | return static_cast<CHECKER *>(CheckerTags[tag]); |
179 | } |
180 | |
181 | |
182 | |
183 | |
184 | |
185 | |
186 | void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr, |
187 | BugReporter &BR); |
188 | |
189 | |
190 | void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr, |
191 | BugReporter &BR); |
192 | |
193 | |
194 | |
195 | |
196 | |
197 | |
198 | |
199 | |
200 | |
201 | |
202 | |
203 | void runCheckersForPreStmt(ExplodedNodeSet &Dst, |
204 | const ExplodedNodeSet &Src, |
205 | const Stmt *S, |
206 | ExprEngine &Eng) { |
207 | runCheckersForStmt(, Dst, Src, S, Eng); |
208 | } |
209 | |
210 | |
211 | |
212 | |
213 | |
214 | |
215 | |
216 | void runCheckersForPostStmt(ExplodedNodeSet &Dst, |
217 | const ExplodedNodeSet &Src, |
218 | const Stmt *S, |
219 | ExprEngine &Eng, |
220 | bool wasInlined = false) { |
221 | runCheckersForStmt(, Dst, Src, S, Eng, wasInlined); |
222 | } |
223 | |
224 | |
225 | void runCheckersForStmt(bool isPreVisit, |
226 | ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, |
227 | const Stmt *S, ExprEngine &Eng, |
228 | bool wasInlined = false); |
229 | |
230 | |
231 | void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst, |
232 | const ExplodedNodeSet &Src, |
233 | const ObjCMethodCall &msg, |
234 | ExprEngine &Eng) { |
235 | runCheckersForObjCMessage(ObjCMessageVisitKind::Pre, Dst, Src, msg, Eng); |
236 | } |
237 | |
238 | |
239 | void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst, |
240 | const ExplodedNodeSet &Src, |
241 | const ObjCMethodCall &msg, |
242 | ExprEngine &Eng, |
243 | bool wasInlined = false) { |
244 | runCheckersForObjCMessage(ObjCMessageVisitKind::Post, Dst, Src, msg, Eng, |
245 | wasInlined); |
246 | } |
247 | |
248 | |
249 | void runCheckersForObjCMessageNil(ExplodedNodeSet &Dst, |
250 | const ExplodedNodeSet &Src, |
251 | const ObjCMethodCall &msg, |
252 | ExprEngine &Eng) { |
253 | runCheckersForObjCMessage(ObjCMessageVisitKind::MessageNil, Dst, Src, msg, |
254 | Eng); |
255 | } |
256 | |
257 | |
258 | void runCheckersForObjCMessage(ObjCMessageVisitKind visitKind, |
259 | ExplodedNodeSet &Dst, |
260 | const ExplodedNodeSet &Src, |
261 | const ObjCMethodCall &msg, ExprEngine &Eng, |
262 | bool wasInlined = false); |
263 | |
264 | |
265 | void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, |
266 | const CallEvent &Call, ExprEngine &Eng) { |
267 | runCheckersForCallEvent(, Dst, Src, Call, Eng); |
268 | } |
269 | |
270 | |
271 | void runCheckersForPostCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, |
272 | const CallEvent &Call, ExprEngine &Eng, |
273 | bool wasInlined = false) { |
274 | runCheckersForCallEvent(, Dst, Src, Call, Eng, |
275 | wasInlined); |
276 | } |
277 | |
278 | |
279 | void runCheckersForCallEvent(bool isPreVisit, ExplodedNodeSet &Dst, |
280 | const ExplodedNodeSet &Src, |
281 | const CallEvent &Call, ExprEngine &Eng, |
282 | bool wasInlined = false); |
283 | |
284 | |
285 | void runCheckersForLocation(ExplodedNodeSet &Dst, |
286 | const ExplodedNodeSet &Src, |
287 | SVal location, |
288 | bool isLoad, |
289 | const Stmt *NodeEx, |
290 | const Stmt *BoundEx, |
291 | ExprEngine &Eng); |
292 | |
293 | |
294 | void runCheckersForBind(ExplodedNodeSet &Dst, |
295 | const ExplodedNodeSet &Src, |
296 | SVal location, SVal val, |
297 | const Stmt *S, ExprEngine &Eng, |
298 | const ProgramPoint &PP); |
299 | |
300 | |
301 | void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR, |
302 | ExprEngine &Eng); |
303 | |
304 | |
305 | void runCheckersForBeginFunction(ExplodedNodeSet &Dst, |
306 | const BlockEdge &L, |
307 | ExplodedNode *Pred, |
308 | ExprEngine &Eng); |
309 | |
310 | |
311 | void runCheckersForEndFunction(NodeBuilderContext &BC, |
312 | ExplodedNodeSet &Dst, |
313 | ExplodedNode *Pred, |
314 | ExprEngine &Eng, |
315 | const ReturnStmt *RS); |
316 | |
317 | |
318 | void runCheckersForBranchCondition(const Stmt *condition, |
319 | ExplodedNodeSet &Dst, ExplodedNode *Pred, |
320 | ExprEngine &Eng); |
321 | |
322 | |
323 | void runCheckersForNewAllocator(const CXXNewExpr *NE, SVal Target, |
324 | ExplodedNodeSet &Dst, |
325 | ExplodedNode *Pred, |
326 | ExprEngine &Eng, |
327 | bool wasInlined = false); |
328 | |
329 | |
330 | |
331 | |
332 | |
333 | |
334 | void runCheckersForLiveSymbols(ProgramStateRef state, |
335 | SymbolReaper &SymReaper); |
336 | |
337 | |
338 | |
339 | |
340 | |
341 | |
342 | void runCheckersForDeadSymbols(ExplodedNodeSet &Dst, |
343 | const ExplodedNodeSet &Src, |
344 | SymbolReaper &SymReaper, const Stmt *S, |
345 | ExprEngine &Eng, |
346 | ProgramPoint::Kind K); |
347 | |
348 | |
349 | |
350 | |
351 | |
352 | |
353 | |
354 | |
355 | |
356 | |
357 | |
358 | |
359 | ProgramStateRef |
360 | runCheckersForRegionChanges(ProgramStateRef state, |
361 | const InvalidatedSymbols *invalidated, |
362 | ArrayRef<const MemRegion *> ExplicitRegions, |
363 | ArrayRef<const MemRegion *> Regions, |
364 | const LocationContext *LCtx, |
365 | const CallEvent *Call); |
366 | |
367 | |
368 | |
369 | |
370 | |
371 | |
372 | |
373 | |
374 | |
375 | |
376 | |
377 | |
378 | |
379 | |
380 | |
381 | |
382 | ProgramStateRef |
383 | runCheckersForPointerEscape(ProgramStateRef State, |
384 | const InvalidatedSymbols &Escaped, |
385 | const CallEvent *Call, |
386 | PointerEscapeKind Kind, |
387 | RegionAndSymbolInvalidationTraits *ITraits); |
388 | |
389 | |
390 | ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state, |
391 | SVal Cond, bool Assumption); |
392 | |
393 | |
394 | |
395 | |
396 | void runCheckersForEvalCall(ExplodedNodeSet &Dst, |
397 | const ExplodedNodeSet &Src, |
398 | const CallEvent &CE, ExprEngine &Eng); |
399 | |
400 | |
401 | void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU, |
402 | AnalysisManager &mgr, |
403 | BugReporter &BR); |
404 | |
405 | |
406 | |
407 | |
408 | |
409 | |
410 | |
411 | |
412 | |
413 | void runCheckersForPrintState(raw_ostream &Out, ProgramStateRef State, |
414 | const char *NL, const char *Sep); |
415 | |
416 | |
417 | |
418 | |
419 | |
420 | |
421 | |
422 | |
423 | using CheckDeclFunc = |
424 | CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)>; |
425 | |
426 | using HandlesDeclFunc = bool (*)(const Decl *D); |
427 | |
428 | void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn); |
429 | |
430 | void _registerForBody(CheckDeclFunc checkfn); |
431 | |
432 | |
433 | |
434 | |
435 | |
436 | using CheckStmtFunc = CheckerFn<void (const Stmt *, CheckerContext &)>; |
437 | |
438 | using CheckObjCMessageFunc = |
439 | CheckerFn<void (const ObjCMethodCall &, CheckerContext &)>; |
440 | |
441 | using CheckCallFunc = |
442 | CheckerFn<void (const CallEvent &, CheckerContext &)>; |
443 | |
444 | using CheckLocationFunc = |
445 | CheckerFn<void (const SVal &location, bool isLoad, const Stmt *S, |
446 | CheckerContext &)>; |
447 | |
448 | using CheckBindFunc = |
449 | CheckerFn<void (const SVal &location, const SVal &val, const Stmt *S, |
450 | CheckerContext &)>; |
451 | |
452 | using CheckEndAnalysisFunc = |
453 | CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>; |
454 | |
455 | using CheckBeginFunctionFunc = CheckerFn<void (CheckerContext &)>; |
456 | |
457 | using CheckEndFunctionFunc = |
458 | CheckerFn<void (const ReturnStmt *, CheckerContext &)>; |
459 | |
460 | using CheckBranchConditionFunc = |
461 | CheckerFn<void (const Stmt *, CheckerContext &)>; |
462 | |
463 | using CheckNewAllocatorFunc = |
464 | CheckerFn<void (const CXXNewExpr *, SVal, CheckerContext &)>; |
465 | |
466 | using CheckDeadSymbolsFunc = |
467 | CheckerFn<void (SymbolReaper &, CheckerContext &)>; |
468 | |
469 | using CheckLiveSymbolsFunc = CheckerFn<void (ProgramStateRef,SymbolReaper &)>; |
470 | |
471 | using CheckRegionChangesFunc = |
472 | CheckerFn<ProgramStateRef (ProgramStateRef, |
473 | const InvalidatedSymbols *symbols, |
474 | ArrayRef<const MemRegion *> ExplicitRegions, |
475 | ArrayRef<const MemRegion *> Regions, |
476 | const LocationContext *LCtx, |
477 | const CallEvent *Call)>; |
478 | |
479 | using CheckPointerEscapeFunc = |
480 | CheckerFn<ProgramStateRef (ProgramStateRef, |
481 | const InvalidatedSymbols &Escaped, |
482 | const CallEvent *Call, PointerEscapeKind Kind, |
483 | RegionAndSymbolInvalidationTraits *ITraits)>; |
484 | |
485 | using EvalAssumeFunc = |
486 | CheckerFn<ProgramStateRef (ProgramStateRef, const SVal &cond, |
487 | bool assumption)>; |
488 | |
489 | using EvalCallFunc = CheckerFn<bool (const CallExpr *, CheckerContext &)>; |
490 | |
491 | using CheckEndOfTranslationUnit = |
492 | CheckerFn<void (const TranslationUnitDecl *, AnalysisManager &, |
493 | BugReporter &)>; |
494 | |
495 | using HandlesStmtFunc = bool (*)(const Stmt *D); |
496 | |
497 | void _registerForPreStmt(CheckStmtFunc checkfn, |
498 | HandlesStmtFunc isForStmtFn); |
499 | void _registerForPostStmt(CheckStmtFunc checkfn, |
500 | HandlesStmtFunc isForStmtFn); |
501 | |
502 | void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn); |
503 | void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn); |
504 | |
505 | void _registerForObjCMessageNil(CheckObjCMessageFunc checkfn); |
506 | |
507 | void _registerForPreCall(CheckCallFunc checkfn); |
508 | void _registerForPostCall(CheckCallFunc checkfn); |
509 | |
510 | void _registerForLocation(CheckLocationFunc checkfn); |
511 | |
512 | void _registerForBind(CheckBindFunc checkfn); |
513 | |
514 | void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn); |
515 | |
516 | void _registerForBeginFunction(CheckBeginFunctionFunc checkfn); |
517 | void _registerForEndFunction(CheckEndFunctionFunc checkfn); |
518 | |
519 | void _registerForBranchCondition(CheckBranchConditionFunc checkfn); |
520 | |
521 | void _registerForNewAllocator(CheckNewAllocatorFunc checkfn); |
522 | |
523 | void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn); |
524 | |
525 | void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn); |
526 | |
527 | void _registerForRegionChanges(CheckRegionChangesFunc checkfn); |
528 | |
529 | void _registerForPointerEscape(CheckPointerEscapeFunc checkfn); |
530 | |
531 | void _registerForConstPointerEscape(CheckPointerEscapeFunc checkfn); |
532 | |
533 | void _registerForEvalAssume(EvalAssumeFunc checkfn); |
534 | |
535 | void _registerForEvalCall(EvalCallFunc checkfn); |
536 | |
537 | void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn); |
538 | |
539 | |
540 | |
541 | |
542 | |
543 | using EventTag = void *; |
544 | using CheckEventFunc = CheckerFn<void (const void *event)>; |
545 | |
546 | template <typename EVENT> |
547 | void _registerListenerForEvent(CheckEventFunc checkfn) { |
548 | EventInfo &info = Events[&EVENT::Tag]; |
549 | info.Checkers.push_back(checkfn); |
550 | } |
551 | |
552 | template <typename EVENT> |
553 | void _registerDispatcherForEvent() { |
554 | EventInfo &info = Events[&EVENT::Tag]; |
555 | info.HasDispatcher = true; |
556 | } |
557 | |
558 | template <typename EVENT> |
559 | void _dispatchEvent(const EVENT &event) const { |
560 | EventsTy::const_iterator I = Events.find(&EVENT::Tag); |
561 | if (I == Events.end()) |
562 | return; |
563 | const EventInfo &info = I->second; |
564 | for (const auto Checker : info.Checkers) |
565 | Checker(&event); |
566 | } |
567 | |
568 | |
569 | |
570 | |
571 | |
572 | private: |
573 | template <typename CHECKER> |
574 | static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); } |
575 | |
576 | template <typename T> |
577 | static void *getTag() { static int tag; return &tag; } |
578 | |
579 | llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags; |
580 | |
581 | std::vector<CheckerDtor> CheckerDtors; |
582 | |
583 | struct DeclCheckerInfo { |
584 | CheckDeclFunc CheckFn; |
585 | HandlesDeclFunc IsForDeclFn; |
586 | }; |
587 | std::vector<DeclCheckerInfo> DeclCheckers; |
588 | |
589 | std::vector<CheckDeclFunc> BodyCheckers; |
590 | |
591 | using CachedDeclCheckers = SmallVector<CheckDeclFunc, 4>; |
592 | using CachedDeclCheckersMapTy = llvm::DenseMap<unsigned, CachedDeclCheckers>; |
593 | CachedDeclCheckersMapTy CachedDeclCheckersMap; |
594 | |
595 | struct StmtCheckerInfo { |
596 | CheckStmtFunc CheckFn; |
597 | HandlesStmtFunc IsForStmtFn; |
598 | bool IsPreVisit; |
599 | }; |
600 | std::vector<StmtCheckerInfo> StmtCheckers; |
601 | |
602 | using CachedStmtCheckers = SmallVector<CheckStmtFunc, 4>; |
603 | using CachedStmtCheckersMapTy = llvm::DenseMap<unsigned, CachedStmtCheckers>; |
604 | CachedStmtCheckersMapTy CachedStmtCheckersMap; |
605 | |
606 | const CachedStmtCheckers &getCachedStmtCheckersFor(const Stmt *S, |
607 | bool isPreVisit); |
608 | |
609 | |
610 | |
611 | const std::vector<CheckObjCMessageFunc> & |
612 | getObjCMessageCheckers(ObjCMessageVisitKind Kind); |
613 | |
614 | std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers; |
615 | std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers; |
616 | std::vector<CheckObjCMessageFunc> ObjCMessageNilCheckers; |
617 | |
618 | std::vector<CheckCallFunc> PreCallCheckers; |
619 | std::vector<CheckCallFunc> PostCallCheckers; |
620 | |
621 | std::vector<CheckLocationFunc> LocationCheckers; |
622 | |
623 | std::vector<CheckBindFunc> BindCheckers; |
624 | |
625 | std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers; |
626 | |
627 | std::vector<CheckBeginFunctionFunc> BeginFunctionCheckers; |
628 | std::vector<CheckEndFunctionFunc> EndFunctionCheckers; |
629 | |
630 | std::vector<CheckBranchConditionFunc> BranchConditionCheckers; |
631 | |
632 | std::vector<CheckNewAllocatorFunc> NewAllocatorCheckers; |
633 | |
634 | std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers; |
635 | |
636 | std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers; |
637 | |
638 | std::vector<CheckRegionChangesFunc> RegionChangesCheckers; |
639 | |
640 | std::vector<CheckPointerEscapeFunc> PointerEscapeCheckers; |
641 | |
642 | std::vector<EvalAssumeFunc> EvalAssumeCheckers; |
643 | |
644 | std::vector<EvalCallFunc> EvalCallCheckers; |
645 | |
646 | std::vector<CheckEndOfTranslationUnit> EndOfTranslationUnitCheckers; |
647 | |
648 | struct EventInfo { |
649 | SmallVector<CheckEventFunc, 4> Checkers; |
650 | bool HasDispatcher = false; |
651 | |
652 | EventInfo() = default; |
653 | }; |
654 | |
655 | using EventsTy = llvm::DenseMap<EventTag, EventInfo>; |
656 | EventsTy Events; |
657 | }; |
658 | |
659 | } |
660 | |
661 | } |
662 | |
663 | #endif |
664 | |