Coverage Report

Created: 2020-02-15 09:57

/Users/buildslave/jenkins/workspace/coverage/llvm-project/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
25.0k
  ProgramPointTag(void *tagKind = nullptr) : TagKind(tagKind) {}
42
  virtual ~ProgramPointTag();
43
  virtual StringRef getTagDescription() const = 0;
44
45
  /// Used to implement 'isKind' in subclasses.
46
303k
  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
8.96M
  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
455k
      Tag(tag, (((unsigned) k) >> 4) & 0x3) {
109
455k
        assert(getKind() == k);
110
455k
        assert(getLocationContext() == l);
111
455k
        assert(getData1() == P);
112
455k
      }
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
8.68M
      Tag(tag, (((unsigned) k) >> 4) & 0x3) {}
123
124
protected:
125
13.1M
  const void *getData1() const { return Data1; }
126
7.77M
  const void *getData2() const { return Data2.getPointer(); }
127
85.8k
  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.30M
  ProgramPoint withTag(const ProgramPointTag *tag) const {
133
1.30M
    return ProgramPoint(getData1(), getData2(), getKind(),
134
1.30M
                        getLocationContext(), tag);
135
1.30M
  }
136
137
  /// Convert to the specified ProgramPoint type, asserting that this
138
  /// ProgramPoint is of the desired type.
139
  template<typename T>
140
1.45M
  T castAs() const {
141
1.45M
    assert(T::isKind(*this));
142
1.45M
    T t;
143
1.45M
    ProgramPoint& PP = t;
144
1.45M
    PP = *this;
145
1.45M
    return t;
146
1.45M
  }
clang::StmtPoint clang::ProgramPoint::castAs<clang::StmtPoint>() const
Line
Count
Source
140
929
  T castAs() const {
141
929
    assert(T::isKind(*this));
142
929
    T t;
143
929
    ProgramPoint& PP = t;
144
929
    PP = *this;
145
929
    return t;
146
929
  }
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
  }
clang::BlockEdge clang::ProgramPoint::castAs<clang::BlockEdge>() const
Line
Count
Source
140
268k
  T castAs() const {
141
268k
    assert(T::isKind(*this));
142
268k
    T t;
143
268k
    ProgramPoint& PP = t;
144
268k
    PP = *this;
145
268k
    return t;
146
268k
  }
clang::BlockEntrance clang::ProgramPoint::castAs<clang::BlockEntrance>() const
Line
Count
Source
140
150k
  T castAs() const {
141
150k
    assert(T::isKind(*this));
142
150k
    T t;
143
150k
    ProgramPoint& PP = t;
144
150k
    PP = *this;
145
150k
    return t;
146
150k
  }
clang::CallEnter clang::ProgramPoint::castAs<clang::CallEnter>() const
Line
Count
Source
140
63.7k
  T castAs() const {
141
63.7k
    assert(T::isKind(*this));
142
63.7k
    T t;
143
63.7k
    ProgramPoint& PP = t;
144
63.7k
    PP = *this;
145
63.7k
    return t;
146
63.7k
  }
clang::PostStmt clang::ProgramPoint::castAs<clang::PostStmt>() const
Line
Count
Source
140
971k
  T castAs() const {
141
971k
    assert(T::isKind(*this));
142
971k
    T t;
143
971k
    ProgramPoint& PP = t;
144
971k
    PP = *this;
145
971k
    return t;
146
971k
  }
Unexecuted instantiation: clang::LoopExit clang::ProgramPoint::castAs<clang::LoopExit>() const
clang::ImplicitCallPoint clang::ProgramPoint::castAs<clang::ImplicitCallPoint>() const
Line
Count
Source
140
1
  T castAs() const {
141
1
    assert(T::isKind(*this));
142
1
    T t;
143
1
    ProgramPoint& PP = t;
144
1
    PP = *this;
145
1
    return t;
146
1
  }
clang::PostInitializer clang::ProgramPoint::castAs<clang::PostInitializer>() const
Line
Count
Source
140
2
  T castAs() const {
141
2
    assert(T::isKind(*this));
142
2
    T t;
143
2
    ProgramPoint& PP = t;
144
2
    PP = *this;
145
2
    return t;
146
2
  }
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
28.0M
  Optional<T> getAs() const {
152
28.0M
    if (!T::isKind(*this))
153
20.5M
      return None;
154
7.50M
    T t;
155
7.50M
    ProgramPoint& PP = t;
156
7.50M
    PP = *this;
157
7.50M
    return t;
158
7.50M
  }
