reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
  200
  201
  202
  203
  204
  205
  206
  207
  208
  209
  210
  211
  212
  213
  214
  215
  216
  217
  218
  219
  220
  221
  222
  223
  224
  225
  226
  227
  228
  229
  230
  231
  232
  233
  234
  235
  236
  237
  238
  239
  240
  241
  242
  243
  244
  245
  246
  247
  248
  249
  250
  251
  252
  253
  254
  255
  256
  257
  258
  259
  260
  261
  262
  263
  264
  265
  266
  267
  268
  269
  270
  271
  272
  273
  274
  275
  276
  277
  278
  279
  280
  281
  282
  283
  284
  285
  286
  287
  288
  289
  290
  291
  292
  293
  294
  295
  296
  297
  298
  299
  300
  301
  302
  303
  304
  305
  306
  307
  308
  309
  310
  311
  312
  313
  314
  315
  316
  317
  318
  319
  320
  321
  322
  323
  324
  325
  326
  327
  328
  329
  330
  331
  332
  333
  334
//===- CheckerDocumentation.cpp - Documentation checker ---------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This checker lists all the checker callbacks and provides documentation for
// checker writers.
//
//===----------------------------------------------------------------------===//

#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"

using namespace clang;
using namespace ento;

// All checkers should be placed into anonymous namespace.
// We place the CheckerDocumentation inside ento namespace to make the
// it visible in doxygen.
namespace clang {
namespace ento {

/// This checker documents the callback functions checkers can use to implement
/// the custom handling of the specific events during path exploration as well
/// as reporting bugs. Most of the callbacks are targeted at path-sensitive
/// checking.
///
/// \sa CheckerContext
class CheckerDocumentation : public Checker< check::PreStmt<ReturnStmt>,
                                       check::PostStmt<DeclStmt>,
                                       check::PreObjCMessage,
                                       check::PostObjCMessage,
                                       check::ObjCMessageNil,
                                       check::PreCall,
                                       check::PostCall,
                                       check::BranchCondition,
                                       check::NewAllocator,
                                       check::Location,
                                       check::Bind,
                                       check::DeadSymbols,
                                       check::BeginFunction,
                                       check::EndFunction,
                                       check::EndAnalysis,
                                       check::EndOfTranslationUnit,
                                       eval::Call,
                                       eval::Assume,
                                       check::LiveSymbols,
                                       check::RegionChanges,
                                       check::PointerEscape,
                                       check::ConstPointerEscape,
                                       check::Event<ImplicitNullDerefEvent>,
                                       check::ASTDecl<FunctionDecl> > {
public:
  /// Pre-visit the Statement.
  ///
  /// The method will be called before the analyzer core processes the
  /// statement. The notification is performed for every explored CFGElement,
  /// which does not include the control flow statements such as IfStmt. The
  /// callback can be specialized to be called with any subclass of Stmt.
  ///
  /// See checkBranchCondition() callback for performing custom processing of
  /// the branching statements.
  ///
  /// check::PreStmt<ReturnStmt>
  void checkPreStmt(const ReturnStmt *DS, CheckerContext &C) const {}

  /// Post-visit the Statement.
  ///
  /// The method will be called after the analyzer core processes the
  /// statement. The notification is performed for every explored CFGElement,
  /// which does not include the control flow statements such as IfStmt. The
  /// callback can be specialized to be called with any subclass of Stmt.
  ///
  /// check::PostStmt<DeclStmt>
  void checkPostStmt(const DeclStmt *DS, CheckerContext &C) const;

  /// Pre-visit the Objective C message.
  ///
  /// This will be called before the analyzer core processes the method call.
  /// This is called for any action which produces an Objective-C message send,
  /// including explicit message syntax and property access.
  ///
  /// check::PreObjCMessage
  void checkPreObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const {}

  /// Post-visit the Objective C message.
  /// \sa checkPreObjCMessage()
  ///
  /// check::PostObjCMessage
  void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const {}

  /// Visit an Objective-C message whose receiver is nil.
  ///
  /// This will be called when the analyzer core processes a method call whose
  /// receiver is definitely nil. In this case, check{Pre/Post}ObjCMessage and
  /// check{Pre/Post}Call will not be called.
  ///
  /// check::ObjCMessageNil
  void checkObjCMessageNil(const ObjCMethodCall &M, CheckerContext &C) const {}

  /// Pre-visit an abstract "call" event.
  ///
  /// This is used for checkers that want to check arguments or attributed
  /// behavior for functions and methods no matter how they are being invoked.
  ///
  /// Note that this includes ALL cross-body invocations, so if you want to
  /// limit your checks to, say, function calls, you should test for that at the
  /// beginning of your callback function.
  ///
  /// check::PreCall
  void checkPreCall(const CallEvent &Call, CheckerContext &C) const {}

  /// Post-visit an abstract "call" event.
  /// \sa checkPreObjCMessage()
  ///
  /// check::PostCall
  void checkPostCall(const CallEvent &Call, CheckerContext &C) const {}

  /// Pre-visit of the condition statement of a branch (such as IfStmt).
  void checkBranchCondition(const Stmt *Condition, CheckerContext &Ctx) const {}

  /// Post-visit the C++ operator new's allocation call.
  ///
  /// Execution of C++ operator new consists of the following phases: (1) call
  /// default or overridden operator new() to allocate memory (2) cast the
  /// return value of operator new() from void pointer type to class pointer
  /// type, (3) assuming that the value is non-null, call the object's
  /// constructor over this pointer, (4) declare that the value of the
  /// new-expression is this pointer. This callback is called between steps
  /// (2) and (3). Post-call for the allocator is called after step (1).
  /// Pre-statement for the new-expression is called on step (4) when the value
  /// of the expression is evaluated.
  /// \param NE     The C++ new-expression that triggered the allocation.
  /// \param Target The allocated region, casted to the class type.
  void checkNewAllocator(const CXXNewExpr *NE, SVal Target,
                         CheckerContext &) const {}

  /// Called on a load from and a store to a location.
  ///
  /// The method will be called each time a location (pointer) value is
  /// accessed.
  /// \param Loc    The value of the location (pointer).
  /// \param IsLoad The flag specifying if the location is a store or a load.
  /// \param S      The load is performed while processing the statement.
  ///
  /// check::Location
  void checkLocation(SVal Loc, bool IsLoad, const Stmt *S,
                     CheckerContext &) const {}

  /// Called on binding of a value to a location.
  ///
  /// \param Loc The value of the location (pointer).
  /// \param Val The value which will be stored at the location Loc.
  /// \param S   The bind is performed while processing the statement S.
  ///
  /// check::Bind
  void checkBind(SVal Loc, SVal Val, const Stmt *S, CheckerContext &) const {}

  /// Called whenever a symbol becomes dead.
  ///
  /// This callback should be used by the checkers to aggressively clean
  /// up/reduce the checker state, which is important for reducing the overall
  /// memory usage. Specifically, if a checker keeps symbol specific information
  /// in the state, it can and should be dropped after the symbol becomes dead.
  /// In addition, reporting a bug as soon as the checker becomes dead leads to
  /// more precise diagnostics. (For example, one should report that a malloced
  /// variable is not freed right after it goes out of scope.)
  ///
  /// \param SR The SymbolReaper object can be queried to determine which
  ///           symbols are dead.
  ///
  /// check::DeadSymbols
  void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const {}


  /// Called when the analyzer core starts analyzing a function,
  /// regardless of whether it is analyzed at the top level or is inlined.
  ///
  /// check::BeginFunction
  void checkBeginFunction(CheckerContext &Ctx) const {}

  /// Called when the analyzer core reaches the end of a
  /// function being analyzed regardless of whether it is analyzed at the top
  /// level or is inlined.
  ///
  /// check::EndFunction
  void checkEndFunction(const ReturnStmt *RS, CheckerContext &Ctx) const {}

  /// Called after all the paths in the ExplodedGraph reach end of path
  /// - the symbolic execution graph is fully explored.
  ///
  /// This callback should be used in cases when a checker needs to have a
  /// global view of the information generated on all paths. For example, to
  /// compare execution summary/result several paths.
  /// See IdempotentOperationChecker for a usage example.
  ///
  /// check::EndAnalysis
  void checkEndAnalysis(ExplodedGraph &G,
                        BugReporter &BR,
                        ExprEngine &Eng) const {}

  /// Called after analysis of a TranslationUnit is complete.
  ///
  /// check::EndOfTranslationUnit
  void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
                                 AnalysisManager &Mgr,
                                 BugReporter &BR) const {}

