Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//===- CheckerManager.h - Static Analyzer Checker Manager -------*- 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
// Defines the Static Analyzer Checker Manager.
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/Diagnostic.h"
18
#include "clang/Basic/LangOptions.h"
19
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
20
#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
21
#include "llvm/ADT/ArrayRef.h"
22
#include "llvm/ADT/DenseMap.h"
23
#include "llvm/ADT/SmallVector.h"
24
#include "llvm/ADT/StringRef.h"
25
#include <vector>
26
 
27
namespace clang {
28
 
29
class AnalyzerOptions;
30
class CallExpr;
31
class Decl;
32
class LocationContext;
33
class Stmt;
34
class TranslationUnitDecl;
35
 
36
namespace ento {
37
 
38
class AnalysisManager;
39
class CXXAllocatorCall;
40
class BugReporter;
41
class CallEvent;
42
class CheckerBase;
43
class CheckerContext;
44
class CheckerRegistry;
45
struct CheckerRegistryData;
46
class ExplodedGraph;
47
class ExplodedNode;
48
class ExplodedNodeSet;
49
class ExprEngine;
50
struct EvalCallOptions;
51
class MemRegion;
52
struct NodeBuilderContext;
53
class ObjCMethodCall;
54
class RegionAndSymbolInvalidationTraits;
55
class SVal;
56
class SymbolReaper;
57
 
58
template <typename T> class CheckerFn;
59
 
60
template <typename RET, typename... Ps>
61
class CheckerFn<RET(Ps...)> {
62
  using Func = RET (*)(void *, Ps...);
63
 
64
  Func Fn;
65
 
66
public:
67
  CheckerBase *Checker;
68
 
69
  CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) {}
70
 
71
  RET operator()(Ps... ps) const {
72
    return Fn(Checker, ps...);
73
  }
74
};
75
 
76
/// Describes the different reasons a pointer escapes
77
/// during analysis.
78
enum PointerEscapeKind {
79
  /// A pointer escapes due to binding its value to a location
80
  /// that the analyzer cannot track.
81
  PSK_EscapeOnBind,
82
 
83
  /// The pointer has been passed to a function call directly.
84
  PSK_DirectEscapeOnCall,
85
 
86
  /// The pointer has been passed to a function indirectly.
87
  /// For example, the pointer is accessible through an
88
  /// argument to a function.
89
  PSK_IndirectEscapeOnCall,
90
 
91
 
92
  /// Escape for a new symbol that was generated into a region
93
  /// that the analyzer cannot follow during a conservative call.
94
  PSK_EscapeOutParameters,
95
 
96
  /// The reason for pointer escape is unknown. For example,
97
  /// a region containing this pointer is invalidated.
98
  PSK_EscapeOther
99
};
100
 
101
/// This wrapper is used to ensure that only StringRefs originating from the
102
/// CheckerRegistry are used as check names. We want to make sure all checker
103
/// name strings have a lifetime that keeps them alive at least until the path
104
/// diagnostics have been processed, since they are expected to be constexpr
105
/// string literals (most likely generated by TblGen).
106
class CheckerNameRef {
107
  friend class ::clang::ento::CheckerRegistry;
108
 
109
  StringRef Name;
110
 
111
  explicit CheckerNameRef(StringRef Name) : Name(Name) {}
112
 
113
public:
114
  CheckerNameRef() = default;
115
 
116
  StringRef getName() const { return Name; }
117
  operator StringRef() const { return Name; }
118
};
119
 
120
enum class ObjCMessageVisitKind {
121
  Pre,
122
  Post,
123
  MessageNil
124
};
125
 
126
class CheckerManager {
127
  ASTContext *Context = nullptr;
128
  const LangOptions LangOpts;
129
  const AnalyzerOptions &AOptions;
130
  const Preprocessor *PP = nullptr;
131
  CheckerNameRef CurrentCheckerName;
132
  DiagnosticsEngine &Diags;
133
  std::unique_ptr<CheckerRegistryData> RegistryData;
134
 
135
public:
136
  // These constructors are defined in the Frontend library, because
137
  // CheckerRegistry, a crucial component of the initialization is in there.
138
  // CheckerRegistry cannot be moved to the Core library, because the checker
139
  // registration functions are defined in the Checkers library, and the library
140
  // dependencies look like this: Core -> Checkers -> Frontend.
141
 
142
  CheckerManager(
143
      ASTContext &Context, AnalyzerOptions &AOptions, const Preprocessor &PP,
144
      ArrayRef<std::string> plugins,
145
      ArrayRef<std::function<void(CheckerRegistry &)>> checkerRegistrationFns);
146
 
147
  /// Constructs a CheckerManager that ignores all non TblGen-generated
148
  /// checkers. Useful for unit testing, unless the checker infrastructure
149
  /// itself is tested.
150
  CheckerManager(ASTContext &Context, AnalyzerOptions &AOptions,
151
                 const Preprocessor &PP)
152
      : CheckerManager(Context, AOptions, PP, {}, {}) {}
153
 
154
  /// Constructs a CheckerManager without requiring an AST. No checker
155
  /// registration will take place. Only useful when one needs to print the
156
  /// help flags through CheckerRegistryData, and the AST is unavailable.
157
  CheckerManager(AnalyzerOptions &AOptions, const LangOptions &LangOpts,
158
                 DiagnosticsEngine &Diags, ArrayRef<std::string> plugins);
159
 
160
  ~CheckerManager();
161
 
162
  void setCurrentCheckerName(CheckerNameRef name) { CurrentCheckerName = name; }
163
  CheckerNameRef getCurrentCheckerName() const { return CurrentCheckerName; }
164
 
165
  bool hasPathSensitiveCheckers() const;
166
 
167
  void finishedCheckerRegistration();
168
 
169
  const LangOptions &getLangOpts() const { return LangOpts; }
170
  const AnalyzerOptions &getAnalyzerOptions() const { return AOptions; }
171
  const Preprocessor &getPreprocessor() const {
172
    assert(PP);
173
    return *PP;
174
  }
175
  const CheckerRegistryData &getCheckerRegistryData() const {
176
    return *RegistryData;
177
  }
178
  DiagnosticsEngine &getDiagnostics() const { return Diags; }
179
  ASTContext &getASTContext() const {
180
    assert(Context);
181
    return *Context;
182
  }
183
 
184
  /// Emits an error through a DiagnosticsEngine about an invalid user supplied
185
  /// checker option value.
186
  void reportInvalidCheckerOptionValue(const CheckerBase *C,
187
                                       StringRef OptionName,
188
                                       StringRef ExpectedValueDesc) const;
189
 
190
  using CheckerRef = CheckerBase *;
191
  using CheckerTag = const void *;
192
  using CheckerDtor = CheckerFn<void ()>;
193
 
194
//===----------------------------------------------------------------------===//
195
// Checker registration.
196
//===----------------------------------------------------------------------===//
197
 
198
  /// Used to register checkers.
199
  /// All arguments are automatically passed through to the checker
200
  /// constructor.
201
  ///
202
  /// \returns a pointer to the checker object.
203
  template <typename CHECKER, typename... AT>
204
  CHECKER *registerChecker(AT &&... Args) {
205
    CheckerTag tag = getTag<CHECKER>();
206
    CheckerRef &ref = CheckerTags[tag];
207
    assert(!ref && "Checker already registered, use getChecker!");
208
 
209
    CHECKER *checker = new CHECKER(std::forward<AT>(Args)...);
210
    checker->Name = CurrentCheckerName;
211
    CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
212
    CHECKER::_register(checker, *this);
213
    ref = checker;
214
    return checker;
215
  }
216
 
217
  template <typename CHECKER>
218
  CHECKER *getChecker() {
219
    CheckerTag tag = getTag<CHECKER>();
220
    assert(CheckerTags.count(tag) != 0 &&
221
           "Requested checker is not registered! Maybe you should add it as a "
222
           "dependency in Checkers.td?");
223
    return static_cast<CHECKER *>(CheckerTags[tag]);
224
  }
225
 
226
//===----------------------------------------------------------------------===//
227
// Functions for running checkers for AST traversing.
228
//===----------------------------------------------------------------------===//
229
 
230
  /// Run checkers handling Decls.
231
  void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
232
                            BugReporter &BR);
233
 
234
  /// Run checkers handling Decls containing a Stmt body.
235
  void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
236
                            BugReporter &BR);