llvm::Optional<clang::PostStore> clang::ProgramPoint::getAs<clang::PostStore>() const
Line
Count
Source
151
1.23M
  Optional<T> getAs() const {
152
1.23M
    if (!T::isKind(*this))
153
1.17M
      return None;
154
58.4k
    T t;
155
58.4k
    ProgramPoint& PP = t;
156
58.4k
    PP = *this;
157
58.4k
    return t;
158
58.4k
  }
llvm::Optional<clang::BlockEntrance> clang::ProgramPoint::getAs<clang::BlockEntrance>() const
Line
Count
Source
151
3.05M
  Optional<T> getAs() const {
152
3.05M
    if (!T::isKind(*this))
153
2.74M
      return None;
154
306k
    T t;
155
306k
    ProgramPoint& PP = t;
156
306k
    PP = *this;
157
306k
    return t;
158
306k
  }
llvm::Optional<clang::BlockEdge> clang::ProgramPoint::getAs<clang::BlockEdge>() const
Line
Count
Source
151
1.88M
  Optional<T> getAs() const {
152
1.88M
    if (!T::isKind(*this))
153
1.57M
      return None;
154
307k
    T t;
155
307k
    ProgramPoint& PP = t;
156
307k
    PP = *this;
157
307k
    return t;
158
307k
  }
llvm::Optional<clang::PreStmt> clang::ProgramPoint::getAs<clang::PreStmt>() const
Line
Count
Source
151
1.26M
  Optional<T> getAs() const {
152
1.26M
    if (!T::isKind(*this))
153
1.24M
      return None;
154
25.3k
    T t;
155
25.3k
    ProgramPoint& PP = t;
156
25.3k
    PP = *this;
157
25.3k
    return t;
158
25.3k
  }
llvm::Optional<clang::StmtPoint> clang::ProgramPoint::getAs<clang::StmtPoint>() const
Line
Count
Source
151
3.52M
  Optional<T> getAs() const {
152
3.52M
    if (!T::isKind(*this))
153
542k
      return None;
154
2.98M
    T t;
155
2.98M
    ProgramPoint& PP = t;
156
2.98M
    PP = *this;
157
2.98M
    return t;
158
2.98M
  }
llvm::Optional<clang::PostImplicitCall> clang::ProgramPoint::getAs<clang::PostImplicitCall>() const
Line
Count
Source
151
1.18M
  Optional<T> getAs() const {
152
1.18M
    if (!T::isKind(*this))
153
1.18M
      return None;
154
2.39k
    T t;
155
2.39k
    ProgramPoint& PP = t;
156
2.39k
    PP = *this;
157
2.39k
    return t;
158
2.39k
  }
llvm::Optional<clang::CallEnter> clang::ProgramPoint::getAs<clang::CallEnter>() const
Line
Count
Source
151
4.54M
  Optional<T> getAs() const {
152
4.54M
    if (!T::isKind(*this))
153
4.47M
      return None;
154
68.2k
    T t;
155
68.2k
    ProgramPoint& PP = t;
156
68.2k
    PP = *this;
157
68.2k
    return t;
158
68.2k
  }
llvm::Optional<clang::CallExitBegin> clang::ProgramPoint::getAs<clang::CallExitBegin>() const
Line
Count
Source
151
283k
  Optional<T> getAs() const {
152
283k
    if (!T::isKind(*this))
153
242k
      return None;
154
41.8k
    T t;
155
41.8k
    ProgramPoint& PP = t;
156
41.8k
    PP = *this;
157
41.8k
    return t;
158
41.8k
  }
llvm::Optional<clang::PostStmt> clang::ProgramPoint::getAs<clang::PostStmt>() const
Line
Count
Source
151
4.32M
  Optional<T> getAs() const {
152
4.32M
    if (!T::isKind(*this))
153
1.03M
      return None;
154
3.28M
    T t;
155
3.28M
    ProgramPoint& PP = t;
156
3.28M
    PP = *this;
157
3.28M
    return t;
158
3.28M
  }
