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
//== Checker.h - Registration mechanism for checkers -------------*- 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 file defines Checker, used to create and register checkers.
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 CXXAllocatorCall &Call,
289
                                 CheckerContext &C) {
290
    ((const CHECKER *)checker)->checkNewAllocator(Call, 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
} // end check namespace
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 CallEvent &Call,
478
                        CheckerContext &C) {
479
    return ((const CHECKER *)checker)->evalCall(Call, C);
480
  }
481
 
482
public:
483
  template <typename CHECKER>
484
  static void _register(CHECKER *checker, CheckerManager &mgr) {
485
    mgr._registerForEvalCall(
486
                     CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
487
  }
488
};
489
 
490
} // end eval namespace
491
 
492
class CheckerBase : public ProgramPointTag {
493
  CheckerNameRef Name;
494
  friend class ::clang::ento::CheckerManager;
495
 
496
public:
497
  StringRef getTagDescription() const override;
498
  CheckerNameRef getCheckerName() const;
499
 
500
  /// See CheckerManager::runCheckersForPrintState.
501
  virtual void printState(raw_ostream &Out, ProgramStateRef State,
502
                          const char *NL, const char *Sep) const { }
503
};
504
 
505
/// Dump checker name to stream.
506
raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker);
507
 
508
/// Tag that can use a checker name as a message provider
509
/// (see SimpleProgramPointTag).
510
class CheckerProgramPointTag : public SimpleProgramPointTag {
511
public:
512
  CheckerProgramPointTag(StringRef CheckerName, StringRef Msg);
513
  CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg);
514
};
515
 
516
template <typename CHECK1, typename... CHECKs>
517
class Checker : public CHECK1, public CHECKs..., public CheckerBase {
518
public:
519
  template <typename CHECKER>
520
  static void _register(CHECKER *checker, CheckerManager &mgr) {
521
    CHECK1::_register(checker, mgr);
522
    Checker<CHECKs...>::_register(checker, mgr);
523
  }
524
};
525
 
526
template <typename CHECK1>
527
class Checker<CHECK1> : public CHECK1, public CheckerBase {
528
public:
529
  template <typename CHECKER>
530
  static void _register(CHECKER *checker, CheckerManager &mgr) {
531
    CHECK1::_register(checker, mgr);
532
  }
533
};
534
 
535
template <typename EVENT>
536
class EventDispatcher {
537
  CheckerManager *Mgr;
538
public:
539
  EventDispatcher() : Mgr(nullptr) { }
540
 
541
  template <typename CHECKER>
542
  static void _register(CHECKER *checker, CheckerManager &mgr) {
543
    mgr._registerDispatcherForEvent<EVENT>();
544
    static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
545
  }
546
 
547
  void dispatchEvent(const EVENT &event) const {
548
    Mgr->_dispatchEvent(event);
549
  }
550
};
551
 
552
/// We dereferenced a location that may be null.
553
struct ImplicitNullDerefEvent {
554
  SVal Location;
555
  bool IsLoad;
556
  ExplodedNode *SinkNode;
557
  BugReporter *BR;
558
  // When true, the dereference is in the source code directly. When false, the
559
  // dereference might happen later (for example pointer passed to a parameter
560
  // that is marked with nonnull attribute.)
561
  bool IsDirectDereference;
562
 
563
  static int Tag;
564
};
565
 
566
} // end ento namespace
567
 
568
} // end clang namespace
569
 
570
#endif