Coverage Report

Created: 2022-01-22 13:19

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