Coverage Report

Created: 2019-02-23 12:57

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h
Line
Count
Source (jump to first uncovered line)
1
//==- ProgramPoint.h - Program Points for Path-Sensitive Analysis --*- 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 the interface ProgramPoint, which identifies a
10
//  distinct location in a function.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#ifndef LLVM_CLANG_ANALYSIS_PROGRAMPOINT_H
15
#define LLVM_CLANG_ANALYSIS_PROGRAMPOINT_H
16
17
#include "clang/Analysis/AnalysisDeclContext.h"
18
#include "clang/Analysis/CFG.h"
19
#include "llvm/ADT/DenseMap.h"
20
#include "llvm/ADT/FoldingSet.h"
21
#include "llvm/ADT/Optional.h"
22
#include "llvm/ADT/PointerIntPair.h"
23
#include "llvm/ADT/StringRef.h"
24
#include "llvm/Support/Casting.h"
25
#include "llvm/Support/DataTypes.h"
26
#include <cassert>
27
#include <string>
28
#include <utility>
29
30
namespace clang {
31
32
class AnalysisDeclContext;
33
class FunctionDecl;
34
class LocationContext;
35
36
/// ProgramPoints can be "tagged" as representing points specific to a given
37
/// analysis entity.  Tags are abstract annotations, with an associated
38
/// description and potentially other information.
39
class ProgramPointTag {
40
public:
41
15.8k
  ProgramPointTag(void *tagKind = nullptr) : TagKind(tagKind) {}
42
  virtual ~ProgramPointTag();
43
  virtual StringRef getTagDescription() const = 0;
44
45
protected:
46
  /// Used to implement 'isKind' in subclasses.
47
0
  const void *getTagKind() { return TagKind; }
48
49
private:
50
  const void *TagKind;
51
};
52
53
class SimpleProgramPointTag : public ProgramPointTag {
54
  std::string Desc;
55
public:
56
  SimpleProgramPointTag(StringRef MsgProvider, StringRef Msg);
57
  StringRef getTagDescription() const override;
58
};
59
60
0
class ProgramPoint {
61
public:
62
  enum Kind { BlockEdgeKind,
63
              BlockEntranceKind,
64
              BlockExitKind,
65
              PreStmtKind,
66
              PreStmtPurgeDeadSymbolsKind,
67
              PostStmtPurgeDeadSymbolsKind,
68
              PostStmtKind,
69
              PreLoadKind,
70
              PostLoadKind,
71
              PreStoreKind,
72
              PostStoreKind,
73
              PostConditionKind,
74
              PostLValueKind,
75
              PostAllocatorCallKind,
76
              MinPostStmtKind = PostStmtKind,
77
              MaxPostStmtKind = PostAllocatorCallKind,
78
              PostInitializerKind,
79
              CallEnterKind,
80
              CallExitBeginKind,
81
              CallExitEndKind,
82
              FunctionExitKind,
83
              PreImplicitCallKind,
84
              PostImplicitCallKind,
85
              MinImplicitCallKind = PreImplicitCallKind,
86
              MaxImplicitCallKind = PostImplicitCallKind,
87
              LoopExitKind,
88
              EpsilonKind};
89
90
private:
91
  const void *Data1;
92
  llvm::PointerIntPair<const void *, 2, unsigned> Data2;
93
94
  // The LocationContext could be NULL to allow ProgramPoint to be used in
95
  // context insensitive analysis.
96
  llvm::PointerIntPair<const LocationContext *, 2, unsigned> L;
97
98
  llvm::PointerIntPair<const ProgramPointTag *, 2, unsigned> Tag;
99
100
protected:
101
3.97M
  ProgramPoint() = default;
102
  ProgramPoint(const void *P,
103
               Kind k,
104
               const LocationContext *l,
105
               const ProgramPointTag *tag = nullptr)
106
    : Data1(P),
107
      Data2(nullptr, (((unsigned) k) >> 0) & 0x3),
108
      L(l, (((unsigned) k) >> 2) & 0x3),
109
256k
      Tag(tag, (((unsigned) k) >> 4) & 0x3) {
110
256k
        assert(getKind() == k);
111
256k
        assert(getLocationContext() == l);
112
256k
        assert(getData1() == P);
113
256k
      }
114
115
  ProgramPoint(const void *P1,
116
               const void *P2,
117
               Kind k,
118
               const LocationContext *l,
119
               const ProgramPointTag *tag = nullptr)
120
    : Data1(P1),
121
      Data2(P2, (((unsigned) k) >> 0) & 0x3),
122
      L(l, (((unsigned) k) >> 2) & 0x3),
123
6.05M
      Tag(tag, (((unsigned) k) >> 4) & 0x3) {}
124
125
protected:
126
7.37M
  const void *getData1() const { return Data1; }
127
4.81M
  const void *getData2() const { return Data2.getPointer(); }
128
66.5k
  void setData2(const void *d) { Data2.setPointer(d); }
129
130
public:
131
  /// Create a new ProgramPoint object that is the same as the original
132
  /// except for using the specified tag value.
133
950k
  ProgramPoint withTag(const ProgramPointTag *tag) const {
134
950k
    return ProgramPoint(getData1(), getData2(), getKind(),
135
950k
                        getLocationContext(), tag);
136
950k
  }
137
138
  /// Convert to the specified ProgramPoint type, asserting that this
139
  /// ProgramPoint is of the desired type.
140
  template<typename T>
141
1.00M
  T castAs() const {
142
1.00M
    assert(T::isKind(*this));
143
1.00M
    T t;
144
1.00M
    ProgramPoint& PP = t;
145
1.00M
    PP = *this;
146
1.00M
    return t;
147
1.00M
  }
clang::StmtPoint clang::ProgramPoint::castAs<clang::StmtPoint>() const
Line
Count
Source
141
815
  T castAs() const {
142
815
    assert(T::isKind(*this));
143
815
    T t;
144
815
    ProgramPoint& PP = t;
145
815
    PP = *this;
146
815
    return t;
147
815
  }
clang::BlockEdge clang::ProgramPoint::castAs<clang::BlockEdge>() const
Line
Count
Source
141
178k
  T castAs() const {
142
178k
    assert(T::isKind(*this));
143
178k
    T t;
144
178k
    ProgramPoint& PP = t;
145
178k
    PP = *this;
146
178k
    return t;
147
178k
  }
clang::BlockEntrance clang::ProgramPoint::castAs<clang::BlockEntrance>() const
Line
Count
Source
141
109k
  T castAs() const {
142
109k
    assert(T::isKind(*this));
143
109k
    T t;
144
109k
    ProgramPoint& PP = t;
145
109k
    PP = *this;
146
109k
    return t;
147
109k
  }
clang::CallEnter clang::ProgramPoint::castAs<clang::CallEnter>() const
Line
Count
Source
141
26.6k
  T castAs() const {
142
26.6k
    assert(T::isKind(*this));
143
26.6k
    T t;
144
26.6k
    ProgramPoint& PP = t;
145
26.6k
    PP = *this;
146
26.6k
    return t;
147
26.6k
  }
clang::PostStmt clang::ProgramPoint::castAs<clang::PostStmt>() const
Line
Count
Source
141
692k
  T castAs() const {
142
692k
    assert(T::isKind(*this));
143
692k
    T t;
144
692k
    ProgramPoint& PP = t;
145
692k
    PP = *this;
146
692k
    return t;
147
692k
  }
clang::CallExitEnd clang::ProgramPoint::castAs<clang::CallExitEnd>() const
Line
Count
Source
141
20
  T castAs() const {
142
20
    assert(T::isKind(*this));
143
20
    T t;
144
20
    ProgramPoint& PP = t;
145
20
    PP = *this;
146
20
    return t;
147
20
  }
Unexecuted instantiation: clang::LoopExit clang::ProgramPoint::castAs<clang::LoopExit>() const
Unexecuted instantiation: clang::ImplicitCallPoint clang::ProgramPoint::castAs<clang::ImplicitCallPoint>() const
Unexecuted instantiation: clang::PostInitializer clang::ProgramPoint::castAs<clang::PostInitializer>() const
148
149
  /// Convert to the specified ProgramPoint type, returning None if this
150
  /// ProgramPoint is not of the desired type.
151
  template<typename T>
152
15.6M
  Optional<T> getAs() const {
153
15.6M
    if (!T::isKind(*this))
154
12.7M
      return None;
155
2.97M
    T t;
156
2.97M
    ProgramPoint& PP = t;
157
2.97M
    PP = *this;
158
2.97M
    return t;
159
2.97M
  }
llvm::Optional<clang::BlockEntrance> clang::ProgramPoint::getAs<clang::BlockEntrance>() const
Line
Count
Source
152
2.04M
  Optional<T> getAs() const {
153
2.04M
    if (!T::isKind(*this))
154
1.83M
      return None;
155
217k
    T t;
156
217k
    ProgramPoint& PP = t;
157
217k
    PP = *this;
158
217k
    return t;
159
217k
  }
llvm::Optional<clang::PostStore> clang::ProgramPoint::getAs<clang::PostStore>() const
Line
Count
Source
152
832k
  Optional<T> getAs() const {
153
832k
    if (!T::isKind(*this))
154
790k
      return None;
155
41.7k
    T t;
156
41.7k
    ProgramPoint& PP = t;
157
41.7k
    PP = *this;
158
41.7k
    return t;
159
41.7k
  }
llvm::Optional<clang::BlockEdge> clang::ProgramPoint::getAs<clang::BlockEdge>() const
Line
Count
Source
152
1.26M
  Optional<T> getAs() const {
153
1.26M
    if (!T::isKind(*this))
154
1.10M
      return None;
155
161k
    T t;
156
161k
    ProgramPoint& PP = t;
157
161k
    PP = *this;
158
161k
    return t;
159
161k
  }
llvm::Optional<clang::PreStmt> clang::ProgramPoint::getAs<clang::PreStmt>() const
Line
Count
Source
152
909k
  Optional<T> getAs() const {
153
909k
    if (!T::isKind(*this))
154
892k
      return None;
155
17.2k
    T t;
156
17.2k
    ProgramPoint& PP = t;
157
17.2k
    PP = *this;
158
17.2k
    return t;
159
17.2k
  }
llvm::Optional<clang::StmtPoint> clang::ProgramPoint::getAs<clang::StmtPoint>() const
Line
Count
Source
152
1.60M
  Optional<T> getAs() const {
153
1.60M
    if (!T::isKind(*this))
154
234k
      return None;
155
1.37M
    T t;
156
1.37M
    ProgramPoint& PP = t;
157
1.37M
    PP = *this;
158
1.37M
    return t;
159
1.37M
  }
llvm::Optional<clang::PostImplicitCall> clang::ProgramPoint::getAs<clang::PostImplicitCall>() const
Line
Count
Source
152
813k
  Optional<T> getAs() const {
153
813k
    if (!T::isKind(*this))
154
813k
      return None;
155
733
    T t;
156
733
    ProgramPoint& PP = t;
157
733
    PP = *this;
158
733
    return t;
159
733
  }
llvm::Optional<clang::CallEnter> clang::ProgramPoint::getAs<clang::CallEnter>() const
Line
Count
Source
152
2.42M
  Optional<T> getAs() const {
153
2.42M
    if (!T::isKind(*this))
154
2.40M
      return None;
155
27.9k
    T t;
156
27.9k
    ProgramPoint& PP = t;
157
27.9k
    PP = *this;
158
27.9k
    return t;
159
27.9k
  }
llvm::Optional<clang::CallExitBegin> clang::ProgramPoint::getAs<clang::CallExitBegin>() const
Line
Count
Source
152
148k
  Optional<T> getAs() const {
153
148k
    if (!T::isKind(*this))
154
130k
      return None;
155
18.6k
    T t;
156
18.6k
    ProgramPoint& PP = t;
157
18.6k
    PP = *this;
158
18.6k
    return t;
159
18.6k
  }
llvm::Optional<clang::PostStmt> clang::ProgramPoint::getAs<clang::PostStmt>() const
Line
Count
Source
152
1.22M
  Optional<T> getAs() const {
153
1.22M
    if (!T::isKind(*this))
154
287k
      return None;
155
937k
    T t;
156
937k
    ProgramPoint& PP = t;
157
937k
    PP = *this;
158
937k
    return t;
159
937k
  }
llvm::Optional<clang::CallExitEnd> clang::ProgramPoint::getAs<clang::CallExitEnd>() const
Line
Count
Source
152
324k
  Optional<T> getAs() const {
153
324k
    if (!T::isKind(*this))
154
299k
      return None;
155
24.8k
    T t;
156
24.8k
    ProgramPoint& PP = t;
157
24.8k
    PP = *this;
158
24.8k
    return t;
159
24.8k
  }
llvm::Optional<clang::PostInitializer> clang::ProgramPoint::getAs<clang::PostInitializer>() const
Line
Count
Source
152
937k
  Optional<T> getAs() const {
153
937k
    if (!T::isKind(*this))
154
921k
      return None;
155
15.5k
    T t;
156
15.5k
    ProgramPoint& PP = t;
157
15.5k
    PP = *this;
158
15.5k
    return t;
159
15.5k
  }
llvm::Optional<clang::LoopExit> clang::ProgramPoint::getAs<clang::LoopExit>() const
Line
Count
Source
152
813k
  Optional<T> getAs() const {
153
813k
    if (!T::isKind(*this))
154
812k
      return None;
155
264
    T t;
156
264
    ProgramPoint& PP = t;
157
264
    PP = *this;
158
264
    return t;
159
264
  }
llvm::Optional<clang::EpsilonPoint> clang::ProgramPoint::getAs<clang::EpsilonPoint>() const
Line
Count
Source
152
812k
  Optional<T> getAs() const {
153
812k
    if (!T::isKind(*this))
154
812k
      return None;
155
31
    T t;
156
31
    ProgramPoint& PP = t;
157
31
    PP = *this;
158
31
    return t;
159
31
  }
llvm::Optional<clang::PreStmtPurgeDeadSymbols> clang::ProgramPoint::getAs<clang::PreStmtPurgeDeadSymbols>() const
Line
Count
Source
152
1.10M
  Optional<T> getAs() const {
153
1.10M
    if (!T::isKind(*this))
154
979k
      return None;
155
129k
    T t;
156
129k
    ProgramPoint& PP = t;
157
129k
    PP = *this;
158
129k
    return t;
159
129k
  }
llvm::Optional<clang::PreImplicitCall> clang::ProgramPoint::getAs<clang::PreImplicitCall>() const
Line
Count
Source
152
339k
  Optional<T> getAs() const {
153
339k
    if (!T::isKind(*this))
154
339k
      return None;
155
48
    T t;
156
48
    ProgramPoint& PP = t;
157
48
    PP = *this;
158
48
    return t;
159
48
  }
llvm::Optional<clang::PostStmtPurgeDeadSymbols> clang::ProgramPoint::getAs<clang::PostStmtPurgeDeadSymbols>() const
Line
Count
Source
152
27.4k
  Optional<T> getAs() const {
153
27.4k
    if (!T::isKind(*this))
154
26.7k
      return None;
155
663
    T t;
156
663
    ProgramPoint& PP = t;
157
663
    PP = *this;
158
663
    return t;
159
663
  }
llvm::Optional<clang::FunctionExitPoint> clang::ProgramPoint::getAs<clang::FunctionExitPoint>() const
Line
Count
Source
152
43.2k
  Optional<T> getAs() const {
153
43.2k
    if (!T::isKind(*this))
154
41.4k
      return None;
155
1.86k
    T t;
156
1.86k
    ProgramPoint& PP = t;
157
1.86k
    PP = *this;
158
1.86k
    return t;
159
1.86k
  }
Unexecuted instantiation: llvm::Optional<clang::PostLoad> clang::ProgramPoint::getAs<clang::PostLoad>() const
Unexecuted instantiation: llvm::Optional<clang::PostLValue> clang::ProgramPoint::getAs<clang::PostLValue>() const
Unexecuted instantiation: llvm::Optional<clang::PostAllocatorCall> clang::ProgramPoint::getAs<clang::PostAllocatorCall>() const
160
161
21.4M
  Kind getKind() const {
162
21.4M
    unsigned x = Tag.getInt();
163
21.4M
    x <<= 2;
164
21.4M
    x |= L.getInt();
165
21.4M
    x <<= 2;
166
21.4M
    x |= Data2.getInt();
167
21.4M
    return (Kind) x;
168
21.4M
  }
169
170
  /// Is this a program point corresponding to purge/removal of dead
171
  /// symbols and bindings.
172
104
  bool isPurgeKind() {
173
104
    Kind K = getKind();
174
104
    return (K == PostStmtPurgeDeadSymbolsKind ||
175
104
            K == PreStmtPurgeDeadSymbolsKind);
176
104
  }
177
178
4.51M
  const ProgramPointTag *getTag() const { return Tag.getPointer(); }
179
180
19.4M
  const LocationContext *getLocationContext() const {
181
19.4M
    return L.getPointer();
182
19.4M
  }
183
184
407k
  const StackFrameContext *getStackFrame() const {
185
407k
    return getLocationContext()->getStackFrame();
186
407k
  }
187
188
  // For use with DenseMap.  This hash is probably slow.
189
0
  unsigned getHashValue() const {
190
0
    llvm::FoldingSetNodeID ID;
191
0
    Profile(ID);
192
0
    return ID.ComputeHash();
193
0
  }
194
195
812k
  bool operator==(const ProgramPoint & RHS) const {
196
812k
    return Data1 == RHS.Data1 &&
197
812k
           
Data2 == RHS.Data2758k
&&
198
812k
           
L == RHS.L316k
&&
199
812k
           
Tag == RHS.Tag316k
;
200
812k
  }
201
202
0
  bool operator!=(const ProgramPoint &RHS) const {
203
0
    return Data1 != RHS.Data1 ||
204
0
           Data2 != RHS.Data2 ||
205
0
           L != RHS.L ||
206
0
           Tag != RHS.Tag;
207
0
  }
208
209
3.55M
  void Profile(llvm::FoldingSetNodeID& ID) const {
210
3.55M
    ID.AddInteger((unsigned) getKind());
211
3.55M
    ID.AddPointer(getData1());
212
3.55M
    ID.AddPointer(getData2());
213
3.55M
    ID.AddPointer(getLocationContext());
214
3.55M
    ID.AddPointer(getTag());
215
3.55M
  }
216
217
  void print(StringRef CR, llvm::raw_ostream &Out) const;
218
219
  LLVM_DUMP_METHOD void dump() const;
220
221
  static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K,
222
                                      const LocationContext *LC,
223
                                      const ProgramPointTag *tag);
224
};
225
226
class BlockEntrance : public ProgramPoint {
227
public:
228
  BlockEntrance(const CFGBlock *B, const LocationContext *L,
229
                const ProgramPointTag *tag = nullptr)
230
123k
    : ProgramPoint(B, BlockEntranceKind, L, tag) {
231
123k
    assert(B && "BlockEntrance requires non-null block");
232
123k
  }
233
234
447k
  const CFGBlock *getBlock() const {
235
447k
    return reinterpret_cast<const CFGBlock*>(getData1());
236
447k
  }
237
238
109k
  Optional<CFGElement> getFirstElement() const {
239
109k
    const CFGBlock *B = getBlock();
240
109k
    return B->empty() ? 
Optional<CFGElement>()12.7k
:
B->front()96.4k
;
241
109k
  }
242
243
private:
244
  friend class ProgramPoint;
245
326k
  BlockEntrance() = default;
246
2.04M
  static bool isKind(const ProgramPoint &Location) {
247
2.04M
    return Location.getKind() == BlockEntranceKind;
248
2.04M
  }
249
};
250
251
class BlockExit : public ProgramPoint {
252
public:
253
  BlockExit(const CFGBlock *B, const LocationContext *L)
254
    : ProgramPoint(B, BlockExitKind, L) {}
255
256
  const CFGBlock *getBlock() const {
257
    return reinterpret_cast<const CFGBlock*>(getData1());
258
  }
259
260
  const Stmt *getTerminator() const {
261
    return getBlock()->getTerminator();
262
  }
263
264
private:
265
  friend class ProgramPoint;
266
  BlockExit() = default;
267
  static bool isKind(const ProgramPoint &Location) {
268
    return Location.getKind() == BlockExitKind;
269
  }
270
};
271
272
class StmtPoint : public ProgramPoint {
273
public:
274
  StmtPoint(const Stmt *S, const void *p2, Kind k, const LocationContext *L,
275
            const ProgramPointTag *tag)
276
4.87M
    : ProgramPoint(S, p2, k, L, tag) {
277
4.87M
    assert(S);
278
4.87M
  }
279
280
2.13M
  const Stmt *getStmt() const { return (const Stmt*) getData1(); }
281
282
  template <typename T>
283
47.4k
  const T* getStmtAs() const { return dyn_cast<T>(getStmt()); }
clang::ObjCMessageExpr const* clang::StmtPoint::getStmtAs<clang::ObjCMessageExpr>() const
Line
Count
Source
283
12
  const T* getStmtAs() const { return dyn_cast<T>(getStmt()); }
clang::BinaryOperator const* clang::StmtPoint::getStmtAs<clang::BinaryOperator>() const
Line
Count
Source
283
12.9k
  const T* getStmtAs() const { return dyn_cast<T>(getStmt()); }
clang::Expr const* clang::StmtPoint::getStmtAs<clang::Expr>() const
Line
Count
Source
283
18.5k
  const T* getStmtAs() const { return dyn_cast<T>(getStmt()); }
clang::DeclStmt const* clang::StmtPoint::getStmtAs<clang::DeclStmt>() const
Line
Count
Source
283
15.9k
  const T* getStmtAs() const { return dyn_cast<T>(getStmt()); }
284
285
protected:
286
3.19M
  StmtPoint() = default;
287
private:
288
  friend class ProgramPoint;
289
1.60M
  static bool isKind(const ProgramPoint &Location) {
290
1.60M
    unsigned k = Location.getKind();
291
1.60M
    return k >= PreStmtKind && 
k <= MaxPostStmtKind1.46M
;
292
1.60M
  }
293
};
294
295
296
class PreStmt : public StmtPoint {
297
public:
298
  PreStmt(const Stmt *S, const LocationContext *L, const ProgramPointTag *tag,
299
          const Stmt *SubStmt = nullptr)
300
721k
    : StmtPoint(S, SubStmt, PreStmtKind, L, tag) {}
301
302
0
  const Stmt *getSubStmt() const { return (const Stmt*) getData2(); }
303
304
private:
305
  friend class ProgramPoint;
306
17.2k
  PreStmt() = default;
307
909k
  static bool isKind(const ProgramPoint &Location) {
308
909k
    return Location.getKind() == PreStmtKind;
309
909k
  }
310
};
311
312
class PostStmt : public StmtPoint {
313
protected:
314
1.67M
  PostStmt() = default;
315
  PostStmt(const Stmt *S, const void *data, Kind k, const LocationContext *L,
316
           const ProgramPointTag *tag = nullptr)
317
    : StmtPoint(S, data, k, L, tag) {}
318
319
public:
320
  explicit PostStmt(const Stmt *S, Kind k, const LocationContext *L,
321
                    const ProgramPointTag *tag = nullptr)
322
496k
    : StmtPoint(S, nullptr, k, L, tag) {}
323
324
  explicit PostStmt(const Stmt *S, const LocationContext *L,
325
                    const ProgramPointTag *tag = nullptr)
326
2.05M
    : StmtPoint(S, nullptr, PostStmtKind, L, tag) {}
327
328
private:
329
  friend class ProgramPoint;
330
1.22M
  static bool isKind(const ProgramPoint &Location) {
331
1.22M
    unsigned k = Location.getKind();
332
1.22M
    return k >= MinPostStmtKind && 
k <= MaxPostStmtKind1.00M
;
333
1.22M
  }
334
};
335
336
class FunctionExitPoint : public ProgramPoint {
337
public:
338
  explicit FunctionExitPoint(const ReturnStmt *S,
339
                             const LocationContext *LC,
340
                             const ProgramPointTag *tag = nullptr)
341
64.7k
      : ProgramPoint(S, FunctionExitKind, LC, tag) {}
342
343
0
  const CFGBlock *getBlock() const {
344
0
    return &getLocationContext()->getCFG()->getExit();
345
0
  }
346
347
1.86k
  const ReturnStmt *getStmt() const {
348
1.86k
    return reinterpret_cast<const ReturnStmt *>(getData1());
349
1.86k
  }
350
351
private:
352
  friend class ProgramPoint;
353
1.86k
  FunctionExitPoint() = default;
354
43.2k
  static bool isKind(const ProgramPoint &Location) {
355
43.2k
    return Location.getKind() == FunctionExitKind;
356
43.2k
  }
357
};
358
359
// PostCondition represents the post program point of a branch condition.
360
class PostCondition : public PostStmt {
361
public:
362
  PostCondition(const Stmt *S, const LocationContext *L,
363
                const ProgramPointTag *tag = nullptr)
364
39.9k
    : PostStmt(S, PostConditionKind, L, tag) {}
365
366
private:
367
  friend class ProgramPoint;
368
  PostCondition() = default;
369
  static bool isKind(const ProgramPoint &Location) {
370
    return Location.getKind() == PostConditionKind;
371
  }
372
};
373
374
class LocationCheck : public StmtPoint {
375
protected:
376
  LocationCheck() = default;
377
  LocationCheck(const Stmt *S, const LocationContext *L,
378
                ProgramPoint::Kind K, const ProgramPointTag *tag)
379
417k
    : StmtPoint(S, nullptr, K, L, tag) {}
380
381
private:
382
  friend class ProgramPoint;
383
  static bool isKind(const ProgramPoint &location) {
384
    unsigned k = location.getKind();
385
    return k == PreLoadKind || k == PreStoreKind;
386
  }
387
};
388
389
class PreLoad : public LocationCheck {
390
public:
391
  PreLoad(const Stmt *S, const LocationContext *L,
392
          const ProgramPointTag *tag = nullptr)
393
348k
    : LocationCheck(S, L, PreLoadKind, tag) {}
394
395
private:
396
  friend class ProgramPoint;
397
  PreLoad() = default;
398
  static bool isKind(const ProgramPoint &location) {
399
    return location.getKind() == PreLoadKind;
400
  }
401
};
402
403
class PreStore : public LocationCheck {
404
public:
405
  PreStore(const Stmt *S, const LocationContext *L,
406
           const ProgramPointTag *tag = nullptr)
407
69.4k
  : LocationCheck(S, L, PreStoreKind, tag) {}
408
409
private:
410
  friend class ProgramPoint;
411
  PreStore() = default;
412
  static bool isKind(const ProgramPoint &location) {
413
    return location.getKind() == PreStoreKind;
414
  }
415
};
416
417
class PostLoad : public PostStmt {
418
public:
419
  PostLoad(const Stmt *S, const LocationContext *L,
420
           const ProgramPointTag *tag = nullptr)
421
146k
    : PostStmt(S, PostLoadKind, L, tag) {}
422
423
private:
424
  friend class ProgramPoint;
425
0
  PostLoad() = default;
426
0
  static bool isKind(const ProgramPoint &Location) {
427
0
    return Location.getKind() == PostLoadKind;
428
0
  }
429
};
430
431
/// Represents a program point after a store evaluation.
432
class PostStore : public PostStmt {
433
public:
434
  /// Construct the post store point.
435
  /// \param Loc can be used to store the information about the location
436
  /// used in the form it was uttered in the code.
437
  PostStore(const Stmt *S, const LocationContext *L, const void *Loc,
438
            const ProgramPointTag *tag = nullptr)
439
66.5k
    : PostStmt(S, PostStoreKind, L, tag) {
440
66.5k
    assert(getData2() == nullptr);
441
66.5k
    setData2(Loc);
442
66.5k
  }
443
444
  /// Returns the information about the location used in the store,
445
  /// how it was uttered in the code.
446
776
  const void *getLocationValue() const {
447
776
    return getData2();
448
776
  }
449
450
private:
451
  friend class ProgramPoint;
452
41.7k
  PostStore() = default;
453
832k
  static bool isKind(const ProgramPoint &Location) {
454
832k
    return Location.getKind() == PostStoreKind;
455
832k
  }
456
};
457
458
class PostLValue : public PostStmt {
459
public:
460
  PostLValue(const Stmt *S, const LocationContext *L,
461
             const ProgramPointTag *tag = nullptr)
462
243k
    : PostStmt(S, PostLValueKind, L, tag) {}
463
464
private:
465
  friend class ProgramPoint;
466
0
  PostLValue() = default;
467
0
  static bool isKind(const ProgramPoint &Location) {
468
0
    return Location.getKind() == PostLValueKind;
469
0
  }
470
};
471
472
/// Represents a point after we ran remove dead bindings BEFORE
473
/// processing the given statement.
474
class PreStmtPurgeDeadSymbols : public StmtPoint {
475
public:
476
  PreStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
477
                       const ProgramPointTag *tag = nullptr)