237
 
238
//===----------------------------------------------------------------------===//
239
// Functions for running checkers for path-sensitive checking.
240
//===----------------------------------------------------------------------===//
241
 
242
  /// Run checkers for pre-visiting Stmts.
243
  ///
244
  /// The notification is performed for every explored CFGElement, which does
245
  /// not include the control flow statements such as IfStmt.
246
  ///
247
  /// \sa runCheckersForBranchCondition, runCheckersForPostStmt
248
  void runCheckersForPreStmt(ExplodedNodeSet &Dst,
249
                             const ExplodedNodeSet &Src,
250
                             const Stmt *S,
251
                             ExprEngine &Eng) {
252
    runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng);
253
  }
254
 
255
  /// Run checkers for post-visiting Stmts.
256
  ///
257
  /// The notification is performed for every explored CFGElement, which does
258
  /// not include the control flow statements such as IfStmt.
259
  ///
260
  /// \sa runCheckersForBranchCondition, runCheckersForPreStmt
261
  void runCheckersForPostStmt(ExplodedNodeSet &Dst,
262
                              const ExplodedNodeSet &Src,
263
                              const Stmt *S,
264
                              ExprEngine &Eng,
265
                              bool wasInlined = false) {
266
    runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng, wasInlined);
267
  }
