Coverage Report

Created: 2021-06-15 06:44

/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
4.61M
      : Data(d), Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {}
94
95
366k
  explicit SVal(BaseKind k, const void *D = nullptr) : Data(D), Kind(k) {}
96
97
public:
98
572k
  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.95M
  T castAs() const {
104
7.95M
    assert(T::isKind(*this));
105
0
    return *static_cast<const T *>(this);
106
7.95M
  }
clang::ento::Loc clang::ento::SVal::castAs<clang::ento::Loc>() const
Line
Count
Source
103
1.39M
  T castAs() const {
104
1.39M
    assert(T::isKind(*this));
105
0
    return *static_cast<const T *>(this);
106
1.39M
  }
clang::ento::nonloc::ConcreteInt clang::ento::SVal::castAs<clang::ento::nonloc::ConcreteInt>() const
Line
Count
Source
103
760k
  T castAs() const {
104
760k
    assert(T::isKind(*this));
105
0
    return *static_cast<const T *>(this);
106
760k
  }
clang::ento::DefinedSVal clang::ento::SVal::castAs<clang::ento::DefinedSVal>() const
Line
Count
Source
103
1.21M
  T castAs() const {
104
1.21M
    assert(T::isKind(*this));
105
0
    return *static_cast<const T *>(this);
106
1.21M
  }
clang::ento::NonLoc clang::ento::SVal::castAs<clang::ento::NonLoc>() const
Line
Count
Source
103
1.29M
  T castAs() const {
104
1.29M
    assert(T::isKind(*this));
105
0
    return *static_cast<const T *>(this);
106
1.29M
  }
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.72M
  T castAs() const {
104
1.72M
    assert(T::isKind(*this));
105
0
    return *static_cast<const T *>(this);
106
1.72M
  }
clang::ento::DefinedOrUnknownSVal clang::ento::SVal::castAs<clang::ento::DefinedOrUnknownSVal>() const
Line
Count
Source
103
485k
  T castAs() const {
104
485k
    assert(T::isKind(*this));
105
0
    return *static_cast<const T *>(this);
106
485k
  }
clang::ento::nonloc::CompoundVal clang::ento::SVal::castAs<clang::ento::nonloc::CompoundVal>() const
Line
Count
Source
103
2.06k
  T castAs() const {
104
2.06k
    assert(T::isKind(*this));
105
0
    return *static_cast<const T *>(this);
106
2.06k
  }
clang::ento::UndefinedVal clang::ento::SVal::castAs<clang::ento::UndefinedVal>() const
Line
Count
Source
103
79.5k
  T castAs() const {
104
79.5k
    assert(T::isKind(*this));
105
0
    return *static_cast<const T *>(this);
106
79.5k
  }
clang::ento::UnknownVal clang::ento::SVal::castAs<clang::ento::UnknownVal>() const
Line
Count
Source
103
10.4k
  T castAs() const {
104
10.4k
    assert(T::isKind(*this));
105
0
    return *static_cast<const T *>(this);
106
10.4k
  }
clang::ento::loc::ConcreteInt clang::ento::SVal::castAs<clang::ento::loc::ConcreteInt>() const
Line
Count
Source
103
43.0k
  T castAs() const {
104
43.0k
    assert(T::isKind(*this));
105
0
    return *static_cast<const T *>(this);
106
43.0k
  }
clang::ento::loc::GotoLabel clang::ento::SVal::castAs<clang::ento::loc::GotoLabel>() const
Line
Count
Source
103
37
  T castAs() const {
104
37
    assert(T::isKind(*this));
105
0
    return *static_cast<const T *>(this);
106
37
  }
clang::ento::nonloc::LazyCompoundVal clang::ento::SVal::castAs<clang::ento::nonloc::LazyCompoundVal>() const
Line
Count
Source
103
21
  T castAs() const {
104
21
    assert(T::isKind(*this));
105
0
    return *static_cast<const T *>(this);
106
21
  }
clang::ento::nonloc::LocAsInteger clang::ento::SVal::castAs<clang::ento::nonloc::LocAsInteger>() const
Line
Count
Source
103
370
  T castAs() const {
104
370
    assert(T::isKind(*this));
105
0
    return *static_cast<const T *>(this);
106
370
  }
