Coverage Report

Created: 2022-07-16 07:03

/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
34.1k
  ProgramPointTag(void *tagKind = nullptr) : TagKind(tagKind) {}
41
  virtual ~ProgramPointTag();
42
  virtual StringRef getTagDescription() const = 0;
43
44
  /// Used to implement 'isKind' in subclasses.
45
849k
  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
14.4M
  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
347k
      Tag(tag, (((unsigned) k) >> 4) & 0x3) {
108
347k
        assert(getKind() == k);
109
0
        assert(getLocationContext() == l);
110
0
        assert(getData1() == P);
111
347k
      }
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
9.39M
      Tag(tag, (((unsigned) k) >> 4) & 0x3) {}
122
123
protected:
124
16.0M
  const void *getData1() const { return Data1; }
125
6.82M
  const void *getData2() const { return Data2.getPointer(); }
126
86.1k
  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.48M
  ProgramPoint withTag(const ProgramPointTag *tag) const {
132
1.48M
    return ProgramPoint(getData1(), getData2(), getKind(),
133
1.48M
                        getLocationContext(), tag);
134
1.48M
  }
135
136
  /// Convert to the specified ProgramPoint type, asserting that this
137
  /// ProgramPoint is of the desired type.
138
  template<typename T>
139
1.44M
  T castAs() const {
140
1.44M
    assert(T::isKind(*this));
141
0
    T t;
142
1.44M
    ProgramPoint& PP = t;
143
1.44M
    PP = *this;
144
1.44M
    return t;
145
1.44M
  }
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
228k
  T castAs() const {
140
228k
    assert(T::isKind(*this));
141
0
    T t;
142
228k
    ProgramPoint& PP = t;
143
228k
    PP = *this;
144
228k
    return t;
145
228k
  }
clang::BlockEntrance clang::ProgramPoint::castAs<clang::BlockEntrance>() const
Line
Count
Source
139
139k
  T castAs() const {
140
139k
    assert(T::isKind(*this));
141
0
    T t;
142
139k
    ProgramPoint& PP = t;
143
139k
    PP = *this;
144
139k
    return t;
145
139k
  }
clang::CallEnter clang::ProgramPoint::castAs<clang::CallEnter>() const
Line
Count
Source
139
35.3k
  T castAs() const {
140
35.3k
    assert(T::isKind(*this));
141
0
    T t;
142
35.3k
    ProgramPoint& PP = t;
143
35.3k
    PP = *this;
144
35.3k
    return t;
145
35.3k
  }
clang::PostStmt clang::ProgramPoint::castAs<clang::PostStmt>() const
Line
Count
Source
139
1.04M
  T castAs() const {
140
1.04M
    assert(T::isKind(*this));
141
0
    T t;
142
1.04M
    ProgramPoint& PP = t;
143
1.04M
    PP = *this;
144
1.04M
    return t;
145
1.04M
  }
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
42.6M
  Optional<T> getAs() const {
151
42.6M
    if (!T::isKind(*this))
152
29.5M
      return None;
153
13.0M
    T t;
154
13.0M
    ProgramPoint& PP = t;
155
13.0M
    PP = *this;
156
13.0M
    return t;
157
42.6M
  }
llvm::Optional<clang::BlockEdge> clang::ProgramPoint::getAs<clang::BlockEdge>() const
Line
Count
Source
150
3.91M
  Optional<T> getAs() const {
151
3.91M
    if (!T::isKind(*this))
152
3.57M
      return None;
153
337k
    T t;
154
337k
    ProgramPoint& PP = t;
155
337k
    PP = *this;
156
337k
    return t;
157
3.91M
  }
llvm::Optional<clang::FunctionExitPoint> clang::ProgramPoint::getAs<clang::FunctionExitPoint>() const
Line
Count
Source
150
141k
  Optional<T> getAs() const {
151
141k
    if (!T::isKind(*this))
152
125k
      return None;
153
15.6k
    T t;
154
15.6k
    ProgramPoint& PP = t;
155
15.6k
    PP = *this;
156
15.6k
    return t;
157
141k
  }
