Coverage Report

Created: 2020-11-24 06:42

/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
2.53M
      : Data(d), Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {}
94
95
359k
  explicit SVal(BaseKind k, const void *D = nullptr) : Data(D), Kind(k) {}
96
97
public:
98
137k
  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
5.64M
  T castAs() const {
104
5.64M
    assert(T::isKind(*this));
105
5.64M
    return *static_cast<const T *>(this);
106
5.64M
  }
clang::ento::DefinedSVal clang::ento::SVal::castAs<clang::ento::DefinedSVal>() const
Line
Count
Source
103
1.09M
  T castAs() const {
104
1.09M
    assert(T::isKind(*this));
105
1.09M
    return *static_cast<const T *>(this);
106
1.09M
  }
clang::ento::NonLoc clang::ento::SVal::castAs<clang::ento::NonLoc>() const
Line
Count
Source
103
1.25M
  T castAs() const {
104
1.25M
    assert(T::isKind(*this));
105
1.25M
    return *static_cast<const T *>(this);
106
1.25M
  }
clang::ento::Loc clang::ento::SVal::castAs<clang::ento::Loc>() const
Line
Count
Source
103
541k
  T castAs() const {
104
541k
    assert(T::isKind(*this));
105
541k
    return *static_cast<const T *>(this);
106
541k
  }
clang::ento::nonloc::ConcreteInt clang::ento::SVal::castAs<clang::ento::nonloc::ConcreteInt>() const
Line
Count
Source
103
743k
  T castAs() const {
104
743k
    assert(T::isKind(*this));
105
743k
    return *static_cast<const T *>(this);
106
743k
  }
clang::ento::loc::MemRegionVal clang::ento::SVal::castAs<clang::ento::loc::MemRegionVal>() const
Line
Count
Source
103
1.30M
  T castAs() const {
104
1.30M
    assert(T::isKind(*this));
105
1.30M
    return *static_cast<const T *>(this);
106
1.30M
  }
clang::ento::DefinedOrUnknownSVal clang::ento::SVal::castAs<clang::ento::DefinedOrUnknownSVal>() const
Line
Count
Source
103
371k
  T castAs() const {
104
371k
    assert(T::isKind(*this));
105
371k
    return *static_cast<const T *>(this);
106
371k
  }
clang::ento::nonloc::CompoundVal clang::ento::SVal::castAs<clang::ento::nonloc::CompoundVal>() const
Line
Count
Source
103
2.01k
  T castAs() const {
104
2.01k
    assert(T::isKind(*this));
105
2.01k
    return *static_cast<const T *>(this);
106
2.01k
  }
clang::ento::nonloc::SymbolVal clang::ento::SVal::castAs<clang::ento::nonloc::SymbolVal>() const
Line
Count
Source
103
339k
  T castAs() const {
104
339k
    assert(T::isKind(*this));
105
339k
    return *static_cast<const T *>(this);
106
339k
  }
clang::ento::nonloc::PointerToMember clang::ento::SVal::castAs<clang::ento::nonloc::PointerToMember>() const
Line
Count
Source
103
40
  T castAs() const {
104
40
    assert(T::isKind(*this));
105
40
    return *static_cast<const T *>(this);
106
40
  }
clang::ento::loc::ConcreteInt clang::ento::SVal::castAs<clang::ento::loc::ConcreteInt>() const
Line
Count
Source
103
243
  T castAs() const {
104
243
    assert(T::isKind(*this));
105
243
    return *static_cast<const T *>(this);
106
243
  }
clang::ento::UndefinedVal clang::ento::SVal::castAs<clang::ento::UndefinedVal>() const
Line
Count
Source
103
1
  T castAs() const {
104
1
    assert(T::isKind(*this));
105
1
    return *static_cast<const T *>(this);
106
1
  }
Unexecuted instantiation: clang::ento::UnknownVal clang::ento::SVal::castAs<clang::ento::UnknownVal>() const
clang::ento::loc::GotoLabel clang::ento::SVal::castAs<clang::ento::loc::GotoLabel>() const
Line
Count
Source
103
2
  T castAs() const {
104
2
    assert(T::isKind(*this));
105
2
    return *static_cast<const T *>(this);
106
2
  }
