Coverage Report

Created: 2018-07-19 20:53

/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.1k
  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
              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.61M
  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
210k
      Tag(tag, (((unsigned) k) >> 4) & 0x3) {
110
210k
        assert(getKind() == k);
111
210k
        assert(getLocationContext() == l);
112
210k
        assert(getData1() == P);
113
210k
      }
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
4.77M
      Tag(tag, (((unsigned) k) >> 4) & 0x3) {}
124
125
protected:
126
6.79M
  const void *getData1() const { return Data1; }
127
4.42M
  const void *getData2() const { return Data2.getPointer(); }
128
59.7k
  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
865k
  ProgramPoint withTag(const ProgramPointTag *tag) const {
134
865k
    return ProgramPoint(getData1(), getData2(), getKind(),
135
865k
                        getLocationContext(), tag);
136
865k
  }
137
138
  /// Convert to the specified ProgramPoint type, asserting that this
139
  /// ProgramPoint is of the desired type.
140
  template<typename T>
141
938k
  T castAs() const {
142
938k
    assert(T::isKind(*this));
143
938k
    T t;
144
938k
    ProgramPoint& PP = t;
145
938k
    PP = *this;
146
938k
    return t;
147
938k
  }
clang::StmtPoint clang::ProgramPoint::castAs<clang::StmtPoint>() const
Line
Count
Source
141
1.14k
  T castAs() const {
142
1.14k
    assert(T::isKind(*this));
143
1.14k
    T t;
144
1.14k
    ProgramPoint& PP = t;
145
1.14k
    PP = *this;
146
1.14k
    return t;
147
1.14k
  }
clang::BlockEdge clang::ProgramPoint::castAs<clang::BlockEdge>() const
Line
Count
Source
141
158k
  T castAs() const {
142
158k
    assert(T::isKind(*this));
143
158k
    T t;
144
158k
    ProgramPoint& PP = t;
145
158k
    PP = *this;
146
158k
    return t;
147
158k
  }
clang::BlockEntrance clang::ProgramPoint::castAs<clang::BlockEntrance>() const
Line
Count
Source
141
98.5k
  T castAs() const {
142
98.5k
    assert(T::isKind(*this));
143
98.5k
    T t;
144
98.5k
    ProgramPoint& PP = t;
145
98.5k
    PP = *this;
146
98.5k
    return t;
147
98.5k
  }
clang::CallEnter clang::ProgramPoint::castAs<clang::CallEnter>() const
Line
Count
Source
141
18.1k
  T castAs() const {
142
18.1k
    assert(T::isKind(*this));
143
18.1k
    T t;
144
18.1k
    ProgramPoint& PP = t;
145
18.1k
    PP = *this;
146
18.1k
    return t;
147
18.1k
  }
clang::PostStmt clang::ProgramPoint::castAs<clang::PostStmt>() const
Line
Count
Source
141
661k
  T castAs() const {
142
661k
    assert(T::isKind(*this));
143
661k
    T t;
144
661k
    ProgramPoint& PP = t;
145
661k
    PP = *this;
146
661k
    return t;
147
661k
  }
clang::CallExitEnd clang::ProgramPoint::castAs<clang::CallExitEnd>() const
Line
Count
Source
141
17
  T castAs() const {
142
17
    assert(T::isKind(*this));
143
17
    T t;
144
17
    ProgramPoint& PP = t;
145
17
    PP = *this;
146
17
    return t;
147
17
  }
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
13.9M
  Optional<T> getAs() const {
153
13.9M
    if (!T::isKind(*this))
154
11.2M
      return None;
155
2.67M
    T t;
156
2.67M
    ProgramPoint& PP = t;
157
2.67M
    PP = *this;
158
2.67M
    return t;
159
2.67M
  }
llvm::Optional<clang::BlockEntrance> clang::ProgramPoint::getAs<clang::BlockEntrance>() const
Line
Count
Source
152
1.87M
  Optional<T> getAs() const {
153
1.87M
    if (!T::isKind(*this))
154
1.67M
      return None;
155
200k
    T t;
156
200k
    ProgramPoint& PP = t;
157
200k
    PP = *this;
158
200k
    return t;
159
200k
  }
