Coverage Report

Created: 2021-01-19 06:58

/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
28.4k
  ProgramPointTag(void *tagKind = nullptr) : TagKind(tagKind) {}
42
  virtual ~ProgramPointTag();
43
  virtual StringRef getTagDescription() const = 0;
44
45
  /// Used to implement 'isKind' in subclasses.
46
424k
  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.55M
  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
321k
      Tag(tag, (((unsigned) k) >> 4) & 0x3) {
109
321k
        assert(getKind() == k);
110
321k
        assert(getLocationContext() == l);
111
321k
        assert(getData1() == P);
112
321k
      }
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
7.77M
      Tag(tag, (((unsigned) k) >> 4) & 0x3) {}
123
124
protected:
125
10.8M
  const void *getData1() const { return Data1; }
126
5.48M
  const void *getData2() const { return Data2.getPointer(); }
127
71.6k
  void setData2(const void *d) { Data2.setPointer(d); }
128
129
public:
130
  /// Create a new ProgramPoint object that is the same as the original
131
  /// except for using the specified tag value.
132
1.15M
  ProgramPoint withTag(const ProgramPointTag *tag) const {
133
1.15M
    return ProgramPoint(getData1(), getData2(), getKind(),
134
1.15M
                        getLocationContext(), tag);
135
1.15M
  }
136
137
  /// Convert to the specified ProgramPoint type, asserting that this
138
  /// ProgramPoint is of the desired type.
139
  template<typename T>
140
1.02M
  T castAs() const {
141
1.02M
    assert(T::isKind(*this));
142
1.02M
    T t;
143
1.02M
    ProgramPoint& PP = t;
144
1.02M
    PP = *this;
145
1.02M
    return t;
146
1.02M
  }
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
201k
  T castAs() const {
141
201k
    assert(T::isKind(*this));
142
201k
    T t;
143
201k
    ProgramPoint& PP = t;
144
201k
    PP = *this;
145
201k
    return t;
146
201k
  }
clang::BlockEntrance clang::ProgramPoint::castAs<clang::BlockEntrance>() const
Line
Count
Source
140
122k
  T castAs() const {
141
122k
    assert(T::isKind(*this));
142
122k
    T t;
143
122k
    ProgramPoint& PP = t;
144
122k
    PP = *this;
145
122k
    return t;
146
122k
  }
clang::CallEnter clang::ProgramPoint::castAs<clang::CallEnter>() const
Line
Count
Source
140
33.7k
  T castAs() const {
141
33.7k
    assert(T::isKind(*this));
142
33.7k
    T t;
143
33.7k
    ProgramPoint& PP = t;
144
33.7k
    PP = *this;
145
33.7k
    return t;
146
33.7k
  }
clang::PostStmt clang::ProgramPoint::castAs<clang::PostStmt>() const
Line
Count
Source
140
665k
  T castAs() const {
141
665k
    assert(T::isKind(*this));
142
665k
    T t;
143
665k
    ProgramPoint& PP = t;
144
665k
    PP = *this;
145
665k
    return t;
146
665k
  }
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
  }
clang::StmtPoint clang::ProgramPoint::castAs<clang::StmtPoint>() const
Line
Count
Source
140
955
  T castAs() const {
141
955
    assert(T::isKind(*this));
142
955
    T t;
143
955
    ProgramPoint& PP = t;
144
955
    PP = *this;
145
955
    return t;
146
955
  }
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
26.8M
  Optional<T> getAs() const {
152
26.8M
    if (!T::isKind(*this))
153
19.3M
      return None;
154
7.52M
    T t;
155
7.52M
    ProgramPoint& PP = t;
156
7.52M
    PP = *this;
157
7.52M
    return t;
158
7.52M
  }
llvm::Optional<clang::BlockEdge> clang::ProgramPoint::getAs<clang::BlockEdge>() const
Line
Count
Source
151
2.30M
  Optional<T> getAs() const {
152
2.30M
    if (!T::isKind(*this))
153
1.98M
      return None;
154
321k
    T t;
155
321k
    ProgramPoint& PP = t;
156
321k
    PP = *this;
157
321k
    return t;
158
321k
  }