clang::ento::nonloc::LazyCompoundVal clang::ento::SVal::castAs<clang::ento::nonloc::LazyCompoundVal>() const
Line
Count
Source
103
12
  T castAs() const {
104
12
    assert(T::isKind(*this));
105
12
    return *static_cast<const T *>(this);
106
12
  }
clang::ento::nonloc::LocAsInteger clang::ento::SVal::castAs<clang::ento::nonloc::LocAsInteger>() const
Line
Count
Source
103
99
  T castAs() const {
104
99
    assert(T::isKind(*this));
105
99
    return *static_cast<const T *>(this);
106
99
  }
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
26.3M
  Optional<T> getAs() const {
112
26.3M
    if (!T::isKind(*this))
113
16.9M
      return None;
114
9.48M
    return *static_cast<const T *>(this);
115
9.48M
  }
llvm::Optional<clang::ento::NonLoc> clang::ento::SVal::getAs<clang::ento::NonLoc>() const
Line
Count
Source
111
377k
  Optional<T> getAs() const {
112
377k
    if (!T::isKind(*this))
113
201k
      return None;
114
176k
    return *static_cast<const T *>(this);
115
176k
  }
llvm::Optional<clang::ento::Loc> clang::ento::SVal::getAs<clang::ento::Loc>() const
Line
Count
Source
111
2.52M
  Optional<T> getAs() const {
112
2.52M
    if (!T::isKind(*this))
113
601k
      return None;
114
1.92M
    return *static_cast<const T *>(this);
115
1.92M
  }
llvm::Optional<clang::ento::nonloc::ConcreteInt> clang::ento::SVal::getAs<clang::ento::nonloc::ConcreteInt>() const
Line
Count
Source
111
1.31M
  Optional<T> getAs() const {
112
1.31M
    if (!T::isKind(*this))
113
1.00M
      return None;
114
318k
    return *static_cast<const T *>(this);
115
318k
  }
llvm::Optional<clang::ento::DefinedSVal> clang::ento::SVal::getAs<clang::ento::DefinedSVal>() const
Line
Count
Source
111
62.1k
  Optional<T> getAs() const {
112
62.1k
    if (!T::isKind(*this))
113
743
      return None;
114
61.3k
    return *static_cast<const T *>(this);
115
61.3k
  }
llvm::Optional<clang::ento::KnownSVal> clang::ento::SVal::getAs<clang::ento::KnownSVal>() const
Line
Count
Source
111
2.66k
  Optional<T> getAs() const {
112
2.66k
    if (!T::isKind(*this))
113
46
      return None;
114
2.61k
    return *static_cast<const T *>(this);
115
2.61k
  }
llvm::Optional<clang::ento::DefinedOrUnknownSVal> clang::ento::SVal::getAs<clang::ento::DefinedOrUnknownSVal>() const
Line
Count
Source
111
3.67k
  Optional<T> getAs() const {
112
3.67k
    if (!T::isKind(*this))
113
1
      return None;
114
3.67k
    return *static_cast<const T *>(this);
115
3.67k
  }
llvm::Optional<clang::ento::loc::GotoLabel> clang::ento::SVal::getAs<clang::ento::loc::GotoLabel>() const
Line
Count
Source
111
7.91k
  Optional<T> getAs() const {
112
7.91k
    if (!T::isKind(*this))
113
7.90k
      return None;
114
16
    return *static_cast<const T *>(this);
115
16
  }
llvm::Optional<clang::ento::loc::ConcreteInt> clang::ento::SVal::getAs<clang::ento::loc::ConcreteInt>() const
Line
Count
Source
111
1.88M
  Optional<T> getAs() const {
112
1.88M
    if (!T::isKind(*this))
113
1.86M
      return None;
114
14.9k
    return *static_cast<const T *>(this);
115
14.9k
  }
llvm::Optional<clang::ento::UndefinedVal> clang::ento::SVal::getAs<clang::ento::UndefinedVal>() const
Line
Count
Source
111
516k
  Optional<T> getAs() const {
112
516k
    if (!T::isKind(*this))
113
515k
      return None;
114
960
    return *static_cast<const T *>(this);
115
960
  }
llvm::Optional<clang::ento::loc::MemRegionVal> clang::ento::SVal::getAs<clang::ento::loc::MemRegionVal>() const
Line
Count
Source
111
8.25M
  Optional<T> getAs() const {
112
8.25M
    if (!T::isKind(*this))
113
3.09M
      return None;
114
5.16M
    return *static_cast<const T *>(this);
115
5.16M
  }