llvm::Optional<clang::PostStore> clang::ProgramPoint::getAs<clang::PostStore>() const
Line
Count
Source
152
791k
  Optional<T> getAs() const {
153
791k
    if (!T::isKind(*this))
154
752k
      return None;
155
39.6k
    T t;
156
39.6k
    ProgramPoint& PP = t;
157
39.6k
    PP = *this;
158
39.6k
    return t;
159
39.6k
  }
llvm::Optional<clang::BlockEdge> clang::ProgramPoint::getAs<clang::BlockEdge>() const
Line
Count
Source
152
1.05M
  Optional<T> getAs() const {
153
1.05M
    if (!T::isKind(*this))
154
922k
      return None;
155
128k
    T t;
156
128k
    ProgramPoint& PP = t;
157
128k
    PP = *this;
158
128k
    return t;
159
128k
  }
llvm::Optional<clang::StmtPoint> clang::ProgramPoint::getAs<clang::StmtPoint>() const
Line
Count
Source
152
1.44M
  Optional<T> getAs() const {
153
1.44M
    if (!T::isKind(*this))
154
188k
      return None;
155
1.25M
    T t;
156
1.25M
    ProgramPoint& PP = t;
157
1.25M
    PP = *this;
158
1.25M
    return t;
159
1.25M
  }
llvm::Optional<clang::PostImplicitCall> clang::ProgramPoint::getAs<clang::PostImplicitCall>() const
Line
Count
Source
152
735k
  Optional<T> getAs() const {
153
735k
    if (!T::isKind(*this))
154
735k
      return None;
155
617
    T t;
156
617
    ProgramPoint& PP = t;
157
617
    PP = *this;
158
617
    return t;
159
617
  }
llvm::Optional<clang::CallEnter> clang::ProgramPoint::getAs<clang::CallEnter>() const
Line
Count
Source
152
2.13M
  Optional<T> getAs() const {
153
2.13M
    if (!T::isKind(*this))
154
2.11M
      return None;
155
20.2k
    T t;
156
20.2k
    ProgramPoint& PP = t;
157
20.2k
    PP = *this;
158
20.2k
    return t;
159
20.2k
  }
llvm::Optional<clang::PostStmt> clang::ProgramPoint::getAs<clang::PostStmt>() const
Line
Count
Source
152
1.08M
  Optional<T> getAs() const {
153
1.08M
    if (!T::isKind(*this))
154
228k
      return None;
155
855k
    T t;
156
855k
    ProgramPoint& PP = t;
157
855k
    PP = *this;
158
855k
    return t;
159
855k
  }
llvm::Optional<clang::CallExitEnd> clang::ProgramPoint::getAs<clang::CallExitEnd>() const
Line
Count
Source
152
233k
  Optional<T> getAs() const {
153
233k
    if (!T::isKind(*this))
154
215k
      return None;
155
18.2k
    T t;
156
18.2k
    ProgramPoint& PP = t;
157
18.2k
    PP = *this;
158
18.2k
    return t;
159
18.2k
  }
llvm::Optional<clang::PreStmt> clang::ProgramPoint::getAs<clang::PreStmt>() const
Line
Count
Source
152
795k
  Optional<T> getAs() const {
153
795k
    if (!T::isKind(*this))
154
781k
      return None;
155
14.1k
    T t;
156
14.1k
    ProgramPoint& PP = t;
157
14.1k
    PP = *this;
158
14.1k
    return t;
159
14.1k
  }
llvm::Optional<clang::PostInitializer> clang::ProgramPoint::getAs<clang::PostInitializer>() const
Line
Count
Source
152
830k
  Optional<T> getAs() const {
153
830k
    if (!T::isKind(*this))
154
820k
      return None;
155
10.1k
    T t;
156
10.1k
    ProgramPoint& PP = t;
157
10.1k
    PP = *this;
158
10.1k
    return t;
159
10.1k
  }
llvm::Optional<clang::CallExitBegin> clang::ProgramPoint::getAs<clang::CallExitBegin>() const
Line
Count
Source
152
99.2k
  Optional<T> getAs() const {
153
99.2k
    if (!T::isKind(*this))
154
85.6k
      return None;
155
13.6k
    T t;
156
13.6k
    ProgramPoint& PP = t;
157
13.6k
    PP = *this;
158
13.6k
    return t;
159
13.6k
  }