clang::ento::nonloc::SymbolVal clang::ento::SVal::castAs<clang::ento::nonloc::SymbolVal>() const
Line
Count
Source
103
945k
  T castAs() const {
104
945k
    assert(T::isKind(*this));
105
0
    return *static_cast<const T *>(this);
106
945k
  }
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
24.6M
  Optional<T> getAs() const {
112
24.6M
    if (!T::isKind(*this))
113
15.5M
      return None;
114
9.12M
    return *static_cast<const T *>(this);
115
24.6M
  }
llvm::Optional<clang::ento::nonloc::ConcreteInt> clang::ento::SVal::getAs<clang::ento::nonloc::ConcreteInt>() const
Line
Count
Source
111
1.13M
  Optional<T> getAs() const {
112
1.13M
    if (!T::isKind(*this))
113
865k
      return None;
114
268k
    return *static_cast<const T *>(this);
115
1.13M
  }
llvm::Optional<clang::ento::NonLoc> clang::ento::SVal::getAs<clang::ento::NonLoc>() const
Line
Count
Source
111
235k
  Optional<T> getAs() const {
112
235k
    if (!T::isKind(*this))
113
203k
      return None;
114
31.3k
    return *static_cast<const T *>(this);
115
235k
  }
llvm::Optional<clang::ento::Loc> clang::ento::SVal::getAs<clang::ento::Loc>() const
Line
Count
Source
111
1.36M
  Optional<T> getAs() const {
112
1.36M
    if (!T::isKind(*this))
113
316k
      return None;
114
1.04M
    return *static_cast<const T *>(this);
115
1.36M
  }
llvm::Optional<clang::ento::KnownSVal> clang::ento::SVal::getAs<clang::ento::KnownSVal>() const
Line
Count
Source
111
2.87k
  Optional<T> getAs() const {
112
2.87k
    if (!T::isKind(*this))
113
66
      return None;
114
2.80k
    return *static_cast<const T *>(this);
115
2.87k
  }
llvm::Optional<clang::ento::DefinedSVal> clang::ento::SVal::getAs<clang::ento::DefinedSVal>() const
Line
Count
Source
111
62.4k
  Optional<T> getAs() const {
112
62.4k
    if (!T::isKind(*this))
113
747
      return None;
114
61.7k
    return *static_cast<const T *>(this);
115
62.4k
  }
llvm::Optional<clang::ento::DefinedOrUnknownSVal> clang::ento::SVal::getAs<clang::ento::DefinedOrUnknownSVal>() const
Line
Count
Source
111
3.07k
  Optional<T> getAs() const {
112
3.07k
    if (!T::isKind(*this))
113
1
      return None;
114
3.07k
    return *static_cast<const T *>(this);
115
3.07k
  }
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.76M
  Optional<T> getAs() const {
112
1.76M
    if (!T::isKind(*this))
113
1.75M
      return None;
114
12.2k
    return *static_cast<const T *>(this);
115
1.76M
  }
llvm::Optional<clang::ento::UndefinedVal> clang::ento::SVal::getAs<clang::ento::UndefinedVal>() const
Line
Count
Source
111
534k
  Optional<T> getAs() const {
112
534k
    if (!T::isKind(*this))
113
533k
      return None;
114
1.02k
    return *static_cast<const T *>(this);
115
534k
  }
llvm::Optional<clang::ento::loc::MemRegionVal> clang::ento::SVal::getAs<clang::ento::loc::MemRegionVal>() const
Line
Count
Source
111
7.65M
  Optional<T> getAs() const {
112
7.65M
    if (!T::isKind(*this))
113
3.03M
      return None;
114
4.61M
    return *static_cast<const T *>(this);
115
7.65M
  }
llvm::Optional<clang::ento::nonloc::SymbolVal> clang::ento::SVal::getAs<clang::ento::nonloc::SymbolVal>() const
Line
Count
Source
111
5.34M
  Optional<T> getAs() const {
112
5.34M
    if (!T::isKind(*this))
113
2.38M
      return None;
114
2.96M
    return *static_cast<const T *>(this);
115
5.34M
  }
llvm::Optional<clang::ento::nonloc::PointerToMember> clang::ento::SVal::getAs<clang::ento::nonloc::PointerToMember>() const
Line
Count
Source
111
22.9k
  Optional<T> getAs() const {
112
22.9k
    if (!T::isKind(*this))
113
22.4k
      return None;
114
493
    return *static_cast<const T *>(this);
115
22.9k
  }