llvm::Optional<clang::FunctionExitPoint> clang::ProgramPoint::getAs<clang::FunctionExitPoint>() const
Line
Count
Source
151
127k
  Optional<T> getAs() const {
152
127k
    if (!T::isKind(*this))
153
112k
      return None;
154
14.9k
    T t;
155
14.9k
    ProgramPoint& PP = t;
156
14.9k
    PP = *this;
157
14.9k
    return t;
158
14.9k
  }
llvm::Optional<clang::PostStmtPurgeDeadSymbols> clang::ProgramPoint::getAs<clang::PostStmtPurgeDeadSymbols>() const
Line
Count
Source
151
42.0k
  Optional<T> getAs() const {
152
42.0k
    if (!T::isKind(*this))
153
41.3k
      return None;
154
674
    T t;
155
674
    ProgramPoint& PP = t;
156
674
    PP = *this;
157
674
    return t;
158
674
  }
llvm::Optional<clang::PostStore> clang::ProgramPoint::getAs<clang::PostStore>() const
Line
Count
Source
151
847k
  Optional<T> getAs() const {
152
847k
    if (!T::isKind(*this))
153
805k
      return None;
154
41.6k
    T t;
155
41.6k
    ProgramPoint& PP = t;
156
41.6k
    PP = *this;
157
41.6k
    return t;
158
41.6k
  }
llvm::Optional<clang::PostStmt> clang::ProgramPoint::getAs<clang::PostStmt>() const
Line
Count
Source
151
3.84M
  Optional<T> getAs() const {
152
3.84M
    if (!T::isKind(*this))
153
866k
      return None;
154
2.97M
    T t;
155
2.97M
    ProgramPoint& PP = t;
156
2.97M
    PP = *this;
157
2.97M
    return t;
158
2.97M
  }
llvm::Optional<clang::PostInitializer> clang::ProgramPoint::getAs<clang::PostInitializer>() const
Line
Count
Source
151
1.28M
  Optional<T> getAs() const {
152
1.28M
    if (!T::isKind(*this))
153
1.23M
      return None;
154
45.7k
    T t;
155
45.7k
    ProgramPoint& PP = t;
156
45.7k
    PP = *this;
157
45.7k
    return t;
158
45.7k
  }
llvm::Optional<clang::PostImplicitCall> clang::ProgramPoint::getAs<clang::PostImplicitCall>() const
Line
Count
Source
151
963k
  Optional<T> getAs() const {
152
963k
    if (!T::isKind(*this))
153
961k
      return None;
154
2.31k
    T t;
155
2.31k
    ProgramPoint& PP = t;
156
2.31k
    PP = *this;
157
2.31k
    return t;
158
2.31k
  }
llvm::Optional<clang::CallExitEnd> clang::ProgramPoint::getAs<clang::CallExitEnd>() const
Line
Count
Source
151
621k
  Optional<T> getAs() const {
152
621k
    if (!T::isKind(*this))
153
520k
      return None;
154
101k
    T t;
155
101k
    ProgramPoint& PP = t;
156
101k
    PP = *this;
157
101k
    return t;
158
101k
  }
llvm::Optional<clang::LoopExit> clang::ProgramPoint::getAs<clang::LoopExit>() const
Line
Count
Source
151
925k
  Optional<T> getAs() const {
152
925k
    if (!T::isKind(*this))
153
925k
      return None;
154
536
    T t;
155
536
    ProgramPoint& PP = t;
156
536
    PP = *this;
157
536
    return t;
158
536
  }
llvm::Optional<clang::PostAllocatorCall> clang::ProgramPoint::getAs<clang::PostAllocatorCall>() const
Line
Count
Source
151
136
  Optional<T> getAs() const {
152
136
    if (!T::isKind(*this))
153
136
      return None;
154
0
    T t;
155
0
    ProgramPoint& PP = t;
156
0
    PP = *this;
157
0
    return t;
158
0
  }