llvm::Optional<clang::LoopExit> clang::ProgramPoint::getAs<clang::LoopExit>() const
Line
Count
Source
152
735k
  Optional<T> getAs() const {
153
735k
    if (!T::isKind(*this))
154
735k
      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
735k
  Optional<T> getAs() const {
153
735k
    if (!T::isKind(*this))
154
735k
      return None;
155
26
    T t;
156
26
    ProgramPoint& PP = t;
157
26
    PP = *this;
158
26
    return t;
159
26
  }
llvm::Optional<clang::PreStmtPurgeDeadSymbols> clang::ProgramPoint::getAs<clang::PreStmtPurgeDeadSymbols>() const
Line
Count
Source
152
1.04M
  Optional<T> getAs() const {
153
1.04M
    if (!T::isKind(*this))
154
924k
      return None;
155
120k
    T t;
156
120k
    ProgramPoint& PP = t;
157
120k
    PP = *this;
158
120k
    return t;
159
120k
  }
llvm::Optional<clang::PreImplicitCall> clang::ProgramPoint::getAs<clang::PreImplicitCall>() const
Line
Count
Source
152
336k
  Optional<T> getAs() const {
153
336k
    if (!T::isKind(*this))
154
336k
      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
25.2k
  Optional<T> getAs() const {
153
25.2k
    if (!T::isKind(*this))
154
24.6k
      return None;
155
556
    T t;
156
556
    ProgramPoint& PP = t;
157
556
    PP = *this;
158
556
    return t;
159
556
  }
160
161
19.1M
  Kind getKind() const {
162
19.1M
    unsigned x = Tag.getInt();
163
19.1M
    x <<= 2;
164
19.1M
    x |= L.getInt();
165
19.1M
    x <<= 2;
166
19.1M
    x |= Data2.getInt();
167
19.1M
    return (Kind) x;
168
19.1M
  }
169
170
  /// Is this a program point corresponding to purge/removal of dead
171
  /// symbols and bindings.
172
89
  bool isPurgeKind() {
173
89
    Kind K = getKind();
174
89
    return (K == PostStmtPurgeDeadSymbolsKind ||
175
89
            K == PreStmtPurgeDeadSymbolsKind);
176
89
  }
177
178
4.20M
  const ProgramPointTag *getTag() const { return Tag.getPointer(); }
179
180
16.8M
  const LocationContext *getLocationContext() const {
181
16.8M
    return L.getPointer();
182
16.8M
  }
183
184
259k
  const StackFrameContext *getStackFrame() const {
185
259k
    return getLocationContext()->getStackFrame();
186
259k
  }
187
188
  // For use with DenseMap.  This hash is probably slow.
189
  unsigned getHashValue() const {
190
    llvm::FoldingSetNodeID ID;
191
    Profile(ID);
192
    return ID.ComputeHash();
193
  }
194
195
734k
  bool operator==(const ProgramPoint & RHS) const {
196
734k
    return Data1 == RHS.Data1 &&
197
734k
           
Data2 == RHS.Data2681k
&&
198
734k
           
L == RHS.L278k
&&
199
734k
           
Tag == RHS.Tag278k
;
200
734k
  }
201
202
  bool operator!=(const ProgramPoint &RHS) const {
203
    return Data1 != RHS.Data1 ||
204
           Data2 != RHS.Data2 ||
205
           L != RHS.L ||
206
           Tag != RHS.Tag;
207
  }
208
209
3.30M
  void Profile(llvm::FoldingSetNodeID& ID) const {
210
3.30M
    ID.AddInteger((unsigned) getKind());
211
3.30M
    ID.AddPointer(getData1());
212
3.30M
    ID.AddPointer(getData2());
213
3.30M
    ID.AddPointer(getLocationContext());
214
3.30M
    ID.AddPointer(getTag());
215
3.30M
  }
216
217
  static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K,
218
                                      const LocationContext *LC,
219
                                      const ProgramPointTag *tag);
220
};
221
222
class BlockEntrance : public ProgramPoint {
223
public:
224
  BlockEntrance(const CFGBlock *B, const LocationContext *L,
225
                const ProgramPointTag *tag = nullptr)
226
158k
    : ProgramPoint(B, BlockEntranceKind, L, tag) {    
227
158k
    assert(B && "BlockEntrance requires non-null block");
228
158k
  }
229
230
409k
  const CFGBlock *getBlock() const {
231
409k
    return reinterpret_cast<const CFGBlock*>(getData1());
232
409k
  }
233
234
98.5k
  Optional<CFGElement> getFirstElement() const {
235
98.5k
    const CFGBlock *B = getBlock();
236
98.5k
    return B->empty() ? 
Optional<CFGElement>()12.6k
:
B->front()85.9k
;
237
98.5k
  }
238
  
239
private:
240
  friend class ProgramPoint;
241
299k
  BlockEntrance() = default;
242
1.87M
  static bool isKind(const ProgramPoint &Location) {
243
1.87M
    return Location.getKind() == BlockEntranceKind;
244
1.87M
  }
245
};
246
247
class BlockExit : public ProgramPoint {
248
public:
249
  BlockExit(const CFGBlock *B, const LocationContext *L)
250
    : ProgramPoint(B, BlockExitKind, L) {}
251
252
  const CFGBlock *getBlock() const {
253
    return reinterpret_cast<const CFGBlock*>(getData1());
254
  }
255
256
  const Stmt *getTerminator() const {
257
    return getBlock()->getTerminator();
258
  }
259
260
private:
261
  friend class ProgramPoint;
262
  BlockExit() = default;
263
  static bool isKind(const ProgramPoint &Location) {
264
    return Location.getKind() == BlockExitKind;
265
  }
266
};
267
268
class StmtPoint : public ProgramPoint {
269
public:
270
  StmtPoint(const Stmt *S, const void *p2, Kind k, const LocationContext *L,
271
            const ProgramPointTag *tag)
272
3.71M
    : ProgramPoint(S, p2, k, L, tag) {
273
3.71M
    assert(S);
274
3.71M
  }
275
276
1.99M
  const Stmt *getStmt() const { return (const Stmt*) getData1(); }
277
278
  template <typename T>
279
40.0k
  const T* getStmtAs() const { return dyn_cast<T>(getStmt()); }
clang::ObjCMessageExpr const* clang::StmtPoint::getStmtAs<clang::ObjCMessageExpr>() const
Line
Count
Source
279
10
  const T* getStmtAs() const { return dyn_cast<T>(getStmt()); }
clang::BinaryOperator const* clang::StmtPoint::getStmtAs<clang::BinaryOperator>() const
Line
Count
Source
279
8.38k
  const T* getStmtAs() const { return dyn_cast<T>(getStmt()); }
clang::Expr const* clang::StmtPoint::getStmtAs<clang::Expr>() const
Line
Count
Source
279
17.7k
  const T* getStmtAs() const { return dyn_cast<T>(getStmt()); }
clang::DeclStmt const* clang::StmtPoint::getStmtAs<clang::DeclStmt>() const
Line
Count
Source
279
13.9k
  const T* getStmtAs() const { return dyn_cast<T>(getStmt()); }
280
281
protected:
282
2.94M
  StmtPoint() = default;
283
private:
284
  friend class ProgramPoint;
285
1.44M
  static bool isKind(const ProgramPoint &Location) {
286
1.44M
    unsigned k = Location.getKind();
287
1.44M
    return k >= PreStmtKind && 
k <= MaxPostStmtKind1.31M
;
288
1.44M
  }
289
};
290
291
292
class PreStmt : public StmtPoint {
293
public:
294
  PreStmt(const Stmt *S, const LocationContext *L, const ProgramPointTag *tag,
295
          const Stmt *SubStmt = nullptr)
296
659k
    : StmtPoint(S, SubStmt, PreStmtKind, L, tag) {}
297
298
0
  const Stmt *getSubStmt() const { return (const Stmt*) getData2(); }
299
300
private:
301
  friend class ProgramPoint;
302
14.1k
  PreStmt() = default;
303
795k
  static bool isKind(const ProgramPoint &Location) {
304
795k
    return Location.getKind() == PreStmtKind;
305
795k
  }
306
};
307
308
class PostStmt : public StmtPoint {
309
protected:
310
1.55M
  PostStmt() = default;
311
  PostStmt(const Stmt *S, const void *data, Kind k, const LocationContext *L,
312
           const ProgramPointTag *tag = nullptr)
313
    : StmtPoint(S, data, k, L, tag) {}
314
315
public:
316
  explicit PostStmt(const Stmt *S, Kind k, const LocationContext *L,
317
                    const ProgramPointTag *tag = nullptr)
318
452k
    : StmtPoint(S, nullptr, k, L, tag) {}
319
320
  explicit PostStmt(const Stmt *S, const LocationContext *L,
321
                    const ProgramPointTag *tag = nullptr)
322
1.84M
    : StmtPoint(S, nullptr, PostStmtKind, L, tag) {}
323
324
private:
325
  friend class ProgramPoint;
326
1.08M
  static bool isKind(const ProgramPoint &Location) {
327
1.08M
    unsigned k = Location.getKind();
328
1.08M
    return k >= MinPostStmtKind && 
k <= MaxPostStmtKind905k
;
329
1.08M
  }
330
};
331
332
// PostCondition represents the post program point of a branch condition.
333
class PostCondition : public PostStmt {
334
public:
335
  PostCondition(const Stmt *S, const LocationContext *L,
336
                const ProgramPointTag *tag = nullptr)
337
36.7k
    : PostStmt(S, PostConditionKind, L, tag) {}
338
339
private:
340
  friend class ProgramPoint;
341
  PostCondition() = default;
342
  static bool isKind(const ProgramPoint &Location) {
343
    return Location.getKind() == PostConditionKind;
344
  }
345
};
346
347
class LocationCheck : public StmtPoint {
348
protected:
349
  LocationCheck() = default;
350
  LocationCheck(const Stmt *S, const LocationContext *L,
351
                ProgramPoint::Kind K, const ProgramPointTag *tag)
352
411k
    : StmtPoint(S, nullptr, K, L, tag) {}
353
    
354
private:
355
  friend class ProgramPoint;
356
  static bool isKind(const ProgramPoint &location) {
357
    unsigned k = location.getKind();
358
    return k == PreLoadKind || k == PreStoreKind;
359
  }
360
};
361
  