llvm::Optional<clang::ento::nonloc::LazyCompoundVal> clang::ento::SVal::getAs<clang::ento::nonloc::LazyCompoundVal>() const
Line
Count
Source
111
2.60M
  Optional<T> getAs() const {
112
2.60M
    if (!T::isKind(*this))
113
2.49M
      return None;
114
117k
    return *static_cast<const T *>(this);
115
2.60M
  }
llvm::Optional<clang::ento::nonloc::LocAsInteger> clang::ento::SVal::getAs<clang::ento::nonloc::LocAsInteger>() const
Line
Count
Source
111
2.98M
  Optional<T> getAs() const {
112
2.98M
    if (!T::isKind(*this))
113
2.98M
      return None;
114
882
    return *static_cast<const T *>(this);
115
2.98M
  }
llvm::Optional<clang::ento::nonloc::CompoundVal> clang::ento::SVal::getAs<clang::ento::nonloc::CompoundVal>() const
Line
Count
Source
111
371k
  Optional<T> getAs() const {
112
371k
    if (!T::isKind(*this))
113
369k
      return None;
114
2.22k
    return *static_cast<const T *>(this);
115
371k
  }
llvm::Optional<clang::ento::UnknownVal> clang::ento::SVal::getAs<clang::ento::UnknownVal>() const
Line
Count
Source
111
533k
  Optional<T> getAs() const {
112
533k
    if (!T::isKind(*this))
113
533k
      return None;
114
0
    return *static_cast<const T *>(this);
115
533k
  }
116
117
21.8M
  unsigned getRawKind() const { return Kind; }
118
32.6M
  BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
119
21.5M
  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.84M
  void Profile(llvm::FoldingSetNodeID &ID) const {
124
4.84M
    ID.AddInteger((unsigned) getRawKind());
125
4.84M
    ID.AddPointer(Data);
126
4.84M
  }
127
128
5.57M
  bool operator==(const SVal &R) const {
129
5.57M
    return getRawKind() == R.getRawKind() && 
Data == R.Data5.46M
;
130
5.57M
  }
131
132
190k
  bool operator!=(const SVal &R) const {
133
190k
    return !(*this == R);
134
190k
  }
135
136
1.78M
  bool isUnknown() const {
137
1.78M
    return getRawKind() == UnknownValKind;
138
1.78M
  }
139
140
1.51M
  bool isUndef() const {
141
1.51M
    return getRawKind() == UndefinedValKind;
142
1.51M
  }
143
144
2.24M
  bool isUnknownOrUndef() const {
145
2.24M
    return getRawKind() <= UnknownValKind;
146
2.24M
  }
147
148
298k
  bool isValid() const {
149
298k
    return getRawKind() > UnknownValKind;
150
298k
  }
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.71M
  SymExpr::symbol_iterator symbol_begin() const {
194
1.71M
    const SymExpr *SE = getAsSymbol(/*IncludeBaseRegions=*/true);
195
1.71M
    if (SE)
196
911k
      return SE->symbol_begin();
197
802k
    else
198
802k
      return SymExpr::symbol_iterator();
199
1.71M
  }
200
201
1.71M
  SymExpr::symbol_iterator symbol_end() const {
202
1.71M
    return SymExpr::symbol_end();
203
1.71M
  }