llvm::Optional<clang::CallExitEnd> clang::ProgramPoint::getAs<clang::CallExitEnd>() const
Line
Count
Source
151
678k
  Optional<T> getAs() const {
152
678k
    if (!T::isKind(*this))
153
540k
      return None;
154
137k
    T t;
155
137k
    ProgramPoint& PP = t;
156
137k
    PP = *this;
157
137k
    return t;
158
137k
  }
llvm::Optional<clang::PreImplicitCall> clang::ProgramPoint::getAs<clang::PreImplicitCall>() const
Line
Count
Source
151
452k
  Optional<T> getAs() const {
152
452k
    if (!T::isKind(*this))
153
452k
      return None;
154
48
    T t;
155
48
    ProgramPoint& PP = t;
156
48
    PP = *this;
157
48
    return t;
158
48
  }
llvm::Optional<clang::FunctionExitPoint> clang::ProgramPoint::getAs<clang::FunctionExitPoint>() const
Line
Count
Source
151
99.1k
  Optional<T> getAs() const {
152
99.1k
    if (!T::isKind(*this))
153
90.7k
      return None;
154
8.42k
    T t;
155
8.42k
    ProgramPoint& PP = t;
156
8.42k
    PP = *this;
157
8.42k
    return t;
158
8.42k
  }
llvm::Optional<clang::PostStmtPurgeDeadSymbols> clang::ProgramPoint::getAs<clang::PostStmtPurgeDeadSymbols>() const
Line
Count
Source
151
35.0k
  Optional<T> getAs() const {
152
35.0k
    if (!T::isKind(*this))
153
34.3k
      return None;
154
675
    T t;
155
675
    ProgramPoint& PP = t;
156
675
    PP = *this;
157
675
    return t;
158
675
  }
llvm::Optional<clang::PostInitializer> clang::ProgramPoint::getAs<clang::PostInitializer>() const
Line
Count
Source
151
1.45M
  Optional<T> getAs() const {
152
1.45M
    if (!T::isKind(*this))
153
1.41M
      return None;
154
42.4k
    T t;
155
42.4k
    ProgramPoint& PP = t;
156
42.4k
    PP = *this;
157
42.4k
    return t;
158
42.4k
  }
llvm::Optional<clang::LoopExit> clang::ProgramPoint::getAs<clang::LoopExit>() const
Line
Count
Source
151
1.10M
  Optional<T> getAs() const {
152
1.10M
    if (!T::isKind(*this))
153
1.10M
      return None;
154
532
    T t;
155
532
    ProgramPoint& PP = t;
156
532
    PP = *this;
157
532
    return t;
158
532
  }
llvm::Optional<clang::PostAllocatorCall> clang::ProgramPoint::getAs<clang::PostAllocatorCall>() const
Line
Count
Source
151
112
  Optional<T> getAs() const {
152
112
    if (!T::isKind(*this))
153
112
      return None;
154
0
    T t;
155
0
    ProgramPoint& PP = t;
156
0
    PP = *this;
157
0
    return t;
158
0
  }
llvm::Optional<clang::EpsilonPoint> clang::ProgramPoint::getAs<clang::EpsilonPoint>() const
Line
Count
Source
151
1.10M
  Optional<T> getAs() const {
152
1.10M
    if (!T::isKind(*this))
153
1.10M
      return None;
154
33
    T t;
155
33
    ProgramPoint& PP = t;
156
33
    PP = *this;
157
33
    return t;
158
33
  }
llvm::Optional<clang::PreStmtPurgeDeadSymbols> clang::ProgramPoint::getAs<clang::PreStmtPurgeDeadSymbols>() const
Line
Count
Source
151
1.85M
  Optional<T> getAs() const {
152
1.85M
    if (!T::isKind(*this))
153
1.61M
      return None;
154
233k
    T t;
155
233k
    ProgramPoint& PP = t;
156
233k
    PP = *this;
157
233k
    return t;
158
233k
  }
llvm::Optional<clang::PreLoad> clang::ProgramPoint::getAs<clang::PreLoad>() const
Line
Count
Source
151
114
  Optional<T> getAs() const {
152
114
    if (!T::isKind(*this))
153
112
      return None;
154
2
    T t;
155
2
    ProgramPoint& PP = t;
156
2
    PP = *this;
157
2
    return t;
158
2
  }