478
982k
    : StmtPoint(S, nullptr, PreStmtPurgeDeadSymbolsKind, L, tag) { }
479
480
private:
481
  friend class ProgramPoint;
482
129k
  PreStmtPurgeDeadSymbols() = default;
483
1.10M
  static bool isKind(const ProgramPoint &Location) {
484
1.10M
    return Location.getKind() == PreStmtPurgeDeadSymbolsKind;
485
1.10M
  }
486
};
487
488
/// Represents a point after we ran remove dead bindings AFTER
489
/// processing the  given statement.
490
class PostStmtPurgeDeadSymbols : public StmtPoint {
491
public:
492
  PostStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
493
                       const ProgramPointTag *tag = nullptr)
494
200k
    : StmtPoint(S, nullptr, PostStmtPurgeDeadSymbolsKind, L, tag) { }
495
496
private:
497
  friend class ProgramPoint;
498
663
  PostStmtPurgeDeadSymbols() = default;
499
27.4k
  static bool isKind(const ProgramPoint &Location) {
500
27.4k
    return Location.getKind() == PostStmtPurgeDeadSymbolsKind;
501
27.4k
  }
502
};
503
504
class BlockEdge : public ProgramPoint {
505
public:
506
  BlockEdge(const CFGBlock *B1, const CFGBlock *B2, const LocationContext *L)
507
177k
    : ProgramPoint(B1, B2, BlockEdgeKind, L) {
508
177k
    assert(B1 && "BlockEdge: source block must be non-null");
509
177k
    assert(B2 && "BlockEdge: destination block must be non-null");
510
177k
  }
511
512
225k
  const CFGBlock *getSrc() const {
513
225k
    return static_cast<const CFGBlock*>(getData1());
514
225k
  }
515
516
201k
  const CFGBlock *getDst() const {
517
201k
    return static_cast<const CFGBlock*>(getData2());
518
201k
  }
519
520
private:
521
  friend class ProgramPoint;
522
340k
  BlockEdge() = default;
523
1.26M
  static bool isKind(const ProgramPoint &Location) {
524
1.26M
    return Location.getKind() == BlockEdgeKind;
525
1.26M
  }
526
};
527
528
class PostInitializer : public ProgramPoint {
529
public:
530
  /// Construct a PostInitializer point that represents a location after
531
  ///   CXXCtorInitializer expression evaluation.
532
  ///
533
  /// \param I The initializer.
534
  /// \param Loc The location of the field being initialized.
535
  PostInitializer(const CXXCtorInitializer *I,
536
                  const void *Loc,
537
                  const LocationContext *L)
538
13.6k
    : ProgramPoint(I, Loc, PostInitializerKind, L) {}
539
540
7.23k
  const CXXCtorInitializer *getInitializer() const {
541
7.23k
    return static_cast<const CXXCtorInitializer *>(getData1());
542
7.23k
  }
543
544
  /// Returns the location of the field.
545
72
  const void *getLocationValue() const {
546
72
    return getData2();
547
72
  }
548
549
private:
550
  friend class ProgramPoint;
551
15.5k
  PostInitializer() = default;
552
937k
  static bool isKind(const ProgramPoint &Location) {
553
937k
    return Location.getKind() == PostInitializerKind;
554
937k
  }
555
};
556
557
/// Represents an implicit call event.
558
///
559
/// The nearest statement is provided for diagnostic purposes.
560
class ImplicitCallPoint : public ProgramPoint {
561
public:
562
  ImplicitCallPoint(const Decl *D, SourceLocation Loc, Kind K,
563
                    const LocationContext *L, const ProgramPointTag *Tag)
564
10.3k
    : ProgramPoint(Loc.getPtrEncoding(), D, K, L, Tag) {}
565
566
0
  const Decl *getDecl() const { return static_cast<const Decl *>(getData2()); }
567
60
  SourceLocation getLocation() const {
568
60
    return SourceLocation::getFromPtrEncoding(getData1());
569
60
  }
570
571
protected:
572
781
  ImplicitCallPoint() = default;
573
private:
574
  friend class ProgramPoint;
575
0
  static bool isKind(const ProgramPoint &Location) {
576
0
    return Location.getKind() >= MinImplicitCallKind &&
577
0
           Location.getKind() <= MaxImplicitCallKind;
578
0
  }
579
};
580
581
/// Represents a program point just before an implicit call event.
582
///
583
/// Explicit calls will appear as PreStmt program points.
584
class PreImplicitCall : public ImplicitCallPoint {
585
public:
586
  PreImplicitCall(const Decl *D, SourceLocation Loc, const LocationContext *L,
587
                  const ProgramPointTag *Tag = nullptr)
588
6.26k
    : ImplicitCallPoint(D, Loc, PreImplicitCallKind, L, Tag) {}
589
590
private:
591
  friend class ProgramPoint;
592
48
  PreImplicitCall() = default;
593
339k
  static bool isKind(const ProgramPoint &Location) {
594
339k
    return Location.getKind() == PreImplicitCallKind;
595
339k
  }
596
};
597
598
/// Represents a program point just after an implicit call event.
599
///
600
/// Explicit calls will appear as PostStmt program points.
601
class PostImplicitCall : public ImplicitCallPoint {
602
public:
603
  PostImplicitCall(const Decl *D, SourceLocation Loc, const LocationContext *L,
604
                   const ProgramPointTag *Tag = nullptr)
605
4.11k
    : ImplicitCallPoint(D, Loc, PostImplicitCallKind, L, Tag) {}
606
607
private:
608
  friend class ProgramPoint;
609
733
  PostImplicitCall() = default;
610
813k
  static bool isKind(const ProgramPoint &Location) {
611
813k
    return Location.getKind() == PostImplicitCallKind;
612
813k
  }
613
};
614
615
class PostAllocatorCall : public StmtPoint {
616
public:
617
  PostAllocatorCall(const Stmt *S, const LocationContext *L,
618
                    const ProgramPointTag *Tag = nullptr)
619
621
      : StmtPoint(S, nullptr, PostAllocatorCallKind, L, Tag) {}
620
621
private:
622
  friend class ProgramPoint;
623
0
  PostAllocatorCall() = default;
624
0
  static bool isKind(const ProgramPoint &Location) {
625
0
    return Location.getKind() == PostAllocatorCallKind;
626
0
  }
627
};
628
629
/// Represents a point when we begin processing an inlined call.
630
/// CallEnter uses the caller's location context.
631
class CallEnter : public ProgramPoint {
632
public:
633
  CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx,
634
            const LocationContext *callerCtx)