  /// Evaluates function call.
  ///
  /// The analysis core treats all function calls in the same way. However, some
  /// functions have special meaning, which should be reflected in the program
  /// state. This callback allows a checker to provide domain specific knowledge
  /// about the particular functions it knows about.
  ///
  /// \returns true if the call has been successfully evaluated
  /// and false otherwise. Note, that only one checker can evaluate a call. If
  /// more than one checker claims that they can evaluate the same call the
  /// first one wins.
  ///
  /// eval::Call
  bool evalCall(const CallExpr *CE, CheckerContext &C) const { return true; }

  /// Handles assumptions on symbolic values.
  ///
  /// This method is called when a symbolic expression is assumed to be true or
  /// false. For example, the assumptions are performed when evaluating a
  /// condition at a branch. The callback allows checkers track the assumptions
  /// performed on the symbols of interest and change the state accordingly.
  ///
  /// eval::Assume
  ProgramStateRef evalAssume(ProgramStateRef State,
                                 SVal Cond,
                                 bool Assumption) const { return State; }

  /// Allows modifying SymbolReaper object. For example, checkers can explicitly
  /// register symbols of interest as live. These symbols will not be marked
  /// dead and removed.
  ///
  /// check::LiveSymbols
  void checkLiveSymbols(ProgramStateRef State, SymbolReaper &SR) const {}