llvm::Optional<clang::ento::nonloc::SymbolVal> clang::ento::SVal::getAs<clang::ento::nonloc::SymbolVal>() const
Line
Count
Source
111
4.57M
  Optional<T> getAs() const {
112
4.57M
    if (!T::isKind(*this))
113
2.87M
      return None;
114
1.69M
    return *static_cast<const T *>(this);
115
1.69M
  }
llvm::Optional<clang::ento::nonloc::PointerToMember> clang::ento::SVal::getAs<clang::ento::nonloc::PointerToMember>() const
Line
Count
Source
111
189k
  Optional<T> getAs() const {
112
189k
    if (!T::isKind(*this))
113
188k
      return None;
114
561
    return *static_cast<const T *>(this);
115
561
  }
llvm::Optional<clang::ento::nonloc::LazyCompoundVal> clang::ento::SVal::getAs<clang::ento::nonloc::LazyCompoundVal>() const
Line
Count
Source
111
2.57M
  Optional<T> getAs() const {
112
2.57M
    if (!T::isKind(*this))
113
2.45M
      return None;
114
116k
    return *static_cast<const T *>(this);
115
116k
  }
llvm::Optional<clang::ento::nonloc::LocAsInteger> clang::ento::SVal::getAs<clang::ento::nonloc::LocAsInteger>() const
Line
Count
Source
111
3.21M
  Optional<T> getAs() const {
112
3.21M
    if (!T::isKind(*this))
113
3.21M
      return None;
114
1.09k
    return *static_cast<const T *>(this);
115
1.09k
  }
llvm::Optional<clang::ento::nonloc::CompoundVal> clang::ento::SVal::getAs<clang::ento::nonloc::CompoundVal>() const
Line
Count
Source
111
365k
  Optional<T> getAs() const {
112
365k
    if (!T::isKind(*this))
113
362k
      return None;
114
2.17k
    return *static_cast<const T *>(this);
115
2.17k
  }
llvm::Optional<clang::ento::UnknownVal> clang::ento::SVal::getAs<clang::ento::UnknownVal>() const
Line
Count
Source
111
514k
  Optional<T> getAs() const {
112
514k
    if (!T::isKind(*this))
113
514k
      return None;
114
0
    return *static_cast<const T *>(this);
115
0
  }
116
117
22.6M
  unsigned getRawKind() const { return Kind; }
118
30.6M
  BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
119
19.1M
  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.77M
  void Profile(llvm::FoldingSetNodeID &ID) const {
124
4.77M
    ID.AddInteger((unsigned) getRawKind());
125
4.77M
    ID.AddPointer(Data);
126
4.77M
  }
127
128
5.52M
  bool operator==(const SVal &R) const {
129
5.52M
    return getRawKind() == R.getRawKind() && 
Data == R.Data5.41M
;
130
5.52M
  }
131
132
188k
  bool operator!=(const SVal &R) const {
133
188k
    return !(*this == R);
134
188k
  }
135
136
1.76M
  bool isUnknown() const {
137
1.76M
    return getRawKind() == UnknownValKind;
138
1.76M
  }
139
140
1.39M
  bool isUndef() const {
141
1.39M
    return getRawKind() == UndefinedValKind;
142
1.39M
  }
143
144
3.32M
  bool isUnknownOrUndef() const {
145
3.32M
    return getRawKind() <= UnknownValKind;
146
3.32M
  }
147
148
294k
  bool isValid() const {
149
294k
    return getRawKind() > UnknownValKind;
150
294k
  }
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.69M
  SymExpr::symbol_iterator symbol_begin() const {
194
1.69M
    const SymExpr *SE = getAsSymbol(/*IncludeBaseRegions=*/true);
195
1.69M
    if (SE)
196
892k
      return SE->symbol_begin();
197
801k
    else
198
801k
      return SymExpr::symbol_iterator();
199
1.69M
  }
200
201
1.69M
  SymExpr::symbol_iterator symbol_end() const {
202
1.69M
    return SymExpr::symbol_end();
203
1.69M
  }