llvm::Optional<clang::PostStmtPurgeDeadSymbols> clang::ProgramPoint::getAs<clang::PostStmtPurgeDeadSymbols>() const
Line
Count
Source
150
58.1k
  Optional<T> getAs() const {
151
58.1k
    if (!T::isKind(*this))
152
57.3k
      return None;
153
808
    T t;
154
808
    ProgramPoint& PP = t;
155
808
    PP = *this;
156
808
    return t;
157
58.1k
  }
llvm::Optional<clang::PostStore> clang::ProgramPoint::getAs<clang::PostStore>() const
Line
Count
Source
150
1.26M
  Optional<T> getAs() const {
151
1.26M
    if (!T::isKind(*this))
152
1.20M
      return None;
153
53.0k
    T t;
154
53.0k
    ProgramPoint& PP = t;
155
53.0k
    PP = *this;
156
53.0k
    return t;
157
1.26M
  }
llvm::Optional<clang::PostStmt> clang::ProgramPoint::getAs<clang::PostStmt>() const
Line
Count
Source
150
6.16M
  Optional<T> getAs() const {
151
6.16M
    if (!T::isKind(*this))
152
1.14M
      return None;
153
5.02M
    T t;
154
5.02M
    ProgramPoint& PP = t;
155
5.02M
    PP = *this;
156
5.02M
    return t;
157
6.16M
  }
llvm::Optional<clang::PostInitializer> clang::ProgramPoint::getAs<clang::PostInitializer>() const
Line
Count
Source
150
1.61M
  Optional<T> getAs() const {
151
1.61M
    if (!T::isKind(*this))
152
1.56M
      return None;
153
47.7k
    T t;
154
47.7k
    ProgramPoint& PP = t;
155
47.7k
    PP = *this;
156
47.7k
    return t;
157
1.61M
  }
llvm::Optional<clang::PostImplicitCall> clang::ProgramPoint::getAs<clang::PostImplicitCall>() const
Line
Count
Source
150
1.26M
  Optional<T> getAs() const {
151
1.26M
    if (!T::isKind(*this))
152
1.26M
      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.26M
  }
llvm::Optional<clang::CallExitEnd> clang::ProgramPoint::getAs<clang::CallExitEnd>() const
Line
Count
Source
150
704k
  Optional<T> getAs() const {
151
704k
    if (!T::isKind(*this))
152
594k
      return None;
153
109k
    T t;
154
109k
    ProgramPoint& PP = t;
155
109k
    PP = *this;
156
109k
    return t;
157
704k
  }
llvm::Optional<clang::LoopExit> clang::ProgramPoint::getAs<clang::LoopExit>() const
Line
Count
Source
150
1.22M
  Optional<T> getAs() const {
151
1.22M
    if (!T::isKind(*this))
152
1.22M
      return None;
153
544
    T t;
154
544
    ProgramPoint& PP = t;
155
544
    PP = *this;
156
544
    return t;
157
1.22M
  }
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.77M
  Optional<T> getAs() const {
151
8.77M
    if (!T::isKind(*this))
152
8.69M
      return None;
153
78.5k
    T t;
154
78.5k
    ProgramPoint& PP = t;
155
78.5k
    PP = *this;
156
78.5k
    return t;
157
8.77M
  }
llvm::Optional<clang::EpsilonPoint> clang::ProgramPoint::getAs<clang::EpsilonPoint>() const
Line
Count
Source
150
1.22M
  Optional<T> getAs() const {
151
1.22M
    if (!T::isKind(*this))
152
1.22M
      return None;
153
36
    T t;
154
36
    ProgramPoint& PP = t;
155
36
    PP = *this;
156
36
    return t;
157
1.22M
  }
llvm::Optional<clang::PreStmtPurgeDeadSymbols> clang::ProgramPoint::getAs<clang::PreStmtPurgeDeadSymbols>() const
Line
Count
Source
150
1.56M
  Optional<T> getAs() const {
151
1.56M
    if (!T::isKind(*this))
152
1.40M
      return None;
153
162k
    T t;
154
162k
    ProgramPoint& PP = t;
155
162k
    PP = *this;
156
162k
    return t;
157
1.56M
  }
llvm::Optional<clang::CallExitBegin> clang::ProgramPoint::getAs<clang::CallExitBegin>() const
Line
Count
Source
150
381k
  Optional<T> getAs() const {
151
381k
    if (!T::isKind(*this))
152
322k
      return None;
153
59.0k
    T t;
154
59.0k
    ProgramPoint& PP = t;
155
59.0k
    PP = *this;
156
59.0k
    return t;
157
381k
  }