llvm::Optional<clang::PreStore> clang::ProgramPoint::getAs<clang::PreStore>() const
Line
Count
Source
151
112
  Optional<T> getAs() const {
152
112
    if (!T::isKind(*this))
153
112
      return None;
154
0
    T t;
155
0
    ProgramPoint& PP = t;
156
0
    PP = *this;
157
0
    return t;
158
0
  }
llvm::Optional<clang::PostCondition> clang::ProgramPoint::getAs<clang::PostCondition>() const
Line
Count
Source
151
112
  Optional<T> getAs() const {
152
112
    if (!T::isKind(*this))
153
112
      return None;
154
0
    T t;
155
0
    ProgramPoint& PP = t;
156
0
    PP = *this;
157
0
    return t;
158
0
  }
llvm::Optional<clang::PostLoad> clang::ProgramPoint::getAs<clang::PostLoad>() const
Line
Count
Source
151
112
  Optional<T> getAs() const {
152
112
    if (!T::isKind(*this))
153
110
      return None;
154
2
    T t;
155
2
    ProgramPoint& PP = t;
156
2
    PP = *this;
157
2
    return t;
158
2
  }
llvm::Optional<clang::PostLValue> clang::ProgramPoint::getAs<clang::PostLValue>() const
Line
Count
Source
151
110
  Optional<T> getAs() const {
152
110
    if (!T::isKind(*this))
153
108
      return None;
154
2
    T t;
155
2
    ProgramPoint& PP = t;
156
2
    PP = *this;
157
2
    return t;
158
2
  }
159
160
39.4M
  Kind getKind() const {
161
39.4M
    unsigned x = Tag.getInt();
162
39.4M
    x <<= 2;
163
39.4M
    x |= L.getInt();
164
39.4M
    x <<= 2;
165
39.4M
    x |= Data2.getInt();
166
39.4M
    return (Kind) x;
167
39.4M
  }
168
169
  /// Is this a program point corresponding to purge/removal of dead
170
  /// symbols and bindings.
171
110
  bool isPurgeKind() {
172
110
    Kind K = getKind();
173
110
    return (K == PostStmtPurgeDeadSymbolsKind ||
174
110
            K == PreStmtPurgeDeadSymbolsKind);
175
110
  }
176
177
9.30M
  const ProgramPointTag *getTag() const { return Tag.getPointer(); }
178
179
32.2M
  const LocationContext *getLocationContext() const {
180
32.2M
    return L.getPointer();
181
32.2M
  }
182
183
1.31M
  const StackFrameContext *getStackFrame() const {
184
1.31M
    return getLocationContext()->getStackFrame();
185
1.31M
  }
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
1.10M
  bool operator==(const ProgramPoint & RHS) const {
195
1.10M
    return Data1 == RHS.Data1 &&
196
1.10M
           
Data2 == RHS.Data21.05M
&&
197
1.10M
           
L == RHS.L488k
&&
198
1.10M
           
Tag == RHS.Tag488k
;
199
1.10M
  }
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
5.82M
  void Profile(llvm::FoldingSetNodeID& ID) const {
209
5.82M
    ID.AddInteger((unsigned) getKind());
210
5.82M
    ID.AddPointer(getData1());
211
5.82M
    ID.AddPointer(getData2());
212
5.82M
    ID.AddPointer(getLocationContext());
213
5.82M
    ID.AddPointer(getTag());
214
5.82M
  }
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
166k
    : ProgramPoint(B, BlockEntranceKind, L, tag) {
230
166k
    assert(B && "BlockEntrance requires non-null block");
231
166k
  }
232
233
619k
  const CFGBlock *getBlock() const {
234
619k
    return reinterpret_cast<const CFGBlock*>(getData1());
235
619k
  }
236
237
150k
  Optional<CFGElement> getFirstElement() const {
238
150k
    const CFGBlock *B = getBlock();
239
150k
    return B->empty() ? 
Optional<CFGElement>()13.3k
:
B->front()136k
;
240
150k
  }
241
242
private:
243
  friend class ProgramPoint;
244
456k
  BlockEntrance() = default;
245
3.20M
  static bool isKind(const ProgramPoint &Location) {
246
3.20M
    return Location.getKind() == BlockEntranceKind;
247
3.20M
  }
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
7.01M
    : ProgramPoint(S, p2, k, L, tag) {
276
7.01M
    assert(S);
277
7.01M
  }