268
 
269
  /// Run checkers for visiting Stmts.
270
  void runCheckersForStmt(bool isPreVisit,
271
                          ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
272
                          const Stmt *S, ExprEngine &Eng,
273
                          bool wasInlined = false);
274
 
275
  /// Run checkers for pre-visiting obj-c messages.
276
  void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst,
277
                                    const ExplodedNodeSet &Src,
278
                                    const ObjCMethodCall &msg,
279
                                    ExprEngine &Eng) {
280
    runCheckersForObjCMessage(ObjCMessageVisitKind::Pre, Dst, Src, msg, Eng);
281
  }
282
 
283
  /// Run checkers for post-visiting obj-c messages.
284
  void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst,
285
                                     const ExplodedNodeSet &Src,
286
                                     const ObjCMethodCall &msg,
287
                                     ExprEngine &Eng,
288
                                     bool wasInlined = false) {
289
    runCheckersForObjCMessage(ObjCMessageVisitKind::Post, Dst, Src, msg, Eng,
290
                              wasInlined);
291
  }
292
 
293
  /// Run checkers for visiting an obj-c message to nil.
294
  void runCheckersForObjCMessageNil(ExplodedNodeSet &Dst,
295
                                    const ExplodedNodeSet &Src,
296
                                    const ObjCMethodCall &msg,
297
                                    ExprEngine &Eng) {
298
    runCheckersForObjCMessage(ObjCMessageVisitKind::MessageNil, Dst, Src, msg,
299
                              Eng);
300
  }
301
 
302
  /// Run checkers for visiting obj-c messages.
303
  void runCheckersForObjCMessage(ObjCMessageVisitKind visitKind,
304
                                 ExplodedNodeSet &Dst,
305
                                 const ExplodedNodeSet &Src,
306
                                 const ObjCMethodCall &msg, ExprEngine &Eng,
307
                                 bool wasInlined = false);
308
 
309
  /// Run checkers for pre-visiting obj-c messages.
310
  void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
311
                             const CallEvent &Call, ExprEngine &Eng) {
312
    runCheckersForCallEvent(/*isPreVisit=*/true, Dst, Src, Call, Eng);
313
  }
314
 
315
  /// Run checkers for post-visiting obj-c messages.
316
  void runCheckersForPostCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
317
                              const CallEvent &Call, ExprEngine &Eng,
318
                              bool wasInlined = false) {
319
    runCheckersForCallEvent(/*isPreVisit=*/false, Dst, Src, Call, Eng,
320
                            wasInlined);
321
  }
322
 
323
  /// Run checkers for visiting obj-c messages.
