Coverage Report

Created: 2018-12-11 17:59

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