• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_GR_RVALUE_H
16 #define LLVM_CLANG_GR_RVALUE_H
17 
18 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
19 #include "llvm/Support/Casting.h"
20 #include "llvm/ADT/ImmutableList.h"
21 
22 namespace llvm {
23   class raw_ostream;
24 }
25 
26 //==------------------------------------------------------------------------==//
27 //  Base SVal types.
28 //==------------------------------------------------------------------------==//
29 
30 namespace clang {
31 
32 namespace ento {
33 
34 class CompoundValData;
35 class LazyCompoundValData;
36 class GRState;
37 class BasicValueFactory;
38 class MemRegion;
39 class TypedRegion;
40 class MemRegionManager;
41 class GRStateManager;
42 class SValBuilder;
43 
44 /// SVal - This represents a symbolic expression, which can be either
45 ///  an L-value or an R-value.
46 ///
47 class SVal {
48 public:
49   enum BaseKind {
50     // The enumerators must be representable using 2 bits.
51     UndefinedKind = 0,  // for subclass UndefinedVal (an uninitialized value)
52     UnknownKind = 1,    // for subclass UnknownVal (a void value)
53     LocKind = 2,        // for subclass Loc (an L-value)
54     NonLocKind = 3      // for subclass NonLoc (an R-value that's not
55                         //   an L-value)
56   };
57   enum { BaseBits = 2, BaseMask = 0x3 };
58 
59 protected:
60   const void* Data;
61 
62   /// The lowest 2 bits are a BaseKind (0 -- 3).
63   ///  The higher bits are an unsigned "kind" value.
64   unsigned Kind;
65 
SVal(const void * d,bool isLoc,unsigned ValKind)66   explicit SVal(const void* d, bool isLoc, unsigned ValKind)
67   : Data(d), Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {}
68 
69   explicit SVal(BaseKind k, const void* D = NULL)
Data(D)70     : Data(D), Kind(k) {}
71 
72 public:
SVal()73   explicit SVal() : Data(0), Kind(0) {}
~SVal()74   ~SVal() {}
75 
76   /// BufferTy - A temporary buffer to hold a set of SVals.
77   typedef llvm::SmallVector<SVal,5> BufferTy;
78 
getRawKind()79   inline unsigned getRawKind() const { return Kind; }
getBaseKind()80   inline BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
getSubKind()81   inline unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; }
82 
83   // This method is required for using SVal in a FoldingSetNode.  It
84   // extracts a unique signature for this SVal object.
Profile(llvm::FoldingSetNodeID & ID)85   inline void Profile(llvm::FoldingSetNodeID& ID) const {
86     ID.AddInteger((unsigned) getRawKind());
87     ID.AddPointer(Data);
88   }
89 
90   inline bool operator==(const SVal& R) const {
91     return getRawKind() == R.getRawKind() && Data == R.Data;
92   }
93 
94   inline bool operator!=(const SVal& R) const {
95     return !(*this == R);
96   }
97 
isUnknown()98   inline bool isUnknown() const {
99     return getRawKind() == UnknownKind;
100   }
101 
isUndef()102   inline bool isUndef() const {
103     return getRawKind() == UndefinedKind;
104   }
105 
isUnknownOrUndef()106   inline bool isUnknownOrUndef() const {
107     return getRawKind() <= UnknownKind;
108   }
109 
isValid()110   inline bool isValid() const {
111     return getRawKind() > UnknownKind;
112   }
113 
114   bool isConstant() const;
115 
116   bool isConstant(int I) const;
117 
118   bool isZeroConstant() const;
119 
120   /// hasConjuredSymbol - If this SVal wraps a conjured symbol, return true;
121   bool hasConjuredSymbol() const;
122 
123   /// getAsFunctionDecl - If this SVal is a MemRegionVal and wraps a
124   /// CodeTextRegion wrapping a FunctionDecl, return that FunctionDecl.
125   /// Otherwise return 0.
126   const FunctionDecl* getAsFunctionDecl() const;
127 
128   /// getAsLocSymbol - If this SVal is a location (subclasses Loc) and
129   ///  wraps a symbol, return that SymbolRef.  Otherwise return NULL.
130   SymbolRef getAsLocSymbol() const;
131 
132   /// Get the symbol in the SVal or its base region.
133   SymbolRef getLocSymbolInBase() const;
134 
135   /// getAsSymbol - If this Sval wraps a symbol return that SymbolRef.
136   ///  Otherwise return a SymbolRef where 'isValid()' returns false.
137   SymbolRef getAsSymbol() const;
138 
139   /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
140   ///  return that expression.  Otherwise return NULL.
141   const SymExpr *getAsSymbolicExpression() const;
142 
143   const MemRegion *getAsRegion() const;
144 
145   void dumpToStream(llvm::raw_ostream& OS) const;
146   void dump() const;
147 
148   // Iterators.
149   class symbol_iterator {
150     llvm::SmallVector<const SymExpr*, 5> itr;
151     void expand();
152   public:
symbol_iterator()153     symbol_iterator() {}
154     symbol_iterator(const SymExpr* SE);
155 
156     symbol_iterator& operator++();
157     SymbolRef operator*();
158 
159     bool operator==(const symbol_iterator& X) const;
160     bool operator!=(const symbol_iterator& X) const;
161   };
162 
symbol_begin()163   symbol_iterator symbol_begin() const {
164     const SymExpr *SE = getAsSymbolicExpression();
165     if (SE)
166       return symbol_iterator(SE);
167     else
168       return symbol_iterator();
169   }
170 
symbol_end()171   symbol_iterator symbol_end() const { return symbol_iterator(); }
172 
173   // Implement isa<T> support.
classof(const SVal *)174   static inline bool classof(const SVal*) { return true; }
175 };
176 
177 
178 class UndefinedVal : public SVal {
179 public:
UndefinedVal()180   UndefinedVal() : SVal(UndefinedKind) {}
UndefinedVal(const void * D)181   UndefinedVal(const void* D) : SVal(UndefinedKind, D) {}
182 
classof(const SVal * V)183   static inline bool classof(const SVal* V) {
184     return V->getBaseKind() == UndefinedKind;
185   }
186 
getData()187   const void* getData() const { return Data; }
188 };
189 
190 class DefinedOrUnknownSVal : public SVal {
191 private:
192   // Do not implement.  We want calling these methods to be a compiler
193   // error since they are tautologically false.
194   bool isUndef() const;
195   bool isValid() const;
196 
197 protected:
DefinedOrUnknownSVal(const void * d,bool isLoc,unsigned ValKind)198   explicit DefinedOrUnknownSVal(const void* d, bool isLoc, unsigned ValKind)
199     : SVal(d, isLoc, ValKind) {}
200 
201   explicit DefinedOrUnknownSVal(BaseKind k, void *D = NULL)
SVal(k,D)202     : SVal(k, D) {}
203 
204 public:
205     // Implement isa<T> support.
classof(const SVal * V)206   static inline bool classof(const SVal *V) {
207     return !V->isUndef();
208   }
209 };
210 
211 class UnknownVal : public DefinedOrUnknownSVal {
212 public:
UnknownVal()213   explicit UnknownVal() : DefinedOrUnknownSVal(UnknownKind) {}
214 
classof(const SVal * V)215   static inline bool classof(const SVal *V) {
216     return V->getBaseKind() == UnknownKind;
217   }
218 };
219 
220 class DefinedSVal : public DefinedOrUnknownSVal {
221 private:
222   // Do not implement.  We want calling these methods to be a compiler
223   // error since they are tautologically true/false.
224   bool isUnknown() const;
225   bool isUnknownOrUndef() const;
226   bool isValid() const;
227 protected:
DefinedSVal(const void * d,bool isLoc,unsigned ValKind)228   explicit DefinedSVal(const void* d, bool isLoc, unsigned ValKind)
229     : DefinedOrUnknownSVal(d, isLoc, ValKind) {}
230 public:
231   // Implement isa<T> support.
classof(const SVal * V)232   static inline bool classof(const SVal *V) {
233     return !V->isUnknownOrUndef();
234   }
235 };
236 
237 class NonLoc : public DefinedSVal {
238 protected:
NonLoc(unsigned SubKind,const void * d)239   explicit NonLoc(unsigned SubKind, const void* d)
240     : DefinedSVal(d, false, SubKind) {}
241 
242 public:
243   void dumpToStream(llvm::raw_ostream& Out) const;
244 
245   // Implement isa<T> support.
classof(const SVal * V)246   static inline bool classof(const SVal* V) {
247     return V->getBaseKind() == NonLocKind;
248   }
249 };
250 
251 class Loc : public DefinedSVal {
252 protected:
Loc(unsigned SubKind,const void * D)253   explicit Loc(unsigned SubKind, const void* D)
254   : DefinedSVal(const_cast<void*>(D), true, SubKind) {}
255 
256 public:
257   void dumpToStream(llvm::raw_ostream& Out) const;
258 
Loc(const Loc & X)259   Loc(const Loc& X) : DefinedSVal(X.Data, true, X.getSubKind()) {}
260 
261   // Implement isa<T> support.
classof(const SVal * V)262   static inline bool classof(const SVal* V) {
263     return V->getBaseKind() == LocKind;
264   }
265 
isLocType(QualType T)266   static inline bool isLocType(QualType T) {
267     return T->isAnyPointerType() || T->isBlockPointerType() ||
268            T->isReferenceType();
269   }
270 };
271 
272 //==------------------------------------------------------------------------==//
273 //  Subclasses of NonLoc.
274 //==------------------------------------------------------------------------==//
275 
276 namespace nonloc {
277 
278 enum Kind { ConcreteIntKind, SymbolValKind, SymExprValKind,
279             LocAsIntegerKind, CompoundValKind, LazyCompoundValKind };
280 
281 class SymbolVal : public NonLoc {
282 public:
SymbolVal(SymbolRef sym)283   SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) {}
284 
getSymbol()285   SymbolRef getSymbol() const {
286     return (const SymbolData*) Data;
287   }
288 
classof(const SVal * V)289   static inline bool classof(const SVal* V) {
290     return V->getBaseKind() == NonLocKind &&
291            V->getSubKind() == SymbolValKind;
292   }
293 
classof(const NonLoc * V)294   static inline bool classof(const NonLoc* V) {
295     return V->getSubKind() == SymbolValKind;
296   }
297 };
298 
299 class SymExprVal : public NonLoc {
300 public:
SymExprVal(const SymExpr * SE)301   explicit SymExprVal(const SymExpr *SE)
302     : NonLoc(SymExprValKind, reinterpret_cast<const void*>(SE)) {}
303 
getSymbolicExpression()304   const SymExpr *getSymbolicExpression() const {
305     return reinterpret_cast<const SymExpr*>(Data);
306   }
307 
classof(const SVal * V)308   static inline bool classof(const SVal* V) {
309     return V->getBaseKind() == NonLocKind &&
310            V->getSubKind() == SymExprValKind;
311   }
312 
classof(const NonLoc * V)313   static inline bool classof(const NonLoc* V) {
314     return V->getSubKind() == SymExprValKind;
315   }
316 };
317 
318 class ConcreteInt : public NonLoc {
319 public:
ConcreteInt(const llvm::APSInt & V)320   explicit ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {}
321 
getValue()322   const llvm::APSInt& getValue() const {
323     return *static_cast<const llvm::APSInt*>(Data);
324   }
325 
326   // Transfer functions for binary/unary operations on ConcreteInts.
327   SVal evalBinOp(SValBuilder &svalBuilder, BinaryOperator::Opcode Op,
328                  const ConcreteInt& R) const;
329 
330   ConcreteInt evalComplement(SValBuilder &svalBuilder) const;
331 
332   ConcreteInt evalMinus(SValBuilder &svalBuilder) const;
333 
334   // Implement isa<T> support.
classof(const SVal * V)335   static inline bool classof(const SVal* V) {
336     return V->getBaseKind() == NonLocKind &&
337            V->getSubKind() == ConcreteIntKind;
338   }
339 
classof(const NonLoc * V)340   static inline bool classof(const NonLoc* V) {
341     return V->getSubKind() == ConcreteIntKind;
342   }
343 };
344 
345 class LocAsInteger : public NonLoc {
346   friend class ento::SValBuilder;
347 
LocAsInteger(const std::pair<SVal,uintptr_t> & data)348   explicit LocAsInteger(const std::pair<SVal, uintptr_t>& data) :
349     NonLoc(LocAsIntegerKind, &data) {
350       assert (isa<Loc>(data.first));
351     }
352 
353 public:
354 
getLoc()355   Loc getLoc() const {
356     return cast<Loc>(((std::pair<SVal, uintptr_t>*) Data)->first);
357   }
358 
getPersistentLoc()359   const Loc& getPersistentLoc() const {
360     const SVal& V = ((std::pair<SVal, uintptr_t>*) Data)->first;
361     return cast<Loc>(V);
362   }
363 
getNumBits()364   unsigned getNumBits() const {
365     return ((std::pair<SVal, unsigned>*) Data)->second;
366   }
367 
368   // Implement isa<T> support.
classof(const SVal * V)369   static inline bool classof(const SVal* V) {
370     return V->getBaseKind() == NonLocKind &&
371            V->getSubKind() == LocAsIntegerKind;
372   }
373 
classof(const NonLoc * V)374   static inline bool classof(const NonLoc* V) {
375     return V->getSubKind() == LocAsIntegerKind;
376   }
377 };
378 
379 class CompoundVal : public NonLoc {
380   friend class ento::SValBuilder;
381 
CompoundVal(const CompoundValData * D)382   explicit CompoundVal(const CompoundValData* D) : NonLoc(CompoundValKind, D) {}
383 
384 public:
getValue()385   const CompoundValData* getValue() const {
386     return static_cast<const CompoundValData*>(Data);
387   }
388 
389   typedef llvm::ImmutableList<SVal>::iterator iterator;
390   iterator begin() const;
391   iterator end() const;
392 
classof(const SVal * V)393   static bool classof(const SVal* V) {
394     return V->getBaseKind() == NonLocKind && V->getSubKind() == CompoundValKind;
395   }
396 
classof(const NonLoc * V)397   static bool classof(const NonLoc* V) {
398     return V->getSubKind() == CompoundValKind;
399   }
400 };
401 
402 class LazyCompoundVal : public NonLoc {
403   friend class ento::SValBuilder;
404 
LazyCompoundVal(const LazyCompoundValData * D)405   explicit LazyCompoundVal(const LazyCompoundValData *D)
406     : NonLoc(LazyCompoundValKind, D) {}
407 public:
getCVData()408   const LazyCompoundValData *getCVData() const {
409     return static_cast<const LazyCompoundValData*>(Data);
410   }
411   const void *getStore() const;
412   const TypedRegion *getRegion() const;
413 
classof(const SVal * V)414   static bool classof(const SVal *V) {
415     return V->getBaseKind() == NonLocKind &&
416            V->getSubKind() == LazyCompoundValKind;
417   }
classof(const NonLoc * V)418   static bool classof(const NonLoc *V) {
419     return V->getSubKind() == LazyCompoundValKind;
420   }
421 };
422 
423 } // end namespace ento::nonloc
424 
425 //==------------------------------------------------------------------------==//
426 //  Subclasses of Loc.
427 //==------------------------------------------------------------------------==//
428 
429 namespace loc {
430 
431 enum Kind { GotoLabelKind, MemRegionKind, ConcreteIntKind, ObjCPropRefKind };
432 
433 class GotoLabel : public Loc {
434 public:
GotoLabel(LabelDecl * Label)435   explicit GotoLabel(LabelDecl *Label) : Loc(GotoLabelKind, Label) {}
436 
getLabel()437   const LabelDecl *getLabel() const {
438     return static_cast<const LabelDecl*>(Data);
439   }
440 
classof(const SVal * V)441   static inline bool classof(const SVal* V) {
442     return V->getBaseKind() == LocKind && V->getSubKind() == GotoLabelKind;
443   }
444 
classof(const Loc * V)445   static inline bool classof(const Loc* V) {
446     return V->getSubKind() == GotoLabelKind;
447   }
448 };
449 
450 
451 class MemRegionVal : public Loc {
452 public:
MemRegionVal(const MemRegion * r)453   explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {}
454 
getRegion()455   const MemRegion* getRegion() const {
456     return static_cast<const MemRegion*>(Data);
457   }
458 
459   const MemRegion* stripCasts() const;
460 
461   template <typename REGION>
getRegionAs()462   const REGION* getRegionAs() const {
463     return llvm::dyn_cast<REGION>(getRegion());
464   }
465 
466   inline bool operator==(const MemRegionVal& R) const {
467     return getRegion() == R.getRegion();
468   }
469 
470   inline bool operator!=(const MemRegionVal& R) const {
471     return getRegion() != R.getRegion();
472   }
473 
474   // Implement isa<T> support.
classof(const SVal * V)475   static inline bool classof(const SVal* V) {
476     return V->getBaseKind() == LocKind &&
477            V->getSubKind() == MemRegionKind;
478   }
479 
classof(const Loc * V)480   static inline bool classof(const Loc* V) {
481     return V->getSubKind() == MemRegionKind;
482   }
483 };
484 
485 class ConcreteInt : public Loc {
486 public:
ConcreteInt(const llvm::APSInt & V)487   explicit ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {}
488 
getValue()489   const llvm::APSInt& getValue() const {
490     return *static_cast<const llvm::APSInt*>(Data);
491   }
492 
493   // Transfer functions for binary/unary operations on ConcreteInts.
494   SVal evalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
495                  const ConcreteInt& R) const;
496 
497   // Implement isa<T> support.
classof(const SVal * V)498   static inline bool classof(const SVal* V) {
499     return V->getBaseKind() == LocKind &&
500            V->getSubKind() == ConcreteIntKind;
501   }
502 
classof(const Loc * V)503   static inline bool classof(const Loc* V) {
504     return V->getSubKind() == ConcreteIntKind;
505   }
506 };
507 
508 /// \brief Pseudo-location SVal used by the ExprEngine to simulate a "load" or
509 /// "store" of an ObjC property for the dot syntax.
510 class ObjCPropRef : public Loc {
511 public:
ObjCPropRef(const ObjCPropertyRefExpr * E)512   explicit ObjCPropRef(const ObjCPropertyRefExpr *E)
513     : Loc(ObjCPropRefKind, E) {}
514 
getPropRefExpr()515   const ObjCPropertyRefExpr *getPropRefExpr() const {
516     return static_cast<const ObjCPropertyRefExpr *>(Data);
517   }
518 
519   // Implement isa<T> support.
classof(const SVal * V)520   static inline bool classof(const SVal* V) {
521     return V->getBaseKind() == LocKind &&
522            V->getSubKind() == ObjCPropRefKind;
523   }
524 
classof(const Loc * V)525   static inline bool classof(const Loc* V) {
526     return V->getSubKind() == ObjCPropRefKind;
527   }
528 };
529 
530 } // end ento::loc namespace
531 } // end GR namespace
532 
533 } // end clang namespace
534 
535 namespace llvm {
536 static inline llvm::raw_ostream& operator<<(llvm::raw_ostream& os,
537                                             clang::ento::SVal V) {
538   V.dumpToStream(os);
539   return os;
540 }
541 
542 } // end llvm namespace
543 
544 #endif
545