324
  void runCheckersForCallEvent(bool isPreVisit, ExplodedNodeSet &Dst,
325
                               const ExplodedNodeSet &Src,
326
                               const CallEvent &Call, ExprEngine &Eng,
327
                               bool wasInlined = false);
328
 
329
  /// Run checkers for load/store of a location.
330
  void runCheckersForLocation(ExplodedNodeSet &Dst,
331
                              const ExplodedNodeSet &Src,
332
                              SVal location,
333
                              bool isLoad,
334
                              const Stmt *NodeEx,
335
                              const Stmt *BoundEx,
336
                              ExprEngine &Eng);
337
 
338
  /// Run checkers for binding of a value to a location.
339
  void runCheckersForBind(ExplodedNodeSet &Dst,
340
                          const ExplodedNodeSet &Src,
341
                          SVal location, SVal val,
342
                          const Stmt *S, ExprEngine &Eng,
343
                          const ProgramPoint &PP);
344
 
345
  /// Run checkers for end of analysis.
346
  void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,
347
                                 ExprEngine &Eng);
348
 
349
  /// Run checkers on beginning of function.
350
  void runCheckersForBeginFunction(ExplodedNodeSet &Dst,
351
                                   const BlockEdge &L,
352
                                   ExplodedNode *Pred,
353
                                   ExprEngine &Eng);
354
 
355
  /// Run checkers on end of function.
356
  void runCheckersForEndFunction(NodeBuilderContext &BC,
357
                                 ExplodedNodeSet &Dst,
358
                                 ExplodedNode *Pred,
359
                                 ExprEngine &Eng,
360
                                 const ReturnStmt *RS);
361
 
362
  /// Run checkers for branch condition.
363
  void runCheckersForBranchCondition(const Stmt *condition,
364
                                     ExplodedNodeSet &Dst, ExplodedNode *Pred,
365
                                     ExprEngine &Eng);
366
 
367
  /// Run checkers between C++ operator new and constructor calls.
368
  void runCheckersForNewAllocator(const CXXAllocatorCall &Call,
369
                                  ExplodedNodeSet &Dst, ExplodedNode *Pred,
370
                                  ExprEngine &Eng, bool wasInlined = false);
371
 
372
  /// Run checkers for live symbols.
373
  ///
374
  /// Allows modifying SymbolReaper object. For example, checkers can explicitly
375
  /// register symbols of interest as live. These symbols will not be marked
376
  /// dead and removed.
377
  void runCheckersForLiveSymbols(ProgramStateRef state,
378
                                 SymbolReaper &SymReaper);
379
 
380
  /// Run checkers for dead symbols.
381
  ///
382
  /// Notifies checkers when symbols become dead. For example, this allows
383
  /// checkers to aggressively clean up/reduce the checker state and produce
384
  /// precise diagnostics.
385
  void runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
386
                                 const ExplodedNodeSet &Src,
387
                                 SymbolReaper &SymReaper, const Stmt *S,
388
                                 ExprEngine &Eng,
389
                                 ProgramPoint::Kind K);
390
 
391
  /// Run checkers for region changes.
392
  ///
393
  /// This corresponds to the check::RegionChanges callback.
394
  /// \param state The current program state.
395
  /// \param invalidated A set of all symbols potentially touched by the change.
396
  /// \param ExplicitRegions The regions explicitly requested for invalidation.
397
  ///   For example, in the case of a function call, these would be arguments.
398
  /// \param Regions The transitive closure of accessible regions,
399
  ///   i.e. all regions that may have been touched by this change.
400
  /// \param Call The call expression wrapper if the regions are invalidated
401
  ///   by a call.
402
  ProgramStateRef
403
  runCheckersForRegionChanges(ProgramStateRef state,
404
                              const InvalidatedSymbols *invalidated,
405
                              ArrayRef<const MemRegion *> ExplicitRegions,
406
                              ArrayRef<const MemRegion *> Regions,
407
                              const LocationContext *LCtx,
408
                              const CallEvent *Call);
409
 
410
  /// Run checkers when pointers escape.
411
  ///
412
  /// This notifies the checkers about pointer escape, which occurs whenever
