Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/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++ allocation function call (operator `new`), via C++ new-expression
45
    Allocator,
46
47
    /// A C++ deallocation function call (operator `delete`), via C++
48
    /// delete-expression
49
    Deallocator
50
  };
51
52
private:
53
  /// Either expression or declaration (but not both at the same time)
54
  /// can be null.
55
56
  /// Call expression, is null when is not known (then declaration is non-null),
57
  /// or for implicit destructor calls (when no expression exists.)
58
  const Expr *E = nullptr;
59
60
  /// Corresponds to a statically known declaration of the called function,
61
  /// or null if it is not known (e.g. for a function pointer).
62
  const Decl *D = nullptr;
63
  Kind K;
64
65
public:
66
1.87k
  AnyCall(const CallExpr *CE) : E(CE) {
67
1.87k
    D = CE->getCalleeDecl();
68
1.87k
    K = (CE->getCallee()->getType()->getAs<BlockPointerType>()) ? 
Block36
69
1.87k
                                                                : 
Function1.84k
;
70
1.87k
    if (D && ((K == Function && 
!isa<FunctionDecl>(D)1.84k
) ||
71
1.87k
              
(1.80k
K == Block1.80k
&&
!isa<BlockDecl>(D)36
)))
72
90
      D = nullptr;
73
1.87k
  }
74
75
  AnyCall(const ObjCMessageExpr *ME)
76
2.20k
      : E(ME), D(ME->getMethodDecl()), K(ObjCMethod) {}
77
78
  AnyCall(const CXXNewExpr *NE)
79
25
      : E(NE), D(NE->getOperatorNew()), K(Allocator) {}
80
81
  AnyCall(const CXXDeleteExpr *NE)
82
0
      : E(NE), D(NE->getOperatorDelete()), K(Deallocator) {}
83
84
  AnyCall(const CXXConstructExpr *NE)
85
114
      : E(NE), D(NE->getConstructor()), K(Constructor) {}
86
87
9
  AnyCall(const CXXDestructorDecl *D) : E(nullptr), D(D), K(Destructor) {}
88
89
0
  AnyCall(const CXXConstructorDecl *D) : E(nullptr), D(D), K(Constructor) {}
90
91
692
  AnyCall(const ObjCMethodDecl *D) : E(nullptr), D(D), K(ObjCMethod) {}
92
93
1.65k
  AnyCall(const FunctionDecl *D) : E(nullptr), D(D) {
94
1.65k
    if (isa<CXXConstructorDecl>(D)) {
95
4
      K = Constructor;
96
1.64k
    } else if (isa <CXXDestructorDecl>(D)) {
97
0
      K = Destructor;
98
1.64k
    } else {
99
1.64k
      K = Function;
100
1.64k
    }
101
1.65k
102
1.65k
  }
103
104
  /// If {@code E} is a generic call (to ObjC method /function/block/etc),
105
  /// return a constructed {@code AnyCall} object. Return None otherwise.
106
4.22k
  static Optional<AnyCall> forExpr(const Expr *E) {
107
4.22k
    if (const auto *ME = dyn_cast<ObjCMessageExpr>(E)) {
108
2.20k
      return AnyCall(ME);
109
2.20k
    } else 
if (const auto *2.01k
CE2.01k
= dyn_cast<CallExpr>(E)) {
110
1.87k
      return AnyCall(CE);
111
1.87k
    } else 
if (const auto *139
CXNE139
= dyn_cast<CXXNewExpr>(E)) {
112
25
      return AnyCall(CXNE);
113
114
    } else if (const auto *CXDE = dyn_cast<CXXDeleteExpr>(E)) {
114
0
      return AnyCall(CXDE);
115
114
    } else if (const auto *CXCE = dyn_cast<CXXConstructExpr>(E)) {
116
114
      return AnyCall(CXCE);
117
114
    } else {
118
0
      return None;
119
0
    }
120
4.22k
  }
121
122
  /// If {@code D} is a callable (Objective-C method or a function), return
123
  /// a constructed {@code AnyCall} object. Return None otherwise.
124
  // FIXME: block support.
125
1.97k
  static Optional<AnyCall> forDecl(const Decl *D) {
126
1.97k
    if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
127
1.47k
      return AnyCall(FD);
128
1.47k
    } else 
if (const auto *498
MD498
= dyn_cast<ObjCMethodDecl>(D)) {
129
456
      return AnyCall(MD);
130
456
    }
131
42
    return None;
132
42
  }
133
134
  /// \returns formal parameters for direct calls (including virtual calls)
135
13.9k
  ArrayRef<ParmVarDecl *> parameters() const {
136
13.9k
    if (!D)
137
152
      return None;
138
13.8k
139
13.8k
    if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
140
7.65k
      return FD->parameters();
141
7.65k
    } else 
if (const auto *6.15k
MD6.15k
= dyn_cast<ObjCMethodDecl>(D)) {
142
6.15k
      return MD->parameters();
143
6.15k
    } else 
if (const auto *0
BD0
= dyn_cast<BlockDecl>(D)) {
144
0
      return BD->parameters();
145
0
    } else {
146
0
      return None;
147
0
    }
148
13.8k
  }
149
150
  using param_const_iterator = ArrayRef<ParmVarDecl *>::const_iterator;
151
5.92k
  param_const_iterator param_begin() const { return parameters().begin(); }
152
5.92k
  param_const_iterator param_end() const { return parameters().end(); }
153
1.32k
  size_t param_size() const { return parameters().size(); }
154
0
  bool param_empty() const { return parameters().empty(); }
155
156
605
  QualType getReturnType(ASTContext &Ctx) const {
157
605
    switch (K) {
158
605
    case Function:
159
545
      if (E)
160
0
        return cast<CallExpr>(E)->getCallReturnType(Ctx);
161
545
      return cast<FunctionDecl>(D)->getReturnType();
162
545
    case ObjCMethod:
163
60
      if (E)
164
0
        return cast<ObjCMessageExpr>(E)->getCallReturnType(Ctx);
165
60
      return cast<ObjCMethodDecl>(D)->getReturnType();
166
60
    case Block:
167
0
      // FIXME: BlockDecl does not know its return type,
168
0
      // hence the asymmetry with the function and method cases above.
169
0
      return cast<CallExpr>(E)->getCallReturnType(Ctx);
170
60
    case Destructor:
171
0
    case Constructor:
172
0
    case Allocator:
173
0
    case Deallocator:
174
0
      return cast<FunctionDecl>(D)->getReturnType();
175
0
    }
176
0
    llvm_unreachable("Unknown AnyCall::Kind");
177
0
  }
178
179
  /// \returns Function identifier if it is a named declaration,
180
  /// {@code nullptr} otherwise.
181
82
  const IdentifierInfo *getIdentifier() const {
182
82
    if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
183
82
      return ND->getIdentifier();
184
0
    return nullptr;
185
0
  }
186
187
3.71k
  const Decl *getDecl() const {
188
3.71k
    return D;
189
3.71k
  }
190
191
2.83k
  const Expr *getExpr() const {
192
2.83k
    return E;
193
2.83k
  }
194
195
5.96k
  Kind getKind() const {
196
5.96k
    return K;
197
5.96k
  }
198
199
0
  void dump() const {
200
0
    if (E)
201
0
      E->dump();
202
0
    if (D)
203
0
      D->dump();
204
0
  }
205
};
206
207
}
208
209
#endif // LLVM_CLANG_ANALYSIS_ANY_CALL_H