1218887Sdim//== SVals.h - Abstract Values for Static Analysis ---------*- C++ -*--==//
2218887Sdim//
3218887Sdim//                     The LLVM Compiler Infrastructure
4218887Sdim//
5218887Sdim// This file is distributed under the University of Illinois Open Source
6218887Sdim// License. See LICENSE.TXT for details.
7218887Sdim//
8218887Sdim//===----------------------------------------------------------------------===//
9218887Sdim//
10218887Sdim//  This file defines SVal, Loc, and NonLoc, classes that represent
11218887Sdim//  abstract r-values for use with path-sensitive value tracking.
12218887Sdim//
13218887Sdim//===----------------------------------------------------------------------===//
14218887Sdim
15218887Sdim#ifndef LLVM_CLANG_GR_RVALUE_H
16218887Sdim#define LLVM_CLANG_GR_RVALUE_H
17218887Sdim
18226633Sdim#include "clang/Basic/LLVM.h"
19249423Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
20218887Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
21218887Sdim#include "llvm/ADT/ImmutableList.h"
22218887Sdim
23218887Sdim//==------------------------------------------------------------------------==//
24218887Sdim//  Base SVal types.
25218887Sdim//==------------------------------------------------------------------------==//
26218887Sdim
27218887Sdimnamespace clang {
28218887Sdim
29218887Sdimnamespace ento {
30218887Sdim
31218887Sdimclass CompoundValData;
32218887Sdimclass LazyCompoundValData;
33226633Sdimclass ProgramState;
34218887Sdimclass BasicValueFactory;
35218887Sdimclass MemRegion;
36249423Sdimclass TypedValueRegion;
37218887Sdimclass MemRegionManager;
38226633Sdimclass ProgramStateManager;
39218887Sdimclass SValBuilder;
40218887Sdim
41218887Sdim/// SVal - This represents a symbolic expression, which can be either
42218887Sdim///  an L-value or an R-value.
43218887Sdim///
44218887Sdimclass SVal {
45218887Sdimpublic:
46218887Sdim  enum BaseKind {
47218887Sdim    // The enumerators must be representable using 2 bits.
48218887Sdim    UndefinedKind = 0,  // for subclass UndefinedVal (an uninitialized value)
49218887Sdim    UnknownKind = 1,    // for subclass UnknownVal (a void value)
50218887Sdim    LocKind = 2,        // for subclass Loc (an L-value)
51218887Sdim    NonLocKind = 3      // for subclass NonLoc (an R-value that's not
52218887Sdim                        //   an L-value)
53218887Sdim  };
54218887Sdim  enum { BaseBits = 2, BaseMask = 0x3 };
55218887Sdim
56218887Sdimprotected:
57226633Sdim  const void *Data;
58218887Sdim
59218887Sdim  /// The lowest 2 bits are a BaseKind (0 -- 3).
60218887Sdim  ///  The higher bits are an unsigned "kind" value.
61218887Sdim  unsigned Kind;
62218887Sdim
63226633Sdim  explicit SVal(const void *d, bool isLoc, unsigned ValKind)
64218887Sdim  : Data(d), Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {}
65218887Sdim
66226633Sdim  explicit SVal(BaseKind k, const void *D = NULL)
67218887Sdim    : Data(D), Kind(k) {}
68218887Sdim
69218887Sdimpublic:
70218887Sdim  explicit SVal() : Data(0), Kind(0) {}
71218887Sdim
72249423Sdim  /// \brief Convert to the specified SVal type, asserting that this SVal is of
73249423Sdim  /// the desired type.
74249423Sdim  template<typename T>
75249423Sdim  T castAs() const {
76249423Sdim    assert(T::isKind(*this));
77249423Sdim    T t;
78249423Sdim    SVal& sv = t;
79249423Sdim    sv = *this;
80249423Sdim    return t;
81249423Sdim  }
82249423Sdim
83249423Sdim  /// \brief Convert to the specified SVal type, returning None if this SVal is
84249423Sdim  /// not of the desired type.
85249423Sdim  template<typename T>
86249423Sdim  Optional<T> getAs() const {
87249423Sdim    if (!T::isKind(*this))
88249423Sdim      return None;
89249423Sdim    T t;
90249423Sdim    SVal& sv = t;
91249423Sdim    sv = *this;
92249423Sdim    return t;
93249423Sdim  }
94249423Sdim
95218887Sdim  /// BufferTy - A temporary buffer to hold a set of SVals.
96226633Sdim  typedef SmallVector<SVal,5> BufferTy;
97218887Sdim
98218887Sdim  inline unsigned getRawKind() const { return Kind; }
99218887Sdim  inline BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
100218887Sdim  inline unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; }
101218887Sdim
102218887Sdim  // This method is required for using SVal in a FoldingSetNode.  It
103218887Sdim  // extracts a unique signature for this SVal object.
104218887Sdim  inline void Profile(llvm::FoldingSetNodeID& ID) const {
105218887Sdim    ID.AddInteger((unsigned) getRawKind());
106218887Sdim    ID.AddPointer(Data);
107218887Sdim  }
108218887Sdim
109218887Sdim  inline bool operator==(const SVal& R) const {
110218887Sdim    return getRawKind() == R.getRawKind() && Data == R.Data;
111218887Sdim  }
112218887Sdim
113218887Sdim  inline bool operator!=(const SVal& R) const {
114218887Sdim    return !(*this == R);
115218887Sdim  }
116218887Sdim
117218887Sdim  inline bool isUnknown() const {
118218887Sdim    return getRawKind() == UnknownKind;
119218887Sdim  }
120218887Sdim
121218887Sdim  inline bool isUndef() const {
122218887Sdim    return getRawKind() == UndefinedKind;
123218887Sdim  }
124218887Sdim
125218887Sdim  inline bool isUnknownOrUndef() const {
126218887Sdim    return getRawKind() <= UnknownKind;
127218887Sdim  }
128218887Sdim
129218887Sdim  inline bool isValid() const {
130218887Sdim    return getRawKind() > UnknownKind;
131218887Sdim  }
132218887Sdim
133218887Sdim  bool isConstant() const;
134218887Sdim
135218887Sdim  bool isConstant(int I) const;
136218887Sdim
137218887Sdim  bool isZeroConstant() const;
138218887Sdim
139218887Sdim  /// hasConjuredSymbol - If this SVal wraps a conjured symbol, return true;
140218887Sdim  bool hasConjuredSymbol() const;
141218887Sdim
142218887Sdim  /// getAsFunctionDecl - If this SVal is a MemRegionVal and wraps a
143218887Sdim  /// CodeTextRegion wrapping a FunctionDecl, return that FunctionDecl.
144218887Sdim  /// Otherwise return 0.
145226633Sdim  const FunctionDecl *getAsFunctionDecl() const;
146218887Sdim
147251662Sdim  /// \brief If this SVal is a location and wraps a symbol, return that
148251662Sdim  ///  SymbolRef. Otherwise return 0.
149251662Sdim  ///
150251662Sdim  /// Casts are ignored during lookup.
151251662Sdim  /// \param IncludeBaseRegions The boolean that controls whether the search
152251662Sdim  /// should continue to the base regions if the region is not symbolic.
153251662Sdim  SymbolRef getAsLocSymbol(bool IncludeBaseRegions = false) const;
154218887Sdim
155218887Sdim  /// Get the symbol in the SVal or its base region.
156218887Sdim  SymbolRef getLocSymbolInBase() const;
157218887Sdim
158251662Sdim  /// \brief If this SVal wraps a symbol return that SymbolRef.
159234353Sdim  /// Otherwise, return 0.
160251662Sdim  ///
161251662Sdim  /// Casts are ignored during lookup.
162251662Sdim  /// \param IncludeBaseRegions The boolean that controls whether the search
163251662Sdim  /// should continue to the base regions if the region is not symbolic.
164251662Sdim  SymbolRef getAsSymbol(bool IncludeBaseRegions = false) const;
165218887Sdim
166218887Sdim  /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
167218887Sdim  ///  return that expression.  Otherwise return NULL.
168218887Sdim  const SymExpr *getAsSymbolicExpression() const;
169218887Sdim
170234353Sdim  const SymExpr* getAsSymExpr() const;
171234353Sdim
172218887Sdim  const MemRegion *getAsRegion() const;
173218887Sdim
174226633Sdim  void dumpToStream(raw_ostream &OS) const;
175218887Sdim  void dump() const;
176218887Sdim
177234353Sdim  SymExpr::symbol_iterator symbol_begin() const {
178218887Sdim    const SymExpr *SE = getAsSymbolicExpression();
179218887Sdim    if (SE)
180234353Sdim      return SE->symbol_begin();
181218887Sdim    else
182234353Sdim      return SymExpr::symbol_iterator();
183218887Sdim  }
184218887Sdim
185234353Sdim  SymExpr::symbol_iterator symbol_end() const {
186234353Sdim    return SymExpr::symbol_end();
187234353Sdim  }
188218887Sdim};
189218887Sdim
190218887Sdim
191218887Sdimclass UndefinedVal : public SVal {
192218887Sdimpublic:
193218887Sdim  UndefinedVal() : SVal(UndefinedKind) {}
194218887Sdim
195249423Sdimprivate:
196249423Sdim  friend class SVal;
197249423Sdim  static bool isKind(const SVal& V) {
198249423Sdim    return V.getBaseKind() == UndefinedKind;
199218887Sdim  }
200218887Sdim};
201218887Sdim
202218887Sdimclass DefinedOrUnknownSVal : public SVal {
203218887Sdimprivate:
204249423Sdim  // We want calling these methods to be a compiler error since they are
205249423Sdim  // tautologically false.
206249423Sdim  bool isUndef() const LLVM_DELETED_FUNCTION;
207249423Sdim  bool isValid() const LLVM_DELETED_FUNCTION;
208218887Sdim
209218887Sdimprotected:
210249423Sdim  DefinedOrUnknownSVal() {}
211226633Sdim  explicit DefinedOrUnknownSVal(const void *d, bool isLoc, unsigned ValKind)
212218887Sdim    : SVal(d, isLoc, ValKind) {}
213218887Sdim
214218887Sdim  explicit DefinedOrUnknownSVal(BaseKind k, void *D = NULL)
215218887Sdim    : SVal(k, D) {}
216218887Sdim
217249423Sdimprivate:
218249423Sdim  friend class SVal;
219249423Sdim  static bool isKind(const SVal& V) {
220249423Sdim    return !V.isUndef();
221218887Sdim  }
222218887Sdim};
223218887Sdim
224218887Sdimclass UnknownVal : public DefinedOrUnknownSVal {
225218887Sdimpublic:
226218887Sdim  explicit UnknownVal() : DefinedOrUnknownSVal(UnknownKind) {}
227218887Sdim
228249423Sdimprivate:
229249423Sdim  friend class SVal;
230249423Sdim  static bool isKind(const SVal &V) {
231249423Sdim    return V.getBaseKind() == UnknownKind;
232218887Sdim  }
233218887Sdim};
234218887Sdim
235218887Sdimclass DefinedSVal : public DefinedOrUnknownSVal {
236218887Sdimprivate:
237249423Sdim  // We want calling these methods to be a compiler error since they are
238249423Sdim  // tautologically true/false.
239249423Sdim  bool isUnknown() const LLVM_DELETED_FUNCTION;
240249423Sdim  bool isUnknownOrUndef() const LLVM_DELETED_FUNCTION;
241249423Sdim  bool isValid() const LLVM_DELETED_FUNCTION;
242218887Sdimprotected:
243249423Sdim  DefinedSVal() {}
244226633Sdim  explicit DefinedSVal(const void *d, bool isLoc, unsigned ValKind)
245218887Sdim    : DefinedOrUnknownSVal(d, isLoc, ValKind) {}
246249423Sdimprivate:
247249423Sdim  friend class SVal;
248249423Sdim  static bool isKind(const SVal& V) {
249249423Sdim    return !V.isUnknownOrUndef();
250218887Sdim  }
251218887Sdim};
252218887Sdim
253249423Sdim
254249423Sdim/// \brief Represents an SVal that is guaranteed to not be UnknownVal.
255249423Sdimclass KnownSVal : public SVal {
256249423Sdim  KnownSVal() {}
257249423Sdim  friend class SVal;
258249423Sdim  static bool isKind(const SVal &V) {
259249423Sdim    return !V.isUnknown();
260249423Sdim  }
261249423Sdimpublic:
262249423Sdim  KnownSVal(const DefinedSVal &V) : SVal(V) {}
263249423Sdim  KnownSVal(const UndefinedVal &V) : SVal(V) {}
264249423Sdim};
265249423Sdim
266218887Sdimclass NonLoc : public DefinedSVal {
267218887Sdimprotected:
268249423Sdim  NonLoc() {}
269226633Sdim  explicit NonLoc(unsigned SubKind, const void *d)
270218887Sdim    : DefinedSVal(d, false, SubKind) {}
271218887Sdim
272218887Sdimpublic:
273226633Sdim  void dumpToStream(raw_ostream &Out) const;
274218887Sdim
275249423Sdimprivate:
276249423Sdim  friend class SVal;
277249423Sdim  static bool isKind(const SVal& V) {
278249423Sdim    return V.getBaseKind() == NonLocKind;
279218887Sdim  }
280218887Sdim};
281218887Sdim
282218887Sdimclass Loc : public DefinedSVal {
283218887Sdimprotected:
284249423Sdim  Loc() {}
285226633Sdim  explicit Loc(unsigned SubKind, const void *D)
286218887Sdim  : DefinedSVal(const_cast<void*>(D), true, SubKind) {}
287218887Sdim
288218887Sdimpublic:
289226633Sdim  void dumpToStream(raw_ostream &Out) const;
290218887Sdim
291218887Sdim  static inline bool isLocType(QualType T) {
292218887Sdim    return T->isAnyPointerType() || T->isBlockPointerType() ||
293263508Sdim           T->isReferenceType() || T->isNullPtrType();
294218887Sdim  }
295249423Sdim
296249423Sdimprivate:
297249423Sdim  friend class SVal;
298249423Sdim  static bool isKind(const SVal& V) {
299249423Sdim    return V.getBaseKind() == LocKind;
300249423Sdim  }
301218887Sdim};
302218887Sdim
303218887Sdim//==------------------------------------------------------------------------==//
304218887Sdim//  Subclasses of NonLoc.
305218887Sdim//==------------------------------------------------------------------------==//
306218887Sdim
307218887Sdimnamespace nonloc {
308218887Sdim
309243830Sdimenum Kind { ConcreteIntKind, SymbolValKind,
310218887Sdim            LocAsIntegerKind, CompoundValKind, LazyCompoundValKind };
311218887Sdim
312234353Sdim/// \brief Represents symbolic expression.
313218887Sdimclass SymbolVal : public NonLoc {
314218887Sdimpublic:
315218887Sdim  SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) {}
316218887Sdim
317218887Sdim  SymbolRef getSymbol() const {
318234353Sdim    return (const SymExpr*) Data;
319218887Sdim  }
320218887Sdim
321249423Sdim  bool isExpression() const {
322234353Sdim    return !isa<SymbolData>(getSymbol());
323234353Sdim  }
324234353Sdim
325249423Sdimprivate:
326249423Sdim  friend class SVal;
327249423Sdim  SymbolVal() {}
328249423Sdim  static bool isKind(const SVal& V) {
329249423Sdim    return V.getBaseKind() == NonLocKind &&
330249423Sdim           V.getSubKind() == SymbolValKind;
331218887Sdim  }
332218887Sdim
333249423Sdim  static bool isKind(const NonLoc& V) {
334249423Sdim    return V.getSubKind() == SymbolValKind;
335218887Sdim  }
336218887Sdim};
337218887Sdim
338234353Sdim/// \brief Value representing integer constant.
339218887Sdimclass ConcreteInt : public NonLoc {
340218887Sdimpublic:
341218887Sdim  explicit ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {}
342218887Sdim
343218887Sdim  const llvm::APSInt& getValue() const {
344218887Sdim    return *static_cast<const llvm::APSInt*>(Data);
345218887Sdim  }
346218887Sdim
347218887Sdim  // Transfer functions for binary/unary operations on ConcreteInts.
348218887Sdim  SVal evalBinOp(SValBuilder &svalBuilder, BinaryOperator::Opcode Op,
349218887Sdim                 const ConcreteInt& R) const;
350218887Sdim
351218887Sdim  ConcreteInt evalComplement(SValBuilder &svalBuilder) const;
352218887Sdim
353218887Sdim  ConcreteInt evalMinus(SValBuilder &svalBuilder) const;
354218887Sdim
355249423Sdimprivate:
356249423Sdim  friend class SVal;
357249423Sdim  ConcreteInt() {}
358249423Sdim  static bool isKind(const SVal& V) {
359249423Sdim    return V.getBaseKind() == NonLocKind &&
360249423Sdim           V.getSubKind() == ConcreteIntKind;
361218887Sdim  }
362218887Sdim
363249423Sdim  static bool isKind(const NonLoc& V) {
364249423Sdim    return V.getSubKind() == ConcreteIntKind;
365218887Sdim  }
366218887Sdim};
367218887Sdim
368218887Sdimclass LocAsInteger : public NonLoc {
369218887Sdim  friend class ento::SValBuilder;
370218887Sdim
371249423Sdim  explicit LocAsInteger(const std::pair<SVal, uintptr_t> &data)
372249423Sdim      : NonLoc(LocAsIntegerKind, &data) {
373249423Sdim    assert (data.first.getAs<Loc>());
374249423Sdim  }
375218887Sdim
376218887Sdimpublic:
377218887Sdim
378218887Sdim  Loc getLoc() const {
379239462Sdim    const std::pair<SVal, uintptr_t> *D =
380239462Sdim      static_cast<const std::pair<SVal, uintptr_t> *>(Data);
381249423Sdim    return D->first.castAs<Loc>();
382218887Sdim  }
383218887Sdim
384249423Sdim  Loc getPersistentLoc() const {
385239462Sdim    const std::pair<SVal, uintptr_t> *D =
386239462Sdim      static_cast<const std::pair<SVal, uintptr_t> *>(Data);
387239462Sdim    const SVal& V = D->first;
388249423Sdim    return V.castAs<Loc>();
389218887Sdim  }
390218887Sdim
391218887Sdim  unsigned getNumBits() const {
392239462Sdim    const std::pair<SVal, uintptr_t> *D =
393239462Sdim      static_cast<const std::pair<SVal, uintptr_t> *>(Data);
394239462Sdim    return D->second;
395218887Sdim  }
396218887Sdim
397249423Sdimprivate:
398249423Sdim  friend class SVal;
399249423Sdim  LocAsInteger() {}
400249423Sdim  static bool isKind(const SVal& V) {
401249423Sdim    return V.getBaseKind() == NonLocKind &&
402249423Sdim           V.getSubKind() == LocAsIntegerKind;
403218887Sdim  }
404218887Sdim
405249423Sdim  static bool isKind(const NonLoc& V) {
406249423Sdim    return V.getSubKind() == LocAsIntegerKind;
407218887Sdim  }
408218887Sdim};
409218887Sdim
410218887Sdimclass CompoundVal : public NonLoc {
411218887Sdim  friend class ento::SValBuilder;
412218887Sdim
413218887Sdim  explicit CompoundVal(const CompoundValData* D) : NonLoc(CompoundValKind, D) {}
414218887Sdim
415218887Sdimpublic:
416218887Sdim  const CompoundValData* getValue() const {
417218887Sdim    return static_cast<const CompoundValData*>(Data);
418218887Sdim  }
419218887Sdim
420218887Sdim  typedef llvm::ImmutableList<SVal>::iterator iterator;
421218887Sdim  iterator begin() const;
422218887Sdim  iterator end() const;
423218887Sdim
424249423Sdimprivate:
425249423Sdim  friend class SVal;
426249423Sdim  CompoundVal() {}
427249423Sdim  static bool isKind(const SVal& V) {
428249423Sdim    return V.getBaseKind() == NonLocKind && V.getSubKind() == CompoundValKind;
429218887Sdim  }
430218887Sdim
431249423Sdim  static bool isKind(const NonLoc& V) {
432249423Sdim    return V.getSubKind() == CompoundValKind;
433218887Sdim  }
434218887Sdim};
435218887Sdim
436218887Sdimclass LazyCompoundVal : public NonLoc {
437218887Sdim  friend class ento::SValBuilder;
438218887Sdim
439218887Sdim  explicit LazyCompoundVal(const LazyCompoundValData *D)
440218887Sdim    : NonLoc(LazyCompoundValKind, D) {}
441218887Sdimpublic:
442218887Sdim  const LazyCompoundValData *getCVData() const {
443218887Sdim    return static_cast<const LazyCompoundValData*>(Data);
444218887Sdim  }
445218887Sdim  const void *getStore() const;
446249423Sdim  const TypedValueRegion *getRegion() const;
447218887Sdim
448249423Sdimprivate:
449249423Sdim  friend class SVal;
450249423Sdim  LazyCompoundVal() {}
451249423Sdim  static bool isKind(const SVal& V) {
452249423Sdim    return V.getBaseKind() == NonLocKind &&
453249423Sdim           V.getSubKind() == LazyCompoundValKind;
454218887Sdim  }
455249423Sdim  static bool isKind(const NonLoc& V) {
456249423Sdim    return V.getSubKind() == LazyCompoundValKind;
457218887Sdim  }
458218887Sdim};
459218887Sdim
460218887Sdim} // end namespace ento::nonloc
461218887Sdim
462218887Sdim//==------------------------------------------------------------------------==//
463218887Sdim//  Subclasses of Loc.
464218887Sdim//==------------------------------------------------------------------------==//
465218887Sdim
466218887Sdimnamespace loc {
467218887Sdim
468239462Sdimenum Kind { GotoLabelKind, MemRegionKind, ConcreteIntKind };
469218887Sdim
470218887Sdimclass GotoLabel : public Loc {
471218887Sdimpublic:
472218887Sdim  explicit GotoLabel(LabelDecl *Label) : Loc(GotoLabelKind, Label) {}
473218887Sdim
474218887Sdim  const LabelDecl *getLabel() const {
475218887Sdim    return static_cast<const LabelDecl*>(Data);
476218887Sdim  }
477218887Sdim
478249423Sdimprivate:
479249423Sdim  friend class SVal;
480249423Sdim  GotoLabel() {}
481249423Sdim  static bool isKind(const SVal& V) {
482249423Sdim    return V.getBaseKind() == LocKind && V.getSubKind() == GotoLabelKind;
483218887Sdim  }
484218887Sdim
485249423Sdim  static bool isKind(const Loc& V) {
486249423Sdim    return V.getSubKind() == GotoLabelKind;
487218887Sdim  }
488218887Sdim};
489218887Sdim
490218887Sdim
491218887Sdimclass MemRegionVal : public Loc {
492218887Sdimpublic:
493218887Sdim  explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {}
494218887Sdim
495234982Sdim  /// \brief Get the underlining region.
496218887Sdim  const MemRegion* getRegion() const {
497218887Sdim    return static_cast<const MemRegion*>(Data);
498218887Sdim  }
499218887Sdim
500234982Sdim  /// \brief Get the underlining region and strip casts.
501239462Sdim  const MemRegion* stripCasts(bool StripBaseCasts = true) const;
502218887Sdim
503218887Sdim  template <typename REGION>
504218887Sdim  const REGION* getRegionAs() const {
505249423Sdim    return dyn_cast<REGION>(getRegion());
506218887Sdim  }
507218887Sdim
508218887Sdim  inline bool operator==(const MemRegionVal& R) const {
509218887Sdim    return getRegion() == R.getRegion();
510218887Sdim  }
511218887Sdim
512218887Sdim  inline bool operator!=(const MemRegionVal& R) const {
513218887Sdim    return getRegion() != R.getRegion();
514218887Sdim  }
515218887Sdim
516249423Sdimprivate:
517249423Sdim  friend class SVal;
518249423Sdim  MemRegionVal() {}
519249423Sdim  static bool isKind(const SVal& V) {
520249423Sdim    return V.getBaseKind() == LocKind &&
521249423Sdim           V.getSubKind() == MemRegionKind;
522218887Sdim  }
523218887Sdim
524249423Sdim  static bool isKind(const Loc& V) {
525249423Sdim    return V.getSubKind() == MemRegionKind;
526218887Sdim  }
527218887Sdim};
528218887Sdim
529218887Sdimclass ConcreteInt : public Loc {
530218887Sdimpublic:
531218887Sdim  explicit ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {}
532218887Sdim
533218887Sdim  const llvm::APSInt& getValue() const {
534218887Sdim    return *static_cast<const llvm::APSInt*>(Data);
535218887Sdim  }
536218887Sdim
537218887Sdim  // Transfer functions for binary/unary operations on ConcreteInts.
538218887Sdim  SVal evalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
539218887Sdim                 const ConcreteInt& R) const;
540218887Sdim
541249423Sdimprivate:
542249423Sdim  friend class SVal;
543249423Sdim  ConcreteInt() {}
544249423Sdim  static bool isKind(const SVal& V) {
545249423Sdim    return V.getBaseKind() == LocKind &&
546249423Sdim           V.getSubKind() == ConcreteIntKind;
547218887Sdim  }
548218887Sdim
549249423Sdim  static bool isKind(const Loc& V) {
550249423Sdim    return V.getSubKind() == ConcreteIntKind;
551218887Sdim  }
552218887Sdim};
553218887Sdim
554218887Sdim} // end ento::loc namespace
555218887Sdim
556249423Sdim} // end ento namespace
557249423Sdim
558218887Sdim} // end clang namespace
559218887Sdim
560218887Sdimnamespace llvm {
561226633Sdimstatic inline raw_ostream &operator<<(raw_ostream &os,
562218887Sdim                                            clang::ento::SVal V) {
563218887Sdim  V.dumpToStream(os);
564218887Sdim  return os;
565218887Sdim}
566218887Sdim
567249423Sdimtemplate <typename T> struct isPodLike;
568249423Sdimtemplate <> struct isPodLike<clang::ento::SVal> {
569249423Sdim  static const bool value = true;
570249423Sdim};
571249423Sdim
572218887Sdim} // end llvm namespace
573218887Sdim
574218887Sdim#endif
575