Coverage Report

Created: 2021-09-21 08:58

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/Analysis/AnyCall.h
Line
Count
Source (jump to first uncovered line)
1
//=== AnyCall.h - Abstraction over different callables --------*- 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
// A utility class for performing generic operations over different callables.
10
//
11
//===----------------------------------------------------------------------===//
12
//
13
#ifndef LLVM_CLANG_ANALYSIS_ANY_CALL_H
14
#define LLVM_CLANG_ANALYSIS_ANY_CALL_H
15
16
#include "clang/AST/Decl.h"
17
#include "clang/AST/ExprCXX.h"
18
#include "clang/AST/ExprObjC.h"
19
20
namespace clang {
21
22
/// An instance of this class corresponds to a call.
23
/// It might be a syntactically-concrete call, done as a part of evaluating an
24
/// expression, or it may be an abstract callee with no associated expression.
25
class AnyCall {
26
public:
27
  enum Kind {
28
    /// A function, function pointer, or a C++ method call
29
    Function,
30
31
    /// A call to an Objective-C method
32
    ObjCMethod,
33
34
    /// A call to an Objective-C block
35
    Block,
36
37
    /// An implicit C++ destructor call (called implicitly
38
    /// or by operator 'delete')
39
    Destructor,
40
41
    /// An implicit or explicit C++ constructor call
42
    Constructor,
43
44
    /// A C++ inherited constructor produced by a "using T::T" directive
45
    InheritedConstructor,
46
47
    /// A C++ allocation function call (operator `new`), via C++ new-expression
48
    Allocator,
49
50
    /// A C++ deallocation function call (operator `delete`), via C++
51
    /// delete-expression
52
    Deallocator
53
  };
54
55
private:
56
  /// Either expression or declaration (but not both at the same time)
57
  /// can be null.
58
59
  /// Call expression, is null when is not known (then declaration is non-null),
60
  /// or for implicit destructor calls (when no expression exists.)
61
  const Expr *E = nullptr;
62
63
  /// Corresponds to a statically known declaration of the called function,
64
  /// or null if it is not known (e.g. for a function pointer).
65
  const Decl *D = nullptr;
66
  Kind K;
67
68
public:
69
1.94k
  AnyCall(const CallExpr *CE) : E(CE) {
70
1.94k
    D = CE->getCalleeDecl();
71
1.94k
    K = (CE->getCallee()->getType()->getAs<BlockPointerType>()) ? 
Block38
72
1.94k
                                                                : 
Function1.91k
;
73
1.94k
    if (D && ((K == Function && 
!isa<FunctionDecl>(D)1.91k
) ||
74
1.94k
              
(1.87k
K == Block1.87k
&&
!isa<BlockDecl>(D)38
)))
75
92
      D = nullptr;
76
1.94k
  }
77
78
  AnyCall(const ObjCMessageExpr *ME)
79
2.31k
      : E(ME), D(ME->getMethodDecl()), K(ObjCMethod) {}
80
81
  AnyCall(const CXXNewExpr *NE)
82
24
      : E(NE), D(NE->getOperatorNew()), K(Allocator) {}
83
84
  AnyCall(const CXXDeleteExpr *NE)
85
1
      : E(NE), D(NE->getOperatorDelete()), K(Deallocator) {}
86
87
  AnyCall(const CXXConstructExpr *NE)
88
126
      : E(NE), D(NE->getConstructor()), K(Constructor) {}
89
90
  AnyCall(const CXXInheritedCtorInitExpr *CIE)
91
1
      : E(CIE), D(CIE->getConstructor()), K(InheritedConstructor) {}
92
93
13
  AnyCall(const CXXDestructorDecl *D) : E(nullptr), D(D), K(Destructor) {}
94
95
0
  AnyCall(const CXXConstructorDecl *D) : E(nullptr), D(D), K(Constructor) {}
96
97
1.52k
  AnyCall(const ObjCMethodDecl *D) : E(nullptr), D(D), K(ObjCMethod) {}
98
99
14.0k
  AnyCall(const FunctionDecl *D) : E(nullptr), D(D) {
100
14.0k
    if (isa<CXXConstructorDecl>(D)) {
101
956
      K = Constructor;
102
13.1k
    } else if (isa <CXXDestructorDecl>(D)) {
103
57
      K = Destructor;
104
13.0k
    } else {
105
13.0k
      K = Function;
106
13.0k
    }
107
108
14.0k
  }
109
110
  /// If @c E is a generic call (to ObjC method /function/block/etc),
111
  /// return a constructed @c AnyCall object. Return None otherwise.
112
4.41k
  static Optional<AnyCall> forExpr(const Expr *E) {
113
4.41k
    if (const auto *ME = dyn_cast<ObjCMessageExpr>(E)) {
114
2.31k
      return AnyCall(ME);
115
2.31k
    } else 
if (const auto *2.10k
CE2.10k
= dyn_cast<CallExpr>(E)) {
116
1.94k
      return AnyCall(CE);
117
1.94k
    } else 
if (const auto *152
CXNE152
= dyn_cast<CXXNewExpr>(E)) {
118
24
      return AnyCall(CXNE);
119
128
    } else if (const auto *CXDE = dyn_cast<CXXDeleteExpr>(E)) {
120
1
      return AnyCall(CXDE);
121
127
    } else if (const auto *CXCE = dyn_cast<CXXConstructExpr>(E)) {
122
126
      return AnyCall(CXCE);
123
126
    } else 
if (const auto *1
CXCIE1
= dyn_cast<CXXInheritedCtorInitExpr>(E)) {
124
1
      return AnyCall(CXCIE);
125
1
    } else {
126
0
      return None;
127
0
    }
128
4.41k
  }
129
130
  /// If @c D is a callable (Objective-C method or a function), return
131
  /// a constructed @c AnyCall object. Return None otherwise.
132
  // FIXME: block support.
133
15.4k
  static Optional<AnyCall> forDecl(const Decl *D) {
134
15.4k
    if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
135
13.9k
      return AnyCall(FD);
136
13.9k
    } else 
if (const auto *1.55k
MD1.55k
= dyn_cast<ObjCMethodDecl>(D)) {
137
1.28k
      return AnyCall(MD);
138
1.28k
    }
139
271
    return None;
140
15.4k
  }
141
142
  /// \returns formal parameters for direct calls (including virtual calls)
143
53.9k
  ArrayRef<ParmVarDecl *> parameters() const {
144
53.9k
    if (!D)
145
152
      return None;
146
147
53.7k
    if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
148
44.8k
      return FD->parameters();
149
44.8k
    } else 
if (const auto *8.87k
MD8.87k
= dyn_cast<ObjCMethodDecl>(D)) {
150
8.87k
      return MD->parameters();
151
8.87k
    } else 
if (const auto *0
BD0
= dyn_cast<BlockDecl>(D)) {
152
0
      return BD->parameters();
153
0
    } else {
154
0
      return None;
155
0
    }
156
53.7k
  }