llvm::Optional<clang::BlockEntrance> clang::ProgramPoint::getAs<clang::BlockEntrance>() const
Line
Count
Source
150
3.14M
  Optional<T> getAs() const {
151
3.14M
    if (!T::isKind(*this))
152
2.86M
      return None;
153
287k
    T t;
154
287k
    ProgramPoint& PP = t;
155
287k
    PP = *this;
156
287k
    return t;
157
3.14M
  }
llvm::Optional<clang::PreImplicitCall> clang::ProgramPoint::getAs<clang::PreImplicitCall>() const
Line
Count
Source
150
523k
  Optional<T> getAs() const {
151
523k
    if (!T::isKind(*this))
152
523k
      return None;
153
24
    T t;
154
24
    ProgramPoint& PP = t;
155
24
    PP = *this;
156
24
    return t;
157
523k
  }
llvm::Optional<clang::StmtPoint> clang::ProgramPoint::getAs<clang::StmtPoint>() const
Line
Count
Source
150
7.41M
  Optional<T> getAs() const {
151
7.41M
    if (!T::isKind(*this))
152
580k
      return None;
153
6.83M
    T t;
154
6.83M
    ProgramPoint& PP = t;
155
6.83M
    PP = *this;
156
6.83M
    return t;
157
7.41M
  }
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.22M
  Optional<T> getAs() const {
151
3.22M
    if (!T::isKind(*this))
152
3.18M
      return None;
153
43.5k
    T t;
154
43.5k
    ProgramPoint& PP = t;
155
43.5k
    PP = *this;
156
43.5k
    return t;
157
3.22M
  }
158
159
52.8M
  Kind getKind() const {
160
52.8M
    unsigned x = Tag.getInt();
161
52.8M
    x <<= 2;
162
52.8M
    x |= L.getInt();
163
52.8M
    x <<= 2;
164
52.8M
    x |= Data2.getInt();
165
52.8M
    return (Kind) x;
166
52.8M
  }
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
11.7M
  const ProgramPointTag *getTag() const { return Tag.getPointer(); }
177
178
39.5M
  const LocationContext *getLocationContext() const {
179
39.5M
    return L.getPointer();
180
39.5M
  }
181
182
1.04M
  const StackFrameContext *getStackFrame() const {
183
1.04M
    return getLocationContext()->getStackFrame();
184
1.04M
  }
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
1.22M
  bool operator==(const ProgramPoint & RHS) const {
194
1.22M
    return Data1 == RHS.Data1 &&
195
1.22M
           
Data2 == RHS.Data21.15M
&&
196
1.22M
           
L == RHS.L479k
&&
197
1.22M
           
Tag == RHS.Tag479k
;
198
1.22M
  }
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.80M
  void Profile(llvm::FoldingSetNodeID& ID) const {
208
4.80M
    ID.AddInteger((unsigned) getKind());
209
4.80M
    ID.AddPointer(getData1());
210
4.80M
    ID.AddPointer(getData2());
211
4.80M
    ID.AddPointer(getLocationContext());
212
4.80M
    ID.AddPointer(getTag());
213
4.80M
  }
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
155k
    : ProgramPoint(B, BlockEntranceKind, L, tag) {
229
155k
    assert(B && "BlockEntrance requires non-null block");
230
155k
  }
231
232
575k
  const CFGBlock *getBlock() const {
233
575k
    return reinterpret_cast<const CFGBlock*>(getData1());
234
575k
  }
235
236
139k
  Optional<CFGElement> getFirstElement() const {
237
139k
    const CFGBlock *B = getBlock();
238
139k
    return B->empty() ? 
Optional<CFGElement>()13.2k
:
B->front()126k
;
239
139k
  }
240
241
private:
242
  friend class ProgramPoint;
243
426k
  BlockEntrance() = default;
244
3.28M
  static bool isKind(const ProgramPoint &Location) {
245
3.28M
    return Location.getKind() == BlockEntranceKind;
246
3.28M
  }
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
7.61M
    : ProgramPoint(S, p2, k, L, tag) {
275
7.61M
    assert(S);
276
7.61M
  }
