aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/clang16/include/clang/Analysis/Analyses/CalledOnceCheck.h
blob: a39d56f9e3091f07769b51074b71751e2ef1a58a (plain) (blame)
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
#pragma once

#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif

//===- CalledOnceCheck.h - Check 'called once' parameters -------*- 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 file defines a check for function-like parameters that should be
//  called exactly one time.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_CALLEDONCECHECK_H
#define LLVM_CLANG_ANALYSIS_ANALYSES_CALLEDONCECHECK_H

namespace clang {

class AnalysisDeclContext;
class BlockDecl;
class CFG;
class Decl;
class Expr;
class ParmVarDecl;
class Stmt;

/// Classification of situations when parameter is not called on every path.
/// \enum IfThen -- then branch of the if statement has no call.
/// \enum IfElse -- else branch of the if statement has no call.
/// \enum Switch -- one of the switch cases doesn't have a call.
/// \enum SwitchSkipped -- there is no call if none of the cases appies.
/// \enum LoopEntered -- no call when the loop is entered.
/// \enum LoopSkipped -- no call when the loop is not entered.
/// \enum FallbackReason -- fallback case when we were not able to figure out
/// the reason.
enum class NeverCalledReason {
  IfThen,
  IfElse,
  Switch,
  SwitchSkipped,
  LoopEntered,
  LoopSkipped,
  FallbackReason,
  LARGEST_VALUE = FallbackReason
};

class CalledOnceCheckHandler {
public:
  CalledOnceCheckHandler() = default;
  virtual ~CalledOnceCheckHandler() = default;

  /// Called when parameter is called twice.
  /// \param Parameter -- parameter that should be called once.
  /// \param Call -- call to report the warning.
  /// \param PrevCall -- previous call.
  /// \param IsCompletionHandler -- true, if parameter is a completion handler.
  /// \param Poised -- true, if the second call is guaranteed to happen after
  /// the first call.
  virtual void handleDoubleCall(const ParmVarDecl *Parameter, const Expr *Call,
                                const Expr *PrevCall, bool IsCompletionHandler,
                                bool Poised) {}

  /// Called when parameter is not called at all.
  /// \param Parameter -- parameter that should be called once.
  /// \param IsCompletionHandler -- true, if parameter is a completion handler.
  virtual void handleNeverCalled(const ParmVarDecl *Parameter,
                                 bool IsCompletionHandler) {}

  /// Called when captured parameter is not called at all.
  /// \param Parameter -- parameter that should be called once.
  /// \param Where -- declaration that captures \p Parameter
  /// \param IsCompletionHandler -- true, if parameter is a completion handler.
  virtual void handleCapturedNeverCalled(const ParmVarDecl *Parameter,
                                         const Decl *Where,
                                         bool IsCompletionHandler) {}

  /// Called when parameter is not called on one of the paths.
  /// Usually we try to find a statement that is the least common ancestor of
  /// the path containing the call and not containing the call.  This helps us
  /// to pinpoint a bad path for the user.
  /// \param Parameter -- parameter that should be called once.
  /// \param Function -- function declaration where the problem occurred.
  /// \param Where -- the least common ancestor statement.
  /// \param Reason -- a reason describing the path without a call.
  /// \param IsCalledDirectly -- true, if parameter actually gets called on
  /// the other path.  It is opposed to be used in some other way (added to some
  /// collection, passed as a parameter, etc.).
  /// \param IsCompletionHandler -- true, if parameter is a completion handler.
  virtual void handleNeverCalled(const ParmVarDecl *Parameter,
                                 const Decl *Function, const Stmt *Where,
                                 NeverCalledReason Reason,
                                 bool IsCalledDirectly,
                                 bool IsCompletionHandler) {}

  /// Called when the block is guaranteed to be called exactly once.
  /// It means that we can be stricter with what we report on that block.
  /// \param Block -- block declaration that is known to be called exactly once.
  virtual void
  handleBlockThatIsGuaranteedToBeCalledOnce(const BlockDecl *Block) {}

  /// Called when the block has no guarantees about how many times it can get
  /// called.
  /// It means that we should be more lenient with reporting warnings in it.
  /// \param Block -- block declaration in question.
  virtual void handleBlockWithNoGuarantees(const BlockDecl *Block) {}
};

/// Check given CFG for 'called once' parameter violations.
///
/// It traverses the function and tracks how such parameters are used.
/// It detects two main violations:
///   * parameter is called twice
///   * parameter is not called
///
/// \param AC -- context.
/// \param Handler -- a handler for found violations.
/// \param CheckConventionalParameters -- true, if we want to check parameters
/// not explicitly marked as 'called once', but having the same requirements
/// according to conventions.
void checkCalledOnceParameters(AnalysisDeclContext &AC,
                               CalledOnceCheckHandler &Handler,
                               bool CheckConventionalParameters);

} // end namespace clang

#endif /* LLVM_CLANG_ANALYSIS_ANALYSES_CALLEDONCECHECK_H */

#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif