Coverage Report

Created: 2021-09-21 08:58

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