clang  3.7.0
SVals.h
Go to the documentation of this file.
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/Basic/LLVM.h"
21 #include "llvm/ADT/ImmutableList.h"
22 
23 //==------------------------------------------------------------------------==//
24 // Base SVal types.
25 //==------------------------------------------------------------------------==//
26 
27 namespace clang {
28 
29 namespace ento {
30 
31 class CompoundValData;
32 class LazyCompoundValData;
33 class ProgramState;
34 class BasicValueFactory;
35 class MemRegion;
36 class TypedValueRegion;
37 class MemRegionManager;
38 class ProgramStateManager;
39 class SValBuilder;
40 
41 /// SVal - This represents a symbolic expression, which can be either
42 /// an L-value or an R-value.
43 ///
44 class SVal {
45 public:
46  enum BaseKind {
47  // The enumerators must be representable using 2 bits.
48  UndefinedKind = 0, // for subclass UndefinedVal (an uninitialized value)
49  UnknownKind = 1, // for subclass UnknownVal (a void value)
50  LocKind = 2, // for subclass Loc (an L-value)
51  NonLocKind = 3 // for subclass NonLoc (an R-value that's not
52  // an L-value)
53  };
54  enum { BaseBits = 2, BaseMask = 0x3 };
55 
56 protected:
57  const void *Data;
58 
59  /// The lowest 2 bits are a BaseKind (0 -- 3).
60  /// The higher bits are an unsigned "kind" value.
61  unsigned Kind;
62 
63  explicit SVal(const void *d, bool isLoc, unsigned ValKind)
64  : Data(d), Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {}
65 
66  explicit SVal(BaseKind k, const void *D = nullptr)
67  : Data(D), Kind(k) {}
68 
69 public:
70  explicit SVal() : Data(nullptr), Kind(0) {}
71 
72  /// \brief Convert to the specified SVal type, asserting that this SVal is of
73  /// the desired type.
74  template<typename T>
75  T castAs() const {
76  assert(T::isKind(*this));
77  T t;
78  SVal& sv = t;
79  sv = *this;
80  return t;
81  }
82 
83  /// \brief Convert to the specified SVal type, returning None if this SVal is
84  /// not of the desired type.
85  template<typename T>
86  Optional<T> getAs() const {
87  if (!T::isKind(*this))
88  return None;
89  T t;
90  SVal& sv = t;
91  sv = *this;
92  return t;
93  }
94 
95  /// BufferTy - A temporary buffer to hold a set of SVals.
97 
98  inline unsigned getRawKind() const { return Kind; }
99  inline BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
100  inline unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; }
101 
102  // This method is required for using SVal in a FoldingSetNode. It
103  // extracts a unique signature for this SVal object.
104  inline void Profile(llvm::FoldingSetNodeID& ID) const {
105  ID.AddInteger((unsigned) getRawKind());
106  ID.AddPointer(Data);
107  }
108 
109  inline bool operator==(const SVal& R) const {
110  return getRawKind() == R.getRawKind() && Data == R.Data;
111  }
112 
113  inline bool operator!=(const SVal& R) const {
114  return !(*this == R);
115  }
116 
117  inline bool isUnknown() const {
118  return getRawKind() == UnknownKind;
119  }
120 
121  inline bool isUndef() const {
122  return getRawKind() == UndefinedKind;
123  }
124 
125  inline bool isUnknownOrUndef() const {
126  return getRawKind() <= UnknownKind;
127  }
128 
129  inline bool isValid() const {
130  return getRawKind() > UnknownKind;
131  }
132 
133  bool isConstant() const;
134 
135  bool isConstant(int I) const;
136 
137  bool isZeroConstant() const;
138 
139  /// hasConjuredSymbol - If this SVal wraps a conjured symbol, return true;
140  bool hasConjuredSymbol() const;
141 
142  /// getAsFunctionDecl - If this SVal is a MemRegionVal and wraps a
143  /// CodeTextRegion wrapping a FunctionDecl, return that FunctionDecl.
144  /// Otherwise return 0.
145  const FunctionDecl *getAsFunctionDecl() const;
146 
147  /// \brief If this SVal is a location and wraps a symbol, return that
148  /// SymbolRef. Otherwise return 0.
149  ///
150  /// Casts are ignored during lookup.
151  /// \param IncludeBaseRegions The boolean that controls whether the search
152  /// should continue to the base regions if the region is not symbolic.
153  SymbolRef getAsLocSymbol(bool IncludeBaseRegions = false) const;
154 
155  /// Get the symbol in the SVal or its base region.
157 
158  /// \brief If this SVal wraps a symbol return that SymbolRef.
159  /// Otherwise, return 0.
160  ///
161  /// Casts are ignored during lookup.
162  /// \param IncludeBaseRegions The boolean that controls whether the search
163  /// should continue to the base regions if the region is not symbolic.
164  SymbolRef getAsSymbol(bool IncludeBaseRegions = false) const;
165 
166  /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
167  /// return that expression. Otherwise return NULL.
168  const SymExpr *getAsSymbolicExpression() const;
169 
170  const SymExpr* getAsSymExpr() const;
171 
172  const MemRegion *getAsRegion() const;
173 
174  void dumpToStream(raw_ostream &OS) const;
175  void dump() const;
176 
178  const SymExpr *SE = getAsSymbolicExpression();
179  if (SE)
180  return SE->symbol_begin();
181  else
182  return SymExpr::symbol_iterator();
183  }
184 
186  return SymExpr::symbol_end();
187  }
188 };
189 
190 
191 class UndefinedVal : public SVal {
192 public:
194 
195 private:
196  friend class SVal;
197  static bool isKind(const SVal& V) {
198  return V.getBaseKind() == UndefinedKind;
199  }
200 };
201 
202 class DefinedOrUnknownSVal : public SVal {
203 private:
204  // We want calling these methods to be a compiler error since they are
205  // tautologically false.
206  bool isUndef() const = delete;
207  bool isValid() const = delete;
208 
209 protected:
211  explicit DefinedOrUnknownSVal(const void *d, bool isLoc, unsigned ValKind)
212  : SVal(d, isLoc, ValKind) {}
213 
214  explicit DefinedOrUnknownSVal(BaseKind k, void *D = nullptr)
215  : SVal(k, D) {}
216 
217 private:
218  friend class SVal;
219  static bool isKind(const SVal& V) {
220  return !V.isUndef();
221  }
222 };
223 
225 public:
227 
228 private:
229  friend class SVal;
230  static bool isKind(const SVal &V) {
231  return V.getBaseKind() == UnknownKind;
232  }
233 };
234 
236 private:
237  // We want calling these methods to be a compiler error since they are
238  // tautologically true/false.
239  bool isUnknown() const = delete;
240  bool isUnknownOrUndef() const = delete;
241  bool isValid() const = delete;
242 protected:
244  explicit DefinedSVal(const void *d, bool isLoc, unsigned ValKind)
245  : DefinedOrUnknownSVal(d, isLoc, ValKind) {}
246 private:
247  friend class SVal;
248  static bool isKind(const SVal& V) {
249  return !V.isUnknownOrUndef();
250  }
251 };
252 
253 
254 /// \brief Represents an SVal that is guaranteed to not be UnknownVal.
255 class KnownSVal : public SVal {
256  KnownSVal() {}
257  friend class SVal;
258  static bool isKind(const SVal &V) {
259  return !V.isUnknown();
260  }
261 public:
262  KnownSVal(const DefinedSVal &V) : SVal(V) {}
263  KnownSVal(const UndefinedVal &V) : SVal(V) {}
264 };
265 
266 class NonLoc : public DefinedSVal {
267 protected:
268  NonLoc() {}
269  explicit NonLoc(unsigned SubKind, const void *d)
270  : DefinedSVal(d, false, SubKind) {}
271 
272 public:
273  void dumpToStream(raw_ostream &Out) const;
274 
275 private:
276  friend class SVal;
277  static bool isKind(const SVal& V) {
278  return V.getBaseKind() == NonLocKind;
279  }
280 };
281 
282 class Loc : public DefinedSVal {
283 protected:
284  Loc() {}
285  explicit Loc(unsigned SubKind, const void *D)
286  : DefinedSVal(const_cast<void*>(D), true, SubKind) {}
287 
288 public:
289  void dumpToStream(raw_ostream &Out) const;
290 
291  static inline bool isLocType(QualType T) {
292  return T->isAnyPointerType() || T->isBlockPointerType() ||
293  T->isReferenceType() || T->isNullPtrType();
294  }
295 
296 private:
297  friend class SVal;
298  static bool isKind(const SVal& V) {
299  return V.getBaseKind() == LocKind;
300  }
301 };
302 
303 //==------------------------------------------------------------------------==//
304 // Subclasses of NonLoc.
305 //==------------------------------------------------------------------------==//
306 
307 namespace nonloc {
308 
311 
312 /// \brief Represents symbolic expression.
313 class SymbolVal : public NonLoc {
314 public:
316 
318  return (const SymExpr*) Data;
319  }
320 
321  bool isExpression() const {
322  return !isa<SymbolData>(getSymbol());
323  }
324 
325 private:
326  friend class SVal;
327  SymbolVal() {}
328  static bool isKind(const SVal& V) {
329  return V.getBaseKind() == NonLocKind &&
330  V.getSubKind() == SymbolValKind;
331  }
332 
333  static bool isKind(const NonLoc& V) {
334  return V.getSubKind() == SymbolValKind;
335  }
336 };
337 
338 /// \brief Value representing integer constant.
339 class ConcreteInt : public NonLoc {
340 public:
341  explicit ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {}
342 
343  const llvm::APSInt& getValue() const {
344  return *static_cast<const llvm::APSInt*>(Data);
345  }
346 
347  // Transfer functions for binary/unary operations on ConcreteInts.
349  const ConcreteInt& R) const;
350 
351  ConcreteInt evalComplement(SValBuilder &svalBuilder) const;
352 
353  ConcreteInt evalMinus(SValBuilder &svalBuilder) const;
354 
355 private:
356  friend class SVal;
357  ConcreteInt() {}
358  static bool isKind(const SVal& V) {
359  return V.getBaseKind() == NonLocKind &&
361  }
362 
363  static bool isKind(const NonLoc& V) {
364  return V.getSubKind() == ConcreteIntKind;
365  }
366 };
367 
368 class LocAsInteger : public NonLoc {
369  friend class ento::SValBuilder;
370 
371  explicit LocAsInteger(const std::pair<SVal, uintptr_t> &data)
372  : NonLoc(LocAsIntegerKind, &data) {
373  assert (data.first.getAs<Loc>());
374  }
375 
376 public:
377 
378  Loc getLoc() const {
379  const std::pair<SVal, uintptr_t> *D =
380  static_cast<const std::pair<SVal, uintptr_t> *>(Data);
381  return D->first.castAs<Loc>();
382  }
383 
385  const std::pair<SVal, uintptr_t> *D =
386  static_cast<const std::pair<SVal, uintptr_t> *>(Data);
387  const SVal& V = D->first;
388  return V.castAs<Loc>();
389  }
390 
391  unsigned getNumBits() const {
392  const std::pair<SVal, uintptr_t> *D =
393  static_cast<const std::pair<SVal, uintptr_t> *>(Data);
394  return D->second;
395  }
396 
397 private:
398  friend class SVal;
399  LocAsInteger() {}
400  static bool isKind(const SVal& V) {
401  return V.getBaseKind() == NonLocKind &&
403  }
404 
405  static bool isKind(const NonLoc& V) {
406  return V.getSubKind() == LocAsIntegerKind;
407  }
408 };
409 
410 class CompoundVal : public NonLoc {
411  friend class ento::SValBuilder;
412 
413  explicit CompoundVal(const CompoundValData* D) : NonLoc(CompoundValKind, D) {}
414 
415 public:
416  const CompoundValData* getValue() const {
417  return static_cast<const CompoundValData*>(Data);
418  }
419 
421  iterator begin() const;
422  iterator end() const;
423 
424 private:
425  friend class SVal;
426  CompoundVal() {}
427  static bool isKind(const SVal& V) {
428  return V.getBaseKind() == NonLocKind && V.getSubKind() == CompoundValKind;
429  }
430 
431  static bool isKind(const NonLoc& V) {
432  return V.getSubKind() == CompoundValKind;
433  }
434 };
435 
436 class LazyCompoundVal : public NonLoc {
437  friend class ento::SValBuilder;
438 
439  explicit LazyCompoundVal(const LazyCompoundValData *D)
440  : NonLoc(LazyCompoundValKind, D) {}
441 public:
443  return static_cast<const LazyCompoundValData*>(Data);
444  }
445  const void *getStore() const;
446  const TypedValueRegion *getRegion() const;
447 
448 private:
449  friend class SVal;
450  LazyCompoundVal() {}
451  static bool isKind(const SVal& V) {
452  return V.getBaseKind() == NonLocKind &&
454  }
455  static bool isKind(const NonLoc& V) {
456  return V.getSubKind() == LazyCompoundValKind;
457  }
458 };
459 
460 } // end namespace ento::nonloc
461 
462 //==------------------------------------------------------------------------==//
463 // Subclasses of Loc.
464 //==------------------------------------------------------------------------==//
465 
466 namespace loc {
467 
469 
470 class GotoLabel : public Loc {
471 public:
472  explicit GotoLabel(LabelDecl *Label) : Loc(GotoLabelKind, Label) {}
473 
474  const LabelDecl *getLabel() const {
475  return static_cast<const LabelDecl*>(Data);
476  }
477 
478 private:
479  friend class SVal;
480  GotoLabel() {}
481  static bool isKind(const SVal& V) {
482  return V.getBaseKind() == LocKind && V.getSubKind() == GotoLabelKind;
483  }
484 
485  static bool isKind(const Loc& V) {
486  return V.getSubKind() == GotoLabelKind;
487  }
488 };
489 
490 
491 class MemRegionVal : public Loc {
492 public:
493  explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {}
494 
495  /// \brief Get the underlining region.
496  const MemRegion* getRegion() const {
497  return static_cast<const MemRegion*>(Data);
498  }
499 
500  /// \brief Get the underlining region and strip casts.
501  const MemRegion* stripCasts(bool StripBaseCasts = true) const;
502 
503  template <typename REGION>
504  const REGION* getRegionAs() const {
505  return dyn_cast<REGION>(getRegion());
506  }
507 
508  inline bool operator==(const MemRegionVal& R) const {
509  return getRegion() == R.getRegion();
510  }
511 
512  inline bool operator!=(const MemRegionVal& R) const {
513  return getRegion() != R.getRegion();
514  }
515 
516 private:
517  friend class SVal;
518  MemRegionVal() {}
519  static bool isKind(const SVal& V) {
520  return V.getBaseKind() == LocKind &&
521  V.getSubKind() == MemRegionKind;
522  }
523 
524  static bool isKind(const Loc& V) {
525  return V.getSubKind() == MemRegionKind;
526  }
527 };
528 
529 class ConcreteInt : public Loc {
530 public:
531  explicit ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {}
532 
533  const llvm::APSInt& getValue() const {
534  return *static_cast<const llvm::APSInt*>(Data);
535  }
536 
537  // Transfer functions for binary/unary operations on ConcreteInts.
539  const ConcreteInt& R) const;
540 
541 private:
542  friend class SVal;
543  ConcreteInt() {}
544  static bool isKind(const SVal& V) {
545  return V.getBaseKind() == LocKind &&
547  }
548 
549  static bool isKind(const Loc& V) {
550  return V.getSubKind() == ConcreteIntKind;
551  }
552 };
553 
554 } // end ento::loc namespace
555 
556 } // end ento namespace
557 
558 } // end clang namespace
559 
560 namespace llvm {
561 static inline raw_ostream &operator<<(raw_ostream &os,
562  clang::ento::SVal V) {
563  V.dumpToStream(os);
564  return os;
565 }
566 
567 template <typename T> struct isPodLike;
568 template <> struct isPodLike<clang::ento::SVal> {
569  static const bool value = true;
570 };
571 
572 } // end llvm namespace
573 
574 #endif
KnownSVal(const UndefinedVal &V)
Definition: SVals.h:263
void Profile(llvm::FoldingSetNodeID &ID) const
Definition: SVals.h:104
const SymExpr * getAsSymExpr() const
Definition: SVals.cpp:128
TypedValueRegion - An abstract class representing regions having a typed value.
Definition: MemRegion.h:498
bool hasConjuredSymbol() const
hasConjuredSymbol - If this SVal wraps a conjured symbol, return true;
Definition: SVals.cpp:32
bool isNullPtrType() const
Definition: Type.h:5439
MemRegion - The root abstract class for all memory regions.
Definition: MemRegion.h:77
SVal(BaseKind k, const void *D=nullptr)
Definition: SVals.h:66
bool operator==(const SVal &R) const
Definition: SVals.h:109
const MemRegion * stripCasts(bool StripBaseCasts=true) const
Get the underlining region and strip casts.
Definition: SVals.cpp:145
bool operator==(const MemRegionVal &R) const
Definition: SVals.h:508
DefinedOrUnknownSVal(const void *d, bool isLoc, unsigned ValKind)
Definition: SVals.h:211
SVal(const void *d, bool isLoc, unsigned ValKind)
Definition: SVals.h:63
void dumpToStream(raw_ostream &Out) const
Definition: SVals.cpp:258
SymbolRef getLocSymbolInBase() const
Get the symbol in the SVal or its base region.
Definition: SVals.cpp:85
Loc(unsigned SubKind, const void *D)
Definition: SVals.h:285
bool isBlockPointerType() const
Definition: Type.h:5238
Value representing integer constant.
Definition: SVals.h:339
bool isZeroConstant() const
Definition: SVals.cpp:186
Symbolic value. These values used to capture symbolic execution of the program.
Definition: SymbolManager.h:42
bool operator!=(const SVal &R) const
Definition: SVals.h:113
bool isReferenceType() const
Definition: Type.h:5241
bool isAnyPointerType() const
Definition: Type.h:5235
BaseKind getBaseKind() const
Definition: SVals.h:99
ConcreteInt(const llvm::APSInt &V)
Definition: SVals.h:341
SymbolRef getAsLocSymbol(bool IncludeBaseRegions=false) const
If this SVal is a location and wraps a symbol, return that SymbolRef. Otherwise return 0...
Definition: SVals.cpp:69
SVal evalBinOp(BasicValueFactory &BasicVals, BinaryOperator::Opcode Op, const ConcreteInt &R) const
Definition: SVals.cpp:221
const FunctionDecl * getAsFunctionDecl() const
Definition: SVals.cpp:51
void dump() const
Definition: SVals.cpp:239
static bool isLocType(QualType T)
Definition: SVals.h:291
BinaryOperatorKind
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
SymbolVal(SymbolRef sym)
Definition: SVals.h:315
bool isUnknownOrUndef() const
Definition: SVals.h:125
SymExpr::symbol_iterator symbol_begin() const
Definition: SVals.h:177
const CompoundValData * getValue() const
Definition: SVals.h:416
unsigned getNumBits() const
Definition: SVals.h:391
bool isConstant() const
Definition: SVals.cpp:174
bool isValid() const
Definition: SVals.h:129
const void * Data
Definition: SVals.h:57
KnownSVal(const DefinedSVal &V)
Definition: SVals.h:262
llvm::ImmutableList< SVal >::iterator iterator
Definition: SVals.h:420
ID
Defines the set of possible language-specific address spaces.
Definition: AddressSpaces.h:27
unsigned getRawKind() const
Definition: SVals.h:98
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
Definition: SVals.h:86
MemRegionVal(const MemRegion *r)
Definition: SVals.h:493
unsigned Kind
Definition: SVals.h:61
const LazyCompoundValData * getCVData() const
Definition: SVals.h:442
#define false
Definition: stdbool.h:33
Kind
NonLoc(unsigned SubKind, const void *d)
Definition: SVals.h:269
SVal evalBinOp(SValBuilder &svalBuilder, BinaryOperator::Opcode Op, const ConcreteInt &R) const
Definition: SVals.cpp:195
const REGION * getRegionAs() const
Definition: SVals.h:504
void dumpToStream(raw_ostream &Out) const
Definition: SVals.cpp:308
SymExpr::symbol_iterator symbol_end() const
Definition: SVals.h:185
SymbolRef getSymbol() const
Definition: SVals.h:317
bool isUndef() const
Definition: SVals.h:121
ConcreteInt evalMinus(SValBuilder &svalBuilder) const
Definition: SVals.cpp:213
DefinedOrUnknownSVal(BaseKind k, void *D=nullptr)
Definition: SVals.h:214
GotoLabel(LabelDecl *Label)
Definition: SVals.h:472
unsigned getSubKind() const
Definition: SVals.h:100
const llvm::APSInt & getValue() const
Definition: SVals.h:533
SmallVector< SVal, 5 > BufferTy
BufferTy - A temporary buffer to hold a set of SVals.
Definition: SVals.h:96
const LabelDecl * getLabel() const
Definition: SVals.h:474
static symbol_iterator symbol_end()
Definition: SymbolManager.h:93
DefinedSVal(const void *d, bool isLoc, unsigned ValKind)
Definition: SVals.h:244
bool isExpression() const
Definition: SVals.h:321
Represents symbolic expression.
Definition: SVals.h:313
const MemRegion * getAsRegion() const
Definition: SVals.cpp:135
Represents an SVal that is guaranteed to not be UnknownVal.
Definition: SVals.h:255
ConcreteInt evalComplement(SValBuilder &svalBuilder) const
Definition: SVals.cpp:208
bool isUnknown() const
Definition: SVals.h:117
const TypedValueRegion * getRegion() const
Definition: SVals.cpp:154
static raw_ostream & operator<<(raw_ostream &os, const clang::ento::MemRegion *R)
Definition: MemRegion.h:1357
void dumpToStream(raw_ostream &OS) const
Definition: SVals.cpp:241
bool operator!=(const MemRegionVal &R) const
Definition: SVals.h:512
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef. Otherwise, return 0.
Definition: SVals.cpp:111
symbol_iterator symbol_begin() const
Definition: SymbolManager.h:90
const SymExpr * getAsSymbolicExpression() const
Definition: SVals.cpp:121
iterator begin() const
Definition: SVals.cpp:162
#define true
Definition: stdbool.h:32
ConcreteInt(const llvm::APSInt &V)
Definition: SVals.h:531
const llvm::APSInt & getValue() const
Definition: SVals.h:343
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
Definition: SVals.h:75
const MemRegion * getRegion() const
Get the underlining region.
Definition: SVals.h:496
Iterator over symbols that the current symbol depends on.
Definition: SymbolManager.h:76
const void * getStore() const
Definition: SVals.cpp:150