362
class PreLoad : public LocationCheck {
363
public:
364
  PreLoad(const Stmt *S, const LocationContext *L,
365
          const ProgramPointTag *tag = nullptr)
366
342k
    : LocationCheck(S, L, PreLoadKind, tag) {}
367
  
368
private:
369
  friend class ProgramPoint;
370
  PreLoad() = default;
371
  static bool isKind(const ProgramPoint &location) {
372
    return location.getKind() == PreLoadKind;
373
  }
374
};
375
376
class PreStore : public LocationCheck {
377
public:
378
  PreStore(const Stmt *S, const LocationContext *L,
379
           const ProgramPointTag *tag = nullptr)
380
69.2k
  : LocationCheck(S, L, PreStoreKind, tag) {}
381
  
382
private:
383
  friend class ProgramPoint;
384
  PreStore() = default;
385
  static bool isKind(const ProgramPoint &location) {
386
    return location.getKind() == PreStoreKind;
387
  }
388
};
389
390
class PostLoad : public PostStmt {
391
public:
392
  PostLoad(const Stmt *S, const LocationContext *L,
393
           const ProgramPointTag *tag = nullptr)
394
139k
    : PostStmt(S, PostLoadKind, L, tag) {}
395
396
private:
397
  friend class ProgramPoint;
398
  PostLoad() = default;
399
  static bool isKind(const ProgramPoint &Location) {
400
    return Location.getKind() == PostLoadKind;
401
  }
402
};
403
404
/// Represents a program point after a store evaluation.
405
class PostStore : public PostStmt {
406
public:
407
  /// Construct the post store point.
408
  /// \param Loc can be used to store the information about the location 
409
  /// used in the form it was uttered in the code.
410
  PostStore(const Stmt *S, const LocationContext *L, const void *Loc,
411
            const ProgramPointTag *tag = nullptr)
412
59.7k
    : PostStmt(S, PostStoreKind, L, tag) {
413
59.7k
    assert(getData2() == nullptr);
414
59.7k
    setData2(Loc);
415
59.7k
  }
416
417
  /// Returns the information about the location used in the store,
418
  /// how it was uttered in the code.
419
715
  const void *getLocationValue() const {
420
715
    return getData2();
421
715
  }
422
423
private:
424
  friend class ProgramPoint;
425
39.6k
  PostStore() = default;
426
791k
  static bool isKind(const ProgramPoint &Location) {
427
791k
    return Location.getKind() == PostStoreKind;
428
791k
  }
429
};
430
431
class PostLValue : public PostStmt {
432
public:
433
  PostLValue(const Stmt *S, const LocationContext *L,
434
             const ProgramPointTag *tag = nullptr)
435
216k
    : PostStmt(S, PostLValueKind, L, tag) {}
436
437
private:
438
  friend class ProgramPoint;
439
  PostLValue() = default;
440
  static bool isKind(const ProgramPoint &Location) {
441
    return Location.getKind() == PostLValueKind;
442
  }
443
};
444
445
/// Represents a point after we ran remove dead bindings BEFORE
446
/// processing the given statement.
447
class PreStmtPurgeDeadSymbols : public StmtPoint {
448
public:
449
  PreStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
450
                       const ProgramPointTag *tag = nullptr)