204
};
205
206
89
inline raw_ostream &operator<<(raw_ostream &os, clang::ento::SVal V) {
207
89
  V.dumpToStream(os);
208
89
  return os;
209
89
}
210
211
class UndefinedVal : public SVal {
212
public:
213
84.1k
  UndefinedVal() : SVal(UndefinedValKind) {}
214
215
private:
216
  friend class SVal;
217
218
516k
  static bool isKind(const SVal& V) {
219
516k
    return V.getBaseKind() == UndefinedValKind;
220
516k
  }
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
2.53M
      : SVal(d, isLoc, ValKind) {}
234
275k
  explicit DefinedOrUnknownSVal(BaseKind k, void *D = nullptr) : SVal(k, D) {}
235
236
private:
237
  friend class SVal;
238
239
374k
  static bool isKind(const SVal& V) {
240
374k
    return !V.isUndef();
241
374k
  }
242
};
243
244
class UnknownVal : public DefinedOrUnknownSVal {
245
public:
246
275k
  explicit UnknownVal() : DefinedOrUnknownSVal(UnknownValKind) {}
247
248
private:
249
  friend class SVal;
250
251
514k
  static bool isKind(const SVal &V) {
252
514k
    return V.getBaseKind() == UnknownValKind;
253
514k
  }
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
2.53M
      : DefinedOrUnknownSVal(d, isLoc, ValKind) {}
268
269
private:
270
  friend class SVal;
271
272
1.15M
  static bool isKind(const SVal& V) {
273
1.15M
    return !V.isUnknownOrUndef();
274
1.15M
  }
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.66k
  static bool isKind(const SVal &V) {
284
2.66k
    return !V.isUnknown();
285
2.66k
  }
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
1.53M
      : 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.3k
||
303
11
           T->isAnyComplexType() || 
T->isVectorType()6
;
304
20.8k
  }
305
306
private:
307
  friend class SVal;
308
309
1.62M
  static bool isKind(const SVal& V) {
310
1.62M
    return V.getBaseKind() == NonLocKind;
311
1.62M
  }
312
};
313
314
class Loc : public DefinedSVal {
315
protected:
316
  Loc() = default;
317
  explicit Loc(unsigned SubKind, const void *D)
318
995k
      : DefinedSVal(const_cast<void *>(D), true, SubKind) {}
319
320
public:
321
  void dumpToStream(raw_ostream &Out) const;
322
323
3.81M
  static bool isLocType(QualType T) {
324
3.81M
    return T->isAnyPointerType() || 
T->isBlockPointerType()2.57M
||
325
2.57M
           T->isReferenceType() || 
T->isNullPtrType()2.45M
;
326
3.81M
  }
327
328
private:
329
  friend class SVal;
330
331
3.07M
  static bool isKind(const SVal& V) {
332
3.07M
    return V.getBaseKind() == LocKind;
333
3.07M
  }
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
680k
  SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) {
347
680k
    assert(sym);
348
680k
    assert(!Loc::isLocType(sym->getType()));
349
680k
  }
350
351
2.22M
  SymbolRef getSymbol() const {
352
2.22M
    return (const SymExpr *) Data;
353
2.22M
  }
354
355
199k
  bool isExpression() const {
356
199k
    return !isa<SymbolData>(getSymbol());
357
199k
  }
358
359
private:
360
  friend class SVal;
361
362
4.91M
  static bool isKind(const SVal& V) {
363
4.91M
    return V.getBaseKind() == NonLocKind &&
364
3.39M
           V.getSubKind() == SymbolValKind;
365
4.91M
  }
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
801k
  explicit ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {}
376
377
868k
  const llvm::APSInt& getValue() const {
378
868k
    return *static_cast<const llvm::APSInt *>(Data);
379
868k
  }
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
2.06M
  static bool isKind(const SVal& V) {
395
2.06M
    return V.getBaseKind() == NonLocKind &&
396
1.37M
           V.getSubKind() == ConcreteIntKind;
397
2.06M
  }
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
132
      : 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
132
    assert(data.first.getBaseKind() == LocKind &&
412
132
           (data.first.getSubKind() == loc::MemRegionValKind ||
413
132
            data.first.getSubKind() == loc::GotoLabelKind));
414
132
  }
415
416
public:
417
980
  Loc getLoc() const {
418
980
    const std::pair<SVal, uintptr_t> *D =
419
980
      static_cast<const std::pair<SVal, uintptr_t> *>(Data);
420
980
    return D->first.castAs<Loc>();
421
980
  }
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
195
  unsigned getNumBits() const {
431
195
    const std::pair<SVal, uintptr_t> *D =
432
195
      static_cast<const std::pair<SVal, uintptr_t> *>(Data);
433
195
    return D->second;
434
195
  }