635
26.6k
    : ProgramPoint(stmt, calleeCtx, CallEnterKind, callerCtx, nullptr) {}
636
637
627
  const Stmt *getCallExpr() const {
638
627
    return static_cast<const Stmt *>(getData1());
639
627
  }
640
641
107k
  const StackFrameContext *getCalleeContext() const {
642
107k
    return static_cast<const StackFrameContext *>(getData2());
643
107k
  }
644
645
  /// Returns the entry block in the CFG for the entered function.
646
53.3k
  const CFGBlock *getEntry() const {
647
53.3k
    const StackFrameContext *CalleeCtx = getCalleeContext();
648
53.3k
    const CFG *CalleeCFG = CalleeCtx->getCFG();
649
53.3k
    return &(CalleeCFG->getEntry());
650
53.3k
  }
651
652
private:
653
  friend class ProgramPoint;
654
54.6k
  CallEnter() = default;
655
2.42M
  static bool isKind(const ProgramPoint &Location) {
656
2.42M
    return Location.getKind() == CallEnterKind;
657
2.42M
  }
658
};
659
660
/// Represents a point when we start the call exit sequence (for inlined call).
661
///
662
/// The call exit is simulated with a sequence of nodes, which occur between
663
/// CallExitBegin and CallExitEnd. The following operations occur between the
664
/// two program points:
665
/// - CallExitBegin
666
/// - Bind the return value
667
/// - Run Remove dead bindings (to clean up the dead symbols from the callee).
668
/// - CallExitEnd
669
class CallExitBegin : public ProgramPoint {
670
public:
671
  // CallExitBegin uses the callee's location context.
672
  CallExitBegin(const StackFrameContext *L, const ReturnStmt *RS)
673
34.9k
    : ProgramPoint(RS, CallExitBeginKind, L, nullptr) { }
674
675
17.2k
  const ReturnStmt *getReturnStmt() const {
676
17.2k
    return static_cast<const ReturnStmt *>(getData1());
677
17.2k
  }
678
679
private:
680
  friend class ProgramPoint;
681
18.6k
  CallExitBegin() = default;
682
148k
  static bool isKind(const ProgramPoint &Location) {
683
148k
    return Location.getKind() == CallExitBeginKind;
684
148k
  }
685
};
686
687
/// Represents a point when we finish the call exit sequence (for inlined call).
688
/// \sa CallExitBegin
689
class CallExitEnd : public ProgramPoint {
690
public:
691
  // CallExitEnd uses the caller's location context.
692
  CallExitEnd(const StackFrameContext *CalleeCtx,
693
              const LocationContext *CallerCtx)
694
33.2k
    : ProgramPoint(CalleeCtx, CallExitEndKind, CallerCtx, nullptr) {}
695
696
29.9k
  const StackFrameContext *getCalleeContext() const {
697
29.9k
    return static_cast<const StackFrameContext *>(getData1());
698
29.9k
  }
699
700
private:
701
  friend class ProgramPoint;
702
24.8k
  CallExitEnd() = default;
703
324k
  static bool isKind(const ProgramPoint &Location) {
704
324k
    return Location.getKind() == CallExitEndKind;
705
324k
  }
706
};
707
708
/// Represents a point when we exit a loop.
709
/// When this ProgramPoint is encountered we can be sure that the symbolic
710
/// execution of the corresponding LoopStmt is finished on the given path.
711
/// Note: It is possible to encounter a LoopExit element when we haven't even
712
/// encountered the loop itself. At the current state not all loop exits will
713
/// result in a LoopExit program point.
714
class LoopExit : public ProgramPoint {
715
public:
716
    LoopExit(const Stmt *LoopStmt, const LocationContext *LC)
717
141
            : ProgramPoint(LoopStmt, nullptr, LoopExitKind, LC) {}
718
719
0
    const Stmt *getLoopStmt() const {
720
0
      return static_cast<const Stmt *>(getData1());
721
0
    }
722
723
private:
724
    friend class ProgramPoint;
725
264
    LoopExit() = default;
726
813k
    static bool isKind(const ProgramPoint &Location) {
727
813k
      return Location.getKind() == LoopExitKind;
728
813k
    }
729
};
730
731
/// This is a meta program point, which should be skipped by all the diagnostic
732
/// reasoning etc.
733
class EpsilonPoint : public ProgramPoint {
734
public:
735
  EpsilonPoint(const LocationContext *L, const void *Data1,
736
               const void *Data2 = nullptr,
737
               const ProgramPointTag *tag = nullptr)
738
35
    : ProgramPoint(Data1, Data2, EpsilonKind, L, tag) {}
739
740
0
  const void *getData() const { return getData1(); }
741
742
private:
743
  friend class ProgramPoint;
744
31
  EpsilonPoint() = default;
745
812k
  static bool isKind(const ProgramPoint &Location) {
746
812k
    return Location.getKind() == EpsilonKind;
747
812k
  }
748
};
749
750
} // end namespace clang
751
752
753
namespace llvm { // Traits specialization for DenseMap
754
755
template <> struct DenseMapInfo<clang::ProgramPoint> {
756
757
static inline clang::ProgramPoint getEmptyKey() {
758
  uintptr_t x =
759
   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7;
760
  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), nullptr);
761
}
762
763
static inline clang::ProgramPoint getTombstoneKey() {
764
  uintptr_t x =
765
   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7;
766
  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), nullptr);
767
}
768
769
static unsigned getHashValue(const clang::ProgramPoint &Loc) {
770
  return Loc.getHashValue();
771
}
772
773
static bool isEqual(const clang::ProgramPoint &L,
774
                    const clang::ProgramPoint &R) {
775
  return L == R;
776
}
777
778
};
779
780
} // end namespace llvm
781
782
#endif