451
273k
    : StmtPoint(S, nullptr, PreStmtPurgeDeadSymbolsKind, L, tag) { }
452
453
private:
454
  friend class ProgramPoint;
455
120k
  PreStmtPurgeDeadSymbols() = default;
456
1.04M
  static bool isKind(const ProgramPoint &Location) {
457
1.04M
    return Location.getKind() == PreStmtPurgeDeadSymbolsKind;
458
1.04M
  }
459
};
460
461
/// Represents a point after we ran remove dead bindings AFTER
462
/// processing the  given statement.
463
class PostStmtPurgeDeadSymbols : public StmtPoint {
464
public:
465
  PostStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
466
                       const ProgramPointTag *tag = nullptr)
467
78.6k
    : StmtPoint(S, nullptr, PostStmtPurgeDeadSymbolsKind, L, tag) { }
468
469
private:
470
  friend class ProgramPoint;
471
556
  PostStmtPurgeDeadSymbols() = default;
472
25.2k
  static bool isKind(const ProgramPoint &Location) {
473
25.2k
    return Location.getKind() == PostStmtPurgeDeadSymbolsKind;
474
25.2k
  }
475
};
476
477
class BlockEdge : public ProgramPoint {
478
public:
479
  BlockEdge(const CFGBlock *B1, const CFGBlock *B2, const LocationContext *L)
480
156k
    : ProgramPoint(B1, B2, BlockEdgeKind, L) {
481
156k
    assert(B1 && "BlockEdge: source block must be non-null");
482
156k
    assert(B2 && "BlockEdge: destination block must be non-null");    
483
156k
  }
484
485
181k
  const CFGBlock *getSrc() const {
486
181k
    return static_cast<const CFGBlock*>(getData1());
487
181k
  }
488
489
175k
  const CFGBlock *getDst() const {
490
175k
    return static_cast<const CFGBlock*>(getData2());
491
175k
  }
492
493
private:
494
  friend class ProgramPoint;
495
287k
  BlockEdge() = default;
496
1.05M
  static bool isKind(const ProgramPoint &Location) {
497
1.05M
    return Location.getKind() == BlockEdgeKind;
498
1.05M
  }
499
};
500
501
class PostInitializer : public ProgramPoint {
502
public:
503
  /// Construct a PostInitializer point that represents a location after
504
  ///   CXXCtorInitializer expression evaluation.
505
  ///
506
  /// \param I The initializer.
507
  /// \param Loc The location of the field being initialized.
508
  PostInitializer(const CXXCtorInitializer *I,
509
                  const void *Loc,
510
                  const LocationContext *L)
511
7.05k
    : ProgramPoint(I, Loc, PostInitializerKind, L) {}
512
513
5.84k
  const CXXCtorInitializer *getInitializer() const {
514
5.84k
    return static_cast<const CXXCtorInitializer *>(getData1());
515
5.84k
  }
516
517
  /// Returns the location of the field.
518
51
  const void *getLocationValue() const {
519
51
    return getData2();
520
51
  }
521
522
private:
523
  friend class ProgramPoint;
524
10.1k
  PostInitializer() = default;
525
830k
  static bool isKind(const ProgramPoint &Location) {
526
830k
    return Location.getKind() == PostInitializerKind;
527
830k
  }
528
};
529
530
/// Represents an implicit call event.
531
///
532
/// The nearest statement is provided for diagnostic purposes.
533
class ImplicitCallPoint : public ProgramPoint {
534
public:
535
  ImplicitCallPoint(const Decl *D, SourceLocation Loc, Kind K,
536
                    const LocationContext *L, const ProgramPointTag *Tag)
537
7.57k
    : ProgramPoint(Loc.getPtrEncoding(), D, K, L, Tag) {}
538
539
0
  const Decl *getDecl() const { return static_cast<const Decl *>(getData2()); }
540
57
  SourceLocation getLocation() const {
541
57
    return SourceLocation::getFromPtrEncoding(getData1());
542
57
  }
543
544
protected:
545
665
  ImplicitCallPoint() = default;
546
private:
547
  friend class ProgramPoint;
548
0
  static bool isKind(const ProgramPoint &Location) {
549
0
    return Location.getKind() >= MinImplicitCallKind &&
550
0
           Location.getKind() <= MaxImplicitCallKind;
551
0
  }
552
};
553
554
/// Represents a program point just before an implicit call event.
555
///
556
/// Explicit calls will appear as PreStmt program points.
557
class PreImplicitCall : public ImplicitCallPoint {
558
public:
559
  PreImplicitCall(const Decl *D, SourceLocation Loc, const LocationContext *L,
560
                  const ProgramPointTag *Tag = nullptr)
561
4.72k
    : ImplicitCallPoint(D, Loc, PreImplicitCallKind, L, Tag) {}
562
563
private:
564
  friend class ProgramPoint;
565
48
  PreImplicitCall() = default;
566
336k
  static bool isKind(const ProgramPoint &Location) {
567
336k
    return Location.getKind() == PreImplicitCallKind;
568
336k
  }
569
};
570
571
/// Represents a program point just after an implicit call event.
572
///
573
/// Explicit calls will appear as PostStmt program points.
574
class PostImplicitCall : public ImplicitCallPoint {
575
public:
576
  PostImplicitCall(const Decl *D, SourceLocation Loc, const LocationContext *L,
577
                   const ProgramPointTag *Tag = nullptr)
578
2.85k
    : ImplicitCallPoint(D, Loc, PostImplicitCallKind, L, Tag) {}
579
580
private:
581
  friend class ProgramPoint;
582
617
  PostImplicitCall() = default;
583
735k
  static bool isKind(const ProgramPoint &Location) {
584
735k
    return Location.getKind() == PostImplicitCallKind;
585
735k
  }
586
};
587
588
class PostAllocatorCall : public StmtPoint {
589
public:
590
  PostAllocatorCall(const Stmt *S, const LocationContext *L,
591
                    const ProgramPointTag *Tag = nullptr)
592
573
      : StmtPoint(S, nullptr, PostAllocatorCallKind, L, Tag) {}
593
594
private:
595
  friend class ProgramPoint;
596
  PostAllocatorCall() = default;
597
  static bool isKind(const ProgramPoint &Location) {
598
    return Location.getKind() == PostAllocatorCallKind;
599
  }
600
};
601
602
/// Represents a point when we begin processing an inlined call.
603
/// CallEnter uses the caller's location context.
604
class CallEnter : public ProgramPoint {
605
public:
606
  CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx, 
607
            const LocationContext *callerCtx)