llvm::Optional<clang::CallEnter> clang::ProgramPoint::getAs<clang::CallEnter>() const
Line
Count
Source
151
5.06M
  Optional<T> getAs() const {
152
5.06M
    if (!T::isKind(*this))
153
4.99M
      return None;
154
71.4k
    T t;
155
71.4k
    ProgramPoint& PP = t;
156
71.4k
    PP = *this;
157
71.4k
    return t;
158
71.4k
  }
llvm::Optional<clang::EpsilonPoint> clang::ProgramPoint::getAs<clang::EpsilonPoint>() const
Line
Count
Source
151
925k
  Optional<T> getAs() const {
152
925k
    if (!T::isKind(*this))
153
925k
      return None;
154
36
    T t;
155
36
    ProgramPoint& PP = t;
156
36
    PP = *this;
157
36
    return t;
158
36
  }
llvm::Optional<clang::PreStmtPurgeDeadSymbols> clang::ProgramPoint::getAs<clang::PreStmtPurgeDeadSymbols>() const
Line
Count
Source
151
1.10M
  Optional<T> getAs() const {
152
1.10M
    if (!T::isKind(*this))
153
969k
      return None;
154
132k
    T t;
155
132k
    ProgramPoint& PP = t;
156
132k
    PP = *this;
157
132k
    return t;
158
132k
  }
llvm::Optional<clang::CallExitBegin> clang::ProgramPoint::getAs<clang::CallExitBegin>() const
Line
Count
Source
151
331k
  Optional<T> getAs() const {
152
331k
    if (!T::isKind(*this))
153
274k
      return None;
154
57.1k
    T t;
155
57.1k
    ProgramPoint& PP = t;
156
57.1k
    PP = *this;
157
57.1k
    return t;
158
57.1k
  }
llvm::Optional<clang::BlockEntrance> clang::ProgramPoint::getAs<clang::BlockEntrance>() const
Line
Count
Source
151
2.47M
  Optional<T> getAs() const {
152
2.47M
    if (!T::isKind(*this))
153
2.22M
      return None;
154
249k
    T t;
155
249k
    ProgramPoint& PP = t;
156
249k
    PP = *this;
157
249k
    return t;
158
249k
  }
llvm::Optional<clang::PreImplicitCall> clang::ProgramPoint::getAs<clang::PreImplicitCall>() const
Line
Count
Source
151
312k
  Optional<T> getAs() const {
152
312k
    if (!T::isKind(*this))
153
312k
      return None;
154
24
    T t;
155
24
    ProgramPoint& PP = t;
156
24
    PP = *this;
157
24
    return t;
158
24
  }
llvm::Optional<clang::StmtPoint> clang::ProgramPoint::getAs<clang::StmtPoint>() const
Line
Count
Source
151
4.01M
  Optional<T> getAs() const {
152
4.01M
    if (!T::isKind(*this))
153
542k
      return None;
154
3.47M
    T t;
155
3.47M
    ProgramPoint& PP = t;
156
3.47M
    PP = *this;
157
3.47M
    return t;
158
3.47M
  }