157
158
  using param_const_iterator = ArrayRef<ParmVarDecl *>::const_iterator;
159
6.21k
  param_const_iterator param_begin() const { return parameters().begin(); }
160
6.21k
  param_const_iterator param_end() const { return parameters().end(); }
161
14.5k
  size_t param_size() const { return parameters().size(); }
162
0
  bool param_empty() const { return parameters().empty(); }
163
164
698
  QualType getReturnType(ASTContext &Ctx) const {
165
698
    switch (K) {
166
630
    case Function:
167
630
      if (E)
168
0
        return cast<CallExpr>(E)->getCallReturnType(Ctx);
169
630
      return cast<FunctionDecl>(D)->getReturnType();
170
62
    case ObjCMethod:
171
62
      if (E)
172
0
        return cast<ObjCMessageExpr>(E)->getCallReturnType(Ctx);
173
62
      return cast<ObjCMethodDecl>(D)->getReturnType();
174
0
    case Block:
175
      // FIXME: BlockDecl does not know its return type,
176
      // hence the asymmetry with the function and method cases above.
177
0
      return cast<CallExpr>(E)->getCallReturnType(Ctx);
178
3
    case Destructor:
179
6
    case Constructor:
180
6
    case InheritedConstructor:
181
6
    case Allocator:
182
6
    case Deallocator:
183
6
      return cast<FunctionDecl>(D)->getReturnType();
184
698
    }
185
0
    llvm_unreachable("Unknown AnyCall::Kind");
186
0
  }
187
188
  /// \returns Function identifier if it is a named declaration,
189
  /// @c nullptr otherwise.
190
84
  const IdentifierInfo *getIdentifier() const {
191
84
    if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
192
84
      return ND->getIdentifier();
193
0
    return nullptr;
194
84
  }
195
196
16.9k
  const Decl *getDecl() const {
197
16.9k
    return D;
198
16.9k
  }
199
200
2.98k
  const Expr *getExpr() const {
201
2.98k
    return E;
202
2.98k
  }
203
204
6.26k
  Kind getKind() const {
205
6.26k
    return K;
206
6.26k
  }
207
208
0
  void dump() const {
209
0
    if (E)
210
0
      E->dump();
211
0
    if (D)
212
0
      D->dump();
213
0
  }
214
};
215
216
}
217
218
#endif // LLVM_CLANG_ANALYSIS_ANY_CALL_H