413
  /// the analyzer cannot track the symbol any more. For example, as a
414
  /// result of assigning a pointer into a global or when it's passed to a
415
  /// function call the analyzer cannot model.
416
  ///
417
  /// \param State The state at the point of escape.
418
  /// \param Escaped The list of escaped symbols.
419
  /// \param Call The corresponding CallEvent, if the symbols escape as
420
  ///        parameters to the given call.
421
  /// \param Kind The reason of pointer escape.
422
  /// \param ITraits Information about invalidation for a particular
423
  ///        region/symbol.
424
  /// \returns Checkers can modify the state by returning a new one.
425
  ProgramStateRef
426
  runCheckersForPointerEscape(ProgramStateRef State,
427
                              const InvalidatedSymbols &Escaped,
428
                              const CallEvent *Call,
429
                              PointerEscapeKind Kind,
430
                              RegionAndSymbolInvalidationTraits *ITraits);
431
 
432
  /// Run checkers for handling assumptions on symbolic values.
433
  ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state,
434
                                           SVal Cond, bool Assumption);
435
 
436
  /// Run checkers for evaluating a call.
437
  ///
438
  /// Warning: Currently, the CallEvent MUST come from a CallExpr!
439
  void runCheckersForEvalCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
440
                              const CallEvent &CE, ExprEngine &Eng,
441
                              const EvalCallOptions &CallOpts);
442
 
443
  /// Run checkers for the entire Translation Unit.
444
  void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU,
445
                                         AnalysisManager &mgr,
446
                                         BugReporter &BR);
447
 
448
  /// Run checkers for debug-printing a ProgramState.
449
  ///
450
  /// Unlike most other callbacks, any checker can simply implement the virtual
451
  /// method CheckerBase::printState if it has custom data to print.
452
  ///
453
  /// \param Out   The output stream
454
  /// \param State The state being printed
455
  /// \param NL    The preferred representation of a newline.
456
  /// \param Space The preferred space between the left side and the message.
457
  /// \param IsDot Whether the message will be printed in 'dot' format.
458
  void runCheckersForPrintStateJson(raw_ostream &Out, ProgramStateRef State,
459
                                    const char *NL = "\n",
460
                                    unsigned int Space = 0,
461
                                    bool IsDot = false) const;
462
 
463
  //===----------------------------------------------------------------------===//
464
  // Internal registration functions for AST traversing.
465
  //===----------------------------------------------------------------------===//
466
 
467
  // Functions used by the registration mechanism, checkers should not touch
468
  // these directly.
469
 
470
  using CheckDeclFunc =
471
      CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)>;
472
 
473
  using HandlesDeclFunc = bool (*)(const Decl *D);
474
 
475
  void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn);
476
 
477
  void _registerForBody(CheckDeclFunc checkfn);
478
 
479
//===----------------------------------------------------------------------===//
480
// Internal registration functions for path-sensitive checking.
481
//===----------------------------------------------------------------------===//
482
 
483
  using CheckStmtFunc = CheckerFn<void (const Stmt *, CheckerContext &)>;
484
 
485
  using CheckObjCMessageFunc =
486
      CheckerFn<void (const ObjCMethodCall &, CheckerContext &)>;
487
 
488
  using CheckCallFunc =
489
      CheckerFn<void (const CallEvent &, CheckerContext &)>;
490
 
491
  using CheckLocationFunc =
492
      CheckerFn<void (const SVal &location, bool isLoad, const Stmt *S,
493
                      CheckerContext &)>;
494
 
495
  using CheckBindFunc =
496
      CheckerFn<void (const SVal &location, const SVal &val, const Stmt *S,
497
                      CheckerContext &)>;
498
 
499
  using CheckEndAnalysisFunc =
500
      CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>;
501
 
502
  using CheckBeginFunctionFunc = CheckerFn<void (CheckerContext &)>;
503
 
504
  using CheckEndFunctionFunc =
505
      CheckerFn<void (const ReturnStmt *, CheckerContext &)>;
506
 
507
  using CheckBranchConditionFunc =
508
      CheckerFn<void (const Stmt *, CheckerContext &)>;
509
 
510
  using CheckNewAllocatorFunc =
511
      CheckerFn<void(const CXXAllocatorCall &Call, CheckerContext &)>;
512
 
513
  using CheckDeadSymbolsFunc =
514
      CheckerFn<void (SymbolReaper &, CheckerContext &)>;
515
 
516
  using CheckLiveSymbolsFunc = CheckerFn<void (ProgramStateRef,SymbolReaper &)>;
517
 
518
  using CheckRegionChangesFunc =
519
      CheckerFn<ProgramStateRef (ProgramStateRef,
520
                                 const InvalidatedSymbols *symbols,
521
                                 ArrayRef<const MemRegion *> ExplicitRegions,
522
                                 ArrayRef<const MemRegion *> Regions,
523
                                 const LocationContext *LCtx,
524
                                 const CallEvent *Call)>;
525
 
526
  using CheckPointerEscapeFunc =
527
      CheckerFn<ProgramStateRef (ProgramStateRef,
528
                                 const InvalidatedSymbols &Escaped,
529
                                 const CallEvent *Call, PointerEscapeKind Kind,
530
                                 RegionAndSymbolInvalidationTraits *ITraits)>;
531
 
532
  using EvalAssumeFunc =
533
      CheckerFn<ProgramStateRef (ProgramStateRef, const SVal &cond,
534
                                 bool assumption)>;
535
 
536
  using EvalCallFunc = CheckerFn<bool (const CallEvent &, CheckerContext &)>;
537
 
538
  using CheckEndOfTranslationUnit =
539
      CheckerFn<void (const TranslationUnitDecl *, AnalysisManager &,
540
                      BugReporter &)>;
541
 
542
  using HandlesStmtFunc = bool (*)(const Stmt *D);
543
 
544
  void _registerForPreStmt(CheckStmtFunc checkfn,
545
                           HandlesStmtFunc isForStmtFn);
546
  void _registerForPostStmt(CheckStmtFunc checkfn,
547
                            HandlesStmtFunc isForStmtFn);
548
 
549
  void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn);
550
  void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn);
551
 
552
  void _registerForObjCMessageNil(CheckObjCMessageFunc checkfn);
553
 
554
  void _registerForPreCall(CheckCallFunc checkfn);
555
  void _registerForPostCall(CheckCallFunc checkfn);
556
 
557
  void _registerForLocation(CheckLocationFunc checkfn);
558
 
559
  void _registerForBind(CheckBindFunc checkfn);
560
 
561
  void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
562
 
563
  void _registerForBeginFunction(CheckBeginFunctionFunc checkfn);
564
  void _registerForEndFunction(CheckEndFunctionFunc checkfn);
565
 
566
  void _registerForBranchCondition(CheckBranchConditionFunc checkfn);
567
 
568
  void _registerForNewAllocator(CheckNewAllocatorFunc checkfn);
569
 
570
  void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn);
571
 
572
  void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn);
573
 
574
  void _registerForRegionChanges(CheckRegionChangesFunc checkfn);
575
 
576
  void _registerForPointerEscape(CheckPointerEscapeFunc checkfn);
577
 
578
  void _registerForConstPointerEscape(CheckPointerEscapeFunc checkfn);
579
 
580
  void _registerForEvalAssume(EvalAssumeFunc checkfn);
581
 
582
  void _registerForEvalCall(EvalCallFunc checkfn);
583
 
584
  void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn);
585
 
586
//===----------------------------------------------------------------------===//
587
// Internal registration functions for events.
588
//===----------------------------------------------------------------------===//
589
 
590
  using EventTag = void *;
591
  using CheckEventFunc = CheckerFn<void (const void *event)>;
592
 
593
  template <typename EVENT>
594
  void _registerListenerForEvent(CheckEventFunc checkfn) {
595
    EventInfo &info = Events[&EVENT::Tag];
596
    info.Checkers.push_back(checkfn);
597
  }
598
 
599
  template <typename EVENT>
600
  void _registerDispatcherForEvent() {
601
    EventInfo &info = Events[&EVENT::Tag];
602
    info.HasDispatcher = true;
603
  }
604
 
605
  template <typename EVENT>