  /// Called when the contents of one or more regions change.
  ///
  /// This can occur in many different ways: an explicit bind, a blanket
  /// invalidation of the region contents, or by passing a region to a function
  /// call whose behavior the analyzer cannot model perfectly.
  ///
  /// \param State The current program state.
  /// \param Invalidated A set of all symbols potentially touched by the change.
  /// \param ExplicitRegions The regions explicitly requested for invalidation.
  ///        For a function call, this would be the arguments. For a bind, this
  ///        would be the region being bound to.
  /// \param Regions The transitive closure of regions accessible from,
  ///        \p ExplicitRegions, i.e. all regions that may have been touched
  ///        by this change. For a simple bind, this list will be the same as
  ///        \p ExplicitRegions, since a bind does not affect the contents of
  ///        anything accessible through the base region.
  /// \param LCtx LocationContext that is useful for getting various contextual
  ///        info, like callstack, CFG etc.
  /// \param Call The opaque call triggering this invalidation. Will be 0 if the
  ///        change was not triggered by a call.
  ///
  /// check::RegionChanges
  ProgramStateRef
    checkRegionChanges(ProgramStateRef State,
                       const InvalidatedSymbols *Invalidated,
                       ArrayRef<const MemRegion *> ExplicitRegions,
                       ArrayRef<const MemRegion *> Regions,
                       const LocationContext *LCtx,
                       const CallEvent *Call) const {
    return State;
  }

  /// Called when pointers escape.
  ///
  /// This notifies the checkers about pointer escape, which occurs whenever
  /// the analyzer cannot track the symbol any more. For example, as a
  /// result of assigning a pointer into a global or when it's passed to a
  /// function call the analyzer cannot model.
  ///
  /// \param State The state at the point of escape.
  /// \param Escaped The list of escaped symbols.
  /// \param Call The corresponding CallEvent, if the symbols escape as
  /// parameters to the given call.
  /// \param Kind How the symbols have escaped.
  /// \returns Checkers can modify the state by returning a new state.
  ProgramStateRef checkPointerEscape(ProgramStateRef State,
                                     const InvalidatedSymbols &Escaped,
                                     const CallEvent *Call,
                                     PointerEscapeKind Kind) const {
    return State;
  }

  /// Called when const pointers escape.
  ///
  /// Note: in most cases checkPointerEscape callback is sufficient.
  /// \sa checkPointerEscape
  ProgramStateRef checkConstPointerEscape(ProgramStateRef State,
                                     const InvalidatedSymbols &Escaped,
                                     const CallEvent *Call,
                                     PointerEscapeKind Kind) const {
    return State;
  }

  /// check::Event<ImplicitNullDerefEvent>
  void checkEvent(ImplicitNullDerefEvent Event) const {}

  /// Check every declaration in the AST.
  ///
  /// An AST traversal callback, which should only be used when the checker is
  /// not path sensitive. It will be called for every Declaration in the AST and
  /// can be specialized to only be called on subclasses of Decl, for example,
  /// FunctionDecl.
  ///
  /// check::ASTDecl<FunctionDecl>
  void checkASTDecl(const FunctionDecl *D,
                    AnalysisManager &Mgr,
                    BugReporter &BR) const {}
};

void CheckerDocumentation::checkPostStmt(const DeclStmt *DS,
                                         CheckerContext &C) const {
}

} // end namespace ento
} // end namespace clang