608
18.1k
    : ProgramPoint(stmt, calleeCtx, CallEnterKind, callerCtx, nullptr) {}
609
610
411
  const Stmt *getCallExpr() const {
611
411
    return static_cast<const Stmt *>(getData1());
612
411
  }
613
614
74.3k
  const StackFrameContext *getCalleeContext() const {
615
74.3k
    return static_cast<const StackFrameContext *>(getData2());
616
74.3k
  }
617
618
  /// Returns the entry block in the CFG for the entered function.
619
36.3k
  const CFGBlock *getEntry() const {
620
36.3k
    const StackFrameContext *CalleeCtx = getCalleeContext();
621
36.3k
    const CFG *CalleeCFG = CalleeCtx->getCFG();
622
36.3k
    return &(CalleeCFG->getEntry());
623
36.3k
  }
624
625
private:
626
  friend class ProgramPoint;
627
38.4k
  CallEnter() = default;
628
2.13M
  static bool isKind(const ProgramPoint &Location) {
629
2.13M
    return Location.getKind() == CallEnterKind;
630
2.13M
  }
631
};
632
633
/// Represents a point when we start the call exit sequence (for inlined call).
634
///
635
/// The call exit is simulated with a sequence of nodes, which occur between
636
/// CallExitBegin and CallExitEnd. The following operations occur between the
637
/// two program points:
638
/// - CallExitBegin
639
/// - Bind the return value
640
/// - Run Remove dead bindings (to clean up the dead symbols from the callee).
641
/// - CallExitEnd
642
class CallExitBegin : public ProgramPoint {
643
public:
644
  // CallExitBegin uses the callee's location context.
645
  CallExitBegin(const StackFrameContext *L, const ReturnStmt *RS)
646
26.5k
    : ProgramPoint(RS, CallExitBeginKind, L, nullptr) { }
647
648
12.9k
  const ReturnStmt *getReturnStmt() const {
649
12.9k
    return static_cast<const ReturnStmt *>(getData1());
650
12.9k
  }
651
652
private:
653
  friend class ProgramPoint;
654
13.6k
  CallExitBegin() = default;
655
99.2k
  static bool isKind(const ProgramPoint &Location) {
656
99.2k
    return Location.getKind() == CallExitBeginKind;
657
99.2k
  }
658
};
659
660
/// Represents a point when we finish the call exit sequence (for inlined call).
661
/// \sa CallExitBegin
662
class CallExitEnd : public ProgramPoint {
663
public:
664
  // CallExitEnd uses the caller's location context.
665
  CallExitEnd(const StackFrameContext *CalleeCtx,
666
              const LocationContext *CallerCtx)
667
24.8k
    : ProgramPoint(CalleeCtx, CallExitEndKind, CallerCtx, nullptr) {}
668
669
21.1k
  const StackFrameContext *getCalleeContext() const {
670
21.1k
    return static_cast<const StackFrameContext *>(getData1());
671
21.1k
  }
672
673
private:
674
  friend class ProgramPoint;
675
18.2k
  CallExitEnd() = default;
676
233k
  static bool isKind(const ProgramPoint &Location) {
677
233k
    return Location.getKind() == CallExitEndKind;
678
233k
  }
679
};
680
681
/// Represents a point when we exit a loop.
682
/// When this ProgramPoint is encountered we can be sure that the symbolic
683
/// execution of the corresponding LoopStmt is finished on the given path.
684
/// Note: It is possible to encounter a LoopExit element when we haven't even
685
/// encountered the loop itself. At the current state not all loop exits will
686
/// result in a LoopExit program point.
687
class LoopExit : public ProgramPoint {
688
public:
689
    LoopExit(const Stmt *LoopStmt, const LocationContext *LC)
690
141
            : ProgramPoint(LoopStmt, nullptr, LoopExitKind, LC) {}
691
692
0
    const Stmt *getLoopStmt() const {
693
0
      return static_cast<const Stmt *>(getData1());
694
0
    }
695
696
private:
697
    friend class ProgramPoint;
698
264
    LoopExit() = default;
699
735k
    static bool isKind(const ProgramPoint &Location) {
700
735k
      return Location.getKind() == LoopExitKind;
701
735k
    }
702
};
703
704
/// This is a meta program point, which should be skipped by all the diagnostic
705
/// reasoning etc.
706
class EpsilonPoint : public ProgramPoint {
707
public:
708
  EpsilonPoint(const LocationContext *L, const void *Data1,
709
               const void *Data2 = nullptr,
710
               const ProgramPointTag *tag = nullptr)
711
30
    : ProgramPoint(Data1, Data2, EpsilonKind, L, tag) {}
712
713
0
  const void *getData() const { return getData1(); }
714
715
private:
716
  friend class ProgramPoint;
717
26
  EpsilonPoint() = default;
718
735k
  static bool isKind(const ProgramPoint &Location) {
719
735k
    return Location.getKind() == EpsilonKind;
720
735k
  }
721
};
722
723
} // end namespace clang
724
725
726
namespace llvm { // Traits specialization for DenseMap
727
728
template <> struct DenseMapInfo<clang::ProgramPoint> {
729
730
static inline clang::ProgramPoint getEmptyKey() {
731
  uintptr_t x =
732
   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7;
733
  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), nullptr);
734
}
735
736
static inline clang::ProgramPoint getTombstoneKey() {
737
  uintptr_t x =
738
   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7;
739
  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), nullptr);
740
}
741
742
static unsigned getHashValue(const clang::ProgramPoint &Loc) {
743
  return Loc.getHashValue();
744
}
745
746
static bool isEqual(const clang::ProgramPoint &L,
747
                    const clang::ProgramPoint &R) {
748
  return L == R;
749
}
750
751
};
752
  
753
template <>
754
struct isPodLike<clang::ProgramPoint> { static const bool value = true; };
755
756
} // end namespace llvm
757
758
#endif