606
  void _dispatchEvent(const EVENT &event) const {
607
    EventsTy::const_iterator I = Events.find(&EVENT::Tag);
608
    if (I == Events.end())
609
      return;
610
    const EventInfo &info = I->second;
611
    for (const auto &Checker : info.Checkers)
612
      Checker(&event);
613
  }
614
 
615
//===----------------------------------------------------------------------===//
616
// Implementation details.
617
//===----------------------------------------------------------------------===//
618
 
619
private:
620
  template <typename CHECKER>
621
  static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); }
622
 
623
  template <typename T>
624
  static void *getTag() { static int tag; return &tag; }
625
 
626
  llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags;
627
 
628
  std::vector<CheckerDtor> CheckerDtors;
629
 
630
  struct DeclCheckerInfo {
631
    CheckDeclFunc CheckFn;
632
    HandlesDeclFunc IsForDeclFn;
633
  };
634
  std::vector<DeclCheckerInfo> DeclCheckers;
635
 
636
  std::vector<CheckDeclFunc> BodyCheckers;
637
 
638
  using CachedDeclCheckers = SmallVector<CheckDeclFunc, 4>;
639
  using CachedDeclCheckersMapTy = llvm::DenseMap<unsigned, CachedDeclCheckers>;
640
  CachedDeclCheckersMapTy CachedDeclCheckersMap;
641
 
642
  struct StmtCheckerInfo {
643
    CheckStmtFunc CheckFn;
644
    HandlesStmtFunc IsForStmtFn;
645
    bool IsPreVisit;
646
  };
647
  std::vector<StmtCheckerInfo> StmtCheckers;
648
 
649
  using CachedStmtCheckers = SmallVector<CheckStmtFunc, 4>;
650
  using CachedStmtCheckersMapTy = llvm::DenseMap<unsigned, CachedStmtCheckers>;
651
  CachedStmtCheckersMapTy CachedStmtCheckersMap;
652
 
653
  const CachedStmtCheckers &getCachedStmtCheckersFor(const Stmt *S,
654
                                                     bool isPreVisit);
655
 
656
  /// Returns the checkers that have registered for callbacks of the
657
  /// given \p Kind.
658
  const std::vector<CheckObjCMessageFunc> &
659
  getObjCMessageCheckers(ObjCMessageVisitKind Kind) const;
660
 
661
  std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers;
662
  std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers;
663
  std::vector<CheckObjCMessageFunc> ObjCMessageNilCheckers;
664
 
665
  std::vector<CheckCallFunc> PreCallCheckers;
666
  std::vector<CheckCallFunc> PostCallCheckers;
667
 
668
  std::vector<CheckLocationFunc> LocationCheckers;
669
 
670
  std::vector<CheckBindFunc> BindCheckers;
671
 
672
  std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers;
673
 
674
  std::vector<CheckBeginFunctionFunc> BeginFunctionCheckers;
675
  std::vector<CheckEndFunctionFunc> EndFunctionCheckers;
676
 
677
  std::vector<CheckBranchConditionFunc> BranchConditionCheckers;
678
 
679
  std::vector<CheckNewAllocatorFunc> NewAllocatorCheckers;
680
 
681
  std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers;
682
 
683
  std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers;
684
 
685
  std::vector<CheckRegionChangesFunc> RegionChangesCheckers;
686
 
687
  std::vector<CheckPointerEscapeFunc> PointerEscapeCheckers;
688
 
689
  std::vector<EvalAssumeFunc> EvalAssumeCheckers;
690
 
691
  std::vector<EvalCallFunc> EvalCallCheckers;
692
 
693
  std::vector<CheckEndOfTranslationUnit> EndOfTranslationUnitCheckers;
694
 
695
  struct EventInfo {
696
    SmallVector<CheckEventFunc, 4> Checkers;
697
    bool HasDispatcher = false;
698
 
699
    EventInfo() = default;
700
  };
701
 
702
  using EventsTy = llvm::DenseMap<EventTag, EventInfo>;
703
  EventsTy Events;
704
};
705
 
706
} // namespace ento
707
 
708
} // namespace clang
709
 
710
#endif // LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H