Coverage Report

Created: 2019-07-24 05:18

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