277
278
7.99M
  const Stmt *getStmt() const { return (const Stmt*) getData1(); }
279
280
  template <typename T>
281
64.1k
  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
37.3k
  const T* getStmtAs() const { return dyn_cast<T>(getStmt()); }
clang::BinaryOperator const* clang::StmtPoint::getStmtAs<clang::BinaryOperator>() const
Line
Count
Source
281
26.7k
  const T* getStmtAs() const { return dyn_cast<T>(getStmt()); }
282
283
protected:
284
13.1M
  StmtPoint() = default;
285
private:
286
  friend class ProgramPoint;
287
7.41M
  static bool isKind(const ProgramPoint &Location) {
288
7.41M
    unsigned k = Location.getKind();
289
7.41M
    return k >= PreStmtKind && 
k <= MaxPostStmtKind7.04M
;
290
7.41M
  }
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.09M
    : 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
43.5k
  PreStmt() = default;
305
3.22M
  static bool isKind(const ProgramPoint &Location) {
306
3.22M
    return Location.getKind() == PreStmtKind;
307
3.22M
  }
308
};
309
310
class PostStmt : public StmtPoint {
311
protected:
312
6.11M
  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
733k
    : StmtPoint(S, nullptr, k, L, tag) {}
321
322
  explicit PostStmt(const Stmt *S, const LocationContext *L,
323
                    const ProgramPointTag *tag = nullptr)
324
3.19M
    : StmtPoint(S, nullptr, PostStmtKind, L, tag) {}
325
326
private:
327
  friend class ProgramPoint;
328
7.21M
  static bool isKind(const ProgramPoint &Location) {
329
7.21M
    unsigned k = Location.getKind();
330
7.21M
    return k >= MinPostStmtKind && 
k <= MaxPostStmtKind6.30M
;
331
7.21M
  }
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
107k
      : 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
141k
  static bool isKind(const ProgramPoint &Location) {
353
141k
    return Location.getKind() == FunctionExitKind;
354
141k
  }
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
50.0k
    : 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
652k
    : 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
573k
    : 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
78.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
227k
    : 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
86.1k
    : PostStmt(S, PostStoreKind, L, tag) {
438
86.1k
    assert(getData2() == nullptr);
439
0
    setData2(Loc);
440
86.1k
  }
441
442
  /// Returns the information about the location used in the store,
443
  /// how it was uttered in the code.
444
1.46k
  const void *getLocationValue() const {
445
1.46k
    return getData2();
446
1.46k
  }
447
448
private:
449
  friend class ProgramPoint;
450
53.0k
  PostStore() = default;
451
1.26M
  static bool isKind(const ProgramPoint &Location) {
452
1.26M
    return Location.getKind() == PostStoreKind;
453
1.26M
  }
454
};
455
456
class PostLValue : public PostStmt {
457
public:
458
  PostLValue(const Stmt *S, const LocationContext *L,
459
             const ProgramPointTag *tag = nullptr)
460
369k
    : 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.63M
    : StmtPoint(S, nullptr, PreStmtPurgeDeadSymbolsKind, L, tag) { }
477
478
private:
479
  friend class ProgramPoint;
480
162k
  PreStmtPurgeDeadSymbols() = default;
481
1.56M
  static bool isKind(const ProgramPoint &Location) {
482
1.56M
    return Location.getKind() == PreStmtPurgeDeadSymbolsKind;
483
1.56M
  }
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
304k
    : StmtPoint(S, nullptr, PostStmtPurgeDeadSymbolsKind, L, tag) { }
493
494
private:
495
  friend class ProgramPoint;
496
808
  PostStmtPurgeDeadSymbols() = default;
497
58.1k
  static bool isKind(const ProgramPoint &Location) {
498
58.1k
    return Location.getKind() == PostStmtPurgeDeadSymbolsKind;
499
58.1k
  }
500
};
501
502
class BlockEdge : public ProgramPoint {
503
public:
504
  BlockEdge(const CFGBlock *B1, const CFGBlock *B2, const LocationContext *L)
505
222k
    : ProgramPoint(B1, B2, BlockEdgeKind, L) {
506
222k
    assert(B1 && "BlockEdge: source block must be non-null");
507
0
    assert(B2 && "BlockEdge: destination block must be non-null");
508
222k
  }
509
510
697k
  const CFGBlock *getSrc() const {
511
697k
    return static_cast<const CFGBlock*>(getData1());
512
697k
  }
513
514
264k
  const CFGBlock *getDst() const {
515
264k
    return static_cast<const CFGBlock*>(getData2());
516
264k
  }
517
518
private:
519
  friend class ProgramPoint;
520
565k
  BlockEdge() = default;
521
4.14M
  static bool isKind(const ProgramPoint &Location) {
522
4.14M
    return Location.getKind() == BlockEdgeKind;
523
4.14M
  }
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.3k
    : ProgramPoint(I, Loc, PostInitializerKind, L) {}
537
538
23.6k
  const CXXCtorInitializer *getInitializer() const {
539
23.6k
    return static_cast<const CXXCtorInitializer *>(getData1());
540
23.6k
  }
541
542
  /// Returns the location of the field.
543
137
  const void *getLocationValue() const {
544
137
    return getData2();
545
137
  }
546
547
private:
548
  friend class ProgramPoint;
549
47.7k
  PostInitializer() = default;
550
1.61M
  static bool isKind(const ProgramPoint &Location) {
551
1.61M
    return Location.getKind() == PostInitializerKind;
552
1.61M
  }
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.46k
  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
523k
  static bool isKind(const ProgramPoint &Location) {
592
523k
    return Location.getKind() == PreImplicitCallKind;
593
523k
  }
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.90k
    : ImplicitCallPoint(D, Loc, PostImplicitCallKind, L, Tag) {}
604
605
private:
606
  friend class ProgramPoint;
607
2.43k
  PostImplicitCall() = default;
608
1.26M
  static bool isKind(const ProgramPoint &Location) {
609
1.26M
    return Location.getKind() == PostImplicitCallKind;
610
1.26M
  }
611
};
612
613
class PostAllocatorCall : public StmtPoint {
614
public:
615
  PostAllocatorCall(const Stmt *S, const LocationContext *L,
616
                    const ProgramPointTag *Tag = nullptr)
617
624
      : 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.3k
    : ProgramPoint(stmt, calleeCtx, CallEnterKind, callerCtx, nullptr) {}
634
635
2.84k
  const Stmt *getCallExpr() const {
636
2.84k
    return static_cast<const Stmt *>(getData1());
637
2.84k
  }
638
639
180k
  const StackFrameContext *getCalleeContext() const {
640
180k
    return static_cast<const StackFrameContext *>(getData2());
641
180k
  }
642
643
  /// Returns the entry block in the CFG for the entered function.
644
70.6k
  const CFGBlock *getEntry() const {
645
70.6k
    const StackFrameContext *CalleeCtx = getCalleeContext();
646
70.6k
    const CFG *CalleeCFG = CalleeCtx->getCFG();
647
70.6k
    return &(CalleeCFG->getEntry());
648
70.6k
  }
649
650
private:
651
  friend class ProgramPoint;
652
113k
  CallEnter() = default;
653
8.80M
  static bool isKind(const ProgramPoint &Location) {
654
8.80M
    return Location.getKind() == CallEnterKind;
655
8.80M
  }
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
43.0k
    : 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
59.0k
  CallExitBegin() = default;
680
381k
  static bool isKind(const ProgramPoint &Location) {
681
381k
    return Location.getKind() == CallExitBeginKind;
682
381k
  }
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.2k
    : ProgramPoint(CalleeCtx, CallExitEndKind, CallerCtx, nullptr) {}
693
694
78.2k
  const StackFrameContext *getCalleeContext() const {
695
78.2k
    return static_cast<const StackFrameContext *>(getData1());
696
78.2k
  }
697
698
private:
699
  friend class ProgramPoint;
700
109k
  CallExitEnd() = default;
701
704k
  static bool isKind(const ProgramPoint &Location) {
702
704k
    return Location.getKind() == CallExitEndKind;
703
704k
  }
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
1.22M
    static bool isKind(const ProgramPoint &Location) {
725
1.22M
      return Location.getKind() == LoopExitKind;
726
1.22M
    }
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
1.22M
  static bool isKind(const ProgramPoint &Location) {
744
1.22M
    return Location.getKind() == EpsilonKind;
745
1.22M
  }
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