llvm::Optional<clang::PreLoad> clang::ProgramPoint::getAs<clang::PreLoad>() const
Line
Count
Source
151
138
  Optional<T> getAs() const {
152
138
    if (!T::isKind(*this))
153
136
      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
136
  Optional<T> getAs() const {
152
136
    if (!T::isKind(*this))
153
136
      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
136
  Optional<T> getAs() const {
152
136
    if (!T::isKind(*this))
153
136
      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
136
  Optional<T> getAs() const {
152
136
    if (!T::isKind(*this))
153
134
      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
134
  Optional<T> getAs() const {
152
134
    if (!T::isKind(*this))
153
130
      return None;
154
4
    T t;
155
4
    ProgramPoint& PP = t;
156
4
    PP = *this;
157
4
    return t;
158
4
  }
llvm::Optional<clang::PreStmt> clang::ProgramPoint::getAs<clang::PreStmt>() const
Line
Count
Source
151
1.65M
  Optional<T> getAs() const {
152
1.65M
    if (!T::isKind(*this))
153
1.61M
      return None;
154
39.0k
    T t;
155
39.0k
    ProgramPoint& PP = t;
156
39.0k
    PP = *this;
157
39.0k
    return t;
158
39.0k
  }
159
160
34.9M
  Kind getKind() const {
161
34.9M
    unsigned x = Tag.getInt();
162
34.9M
    x <<= 2;
163
34.9M
    x |= L.getInt();
164
34.9M
    x <<= 2;
165
34.9M
    x |= Data2.getInt();
166
34.9M
    return (Kind) x;
167
34.9M
  }
168
169
  /// Is this a program point corresponding to purge/removal of dead
170
  /// symbols and bindings.
171
119
  bool isPurgeKind() {
172
119
    Kind K = getKind();
173
119
    return (K == PostStmtPurgeDeadSymbolsKind ||
174
119
            K == PreStmtPurgeDeadSymbolsKind);
175
119
  }
176
177
7.50M
  const ProgramPointTag *getTag() const { return Tag.getPointer(); }
178
179
27.9M
  const LocationContext *getLocationContext() const {
180
27.9M
    return L.getPointer();
181
27.9M
  }
182
183
982k
  const StackFrameContext *getStackFrame() const {
184
982k
    return getLocationContext()->getStackFrame();
185
982k
  }
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
924k
  bool operator==(const ProgramPoint & RHS) const {
195
924k
    return Data1 == RHS.Data1 &&
196
867k
           Data2 == RHS.Data2 &&
197
380k
           L == RHS.L &&
198
380k
           Tag == RHS.Tag;
199
924k
  }
200
201
0
  bool operator!=(const ProgramPoint &RHS) const {
202
0
    return Data1 != RHS.Data1 ||
203
0
           Data2 != RHS.Data2 ||
204
0
           L != RHS.L ||
205
0
           Tag != RHS.Tag;
206
0
  }
207
208
3.85M
  void Profile(llvm::FoldingSetNodeID& ID) const {
209
3.85M
    ID.AddInteger((unsigned) getKind());
210
3.85M
    ID.AddPointer(getData1());
211
3.85M
    ID.AddPointer(getData2());
212
3.85M
    ID.AddPointer(getLocationContext());
213
3.85M
    ID.AddPointer(getTag());
214
3.85M
  }
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
137k
    : ProgramPoint(B, BlockEntranceKind, L, tag) {
230
137k
    assert(B && "BlockEntrance requires non-null block");
231
137k
  }
232
233
506k
  const CFGBlock *getBlock() const {
234
506k
    return reinterpret_cast<const CFGBlock*>(getData1());
235
506k
  }
236
237
122k
  Optional<CFGElement> getFirstElement() const {
238
122k
    const CFGBlock *B = getBlock();
239
109k
    return B->empty() ? 
Optional<CFGElement>()12.9k
: B->front();
240
122k
  }
241
242
private:
243
  friend class ProgramPoint;
244
371k
  BlockEntrance() = default;
245
2.59M
  static bool isKind(const ProgramPoint &Location) {
246
2.59M
    return Location.getKind() == BlockEntranceKind;
247
2.59M
  }
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
6.35M
    : ProgramPoint(S, p2, k, L, tag) {
276
6.35M
    assert(S);
277
6.35M
  }
278
279
4.24M
  const Stmt *getStmt() const { return (const Stmt*) getData1(); }
280
281
  template <typename T>
282
55.0k
  const T* getStmtAs() const { return dyn_cast<T>(getStmt()); }
clang::ObjCMessageExpr const* clang::StmtPoint::getStmtAs<clang::ObjCMessageExpr>() const
Line
Count
Source
282
16
  const T* getStmtAs() const { return dyn_cast<T>(getStmt()); }
clang::DeclStmt const* clang::StmtPoint::getStmtAs<clang::DeclStmt>() const
Line
Count
Source
282
32.3k
  const T* getStmtAs() const { return dyn_cast<T>(getStmt()); }
clang::BinaryOperator const* clang::StmtPoint::getStmtAs<clang::BinaryOperator>() const
Line
Count
Source
282
22.6k
  const T* getStmtAs() const { return dyn_cast<T>(getStmt()); }
283
284
protected:
285
7.33M
  StmtPoint() = default;
286
private:
287
  friend class ProgramPoint;
288
4.01M
  static bool isKind(const ProgramPoint &Location) {
289
4.01M
    unsigned k = Location.getKind();
290
4.01M
    return k >= PreStmtKind && 
k <= MaxPostStmtKind3.68M
;
291
4.01M
  }
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
963k
    : 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
39.0k
  PreStmt() = default;
306
1.65M
  static bool isKind(const ProgramPoint &Location) {
307
1.65M
    return Location.getKind() == PreStmtKind;
308
1.65M
  }
309
};
310
311
class PostStmt : public StmtPoint {
312
protected:
313
3.68M
  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
537k
    : StmtPoint(S, nullptr, k, L, tag) {}
322
323
  explicit PostStmt(const Stmt *S, const LocationContext *L,
324
                    const ProgramPointTag *tag = nullptr)
325
2.61M
    : StmtPoint(S, nullptr, PostStmtKind, L, tag) {}
326
327
private:
328
  friend class ProgramPoint;
329
4.50M
  static bool isKind(const ProgramPoint &Location) {
330
4.50M
    unsigned k = Location.getKind();
331
4.50M
    return k >= MinPostStmtKind && 
k <= MaxPostStmtKind3.87M
;
332
4.50M
  }
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
103k
      : ProgramPoint(S, FunctionExitKind, LC, tag) {}
341
342
0
  const CFGBlock *getBlock() const {
343
0
    return &getLocationContext()->getCFG()->getExit();
344
0
  }
345
346
14.9k
  const ReturnStmt *getStmt() const {
347
14.9k
    return reinterpret_cast<const ReturnStmt *>(getData1());
348
14.9k
  }
349
350
private:
351
  friend class ProgramPoint;
352
14.9k
  FunctionExitPoint() = default;
353
127k
  static bool isKind(const ProgramPoint &Location) {
354
127k
    return Location.getKind() == FunctionExitKind;
355
127k
  }
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
42.8k
    : PostStmt(S, PostConditionKind, L, tag) {}
364
365
private:
366
  friend class ProgramPoint;
367
0
  PostCondition() = default;
368
136
  static bool isKind(const ProgramPoint &Location) {
369
136
    return Location.getKind() == PostConditionKind;
370
136
  }
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
427k
    : 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
356k
    : LocationCheck(S, L, PreLoadKind, tag) {}
393
394
private:
395
  friend class ProgramPoint;
396
2
  PreLoad() = default;
397
138
  static bool isKind(const ProgramPoint &location) {
398
138
    return location.getKind() == PreLoadKind;
399
138
  }
400
};
401
402
class PreStore : public LocationCheck {
403
public:
404
  PreStore(const Stmt *S, const LocationContext *L,
405
           const ProgramPointTag *tag = nullptr)
406
70.8k
  : LocationCheck(S, L, PreStoreKind, tag) {}
407
408
private:
409
  friend class ProgramPoint;
410
0
  PreStore() = default;
411
136
  static bool isKind(const ProgramPoint &location) {
412
136
    return location.getKind() == PreStoreKind;
413
136
  }
414
};
415
416
class PostLoad : public PostStmt {
417
public:
418
  PostLoad(const Stmt *S, const LocationContext *L,
419
           const ProgramPointTag *tag = nullptr)
420
147k
    : PostStmt(S, PostLoadKind, L, tag) {}
421
422
private:
423
  friend class ProgramPoint;
424
2
  PostLoad() = default;
425
136
  static bool isKind(const ProgramPoint &Location) {
426
136
    return Location.getKind() == PostLoadKind;
427
136
  }
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
71.6k
    : PostStmt(S, PostStoreKind, L, tag) {
439
71.6k
    assert(getData2() == nullptr);
440
71.6k
    setData2(Loc);
441
71.6k
  }
442
443
  /// Returns the information about the location used in the store,
444
  /// how it was uttered in the code.
445
1.23k
  const void *getLocationValue() const {
446
1.23k
    return getData2();
447
1.23k
  }
448
449
private:
450
  friend class ProgramPoint;
451
41.6k
  PostStore() = default;
452
847k
  static bool isKind(const ProgramPoint &Location) {
453
847k
    return Location.getKind() == PostStoreKind;
454
847k
  }
455
};
456
457
class PostLValue : public PostStmt {
458
public:
459
  PostLValue(const Stmt *S, const LocationContext *L,
460
             const ProgramPointTag *tag = nullptr)
461
275k
    : PostStmt(S, PostLValueKind, L, tag) {}
462
463
private:
464
  friend class ProgramPoint;
465
4
  PostLValue() = default;
466
134
  static bool isKind(const ProgramPoint &Location) {
467
134
    return Location.getKind() == PostLValueKind;
468
134
  }
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.51M
    : StmtPoint(S, nullptr, PreStmtPurgeDeadSymbolsKind, L, tag) { }
478
479
private:
480
  friend class ProgramPoint;
481
132k
  PreStmtPurgeDeadSymbols() = default;
482
1.10M
  static bool isKind(const ProgramPoint &Location) {
483
1.10M
    return Location.getKind() == PreStmtPurgeDeadSymbolsKind;
484
1.10M
  }
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
294k
    : StmtPoint(S, nullptr, PostStmtPurgeDeadSymbolsKind, L, tag) { }
494
495
private:
496
  friend class ProgramPoint;
497
674
  PostStmtPurgeDeadSymbols() = default;
498
42.0k
  static bool isKind(const ProgramPoint &Location) {
499
42.0k
    return Location.getKind() == PostStmtPurgeDeadSymbolsKind;
500
42.0k
  }
501
};
502
503
class BlockEdge : public ProgramPoint {
504
public:
505
  BlockEdge(const CFGBlock *B1, const CFGBlock *B2, const LocationContext *L)
506
200k
    : ProgramPoint(B1, B2, BlockEdgeKind, L) {
507
200k
    assert(B1 && "BlockEdge: source block must be non-null");
508
200k
    assert(B2 && "BlockEdge: destination block must be non-null");
509
200k
  }
510
511
646k
  const CFGBlock *getSrc() const {
512
646k
    return static_cast<const CFGBlock*>(getData1());
513
646k
  }
514
515
237k
  const CFGBlock *getDst() const {
516
237k
    return static_cast<const CFGBlock*>(getData2());
517
237k
  }
518
519
private:
520
  friend class ProgramPoint;
521
523k
  BlockEdge() = default;
522
2.50M
  static bool isKind(const ProgramPoint &Location) {
523
2.50M
    return Location.getKind() == BlockEdgeKind;
524
2.50M
  }
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
19.9k
    : ProgramPoint(I, Loc, PostInitializerKind, L) {}
538
539
22.1k
  const CXXCtorInitializer *getInitializer() const {
540
22.1k
    return static_cast<const CXXCtorInitializer *>(getData1());
541
22.1k
  }
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
45.7k
  PostInitializer() = default;
551
1.28M
  static bool isKind(const ProgramPoint &Location) {
552
1.28M
    return Location.getKind() == PostInitializerKind;
553
1.28M
  }
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
13.2k
    : ProgramPoint(Loc.getPtrEncoding(), D, K, L, Tag) {}
564
565
1
  const Decl *getDecl() const { return static_cast<const Decl *>(getData2()); }
566
37
  SourceLocation getLocation() const {
567
37
    return SourceLocation::getFromPtrEncoding(getData1());
568
37
  }
569
570
protected:
571
2.33k
  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
7.56k
    : ImplicitCallPoint(D, Loc, PreImplicitCallKind, L, Tag) {}
588
589
private:
590
  friend class ProgramPoint;
591
24
  PreImplicitCall() = default;
592
312k
  static bool isKind(const ProgramPoint &Location) {
593
312k
    return Location.getKind() == PreImplicitCallKind;
594
312k
  }
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.71k
    : ImplicitCallPoint(D, Loc, PostImplicitCallKind, L, Tag) {}
605
606
private:
607
  friend class ProgramPoint;
608
2.31k
  PostImplicitCall() = default;
609
963k
  static bool isKind(const ProgramPoint &Location) {
610
963k
    return Location.getKind() == PostImplicitCallKind;
611
963k
  }
612
};
613
614
class PostAllocatorCall : public StmtPoint {
615
public:
616
  PostAllocatorCall(const Stmt *S, const LocationContext *L,
617
                    const ProgramPointTag *Tag = nullptr)
618
554
      : StmtPoint(S, nullptr, PostAllocatorCallKind, L, Tag) {}
619
620
private:
621
  friend class ProgramPoint;
622
0
  PostAllocatorCall() = default;
623
136
  static bool isKind(const ProgramPoint &Location) {
624
136
    return Location.getKind() == PostAllocatorCallKind;
625
136
  }
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
33.7k
    : ProgramPoint(stmt, calleeCtx, CallEnterKind, callerCtx, nullptr) {}
635
636
2.70k
  const Stmt *getCallExpr() const {
637
2.70k
    return static_cast<const Stmt *>(getData1());
638
2.70k
  }
639
640
170k
  const StackFrameContext *getCalleeContext() const {
641
170k
    return static_cast<const StackFrameContext *>(getData2());
642
170k
  }
643
644
  /// Returns the entry block in the CFG for the entered function.
645
67.5k
  const CFGBlock *getEntry() const {
646
67.5k
    const StackFrameContext *CalleeCtx = getCalleeContext();
647
67.5k
    const CFG *CalleeCFG = CalleeCtx->getCFG();
648
67.5k
    return &(CalleeCFG->getEntry());
649
67.5k
  }
650
651
private:
652
  friend class ProgramPoint;
653
105k
  CallEnter() = default;
654
5.10M
  static bool isKind(const ProgramPoint &Location) {
655
5.10M
    return Location.getKind() == CallEnterKind;
656
5.10M
  }
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
41.2k
    : ProgramPoint(RS, CallExitBeginKind, L, nullptr) { }
673
674
53.8k
  const ReturnStmt *getReturnStmt() const {
675
53.8k
    return static_cast<const ReturnStmt *>(getData1());
676
53.8k
  }
677
678
private:
679
  friend class ProgramPoint;
680
57.1k
  CallExitBegin() = default;
681
331k
  static bool isKind(const ProgramPoint &Location) {
682
331k
    return Location.getKind() == CallExitBeginKind;
683
331k
  }
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
39.4k
    : ProgramPoint(CalleeCtx, CallExitEndKind, CallerCtx, nullptr) {}
694
695
72.8k
  const StackFrameContext *getCalleeContext() const {
696
72.8k
    return static_cast<const StackFrameContext *>(getData1());
697
72.8k
  }
698
699
private:
700
  friend class ProgramPoint;
701
101k
  CallExitEnd() = default;
702
621k
  static bool isKind(const ProgramPoint &Location) {
703
621k
    return Location.getKind() == CallExitEndKind;
704
621k
  }
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
144
            : 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
536
    LoopExit() = default;
725
925k
    static bool isKind(const ProgramPoint &Location) {
726
925k
      return Location.getKind() == LoopExitKind;
727
925k
    }
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
40
    : ProgramPoint(Data1, Data2, EpsilonKind, L, tag) {}
738
739
0
  const void *getData() const { return getData1(); }
740
741
private:
742
  friend class ProgramPoint;
743
36
  EpsilonPoint() = default;
744
925k
  static bool isKind(const ProgramPoint &Location) {
745
925k
    return Location.getKind() == EpsilonKind;
746
925k
  }
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