204
};
205
206
130
inline raw_ostream &operator<<(raw_ostream &os, clang::ento::SVal V) {
207
130
  V.dumpToStream(os);
208
130
  return os;
209
130
}
210
211
class UndefinedVal : public SVal {
212
public:
213
88.3k
  UndefinedVal() : SVal(UndefinedValKind) {}
214
215
private:
216
  friend class SVal;
217
218
614k
  static bool isKind(const SVal& V) {
219
614k
    return V.getBaseKind() == UndefinedValKind;
220
614k
  }
221
};
222
223
class DefinedOrUnknownSVal : public SVal {
224
public:
225
  // We want calling these methods to be a compiler error since they are
226
  // tautologically false.
227
  bool isUndef() const = delete;
228
  bool isValid() const = delete;
229
230
protected:
231
  DefinedOrUnknownSVal() = default;
232
  explicit DefinedOrUnknownSVal(const void *d, bool isLoc, unsigned ValKind)
233
4.61M
      : SVal(d, isLoc, ValKind) {}
234
278k
  explicit DefinedOrUnknownSVal(BaseKind k, void *D = nullptr) : SVal(k, D) {}
235
236
private:
237
  friend class SVal;
238
239
488k
  static bool isKind(const SVal& V) {
240
488k
    return !V.isUndef();
241
488k
  }
242
};
243
244
class UnknownVal : public DefinedOrUnknownSVal {
245
public:
246
278k
  explicit UnknownVal() : DefinedOrUnknownSVal(UnknownValKind) {}
247
248
private:
249
  friend class SVal;
250
251
543k
  static bool isKind(const SVal &V) {
252
543k
    return V.getBaseKind() == UnknownValKind;
253
543k
  }
254
};
255
256
class DefinedSVal : public DefinedOrUnknownSVal {
257
public:
258
  // We want calling these methods to be a compiler error since they are
259
  // tautologically true/false.
260
  bool isUnknown() const = delete;
261
  bool isUnknownOrUndef() const = delete;
262
  bool isValid() const = delete;
263
264
protected:
265
  DefinedSVal() = default;
266
  explicit DefinedSVal(const void *d, bool isLoc, unsigned ValKind)
267
4.61M
      : DefinedOrUnknownSVal(d, isLoc, ValKind) {}
268
269
private:
270
  friend class SVal;
271
272
1.27M
  static bool isKind(const SVal& V) {
273
1.27M
    return !V.isUnknownOrUndef();
274
1.27M
  }
275
};
276
277
/// Represents an SVal that is guaranteed to not be UnknownVal.
278
class KnownSVal : public SVal {
279
  friend class SVal;
280
281
  KnownSVal() = default;
282
283
2.89k
  static bool isKind(const SVal &V) {
284
2.89k
    return !V.isUnknown();
285
2.89k
  }
286
287
public:
288
0
  KnownSVal(const DefinedSVal &V) : SVal(V) {}
289
6
  KnownSVal(const UndefinedVal &V) : SVal(V) {}
290
};
291
292
class NonLoc : public DefinedSVal {
293
protected:
294
  NonLoc() = default;
295
  explicit NonLoc(unsigned SubKind, const void *d)
296
3.42M
      : DefinedSVal(d, false, SubKind) {}
297
298
public:
299
  void dumpToStream(raw_ostream &Out) const;
300
301
20.8k
  static bool isCompoundType(QualType T) {
302
20.8k
    return T->isArrayType() || 
T->isRecordType()19.4k
||
303
20.8k
           
T->isAnyComplexType()11
||
T->isVectorType()6
;
304
20.8k
  }
305
306
private:
307
  friend class SVal;
308
309
1.53M
  static bool isKind(const SVal& V) {
310
1.53M
    return V.getBaseKind() == NonLocKind;
311
1.53M
  }
312
};
313
314
class Loc : public DefinedSVal {
315
protected:
316
  Loc() = default;
317
  explicit Loc(unsigned SubKind, const void *D)
318
1.19M
      : DefinedSVal(const_cast<void *>(D), true, SubKind) {}
319
320
public:
321
  void dumpToStream(raw_ostream &Out) const;
322
323
6.26M
  static bool isLocType(QualType T) {
324
6.26M
    return T->isAnyPointerType() || 
T->isBlockPointerType()5.58M
||
325
6.26M
           
T->isReferenceType()5.58M
||
T->isNullPtrType()5.47M
;
326
6.26M
  }
327
328
private:
329
  friend class SVal;
330
331
2.75M
  static bool isKind(const SVal& V) {
332
2.75M
    return V.getBaseKind() == LocKind;
333
2.75M
  }
334
};
335
336
//==------------------------------------------------------------------------==//
337
//  Subclasses of NonLoc.
338
//==------------------------------------------------------------------------==//
339
340
namespace nonloc {
341
342
/// Represents symbolic expression that isn't a location.
343
class SymbolVal : public NonLoc {
344
public:
345
  SymbolVal() = delete;
346
2.52M
  SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) {
347
2.52M
    assert(sym);
348
0
    assert(!Loc::isLocType(sym->getType()));
349
2.52M
  }
350
351
4.09M
  SymbolRef getSymbol() const {
352
4.09M
    return (const SymExpr *) Data;
353
4.09M
  }
354
355
200k
  bool isExpression() const {
356
200k
    return !isa<SymbolData>(getSymbol());
357
200k
  }
358
359
private:
360
  friend class SVal;
361
362
6.29M
  static bool isKind(const SVal& V) {
363
6.29M
    return V.getBaseKind() == NonLocKind &&
364
6.29M
           
V.getSubKind() == SymbolValKind5.24M
;
365
6.29M
  }
366
367
0
  static bool isKind(const NonLoc& V) {
368
0
    return V.getSubKind() == SymbolValKind;
369
0
  }
370
};
371
372
/// Value representing integer constant.
373
class ConcreteInt : public NonLoc {
374
public:
375
839k
  explicit ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {}
376
377
887k
  const llvm::APSInt& getValue() const {
378
887k
    return *static_cast<const llvm::APSInt *>(Data);
379
887k
  }
380
381
  // Transfer functions for binary/unary operations on ConcreteInts.
382
  SVal evalBinOp(SValBuilder &svalBuilder, BinaryOperator::Opcode Op,
383
                 const ConcreteInt& R) const;
384
385
  ConcreteInt evalComplement(SValBuilder &svalBuilder) const;
386
387
  ConcreteInt evalMinus(SValBuilder &svalBuilder) const;
388
389
private:
390
  friend class SVal;
391
392
  ConcreteInt() = default;
393
394
1.89M
  static bool isKind(const SVal& V) {
395
1.89M
    return V.getBaseKind() == NonLocKind &&
396
1.89M
           
V.getSubKind() == ConcreteIntKind1.79M
;
397
1.89M
  }
398
399
0
  static bool isKind(const NonLoc& V) {
400
0
    return V.getSubKind() == ConcreteIntKind;
401
0
  }
402
};
403
404
class LocAsInteger : public NonLoc {
405
  friend class ento::SValBuilder;
406
407
  explicit LocAsInteger(const std::pair<SVal, uintptr_t> &data)
408
152
      : NonLoc(LocAsIntegerKind, &data) {
409
    // We do not need to represent loc::ConcreteInt as LocAsInteger,
410
    // as it'd collapse into a nonloc::ConcreteInt instead.
411
152
    assert(data.first.getBaseKind() == LocKind &&
412
152
           (data.first.getSubKind() == loc::MemRegionValKind ||
413
152
            data.first.getSubKind() == loc::GotoLabelKind));
414
152
  }
415
416
public:
417
1.23k
  Loc getLoc() const {
418
1.23k
    const std::pair<SVal, uintptr_t> *D =
419
1.23k
      static_cast<const std::pair<SVal, uintptr_t> *>(Data);
420
1.23k
    return D->first.castAs<Loc>();
421
1.23k
  }
422
423
0
  Loc getPersistentLoc() const {
424
0
    const std::pair<SVal, uintptr_t> *D =
425
0
      static_cast<const std::pair<SVal, uintptr_t> *>(Data);
426
0
    const SVal& V = D->first;
427
0
    return V.castAs<Loc>();
428
0
  }
429
430
214
  unsigned getNumBits() const {
431
214
    const std::pair<SVal, uintptr_t> *D =
432
214
      static_cast<const std::pair<SVal, uintptr_t> *>(Data);
433
214
    return D->second;
434
214
  }
435
436
private:
437
  friend class SVal;
438
439
  LocAsInteger() = default;
440
441
2.98M
  static bool isKind(const SVal& V) {
442
2.98M
    return V.getBaseKind() == NonLocKind &&
443
2.98M
           
V.getSubKind() == LocAsIntegerKind2.42M
;
444
2.98M
  }
445
446
0
  static bool isKind(const NonLoc& V) {
447
0
    return V.getSubKind() == LocAsIntegerKind;
448
0
  }
449
};
450
451
class CompoundVal : public NonLoc {
452
  friend class ento::SValBuilder;
453
454
1.13k
  explicit CompoundVal(const CompoundValData* D) : NonLoc(CompoundValKind, D) {}
455
456
public:
457
6.48k
  const CompoundValData* getValue() const {
458
6.48k
    return static_cast<const CompoundValData *>(Data);
459
6.48k
  }
460
461
  using iterator = llvm::ImmutableList<SVal>::iterator;
462
463
  iterator begin() const;
464
  iterator end() const;
465
466
private:
467
  friend class SVal;
468
469
  CompoundVal() = default;
470
471
373k
  static bool isKind(const SVal& V) {
472
373k
    return V.getBaseKind() == NonLocKind && 
V.getSubKind() == CompoundValKind265k
;
473
373k
  }
474
475
0
  static bool isKind(const NonLoc& V) {
476
0
    return V.getSubKind() == CompoundValKind;
477
0
  }
478
};
479
480
class LazyCompoundVal : public NonLoc {
481
  friend class ento::SValBuilder;
482
483
  explicit LazyCompoundVal(const LazyCompoundValData *D)
484
55.2k
      : NonLoc(LazyCompoundValKind, D) {}
485
486
public:
487
73.1k
  const LazyCompoundValData *getCVData() const {
488
73.1k
    return static_cast<const LazyCompoundValData *>(Data);
489
73.1k
  }
490
491
  const void *getStore() const;
492
  const TypedValueRegion *getRegion() const;
493
494
private:
495
  friend class SVal;
496
497
  LazyCompoundVal() = default;
498
499
2.60M
  static bool isKind(const SVal& V) {
500
2.60M
    return V.getBaseKind() == NonLocKind &&
501
2.60M
           
V.getSubKind() == LazyCompoundValKind1.84M
;
502
2.60M
  }
503
504
0
  static bool isKind(const NonLoc& V) {
505
0
    return V.getSubKind() == LazyCompoundValKind;
506
0
  }
507
};
508
509
/// Value representing pointer-to-member.
510
///
511
/// This value is qualified as NonLoc because neither loading nor storing
512
/// operations are applied to it. Instead, the analyzer uses the L-value coming
513
/// from pointer-to-member applied to an object.
514
/// This SVal is represented by a NamedDecl which can be a member function
515
/// pointer or a member data pointer and an optional list of CXXBaseSpecifiers.
516
/// This list is required to accumulate the pointer-to-member cast history to
517
/// figure out the correct subobject field. In particular, implicit casts grow
518
/// this list and explicit casts like static_cast shrink this list.
519
class PointerToMember : public NonLoc {
520
  friend class ento::SValBuilder;
521
522
public:
523
  using PTMDataType =
524
      llvm::PointerUnion<const NamedDecl *, const PointerToMemberData *>;
525
526
626
  const PTMDataType getPTMData() const {
527
626
    return PTMDataType::getFromOpaqueValue(const_cast<void *>(Data));
528
626
  }
529
530
  bool isNullMemberPointer() const;
531
532
  const NamedDecl *getDecl() const;
533
534
  template<typename AdjustedDecl>
535
59
  const AdjustedDecl *getDeclAs() const {
536
59
    return dyn_cast_or_null<AdjustedDecl>(getDecl());
537
59
  }
clang::FieldDecl const* clang::ento::nonloc::PointerToMember::getDeclAs<clang::FieldDecl>() const
Line
Count
Source
535
36
  const AdjustedDecl *getDeclAs() const {
536
36
    return dyn_cast_or_null<AdjustedDecl>(getDecl());
537
36
  }
clang::IndirectFieldDecl const* clang::ento::nonloc::PointerToMember::getDeclAs<clang::IndirectFieldDecl>() const
Line
Count
Source
535
23
  const AdjustedDecl *getDeclAs() const {
536
23
    return dyn_cast_or_null<AdjustedDecl>(getDecl());
537
23
  }
538
539
  using iterator = llvm::ImmutableList<const CXXBaseSpecifier *>::iterator;
540
541
  iterator begin() const;
542
  iterator end() const;
543
544
private:
545
  friend class SVal;
546
547
  PointerToMember() = default;
548
  explicit PointerToMember(const PTMDataType D)
549
94
      : NonLoc(PointerToMemberKind, D.getOpaqueValue()) {}
550
551
23.0k
  static bool isKind(const SVal& V) {
552
23.0k
    return V.getBaseKind() == NonLocKind &&
553
23.0k
           
V.getSubKind() == PointerToMemberKind733
;
554
23.0k
  }
555
556
0
  static bool isKind(const NonLoc& V) {
557
0
    return V.getSubKind() == PointerToMemberKind;
558
0
  }
559
};
560
561
} // namespace nonloc
562
563
//==------------------------------------------------------------------------==//
564
//  Subclasses of Loc.
565
//==------------------------------------------------------------------------==//
566
567
namespace loc {
568
569
class GotoLabel : public Loc {
570
public:
571
80
  explicit GotoLabel(const LabelDecl *Label) : Loc(GotoLabelKind, Label) {
572
80
    assert(Label);
573
80
  }
574
575
16
  const LabelDecl *getLabel() const {
576
16
    return static_cast<const LabelDecl *>(Data);
577
16
  }
578
579
private:
580
  friend class SVal;
581
582
  GotoLabel() = default;
583
584
7.99k
  static bool isKind(const SVal& V) {
585
7.99k
    return V.getBaseKind() == LocKind && 
V.getSubKind() == GotoLabelKind7.98k
;
586
7.99k
  }
587
588
0
  static bool isKind(const Loc& V) {
589
0
    return V.getSubKind() == GotoLabelKind;
590
0
  }
591
};
592
593
class MemRegionVal : public Loc {
594
public:
595
1.18M
  explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionValKind, r) {
596
1.18M
    assert(r);
597
1.18M
  }
598
599
  /// Get the underlining region.
600
5.52M
  const MemRegion *getRegion() const {
601
5.52M
    return static_cast<const MemRegion *>(Data);
602
5.52M
  }
603
604
  /// Get the underlining region and strip casts.
605
  const MemRegion* stripCasts(bool StripBaseCasts = true) const;
606
607
  template <typename REGION>
608
8.88k
  const REGION* getRegionAs() const {
609
8.88k
    return dyn_cast<REGION>(getRegion());
610
8.88k
  }
clang::ento::FieldRegion const* clang::ento::loc::MemRegionVal::getRegionAs<clang::ento::FieldRegion>() const
Line
Count
Source
608
662
  const REGION* getRegionAs() const {
609
662
    return dyn_cast<REGION>(getRegion());
610
662
  }
clang::ento::TypedValueRegion const* clang::ento::loc::MemRegionVal::getRegionAs<clang::ento::TypedValueRegion>() const
Line
Count
Source
608
80
  const REGION* getRegionAs() const {
609
80
    return dyn_cast<REGION>(getRegion());
610
80
  }
clang::ento::SymbolicRegion const* clang::ento::loc::MemRegionVal::getRegionAs<clang::ento::SymbolicRegion>() const
Line
Count
Source
608
179
  const REGION* getRegionAs() const {
609
179
    return dyn_cast<REGION>(getRegion());
610
179
  }
clang::ento::AllocaRegion const* clang::ento::loc::MemRegionVal::getRegionAs<clang::ento::AllocaRegion>() const
Line
Count
Source
608
43
  const REGION* getRegionAs() const {
609
43
    return dyn_cast<REGION>(getRegion());
610
43
  }
clang::ento::SubRegion const* clang::ento::loc::MemRegionVal::getRegionAs<clang::ento::SubRegion>() const
Line
Count
Source
608
7.92k
  const REGION* getRegionAs() const {
609
7.92k
    return dyn_cast<REGION>(getRegion());
610
7.92k
  }
611
612
0
  bool operator==(const MemRegionVal &R) const {
613
0
    return getRegion() == R.getRegion();
614
0
  }
615
616
0
  bool operator!=(const MemRegionVal &R) const {
617
0
    return getRegion() != R.getRegion();
618
0
  }
619
620
private:
621
  friend class SVal;
622
623
  MemRegionVal() = default;
624
625
9.37M
  static bool isKind(const SVal& V) {
626
9.37M
    return V.getBaseKind() == LocKind &&
627
9.37M
           
V.getSubKind() == MemRegionValKind6.39M
;
628
9.37M
  }
629
630
0
  static bool isKind(const Loc& V) {
631
0
    return V.getSubKind() == MemRegionValKind;
632
0
  }
633
};
634
635
class ConcreteInt : public Loc {
636
public:
637
10.1k
  explicit ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {}
638
639
10.0k
  const llvm::APSInt &getValue() const {
640
10.0k
    return *static_cast<const llvm::APSInt *>(Data);
641
10.0k
  }
642
643
  // Transfer functions for binary/unary operations on ConcreteInts.
644
  SVal evalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
645
                 const ConcreteInt& R) const;
646
647
private:
648
  friend class SVal;
649
650
  ConcreteInt() = default;
651
652
1.80M
  static bool isKind(const SVal& V) {
653
1.80M
    return V.getBaseKind() == LocKind &&
654
1.80M
           
V.getSubKind() == ConcreteIntKind888k
;
655
1.80M
  }
656
657
0
  static bool isKind(const Loc& V) {
658
0
    return V.getSubKind() == ConcreteIntKind;
659
0
  }
660
};
661
662
} // namespace loc
663
664
} // namespace ento
665
666
} // namespace clang
667
668
#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H