435
436
private:
437
  friend class SVal;
438
439
  LocAsInteger() = default;
440
441
3.21M
  static bool isKind(const SVal& V) {
442
3.21M
    return V.getBaseKind() == NonLocKind &&
443
2.61M
           V.getSubKind() == LocAsIntegerKind;
444
3.21M
  }
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.11k
  explicit CompoundVal(const CompoundValData* D) : NonLoc(CompoundValKind, D) {}
455
456
public:
457
6.36k
  const CompoundValData* getValue() const {
458
6.36k
    return static_cast<const CompoundValData *>(Data);
459
6.36k
  }
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
367k
  static bool isKind(const SVal& V) {
472
367k
    return V.getBaseKind() == NonLocKind && 
V.getSubKind() == CompoundValKind258k
;
473
367k
  }
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
54.1k
      : NonLoc(LazyCompoundValKind, D) {}
485
486
public:
487
71.2k
  const LazyCompoundValData *getCVData() const {
488
71.2k
    return static_cast<const LazyCompoundValData *>(Data);
489
71.2k
  }
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.57M
  static bool isKind(const SVal& V) {
500
2.57M
    return V.getBaseKind() == NonLocKind &&
501
1.81M
           V.getSubKind() == LazyCompoundValKind;
502
2.57M
  }
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 DeclaratorDecl which can be a member function
515
/// pointer or a member data pointer and a list of CXXBaseSpecifiers. This list
516
/// is required to accumulate the pointer-to-member cast history to figure out
517
/// the correct subobject field.
518
class PointerToMember : public NonLoc {
519
  friend class ento::SValBuilder;
520
521
public:
522
  using PTMDataType =
523
      llvm::PointerUnion<const NamedDecl *, const PointerToMemberData *>;
524
525
607
  const PTMDataType getPTMData() const {
526
607
    return PTMDataType::getFromOpaqueValue(const_cast<void *>(Data));
527
607
  }
528
529
  bool isNullMemberPointer() const;
530
531
  const NamedDecl *getDecl() const;
532
533
  template<typename AdjustedDecl>
534
56
  const AdjustedDecl *getDeclAs() const {
535
56
    return dyn_cast_or_null<AdjustedDecl>(getDecl());
536
56
  }
clang::FieldDecl const* clang::ento::nonloc::PointerToMember::getDeclAs<clang::FieldDecl>() const
Line
Count
Source
534
33
  const AdjustedDecl *getDeclAs() const {
535
33
    return dyn_cast_or_null<AdjustedDecl>(getDecl());
536
33
  }
clang::IndirectFieldDecl const* clang::ento::nonloc::PointerToMember::getDeclAs<clang::IndirectFieldDecl>() const
Line
Count
Source
534
23
  const AdjustedDecl *getDeclAs() const {
535
23
    return dyn_cast_or_null<AdjustedDecl>(getDecl());
536
23
  }
537
538
  using iterator = llvm::ImmutableList<const CXXBaseSpecifier *>::iterator;
539
540
  iterator begin() const;
541
  iterator end() const;
542
543
private:
544
  friend class SVal;
545
546
  PointerToMember() = default;
547
  explicit PointerToMember(const PTMDataType D)
548
86
      : NonLoc(PointerToMemberKind, D.getOpaqueValue()) {}
549
550
189k
  static bool isKind(const SVal& V) {
551
189k
    return V.getBaseKind() == NonLocKind &&
552
167k
           V.getSubKind() == PointerToMemberKind;
553
189k
  }
554
555
0
  static bool isKind(const NonLoc& V) {
556
0
    return V.getSubKind() == PointerToMemberKind;
557
0
  }
558
};
559
560
} // namespace nonloc
561
562
//==------------------------------------------------------------------------==//
563
//  Subclasses of Loc.
564
//==------------------------------------------------------------------------==//
565
566
namespace loc {
567
568
class GotoLabel : public Loc {
569
public:
570
60
  explicit GotoLabel(const LabelDecl *Label) : Loc(GotoLabelKind, Label) {
571
60
    assert(Label);
572
60
  }
573
574
12
  const LabelDecl *getLabel() const {
575
12
    return static_cast<const LabelDecl *>(Data);
576
12
  }
577
578
private:
579
  friend class SVal;
580
581
  GotoLabel() = default;
582
583
7.91k
  static bool isKind(const SVal& V) {
584
7.91k
    return V.getBaseKind() == LocKind && 
V.getSubKind() == GotoLabelKind7.91k
;
585
7.91k
  }
586
587
0
  static bool isKind(const Loc& V) {
588
0
    return V.getSubKind() == GotoLabelKind;
589
0
  }
590
};
591
592
class MemRegionVal : public Loc {
593
public:
594
985k
  explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionValKind, r) {
595
985k
    assert(r);
596
985k
  }
597
598
  /// Get the underlining region.
599
5.79M
  const MemRegion *getRegion() const {
600
5.79M
    return static_cast<const MemRegion *>(Data);
601
5.79M
  }
602
603
  /// Get the underlining region and strip casts.
604
  const MemRegion* stripCasts(bool StripBaseCasts = true) const;
605
606
  template <typename REGION>
607
8.82k
  const REGION* getRegionAs() const {
608
8.82k
    return dyn_cast<REGION>(getRegion());
609
8.82k
  }
clang::ento::FieldRegion const* clang::ento::loc::MemRegionVal::getRegionAs<clang::ento::FieldRegion>() const
Line
Count
Source
607
662
  const REGION* getRegionAs() const {
608
662
    return dyn_cast<REGION>(getRegion());
609
662
  }
clang::ento::TypedValueRegion const* clang::ento::loc::MemRegionVal::getRegionAs<clang::ento::TypedValueRegion>() const
Line
Count
Source
607
80
  const REGION* getRegionAs() const {
608
80
    return dyn_cast<REGION>(getRegion());
609
80
  }
clang::ento::SymbolicRegion const* clang::ento::loc::MemRegionVal::getRegionAs<clang::ento::SymbolicRegion>() const
Line
Count
Source
607
156
  const REGION* getRegionAs() const {
608
156
    return dyn_cast<REGION>(getRegion());
609
156
  }
clang::ento::AllocaRegion const* clang::ento::loc::MemRegionVal::getRegionAs<clang::ento::AllocaRegion>() const
Line
Count
Source
607
39
  const REGION* getRegionAs() const {
608
39
    return dyn_cast<REGION>(getRegion());
609
39
  }
clang::ento::SubRegion const* clang::ento::loc::MemRegionVal::getRegionAs<clang::ento::SubRegion>() const
Line
Count
Source
607
7.88k
  const REGION* getRegionAs() const {
608
7.88k
    return dyn_cast<REGION>(getRegion());
609
7.88k
  }
610
611
0
  bool operator==(const MemRegionVal &R) const {
612
0
    return getRegion() == R.getRegion();
613
0
  }
614
615
0
  bool operator!=(const MemRegionVal &R) const {
616
0
    return getRegion() != R.getRegion();
617
0
  }
618
619
private:
620
  friend class SVal;
621
622
  MemRegionVal() = default;
623
624
9.55M
  static bool isKind(const SVal& V) {
625
9.55M
    return V.getBaseKind() == LocKind &&
626
6.55M
           V.getSubKind() == MemRegionValKind;
627
9.55M
  }
628
629
0
  static bool isKind(const Loc& V) {
630
0
    return V.getSubKind() == MemRegionValKind;
631
0
  }
632
};
633
634
class ConcreteInt : public Loc {
635
public:
636
9.53k
  explicit ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {}
637
638
9.99k
  const llvm::APSInt &getValue() const {
639
9.99k
    return *static_cast<const llvm::APSInt *>(Data);
640
9.99k
  }
641
642
  // Transfer functions for binary/unary operations on ConcreteInts.
643
  SVal evalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
644
                 const ConcreteInt& R) const;
645
646
private:
647
  friend class SVal;
648
649
  ConcreteInt() = default;
650
651
1.88M
  static bool isKind(const SVal& V) {
652
1.88M
    return V.getBaseKind() == LocKind &&
653
1.41M
           V.getSubKind() == ConcreteIntKind;
654
1.88M
  }
655
656
0
  static bool isKind(const Loc& V) {
657
0
    return V.getSubKind() == ConcreteIntKind;
658
0
  }
659
};
660
661
} // namespace loc
662
663
} // namespace ento
664
665
} // namespace clang
666
667
#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H