278
279
4.04M
  const Stmt *getStmt() const { return (const Stmt*) getData1(); }
280
281
  template <typename T>
282
53.1k
  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
22.1k
  const T* getStmtAs() const { return dyn_cast<T>(getStmt()); }
clang::DeclStmt const* clang::StmtPoint::getStmtAs<clang::DeclStmt>() const
Line
Count
Source
282
31.0k
  const T* getStmtAs() const { return dyn_cast<T>(getStmt()); }
283
284
protected:
285
7.56M
  StmtPoint() = default;
286
private:
287
  friend class ProgramPoint;
288
3.52M
  static bool isKind(const ProgramPoint &Location) {
289
3.52M
    unsigned k = Location.getKind();
290
3.52M
    return k >= PreStmtKind && 
k <= MaxPostStmtKind3.20M
;
291
3.52M
  }
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
1.17M
    : 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
25.3k
  PreStmt() = default;
306
1.26M
  static bool isKind(const ProgramPoint &Location) {
307
1.26M
    return Location.getKind() == PreStmtKind;
308
1.26M
  }
309
};
310
311
class PostStmt : public StmtPoint {
312
protected:
313
4.31M
  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
634k
    : StmtPoint(S, nullptr, k, L, tag) {}
322
323
  explicit PostStmt(const Stmt *S, const LocationContext *L,
324
                    const ProgramPointTag *tag = nullptr)
325
2.98M
    : StmtPoint(S, nullptr, PostStmtKind, L, tag) {}
326
327
private:
328
  friend class ProgramPoint;
329
5.29M
  static bool isKind(const ProgramPoint &Location) {
330
5.29M
    unsigned k = Location.getKind();
331
5.29M
    return k >= MinPostStmtKind && 
k <= MaxPostStmtKind4.61M
;
332
5.29M
  }
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
135k
      : ProgramPoint(S, FunctionExitKind, LC, tag) {}
341
342
0
  const CFGBlock *getBlock() const {
343
0
    return &getLocationContext()->getCFG()->getExit();
344
0
  }
345
346
8.42k
  const ReturnStmt *getStmt() const {
347
8.42k
    return reinterpret_cast<const ReturnStmt *>(getData1());
348
8.42k
  }
349
350
private:
351
  friend class ProgramPoint;
352
8.42k
  FunctionExitPoint() = default;
353
99.1k
  static bool isKind(const ProgramPoint &Location) {
354
99.1k
    return Location.getKind() == FunctionExitKind;
355
99.1k
  }
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
47.6k
    : PostStmt(S, PostConditionKind, L, tag) {}
364
365
private:
366
  friend class ProgramPoint;
367
0
  PostCondition() = default;
368
112
  static bool isKind(const ProgramPoint &Location) {
369
112
    return Location.getKind() == PostConditionKind;
370
112
  }
371
};
372
373
class LocationCheck : public StmtPoint {
374
protected:
375
2
  LocationCheck() = default;
376
  LocationCheck(const Stmt *S, const LocationContext *L,
377
                ProgramPoint::Kind K, const ProgramPointTag *tag)
378
503k
    : 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
427k
    : LocationCheck(S, L, PreLoadKind, tag) {}
393
394
private:
395
  friend class ProgramPoint;
396
2
  PreLoad() = default;
397
114
  static bool isKind(const ProgramPoint &location) {
398
114
    return location.getKind() == PreLoadKind;
399
114
  }
400
};
401
402
class PreStore : public LocationCheck {
403
public:
404
  PreStore(const Stmt *S, const LocationContext *L,
405
           const ProgramPointTag *tag = nullptr)
406
76.1k
  : LocationCheck(S, L, PreStoreKind, tag) {}
407
408
private:
409
  friend class ProgramPoint;
410
0
  PreStore() = default;
411
112
  static bool isKind(const ProgramPoint &location) {
412
112
    return location.getKind() == PreStoreKind;
413
112
  }
414
};
415
416
class PostLoad : public PostStmt {
417
public:
418
  PostLoad(const Stmt *S, const LocationContext *L,
419
           const ProgramPointTag *tag = nullptr)
420
179k
    : PostStmt(S, PostLoadKind, L, tag) {}
421
422
private:
423
  friend class ProgramPoint;
424
2
  PostLoad() = default;
425
112
  static bool isKind(const ProgramPoint &Location) {
426
112
    return Location.getKind() == PostLoadKind;
427
112
  }
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
85.8k
    : PostStmt(S, PostStoreKind, L, tag) {
439
85.8k
    assert(getData2() == nullptr);
440
85.8k
    setData2(Loc);
441
85.8k
  }
442
443
  /// Returns the information about the location used in the store,
444
  /// how it was uttered in the code.
445
1.22k
  const void *getLocationValue() const {
446
1.22k
    return getData2();
447
1.22k
  }
448
449
private:
450
  friend class ProgramPoint;
451
58.4k
  PostStore() = default;
452
1.23M
  static bool isKind(const ProgramPoint &Location) {
453
1.23M
    return Location.getKind() == PostStoreKind;
454
1.23M
  }
455
};
456
457
class PostLValue : public PostStmt {
458
public:
459
  PostLValue(const Stmt *S, const LocationContext *L,
460
             const ProgramPointTag *tag = nullptr)
461
321k
    : PostStmt(S, PostLValueKind, L, tag) {}
462
463
private:
464
  friend class ProgramPoint;
465
2
  PostLValue() = default;
466
110
  static bool isKind(const ProgramPoint &Location) {
467
110
    return Location.getKind() == PostLValueKind;
468
110
  }
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.41M
    : StmtPoint(S, nullptr, PreStmtPurgeDeadSymbolsKind, L, tag) { }
478
479
private:
480
  friend class ProgramPoint;
481
233k
  PreStmtPurgeDeadSymbols() = default;
482
1.85M
  static bool isKind(const ProgramPoint &Location) {
483
1.85M
    return Location.getKind() == PreStmtPurgeDeadSymbolsKind;
484
1.85M
  }
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
303k
    : StmtPoint(S, nullptr, PostStmtPurgeDeadSymbolsKind, L, tag) { }
494
495
private:
496
  friend class ProgramPoint;
497
675
  PostStmtPurgeDeadSymbols() = default;
498
35.0k
  static bool isKind(const ProgramPoint &Location) {
499
35.0k
    return Location.getKind() == PostStmtPurgeDeadSymbolsKind;
500
35.0k
  }
501
};
502
503
class BlockEdge : public ProgramPoint {
504
public:
505
  BlockEdge(const CFGBlock *B1, const CFGBlock *B2, const LocationContext *L)
506
266k
    : ProgramPoint(B1, B2, BlockEdgeKind, L) {
507
266k
    assert(B1 && "BlockEdge: source block must be non-null");
508
266k
    assert(B2 && "BlockEdge: destination block must be non-null");
509
266k
  }
510
511
766k
  const CFGBlock *getSrc() const {
512
766k
    return static_cast<const CFGBlock*>(getData1());
513
766k
  }
514
515
301k
  const CFGBlock *getDst() const {
516
301k
    return static_cast<const CFGBlock*>(getData2());
517
301k
  }
518
519
private:
520
  friend class ProgramPoint;
521
576k
  BlockEdge() = default;
522
2.15M
  static bool isKind(const ProgramPoint &Location) {
523
2.15M
    return Location.getKind() == BlockEdgeKind;
524
2.15M
  }
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
23.2k
    : ProgramPoint(I, Loc, PostInitializerKind, L) {}
538
539
15.6k
  const CXXCtorInitializer *getInitializer() const {
540
15.6k
    return static_cast<const CXXCtorInitializer *>(getData1());
541
15.6k
  }
542
543
  /// Returns the location of the field.
544
99
  const void *getLocationValue() const {
545
99
    return getData2();
546
99
  }
547
548
private:
549
  friend class ProgramPoint;
550
42.4k
  PostInitializer() = default;
551
1.45M
  static bool isKind(const ProgramPoint &Location) {
552
1.45M
    return Location.getKind() == PostInitializerKind;
553
1.45M
  }
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
14.3k
    : ProgramPoint(Loc.getPtrEncoding(), D, K, L, Tag) {}
564
565
1
  const Decl *getDecl() const { return static_cast<const Decl *>(getData2()); }
566
61
  SourceLocation getLocation() const {
567
61
    return SourceLocation::getFromPtrEncoding(getData1());
568
61
  }
569
570
protected:
571
2.44k
  ImplicitCallPoint() = default;
572
private:
573
  friend class ProgramPoint;
574
1
  static bool isKind(const ProgramPoint &Location) {
575
1
    return Location.getKind() >= MinImplicitCallKind &&
576
1
           Location.getKind() <= MaxImplicitCallKind;
577
1
  }
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
8.74k
    : ImplicitCallPoint(D, Loc, PreImplicitCallKind, L, Tag) {}
588
589
private:
590
  friend class ProgramPoint;
591
48
  PreImplicitCall() = default;
592
452k
  static bool isKind(const ProgramPoint &Location) {
593
452k
    return Location.getKind() == PreImplicitCallKind;
594
452k
  }
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
5.60k
    : ImplicitCallPoint(D, Loc, PostImplicitCallKind, L, Tag) {}
605
606
private:
607
  friend class ProgramPoint;
608
2.39k
  PostImplicitCall() = default;
609
1.18M
  static bool isKind(const ProgramPoint &Location) {
610
1.18M
    return Location.getKind() == PostImplicitCallKind;
611
1.18M
  }
612
};
613
614
class PostAllocatorCall : public StmtPoint {
615
public:
616
  PostAllocatorCall(const Stmt *S, const LocationContext *L,
617
                    const ProgramPointTag *Tag = nullptr)
618
644
      : StmtPoint(S, nullptr, PostAllocatorCallKind, L, Tag) {}
619
620
private:
621
  friend class ProgramPoint;
622
0
  PostAllocatorCall() = default;
623
112
  static bool isKind(const ProgramPoint &Location) {
624
112
    return Location.getKind() == PostAllocatorCallKind;
625
112
  }
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
63.7k
    : ProgramPoint(stmt, calleeCtx, CallEnterKind, callerCtx, nullptr) {}
635
636
2.25k
  const Stmt *getCallExpr() const {
637
2.25k
    return static_cast<const Stmt *>(getData1());
638
2.25k
  }
639
640
251k
  const StackFrameContext *getCalleeContext() const {
641
251k
    return static_cast<const StackFrameContext *>(getData2());
642
251k
  }
643
644
  /// Returns the entry block in the CFG for the entered function.
645
127k
  const CFGBlock *getEntry() const {
646
127k
    const StackFrameContext *CalleeCtx = getCalleeContext();
647
127k
    const CFG *CalleeCFG = CalleeCtx->getCFG();
648
127k
    return &(CalleeCFG->getEntry());
649
127k
  }
650
651
private:
652
  friend class ProgramPoint;
653
131k
  CallEnter() = default;
654
4.60M
  static bool isKind(const ProgramPoint &Location) {
655
4.60M
    return Location.getKind() == CallEnterKind;
656
4.60M
  }
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
77.9k
    : ProgramPoint(RS, CallExitBeginKind, L, nullptr) { }
673
674
38.6k
  const ReturnStmt *getReturnStmt() const {
675
38.6k
    return static_cast<const ReturnStmt *>(getData1());
676
38.6k
  }
677
678
private:
679
  friend class ProgramPoint;
680
41.8k
  CallExitBegin() = default;
681
283k
  static bool isKind(const ProgramPoint &Location) {
682
283k
    return Location.getKind() == CallExitBeginKind;
683
283k
  }
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
75.4k
    : ProgramPoint(CalleeCtx, CallExitEndKind, CallerCtx, nullptr) {}
694
695
71.4k
  const StackFrameContext *getCalleeContext() const {
696
71.4k
    return static_cast<const StackFrameContext *>(getData1());
697
71.4k
  }
698
699
private:
700
  friend class ProgramPoint;
701
137k
  CallExitEnd() = default;
702
678k
  static bool isKind(const ProgramPoint &Location) {
703
678k
    return Location.getKind() == CallExitEndKind;
704
678k
  }
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
142
            : 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
532
    LoopExit() = default;
725
1.10M
    static bool isKind(const ProgramPoint &Location) {
726
1.10M
      return Location.getKind() == LoopExitKind;
727
1.10M
    }
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
37
    : ProgramPoint(Data1, Data2, EpsilonKind, L, tag) {}
738
739
0
  const void *getData() const { return getData1(); }
740
741
private:
742
  friend class ProgramPoint;
743
33
  EpsilonPoint() = default;
744
1.10M
  static bool isKind(const ProgramPoint &Location) {
745
1.10M
    return Location.getKind() == EpsilonKind;
746
1.10M
  }
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