Clang Project

clang_source_code/include/clang/StaticAnalyzer/Core/Checker.h
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
22namespace clang {
23namespace ento {
24  class BugReporter;
25
26namespace check {
27
28template <typename DECL>
29class ASTDecl {
30  template <typename CHECKER>
31  static void _checkDecl(void *checkerconst Decl *DAnalysisManagermgr,
32                         BugReporter &BR) {
33    ((const CHECKER *)checker)->checkASTDecl(cast<DECL>(D), mgrBR);
34  }
35
36  static bool _handlesDecl(const Decl *D) {
37    return isa<DECL>(D);
38  }
39public:
40  template <typename CHECKER>
41  static void _register(CHECKER *checkerCheckerManager &mgr) {
42    mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker,
43                                                       _checkDecl<CHECKER>),
44                         _handlesDecl);
45  }
46};
47
48class ASTCodeBody {
49  template <typename CHECKER>
50  static void _checkBody(void *checkerconst Decl *DAnalysisManagermgr,
51                         BugReporter &BR) {
52    ((const CHECKER *)checker)->checkASTCodeBody(DmgrBR);
53  }
54
55public:
56  template <typename CHECKER>
57  static void _register(CHECKER *checkerCheckerManager &mgr) {
58    mgr._registerForBody(CheckerManager::CheckDeclFunc(checker,
59                                                       _checkBody<CHECKER>));
60  }
61};
62
63class EndOfTranslationUnit {
64  template <typename CHECKER>
65  static void _checkEndOfTranslationUnit(void *checker,
66                                         const TranslationUnitDecl *TU,
67                                         AnalysisManagermgr,
68                                         BugReporter &BR) {
69    ((const CHECKER *)checker)->checkEndOfTranslationUnit(TUmgrBR);
70  }
71
72public:
73  template <typename CHECKER>
74  static void _register(CHECKER *checkerCheckerManager &mgr){
75    mgr._registerForEndOfTranslationUnit(
76                              CheckerManager::CheckEndOfTranslationUnit(checker,
77                                          _checkEndOfTranslationUnit<CHECKER>));
78  }
79};
80
81template <typename STMT>
82class PreStmt {
83  template <typename CHECKER>
84  static void _checkStmt(void *checkerconst Stmt *SCheckerContext &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  }
91public:
92  template <typename CHECKER>
93  static void _register(CHECKER *checkerCheckerManager &mgr) {
94    mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker,
95                                                          _checkStmt<CHECKER>),
96                            _handlesStmt);
97  }
98};
99
100template <typename STMT>
101class PostStmt {
102  template <typename CHECKER>
103  static void _checkStmt(void *checkerconst Stmt *SCheckerContext &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  }
110public:
111  template <typename CHECKER>
112  static void _register(CHECKER *checkerCheckerManager &mgr) {
113    mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker,
114                                                           _checkStmt<CHECKER>),
115                             _handlesStmt);
116  }
117};
118
119class PreObjCMessage {
120  template <typename CHECKER>
121  static void _checkObjCMessage(void *checkerconst ObjCMethodCall &msg,
122                                CheckerContext &C) {
123    ((const CHECKER *)checker)->checkPreObjCMessage(msgC);
124  }
125
126public:
127  template <typename CHECKER>
128  static void _register(CHECKER *checkerCheckerManager &mgr) {
129    mgr._registerForPreObjCMessage(
130     CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
131  }
132};
133
134class ObjCMessageNil {
135  template <typename CHECKER>
136  static void _checkObjCMessage(void *checkerconst ObjCMethodCall &msg,
137                                CheckerContext &C) {
138    ((const CHECKER *)checker)->checkObjCMessageNil(msgC);
139  }
140
141public:
142  template <typename CHECKER>
143  static void _register(CHECKER *checkerCheckerManager &mgr) {
144    mgr._registerForObjCMessageNil(
145     CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
146  }
147};
148
149class PostObjCMessage {
150  template <typename CHECKER>
151  static void _checkObjCMessage(void *checkerconst ObjCMethodCall &msg,
152                                CheckerContext &C) {
153    ((const CHECKER *)checker)->checkPostObjCMessage(msgC);
154  }
155
156public:
157  template <typename CHECKER>
158  static void _register(CHECKER *checkerCheckerManager &mgr) {
159    mgr._registerForPostObjCMessage(
160     CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
161  }
162};
163
164class PreCall {
165  template <typename CHECKER>
166  static void _checkCall(void *checkerconst CallEvent &msg,
167                         CheckerContext &C) {
168    ((const CHECKER *)checker)->checkPreCall(msgC);
169  }
170
171public:
172  template <typename CHECKER>
173  static void _register(CHECKER *checkerCheckerManager &mgr) {
174    mgr._registerForPreCall(
175     CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
176  }
177};
178
179class PostCall {
180  template <typename CHECKER>
181  static void _checkCall(void *checkerconst CallEvent &msg,
182                         CheckerContext &C) {
183    ((const CHECKER *)checker)->checkPostCall(msgC);
184  }
185
186public:
187  template <typename CHECKER>
188  static void _register(CHECKER *checkerCheckerManager &mgr) {
189    mgr._registerForPostCall(
190     CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
191  }
192};
193
194class Location {
195  template <typename CHECKER>
196  static void _checkLocation(void *checker,
197                             const SVal &locationbool isLoadconst Stmt *S,
198                             CheckerContext &C) {
199    ((const CHECKER *)checker)->checkLocation(locationisLoadSC);
200  }
201
202public:
203  template <typename CHECKER>
204  static void _register(CHECKER *checkerCheckerManager &mgr) {
205    mgr._registerForLocation(
206           CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>));
207  }
208};
209
210class Bind {
211  template <typename CHECKER>
212  static void _checkBind(void *checker,
213                         const SVal &locationconst SVal &valconst Stmt *S,
214                         CheckerContext &C) {
215    ((const CHECKER *)checker)->checkBind(locationvalSC);
216  }
217
218public:
219  template <typename CHECKER>
220  static void _register(CHECKER *checkerCheckerManager &mgr) {
221    mgr._registerForBind(
222           CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>));
223  }
224};
225
226class EndAnalysis {
227  template <typename CHECKER>
228  static void _checkEndAnalysis(void *checkerExplodedGraph &G,
229                                BugReporter &BRExprEngine &Eng) {
230    ((const CHECKER *)checker)->checkEndAnalysis(GBREng);
231  }
232
233public:
234  template <typename CHECKER>
235  static void _register(CHECKER *checkerCheckerManager &mgr) {
236    mgr._registerForEndAnalysis(
237     CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
238  }
239};
240
241class BeginFunction {
242  template <typename CHECKER>
243  static void _checkBeginFunction(void *checkerCheckerContext &C) {
244    ((const CHECKER *)checker)->checkBeginFunction(C);
245  }
246
247public:
248  template <typename CHECKER>
249  static void _register(CHECKER *checkerCheckerManager &mgr) {
250    mgr._registerForBeginFunction(CheckerManager::CheckBeginFunctionFunc(
251        checker, _checkBeginFunction<CHECKER>));
252  }
253};
254
255class EndFunction {
256  template <typename CHECKER>
257  static void _checkEndFunction(void *checkerconst ReturnStmt *RS,
258                                CheckerContext &C) {
259    ((const CHECKER *)checker)->checkEndFunction(RSC);
260  }
261
262public:
263  template <typename CHECKER>
264  static void _register(CHECKER *checkerCheckerManager &mgr) {
265    mgr._registerForEndFunction(
266     CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>));
267  }
268};
269
270class BranchCondition {
271  template <typename CHECKER>
272  static void _checkBranchCondition(void *checkerconst Stmt *Condition,
273                                    CheckerContext & C) {
274    ((const CHECKER *)checker)->checkBranchCondition(ConditionC);
275  }
276
277public:
278  template <typename CHECKER>
279  static void _register(CHECKER *checkerCheckerManager &mgr) {
280    mgr._registerForBranchCondition(
281      CheckerManager::CheckBranchConditionFunc(checker,
282                                               _checkBranchCondition<CHECKER>));
283  }
284};
285
286class NewAllocator {
287  template <typename CHECKER>
288  static void _checkNewAllocator(void *checkerconst CXXNewExpr *NE,
289                                 SVal TargetCheckerContext &C) {
290    ((const CHECKER *)checker)->checkNewAllocator(NETargetC);
291  }
292
293public:
294  template <typename CHECKER>
295  static void _register(CHECKER *checkerCheckerManager &mgr) {
296    mgr._registerForNewAllocator(
297        CheckerManager::CheckNewAllocatorFunc(checker,
298                                              _checkNewAllocator<CHECKER>));
299  }
300};
301
302class LiveSymbols {
303  template <typename CHECKER>
304  static void _checkLiveSymbols(void *checkerProgramStateRef state,
305                                SymbolReaper &SR) {
306    ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
307  }
308
309public:
310  template <typename CHECKER>
311  static void _register(CHECKER *checkerCheckerManager &mgr) {
312    mgr._registerForLiveSymbols(
313     CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
314  }
315};
316
317class DeadSymbols {
318  template <typename CHECKER>
319  static void _checkDeadSymbols(void *checker,
320                                SymbolReaper &SRCheckerContext &C) {
321    ((const CHECKER *)checker)->checkDeadSymbols(SRC);
322  }
323
324public:
325  template <typename CHECKER>
326  static void _register(CHECKER *checkerCheckerManager &mgr) {
327    mgr._registerForDeadSymbols(
328     CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
329  }
330};
331
332class 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
347public:
348  template <typename CHECKER>
349  static void _register(CHECKER *checkerCheckerManager &mgr) {
350    mgr._registerForRegionChanges(
351          CheckerManager::CheckRegionChangesFunc(checker,
352                                                 _checkRegionChanges<CHECKER>));
353  }
354};
355
356class 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
390public:
391  template <typename CHECKER>
392  static void _register(CHECKER *checkerCheckerManager &mgr) {
393    mgr._registerForPointerEscape(
394          CheckerManager::CheckPointerEscapeFunc(checker,
395                                                _checkPointerEscape<CHECKER>));
396  }
397};
398
399class 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
430public:
431  template <typename CHECKER>
432  static void _register(CHECKER *checkerCheckerManager &mgr) {
433    mgr._registerForPointerEscape(
434      CheckerManager::CheckPointerEscapeFunc(checker,
435                                            _checkConstPointerEscape<CHECKER>));
436  }
437};
438
439
440template <typename EVENT>
441class Event {
442  template <typename CHECKER>
443  static void _checkEvent(void *checkerconst void *event) {
444    ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
445  }
446public:
447  template <typename CHECKER>
448  static void _register(CHECKER *checkerCheckerManager &mgr) {
449    mgr._registerListenerForEvent<EVENT>(
450                 CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
451  }
452};
453
454// end check namespace
455
456namespace eval {
457
458class 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
467public:
468  template <typename CHECKER>
469  static void _register(CHECKER *checkerCheckerManager &mgr) {
470    mgr._registerForEvalAssume(
471                 CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
472  }
473};
474
475class Call {
476  template <typename CHECKER>
477  static bool _evalCall(void *checkerconst CallExpr *CECheckerContext &C) {
478    return ((const CHECKER *)checker)->evalCall(CEC);
479  }
480
481public:
482  template <typename CHECKER>
483  static void _register(CHECKER *checkerCheckerManager &mgr) {
484    mgr._registerForEvalCall(
485                     CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
486  }
487};
488
489// end eval namespace
490
491class CheckerBase : public ProgramPointTag {
492  CheckName Name;
493  friend class ::clang::ento::CheckerManager;
494
495public:
496  StringRef getTagDescription() const override;
497  CheckName getCheckName() const;
498
499  /// See CheckerManager::runCheckersForPrintState.
500  virtual void printState(raw_ostream &OutProgramStateRef State,
501                          const char *NLconst char *Sepconst { }
502};
503
504/// Dump checker name to stream.
505raw_ostreamoperator<<(raw_ostream &Outconst CheckerBase &Checker);
506
507/// Tag that can use a checker name as a message provider
508/// (see SimpleProgramPointTag).
509class CheckerProgramPointTag : public SimpleProgramPointTag {
510public:
511  CheckerProgramPointTag(StringRef CheckerNameStringRef Msg);
512  CheckerProgramPointTag(const CheckerBase *CheckerStringRef Msg);
513};
514
515template <typename CHECK1, typename... CHECKs>
516class Checker : public CHECK1, public CHECKs..., public CheckerBase {
517public:
518  template <typename CHECKER>
519  static void _register(CHECKER *checkerCheckerManager &mgr) {
520    CHECK1::_register(checkermgr);
521    Checker<CHECKs...>::_register(checkermgr);
522  }
523};
524
525template <typename CHECK1>
526class Checker<CHECK1> : public CHECK1, public CheckerBase {
527public:
528  template <typename CHECKER>
529  static void _register(CHECKER *checkerCheckerManager &mgr) {
530    CHECK1::_register(checkermgr);
531  }
532};
533
534template <typename EVENT>
535class EventDispatcher {
536  CheckerManager *Mgr;
537public:
538  EventDispatcher() : Mgr(nullptr) { }
539
540  template <typename CHECKER>
541  static void _register(CHECKER *checkerCheckerManager &mgr) {
542    mgr._registerDispatcherForEvent<EVENT>();
543    static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
544  }
545
546  void dispatchEvent(const EVENT &eventconst {
547    Mgr->_dispatchEvent(event);
548  }
549};
550
551/// We dereferenced a location that may be null.
552struct ImplicitNullDerefEvent {
553  SVal Location;
554  bool IsLoad;
555  ExplodedNode *SinkNode;
556  BugReporter *BR;
557  // When true, the dereference is in the source code directly. When false, the
558  // dereference might happen later (for example pointer passed to a parameter
559  // that is marked with nonnull attribute.)
560  bool IsDirectDereference;
561
562  static int Tag;
563};
564
565/// A helper class which wraps a boolean value set to false by default.
566///
567/// This class should behave exactly like 'bool' except that it doesn't need to
568/// be explicitly initialized.
569struct DefaultBool {
570  bool val;
571  DefaultBool() : val(false) {}
572  /*implicit*/ operator bool&() { return val; }
573  /*implicit*/ operator const bool&() const { return val; }
574  DefaultBool &operator=(bool b) { val = breturn *this; }
575};
576
577// end ento namespace
578
579// end clang namespace
580
581#endif
582
clang::ento::check::ASTDecl::_checkDecl
clang::ento::check::ASTDecl::_handlesDecl
clang::ento::check::ASTDecl::_register
clang::ento::check::ASTCodeBody::_checkBody
clang::ento::check::ASTCodeBody::_register
clang::ento::check::EndOfTranslationUnit::_checkEndOfTranslationUnit
clang::ento::check::EndOfTranslationUnit::_register
clang::ento::check::PreStmt::_checkStmt
clang::ento::check::PreStmt::_handlesStmt
clang::ento::check::PreStmt::_register
clang::ento::check::PostStmt::_checkStmt
clang::ento::check::PostStmt::_handlesStmt
clang::ento::check::PostStmt::_register
clang::ento::check::PreObjCMessage::_checkObjCMessage
clang::ento::check::PreObjCMessage::_register
clang::ento::check::ObjCMessageNil::_checkObjCMessage
clang::ento::check::ObjCMessageNil::_register
clang::ento::check::PostObjCMessage::_checkObjCMessage
clang::ento::check::PostObjCMessage::_register
clang::ento::check::PreCall::_checkCall
clang::ento::check::PreCall::_register
clang::ento::check::PostCall::_checkCall
clang::ento::check::PostCall::_register
clang::ento::check::Location::_checkLocation
clang::ento::check::Location::_register
clang::ento::check::Bind::_checkBind
clang::ento::check::Bind::_register
clang::ento::check::EndAnalysis::_checkEndAnalysis
clang::ento::check::EndAnalysis::_register
clang::ento::check::BeginFunction::_checkBeginFunction
clang::ento::check::BeginFunction::_register
clang::ento::check::EndFunction::_checkEndFunction
clang::ento::check::EndFunction::_register
clang::ento::check::BranchCondition::_checkBranchCondition
clang::ento::check::BranchCondition::_register
clang::ento::check::NewAllocator::_checkNewAllocator
clang::ento::check::NewAllocator::_register
clang::ento::check::LiveSymbols::_checkLiveSymbols
clang::ento::check::LiveSymbols::_register
clang::ento::check::DeadSymbols::_checkDeadSymbols
clang::ento::check::DeadSymbols::_register
clang::ento::check::RegionChanges::_checkRegionChanges
clang::ento::check::RegionChanges::_register
clang::ento::check::PointerEscape::_checkPointerEscape
clang::ento::check::PointerEscape::_register
clang::ento::check::ConstPointerEscape::_checkConstPointerEscape
clang::ento::check::ConstPointerEscape::_register
clang::ento::check::Event::_checkEvent
clang::ento::check::Event::_register
clang::ento::eval::Assume::_evalAssume
clang::ento::eval::Assume::_register
clang::ento::eval::Call::_evalCall
clang::ento::eval::Call::_register
clang::ento::CheckerBase::Name
clang::ento::CheckerBase::getTagDescription
clang::ento::CheckerBase::getCheckName
clang::ento::CheckerBase::printState
clang::ento::Checker::_register
clang::ento::Checker::_register
clang::ento::EventDispatcher::Mgr
clang::ento::EventDispatcher::_register
clang::ento::EventDispatcher::dispatchEvent
clang::ento::ImplicitNullDerefEvent::Location
clang::ento::ImplicitNullDerefEvent::IsLoad
clang::ento::ImplicitNullDerefEvent::SinkNode
clang::ento::ImplicitNullDerefEvent::BR
clang::ento::ImplicitNullDerefEvent::IsDirectDereference
clang::ento::ImplicitNullDerefEvent::Tag
clang::ento::DefaultBool::val