Coverage Report

Created: 2018-11-16 02:38

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