Coverage Report

Created: 2022-05-17 06:19

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
Line
Count
Source (jump to first uncovered line)
1
//===- SVals.h - Abstract Values for Static 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 SVal, Loc, and NonLoc, classes that represent
10
//  abstract r-values for use with path-sensitive value tracking.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H
15
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H
16
17
#include "clang/AST/Expr.h"
18
#include "clang/AST/Type.h"
19
#include "clang/Basic/LLVM.h"
20
#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
21
#include "llvm/ADT/FoldingSet.h"
22
#include "llvm/ADT/ImmutableList.h"
23
#include "llvm/ADT/None.h"
24
#include "llvm/ADT/Optional.h"
25
#include "llvm/ADT/PointerUnion.h"
26
#include "llvm/Support/Casting.h"
27
#include <cassert>
28
#include <cstdint>
29
#include <utility>
30
31
//==------------------------------------------------------------------------==//
32
//  Base SVal types.
33
//==------------------------------------------------------------------------==//
34
35
namespace clang {
36
37
class CXXBaseSpecifier;
38
class FunctionDecl;
39
class LabelDecl;
40
41
namespace ento {
42
43
class BasicValueFactory;
44
class CompoundValData;
45
class LazyCompoundValData;
46
class MemRegion;
47
class PointerToMemberData;
48
class SValBuilder;
49
class TypedValueRegion;
50
51
namespace nonloc {
52
53
/// Sub-kinds for NonLoc values.
54
enum Kind {
55
#define NONLOC_SVAL(Id, Parent) Id ## Kind,
56
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def"
57
};
58
59
} // namespace nonloc
60
61
namespace loc {
62
63
/// Sub-kinds for Loc values.
64
enum Kind {
65
#define LOC_SVAL(Id, Parent) Id ## Kind,
66
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def"
67
};
68
69
} // namespace loc
70
71
/// SVal - This represents a symbolic expression, which can be either
72
///  an L-value or an R-value.
73
///
74
class SVal {
75
public:
76
  enum BaseKind {
77
    // The enumerators must be representable using 2 bits.
78
#define BASIC_SVAL(Id, Parent) Id ## Kind,
79
#define ABSTRACT_SVAL_WITH_KIND(Id, Parent) Id ## Kind,
80
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def"
81
  };
82
  enum { BaseBits = 2, BaseMask = 0b11 };
83
84
protected:
85
  const void *Data = nullptr;
86
87
  /// The lowest 2 bits are a BaseKind (0 -- 3).
88
  ///  The higher bits are an unsigned "kind" value.
89
  unsigned Kind = 0;
90
91
  explicit SVal(const void *d, bool isLoc, unsigned ValKind)
92
5.51M
      : Data(d), Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {}
93
94
1.16M
  explicit SVal(BaseKind k, const void *D = nullptr) : Data(D), Kind(k) {}
95
96
public:
97
798k
  explicit SVal() = default;
98
99
  /// Convert to the specified SVal type, asserting that this SVal is of
100
  /// the desired type.
101
  template<typename T>
102
9.06M
  T castAs() const {
103
9.06M
    assert(T::isKind(*this));
104
0
    return *static_cast<const T *>(this);
105
9.06M
  }
clang::ento::DefinedSVal clang::ento::SVal::castAs<clang::ento::DefinedSVal>() const
Line
Count
Source
102
1.33M
  T castAs() const {
103
1.33M
    assert(T::isKind(*this));
104
0
    return *static_cast<const T *>(this);
105
1.33M
  }
clang::ento::NonLoc clang::ento::SVal::castAs<clang::ento::NonLoc>() const
Line
Count
Source
102
1.67M
  T castAs() const {
103
1.67M
    assert(T::isKind(*this));
104
0
    return *static_cast<const T *>(this);
105
1.67M
  }
clang::ento::Loc clang::ento::SVal::castAs<clang::ento::Loc>() const
Line
Count
Source
102
1.34M
  T castAs() const {
103
1.34M
    assert(T::isKind(*this));
104
0
    return *static_cast<const T *>(this);
105
1.34M
  }
clang::ento::nonloc::ConcreteInt clang::ento::SVal::castAs<clang::ento::nonloc::ConcreteInt>() const
Line
Count
Source
102
960k
  T castAs() const {
103
960k
    assert(T::isKind(*this));
104
0
    return *static_cast<const T *>(this);
105
960k
  }
clang::ento::KnownSVal clang::ento::SVal::castAs<clang::ento::KnownSVal>() const
Line
Count
Source
102
18
  T castAs() const {
103
18
    assert(T::isKind(*this));
104
0
    return *static_cast<const T *>(this);
105
18
  }
clang::ento::loc::MemRegionVal clang::ento::SVal::castAs<clang::ento::loc::MemRegionVal>() const
Line
Count
Source
102
1.82M
  T castAs() const {
103
1.82M
    assert(T::isKind(*this));
104
0
    return *static_cast<const T *>(this);
105
1.82M
  }
clang::ento::DefinedOrUnknownSVal clang::ento::SVal::castAs<clang::ento::DefinedOrUnknownSVal>() const
Line
Count
Source
102
579k
  T castAs() const {
103
579k
    assert(T::isKind(*this));
104
0
    return *static_cast<const T *>(this);
105
579k
  }
clang::ento::nonloc::CompoundVal clang::ento::SVal::castAs<clang::ento::nonloc::CompoundVal>() const
Line
Count
Source
102
2.32k
  T castAs() const {
103
2.32k
    assert(T::isKind(*this));
104
0
    return *static_cast<const T *>(this);
105
2.32k
  }
clang::ento::UndefinedVal clang::ento::SVal::castAs<clang::ento::UndefinedVal>() const
Line
Count
Source
102
90.7k
  T castAs() const {
103
90.7k
    assert(T::isKind(*this));
104
0
    return *static_cast<const T *>(this);
105
90.7k
  }
clang::ento::UnknownVal clang::ento::SVal::castAs<clang::ento::UnknownVal>() const
Line
Count
Source
102
10.6k
  T castAs() const {
103
10.6k
    assert(T::isKind(*this));
104
0
    return *static_cast<const T *>(this);
105
10.6k
  }
clang::ento::loc::ConcreteInt clang::ento::SVal::castAs<clang::ento::loc::ConcreteInt>() const
Line
Count
Source
102
87.7k
  T castAs() const {
103
87.7k
    assert(T::isKind(*this));
104
0
    return *static_cast<const T *>(this);
105
87.7k
  }
clang::ento::loc::GotoLabel clang::ento::SVal::castAs<clang::ento::loc::GotoLabel>() const
Line
Count
Source
102
189
  T castAs() const {
103
189
    assert(T::isKind(*this));
104
0
    return *static_cast<const T *>(this);
105
189
  }
clang::ento::nonloc::LazyCompoundVal clang::ento::SVal::castAs<clang::ento::nonloc::LazyCompoundVal>() const
Line
Count
Source
102
42
  T castAs() const {
103
42
    assert(T::isKind(*this));
104
0
    return *static_cast<const T *>(this);
105
42
  }
clang::ento::nonloc::LocAsInteger clang::ento::SVal::castAs<clang::ento::nonloc::LocAsInteger>() const
Line
Count
Source
102
1.41k
  T castAs() const {
103
1.41k
    assert(T::isKind(*this));
104
0
    return *static_cast<const T *>(this);
105
1.41k
  }
clang::ento::nonloc::SymbolVal clang::ento::SVal::castAs<clang::ento::nonloc::SymbolVal>() const
Line
Count
Source
102
1.15M
  T castAs() const {
103
1.15M
    assert(T::isKind(*this));
104
0
    return *static_cast<const T *>(this);
105
1.15M
  }
clang::ento::nonloc::PointerToMember clang::ento::SVal::castAs<clang::ento::nonloc::PointerToMember>() const
Line
Count
Source
102
138
  T castAs() const {
103
138
    assert(T::isKind(*this));
104
0
    return *static_cast<const T *>(this);
105
138
  }
106
107
  /// Convert to the specified SVal type, returning None if this SVal is
108
  /// not of the desired type.
109
  template<typename T>
110
27.2M
  Optional<T> getAs() const {
111
27.2M
    if (!T::isKind(*this))
112
17.1M
      return None;
113
10.1M
    return *static_cast<const T *>(this);
114
27.2M
  }
llvm::Optional<clang::ento::NonLoc> clang::ento::SVal::getAs<clang::ento::NonLoc>() const
Line
Count
Source
110
455k
  Optional<T> getAs() const {
111
455k
    if (!T::isKind(*this))
112
213k
      return None;
113
242k
    return *static_cast<const T *>(this);
114
455k
  }
llvm::Optional<clang::ento::Loc> clang::ento::SVal::getAs<clang::ento::Loc>() const
Line
Count
Source
110
1.45M
  Optional<T> getAs() const {
111
1.45M
    if (!T::isKind(*this))
112
369k
      return None;
113
1.08M
    return *static_cast<const T *>(this);
114
1.45M
  }
llvm::Optional<clang::ento::nonloc::ConcreteInt> clang::ento::SVal::getAs<clang::ento::nonloc::ConcreteInt>() const
Line
Count
Source
110
1.82M
  Optional<T> getAs() const {
111
1.82M
    if (!T::isKind(*this))
112
1.52M
      return None;
113
291k
    return *static_cast<const T *>(this);
114
1.82M
  }
llvm::Optional<clang::ento::KnownSVal> clang::ento::SVal::getAs<clang::ento::KnownSVal>() const
Line
Count
Source
110
3.20k
  Optional<T> getAs() const {
111
3.20k
    if (!T::isKind(*this))
112
97
      return None;
113
3.10k
    return *static_cast<const T *>(this);
114
3.20k
  }
llvm::Optional<clang::ento::DefinedSVal> clang::ento::SVal::getAs<clang::ento::DefinedSVal>() const
Line
Count
Source
110
63.4k
  Optional<T> getAs() const {
111
63.4k
    if (!T::isKind(*this))
112
767
      return None;
113
62.7k
    return *static_cast<const T *>(this);
114
63.4k
  }
llvm::Optional<clang::ento::DefinedOrUnknownSVal> clang::ento::SVal::getAs<clang::ento::DefinedOrUnknownSVal>() const
Line
Count
Source
110
3.44k
  Optional<T> getAs() const {
111
3.44k
    if (!T::isKind(*this))
112
1
      return None;
113
3.44k
    return *static_cast<const T *>(this);
114
3.44k
  }
llvm::Optional<clang::ento::loc::GotoLabel> clang::ento::SVal::getAs<clang::ento::loc::GotoLabel>() const
Line
Count
Source
110
7.02k
  Optional<T> getAs() const {
111
7.02k
    if (!T::isKind(*this))
112
7.00k
      return None;
113
20
    return *static_cast<const T *>(this);
114
7.02k
  }
llvm::Optional<clang::ento::loc::ConcreteInt> clang::ento::SVal::getAs<clang::ento::loc::ConcreteInt>() const
Line
Count
Source
110
2.03M
  Optional<T> getAs() const {
111
2.03M
    if (!T::isKind(*this))
112
2.02M
      return None;
113
14.1k
    return *static_cast<const T *>(this);
114
2.03M
  }
llvm::Optional<clang::ento::UndefinedVal> clang::ento::SVal::getAs<clang::ento::UndefinedVal>() const
Line
Count
Source
110
588k
  Optional<T> getAs() const {
111
588k
    if (!T::isKind(*this))
112
586k
      return None;
113
1.61k
    return *static_cast<const T *>(this);
114
588k
  }
llvm::Optional<clang::ento::loc::MemRegionVal> clang::ento::SVal::getAs<clang::ento::loc::MemRegionVal>() const
Line
Count
Source
110
8.07M
  Optional<T> getAs() const {
111
8.07M
    if (!T::isKind(*this))
112
3.17M
      return None;
113
4.90M
    return *static_cast<const T *>(this);
114
8.07M
  }
llvm::Optional<clang::ento::nonloc::SymbolVal> clang::ento::SVal::getAs<clang::ento::nonloc::SymbolVal>() const
Line
Count
Source
110
6.01M
  Optional<T> getAs() const {
111
6.01M
    if (!T::isKind(*this))
112
2.60M
      return None;
113
3.40M
    return *static_cast<const T *>(this);
114
6.01M
  }
llvm::Optional<clang::ento::nonloc::PointerToMember> clang::ento::SVal::getAs<clang::ento::nonloc::PointerToMember>() const
Line
Count
Source
110
26.5k
  Optional<T> getAs() const {
111
26.5k
    if (!T::isKind(*this))
112
26.0k
      return None;
113
495
    return *static_cast<const T *>(this);
114
26.5k
  }
llvm::Optional<clang::ento::nonloc::LazyCompoundVal> clang::ento::SVal::getAs<clang::ento::nonloc::LazyCompoundVal>() const
Line
Count
Source
110
2.66M
  Optional<T> getAs() const {
111
2.66M
    if (!T::isKind(*this))
112
2.54M
      return None;
113
117k
    return *static_cast<const T *>(this);
114
2.66M
  }
llvm::Optional<clang::ento::nonloc::LocAsInteger> clang::ento::SVal::getAs<clang::ento::nonloc::LocAsInteger>() const
Line
Count
Source
110
3.12M
  Optional<T> getAs() const {
111
3.12M
    if (!T::isKind(*this))
112
3.11M
      return None;
113
2.87k
    return *static_cast<const T *>(this);
114
3.12M
  }
llvm::Optional<clang::ento::nonloc::CompoundVal> clang::ento::SVal::getAs<clang::ento::nonloc::CompoundVal>() const
Line
Count
Source
110
373k
  Optional<T> getAs() const {
111
373k
    if (!T::isKind(*this))
112
371k
      return None;
113
2.41k
    return *static_cast<const T *>(this);
114
373k
  }
llvm::Optional<clang::ento::UnknownVal> clang::ento::SVal::getAs<clang::ento::UnknownVal>() const
Line
Count
Source
110
586k
  Optional<T> getAs() const {
111
586k
    if (!T::isKind(*this))
112
586k
      return None;
113
0
    return *static_cast<const T *>(this);
114
586k
  }
115
116
27.2M
  unsigned getRawKind() const { return Kind; }
117
36.6M
  BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
118
24.2M
  unsigned getSubKind() const { return Kind >> BaseBits; }
119
120
  // This method is required for using SVal in a FoldingSetNode.  It
121
  // extracts a unique signature for this SVal object.
122
5.13M
  void Profile(llvm::FoldingSetNodeID &ID) const {
123
5.13M
    ID.AddInteger((unsigned) getRawKind());
124
5.13M
    ID.AddPointer(Data);
125
5.13M
  }
126
127
7.49M
  bool operator==(const SVal &R) const {
128
7.49M
    return getRawKind() == R.getRawKind() && 
Data == R.Data7.36M
;
129
7.49M
  }
130
131
1.94M
  bool operator!=(const SVal &R) const {
132
1.94M
    return !(*this == R);
133
1.94M
  }
134
135
1.88M
  bool isUnknown() const {
136
1.88M
    return getRawKind() == UnknownValKind;
137
1.88M
  }
138
139
2.42M
  bool isUndef() const {
140
2.42M
    return getRawKind() == UndefinedValKind;
141
2.42M
  }
142
143
2.54M
  bool isUnknownOrUndef() const {
144
2.54M
    return getRawKind() <= UnknownValKind;
145
2.54M
  }
146
147
310k
  bool isValid() const {
148
310k
    return getRawKind() > UnknownValKind;
149
310k
  }
150
151
  bool isConstant() const;
152
153
  bool isConstant(int I) const;
154
155
  bool isZeroConstant() const;
156
157
  /// hasConjuredSymbol - If this SVal wraps a conjured symbol, return true;
158
  bool hasConjuredSymbol() const;
159
160
  /// getAsFunctionDecl - If this SVal is a MemRegionVal and wraps a
161
  /// CodeTextRegion wrapping a FunctionDecl, return that FunctionDecl.
162
  /// Otherwise return 0.
163
  const FunctionDecl *getAsFunctionDecl() const;
164
165
  /// If this SVal is a location and wraps a symbol, return that
166
  ///  SymbolRef. Otherwise return 0.
167
  ///
168
  /// Casts are ignored during lookup.
169
  /// \param IncludeBaseRegions The boolean that controls whether the search
170
  /// should continue to the base regions if the region is not symbolic.
171
  SymbolRef getAsLocSymbol(bool IncludeBaseRegions = false) const;
172
173
  /// Get the symbol in the SVal or its base region.
174
  SymbolRef getLocSymbolInBase() const;
175
176
  /// If this SVal wraps a symbol return that SymbolRef.
177
  /// Otherwise, return 0.
178
  ///
179
  /// Casts are ignored during lookup.
180
  /// \param IncludeBaseRegions The boolean that controls whether the search
181
  /// should continue to the base regions if the region is not symbolic.
182
  SymbolRef getAsSymbol(bool IncludeBaseRegions = false) const;
183
184
  const MemRegion *getAsRegion() const;
185
186
  /// printJson - Pretty-prints in JSON format.
187
  void printJson(raw_ostream &Out, bool AddQuotes) const;
188
189
  void dumpToStream(raw_ostream &OS) const;
190
  void dump() const;
191
192
1.73M
  SymExpr::symbol_iterator symbol_begin() const {
193
1.73M
    const SymExpr *SE = getAsSymbol(/*IncludeBaseRegions=*/true);
194
1.73M
    if (SE)
195
923k
      return SE->symbol_begin();
196
807k
    else
197
807k
      return SymExpr::symbol_iterator();
198
1.73M
  }
199
200
1.73M
  SymExpr::symbol_iterator symbol_end() const {
201
1.73M
    return SymExpr::symbol_end();
202
1.73M
  }
203
204
  /// Try to get a reasonable type for the given value.
205
  ///
206
  /// \returns The best approximation of the value type or Null.
207
  /// In theory, all symbolic values should be typed, but this function
208
  /// is still a WIP and might have a few blind spots.
209
  ///
210
  /// \note This function should not be used when the user has access to the
211
  /// bound expression AST node as well, since AST always has exact types.
212
  ///
213
  /// \note Loc values are interpreted as pointer rvalues for the purposes of
214
  /// this method.
215
  QualType getType(const ASTContext &) const;
216
};
217
218
143
inline raw_ostream &operator<<(raw_ostream &os, clang::ento::SVal V) {
219
143
  V.dumpToStream(os);
220
143
  return os;
221
143
}
222
223
class UndefinedVal : public SVal {
224
public:
225
870k
  UndefinedVal() : SVal(UndefinedValKind) {}
226
227
private:
228
  friend class SVal;
229
230
679k
  static bool isKind(const SVal& V) {
231
679k
    return V.getBaseKind() == UndefinedValKind;
232
679k
  }
233
};
234
235
class DefinedOrUnknownSVal : public SVal {
236
public:
237
  // We want calling these methods to be a compiler error since they are
238
  // tautologically false.
239
  bool isUndef() const = delete;
240
  bool isValid() const = delete;
241
242
protected:
243
  DefinedOrUnknownSVal() = default;
244
  explicit DefinedOrUnknownSVal(const void *d, bool isLoc, unsigned ValKind)
245
5.51M
      : SVal(d, isLoc, ValKind) {}
246
298k
  explicit DefinedOrUnknownSVal(BaseKind k, void *D = nullptr) : SVal(k, D) {}
247
248
private:
249
  friend class SVal;
250
251
582k
  static bool isKind(const SVal& V) {
252
582k
    return !V.isUndef();
253
582k
  }
254
};
255
256
class UnknownVal : public DefinedOrUnknownSVal {
257
public:
258
298k
  explicit UnknownVal() : DefinedOrUnknownSVal(UnknownValKind) {}
259
260
private:
261
  friend class SVal;
262
263
597k
  static bool isKind(const SVal &V) {
264
597k
    return V.getBaseKind() == UnknownValKind;
265
597k
  }
266
};
267
268
class DefinedSVal : public DefinedOrUnknownSVal {
269
public:
270
  // We want calling these methods to be a compiler error since they are
271
  // tautologically true/false.
272
  bool isUnknown() const = delete;
273
  bool isUnknownOrUndef() const = delete;
274
  bool isValid() const = delete;
275
276
protected:
277
  DefinedSVal() = default;
278
  explicit DefinedSVal(const void *d, bool isLoc, unsigned ValKind)
279
5.51M
      : DefinedOrUnknownSVal(d, isLoc, ValKind) {}
280
281
private:
282
  friend class SVal;
283
284
1.39M
  static bool isKind(const SVal& V) {
285
1.39M
    return !V.isUnknownOrUndef();
286
1.39M
  }
287
};
288
289
/// Represents an SVal that is guaranteed to not be UnknownVal.
290
class KnownSVal : public SVal {
291
  friend class SVal;
292
293
  KnownSVal() = default;
294
295
3.22k
  static bool isKind(const SVal &V) {
296
3.22k
    return !V.isUnknown();
297
3.22k
  }
298
299
public:
300
0
  KnownSVal(const DefinedSVal &V) : SVal(V) {}
301
6
  KnownSVal(const UndefinedVal &V) : SVal(V) {}
302
};
303
304
class NonLoc : public DefinedSVal {
305
protected:
306
  NonLoc() = default;
307
  explicit NonLoc(unsigned SubKind, const void *d)
308
4.04M
      : DefinedSVal(d, false, SubKind) {}
309
310
public:
311
  void dumpToStream(raw_ostream &Out) const;
312
313
21.3k
  static bool isCompoundType(QualType T) {
314
21.3k
    return T->isArrayType() || 
T->isRecordType()19.7k
||
315
21.3k
           
T->isAnyComplexType()11
||
T->isVectorType()6
;
316
21.3k
  }
317
318
private:
319
  friend class SVal;
320
321
2.12M
  static bool isKind(const SVal& V) {
322
2.12M
    return V.getBaseKind() == NonLocKind;
323
2.12M
  }
324
};
325
326
class Loc : public DefinedSVal {
327
protected:
328
  Loc() = default;
329
  explicit Loc(unsigned SubKind, const void *D)
330
1.46M
      : DefinedSVal(const_cast<void *>(D), true, SubKind) {}
331
332
public:
333
  void dumpToStream(raw_ostream &Out) const;
334
335
7.79M
  static bool isLocType(QualType T) {
336
7.79M
    return T->isAnyPointerType() || 
T->isBlockPointerType()6.70M
||
337
7.79M
           
T->isReferenceType()6.70M
||
T->isNullPtrType()6.66M
;
338
7.79M
  }
339
340
private:
341
  friend class SVal;
342
343
2.79M
  static bool isKind(const SVal& V) {
344
2.79M
    return V.getBaseKind() == LocKind;
345
2.79M
  }
346
};
347
348
//==------------------------------------------------------------------------==//
349
//  Subclasses of NonLoc.
350
//==------------------------------------------------------------------------==//
351
352
namespace nonloc {
353
354
/// Represents symbolic expression that isn't a location.
355
class SymbolVal : public NonLoc {
356
public:
357
  SymbolVal() = delete;
358
3.09M
  SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) {
359
3.09M
    assert(sym);
360
0
    assert(!Loc::isLocType(sym->getType()));
361
3.09M
  }
362
363
4.76M
  SymbolRef getSymbol() const {
364
4.76M
    return (const SymExpr *) Data;
365
4.76M
  }
366
367
212k
  bool isExpression() const {
368
212k
    return !isa<SymbolData>(getSymbol());
369
212k
  }
370
371
private:
372
  friend class SVal;
373
374
7.16M
  static bool isKind(const SVal& V) {
375
7.16M
    return V.getBaseKind() == NonLocKind &&
376
7.16M
           
V.getSubKind() == SymbolValKind5.95M
;
377
7.16M
  }
378
379
0
  static bool isKind(const NonLoc& V) {
380
0
    return V.getSubKind() == SymbolValKind;
381
0
  }
382
};
383
384
/// Value representing integer constant.
385
class ConcreteInt : public NonLoc {
386
public:
387
890k
  explicit ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {}
388
389
961k
  const llvm::APSInt& getValue() const {
390
961k
    return *static_cast<const llvm::APSInt *>(Data);
391
961k
  }
392
393
  // Transfer functions for binary/unary operations on ConcreteInts.
394
  SVal evalBinOp(SValBuilder &svalBuilder, BinaryOperator::Opcode Op,
395
                 const ConcreteInt& R) const;
396
397
  ConcreteInt evalComplement(SValBuilder &svalBuilder) const;
398
399
  ConcreteInt evalMinus(SValBuilder &svalBuilder) const;
400
401
private:
402
  friend class SVal;
403
404
  ConcreteInt() = default;
405
406
2.78M
  static bool isKind(const SVal& V) {
407
2.78M
    return V.getBaseKind() == NonLocKind &&
408
2.78M
           
V.getSubKind() == ConcreteIntKind2.51M
;
409
2.78M
  }
410
411
0
  static bool isKind(const NonLoc& V) {
412
0
    return V.getSubKind() == ConcreteIntKind;
413
0
  }
414
};
415
416
class LocAsInteger : public NonLoc {
417
  friend class ento::SValBuilder;
418
419
  explicit LocAsInteger(const std::pair<SVal, uintptr_t> &data)
420
406
      : NonLoc(LocAsIntegerKind, &data) {
421
    // We do not need to represent loc::ConcreteInt as LocAsInteger,
422
    // as it'd collapse into a nonloc::ConcreteInt instead.
423
406
    assert(data.first.getBaseKind() == LocKind &&
424
406
           (data.first.getSubKind() == loc::MemRegionValKind ||
425
406
            data.first.getSubKind() == loc::GotoLabelKind));
426
406
  }
427
428
public:
429
3.87k
  Loc getLoc() const {
430
3.87k
    const std::pair<SVal, uintptr_t> *D =
431
3.87k
      static_cast<const std::pair<SVal, uintptr_t> *>(Data);
432
3.87k
    return D->first.castAs<Loc>();
433
3.87k
  }
434
435
0
  Loc getPersistentLoc() const {
436
0
    const std::pair<SVal, uintptr_t> *D =
437
0
      static_cast<const std::pair<SVal, uintptr_t> *>(Data);
438
0
    const SVal& V = D->first;
439
0
    return V.castAs<Loc>();
440
0
  }
441
442
643
  unsigned getNumBits() const {
443
643
    const std::pair<SVal, uintptr_t> *D =
444
643
      static_cast<const std::pair<SVal, uintptr_t> *>(Data);
445
643
    return D->second;
446
643
  }
447
448
private:
449
  friend class SVal;
450
451
  LocAsInteger() = default;
452
453
3.12M
  static bool isKind(const SVal& V) {
454
3.12M
    return V.getBaseKind() == NonLocKind &&
455
3.12M
           
V.getSubKind() == LocAsIntegerKind2.52M
;
456
3.12M
  }
457
458
0
  static bool isKind(const NonLoc& V) {
459
0
    return V.getSubKind() == LocAsIntegerKind;
460
0
  }
461
};
462
463
class CompoundVal : public NonLoc {
464
  friend class ento::SValBuilder;
465
466
1.24k
  explicit CompoundVal(const CompoundValData* D) : NonLoc(CompoundValKind, D) {}
467
468
public:
469
7.18k
  const CompoundValData* getValue() const {
470
7.18k
    return static_cast<const CompoundValData *>(Data);
471
7.18k
  }
472
473
  using iterator = llvm::ImmutableList<SVal>::iterator;
474
475
  iterator begin() const;
476
  iterator end() const;
477
478
private:
479
  friend class SVal;
480
481
  CompoundVal() = default;
482
483
375k
  static bool isKind(const SVal& V) {
484
375k
    return V.getBaseKind() == NonLocKind && 
V.getSubKind() == CompoundValKind265k
;
485
375k
  }
486
487
0
  static bool isKind(const NonLoc& V) {
488
0
    return V.getSubKind() == CompoundValKind;
489
0
  }
490
};
491
492
class LazyCompoundVal : public NonLoc {
493
  friend class ento::SValBuilder;
494
495
  explicit LazyCompoundVal(const LazyCompoundValData *D)
496
57.0k
      : NonLoc(LazyCompoundValKind, D) {}
497
498
public:
499
72.4k
  const LazyCompoundValData *getCVData() const {
500
72.4k
    return static_cast<const LazyCompoundValData *>(Data);
501
72.4k
  }
502
503
  const void *getStore() const;
504
  const TypedValueRegion *getRegion() const;
505
506
private:
507
  friend class SVal;
508
509
  LazyCompoundVal() = default;
510
511
2.66M
  static bool isKind(const SVal& V) {
512
2.66M
    return V.getBaseKind() == NonLocKind &&
513
2.66M
           
V.getSubKind() == LazyCompoundValKind1.87M
;
514
2.66M
  }
515
516
0
  static bool isKind(const NonLoc& V) {
517
0
    return V.getSubKind() == LazyCompoundValKind;
518
0
  }
519
};
520
521
/// Value representing pointer-to-member.
522
///
523
/// This value is qualified as NonLoc because neither loading nor storing
524
/// operations are applied to it. Instead, the analyzer uses the L-value coming
525
/// from pointer-to-member applied to an object.
526
/// This SVal is represented by a NamedDecl which can be a member function
527
/// pointer or a member data pointer and an optional list of CXXBaseSpecifiers.
528
/// This list is required to accumulate the pointer-to-member cast history to
529
/// figure out the correct subobject field. In particular, implicit casts grow
530
/// this list and explicit casts like static_cast shrink this list.
531
class PointerToMember : public NonLoc {
532
  friend class ento::SValBuilder;
533
534
public:
535
  using PTMDataType =
536
      llvm::PointerUnion<const NamedDecl *, const PointerToMemberData *>;
537
538
628
  const PTMDataType getPTMData() const {
539
628
    return PTMDataType::getFromOpaqueValue(const_cast<void *>(Data));
540
628
  }
541
542
  bool isNullMemberPointer() const;
543
544
  const NamedDecl *getDecl() const;
545
546
  template<typename AdjustedDecl>
547
59
  const AdjustedDecl *getDeclAs() const {
548
59
    return dyn_cast_or_null<AdjustedDecl>(getDecl());
549
59
  }
clang::FieldDecl const* clang::ento::nonloc::PointerToMember::getDeclAs<clang::FieldDecl>() const
Line
Count
Source
547
36
  const AdjustedDecl *getDeclAs() const {
548
36
    return dyn_cast_or_null<AdjustedDecl>(getDecl());
549
36
  }
clang::IndirectFieldDecl const* clang::ento::nonloc::PointerToMember::getDeclAs<clang::IndirectFieldDecl>() const
Line
Count
Source
547
23
  const AdjustedDecl *getDeclAs() const {
548
23
    return dyn_cast_or_null<AdjustedDecl>(getDecl());
549
23
  }
550
551
  using iterator = llvm::ImmutableList<const CXXBaseSpecifier *>::iterator;
552
553
  iterator begin() const;
554
  iterator end() const;
555
556
private:
557
  friend class SVal;
558
559
  PointerToMember() = default;
560
  explicit PointerToMember(const PTMDataType D)
561
96
      : NonLoc(PointerToMemberKind, D.getOpaqueValue()) {}
562
563
26.6k
  static bool isKind(const SVal& V) {
564
26.6k
    return V.getBaseKind() == NonLocKind &&
565
26.6k
           
V.getSubKind() == PointerToMemberKind924
;
566
26.6k
  }
567
568
0
  static bool isKind(const NonLoc& V) {
569
0
    return V.getSubKind() == PointerToMemberKind;
570
0
  }
571
};
572
573
} // namespace nonloc
574
575
//==------------------------------------------------------------------------==//
576
//  Subclasses of Loc.
577
//==------------------------------------------------------------------------==//
578
579
namespace loc {
580
581
class GotoLabel : public Loc {
582
public:
583
156
  explicit GotoLabel(const LabelDecl *Label) : Loc(GotoLabelKind, Label) {
584
156
    assert(Label);
585
156
  }
586
587
16
  const LabelDecl *getLabel() const {
588
16
    return static_cast<const LabelDecl *>(Data);
589
16
  }
590
591
private:
592
  friend class SVal;
593
594
  GotoLabel() = default;
595
596
7.20k
  static bool isKind(const SVal& V) {
597
7.20k
    return V.getBaseKind() == LocKind && 
V.getSubKind() == GotoLabelKind7.20k
;
598
7.20k
  }
599
600
0
  static bool isKind(const Loc& V) {
601
0
    return V.getSubKind() == GotoLabelKind;
602
0
  }
603
};
604
605
class MemRegionVal : public Loc {
606
public:
607
1.40M
  explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionValKind, r) {
608
1.40M
    assert(r);
609
1.40M
  }
610
611
  /// Get the underlining region.
612
5.91M
  const MemRegion *getRegion() const {
613
5.91M
    return static_cast<const MemRegion *>(Data);
614
5.91M
  }
615
616
  /// Get the underlining region and strip casts.
617
  const MemRegion* stripCasts(bool StripBaseCasts = true) const;
618
619
  template <typename REGION>
620
8.04k
  const REGION* getRegionAs() const {
621
8.04k
    return dyn_cast<REGION>(getRegion());
622
8.04k
  }
clang::ento::FieldRegion const* clang::ento::loc::MemRegionVal::getRegionAs<clang::ento::FieldRegion>() const
Line
Count
Source
620
662
  const REGION* getRegionAs() const {
621
662
    return dyn_cast<REGION>(getRegion());
622
662
  }
clang::ento::TypedValueRegion const* clang::ento::loc::MemRegionVal::getRegionAs<clang::ento::TypedValueRegion>() const
Line
Count
Source
620
80
  const REGION* getRegionAs() const {
621
80
    return dyn_cast<REGION>(getRegion());
622
80
  }
clang::ento::SymbolicRegion const* clang::ento::loc::MemRegionVal::getRegionAs<clang::ento::SymbolicRegion>() const
Line
Count
Source
620
243
  const REGION* getRegionAs() const {
621
243
    return dyn_cast<REGION>(getRegion());
622
243
  }
clang::ento::AllocaRegion const* clang::ento::loc::MemRegionVal::getRegionAs<clang::ento::AllocaRegion>() const
Line
Count
Source
620
72
  const REGION* getRegionAs() const {
621
72
    return dyn_cast<REGION>(getRegion());
622
72
  }
clang::ento::SubRegion const* clang::ento::loc::MemRegionVal::getRegionAs<clang::ento::SubRegion>() const
Line
Count
Source
620
6.98k
  const REGION* getRegionAs() const {
621
6.98k
    return dyn_cast<REGION>(getRegion());
622
6.98k
  }
623
624
0
  bool operator==(const MemRegionVal &R) const {
625
0
    return getRegion() == R.getRegion();
626
0
  }
627
628
0
  bool operator!=(const MemRegionVal &R) const {
629
0
    return getRegion() != R.getRegion();
630
0
  }
631
632
private:
633
  friend class SVal;
634
635
  MemRegionVal() = default;
636
637
9.89M
  static bool isKind(const SVal& V) {
638
9.89M
    return V.getBaseKind() == LocKind &&
639
9.89M
           
V.getSubKind() == MemRegionValKind6.78M
;
640
9.89M
  }
641
642
0
  static bool isKind(const Loc& V) {
643
0
    return V.getSubKind() == MemRegionValKind;
644
0
  }
645
};
646
647
class ConcreteInt : public Loc {
648
public:
649
57.4k
  explicit ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {}
650
651
97.3k
  const llvm::APSInt &getValue() const {
652
97.3k
    return *static_cast<const llvm::APSInt *>(Data);
653
97.3k
  }
654
655
  // Transfer functions for binary/unary operations on ConcreteInts.
656
  SVal evalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
657
                 const ConcreteInt& R) const;
658
659
private:
660
  friend class SVal;
661
662
  ConcreteInt() = default;
663
664
2.12M
  static bool isKind(const SVal& V) {
665
2.12M
    return V.getBaseKind() == LocKind &&
666
2.12M
           
V.getSubKind() == ConcreteIntKind1.10M
;
667
2.12M
  }
668
669
0
  static bool isKind(const Loc& V) {
670
0
    return V.getSubKind() == ConcreteIntKind;
671
0
  }
672
};
673
674
} // namespace loc
675
676
} // namespace ento
677
678
} // namespace clang
679
680
#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H