Home | History | Annotate | Download | only in PathSensitive
      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/Basic/LLVM.h"
     19 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
     20 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.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 = NULL)
     67     : Data(D), Kind(k) {}
     68 
     69 public:
     70   explicit SVal() : Data(0), 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.
     96   typedef SmallVector<SVal,5> BufferTy;
     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.
    156   SymbolRef getLocSymbolInBase() const;
    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 
    177   SymExpr::symbol_iterator symbol_begin() const {
    178     const SymExpr *SE = getAsSymbolicExpression();
    179     if (SE)
    180       return SE->symbol_begin();
    181     else
    182       return SymExpr::symbol_iterator();
    183   }
    184 
    185   SymExpr::symbol_iterator symbol_end() const {
    186     return SymExpr::symbol_end();
    187   }
    188 };
    189 
    190 
    191 class UndefinedVal : public SVal {
    192 public:
    193   UndefinedVal() : SVal(UndefinedKind) {}
    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 LLVM_DELETED_FUNCTION;
    207   bool isValid() const LLVM_DELETED_FUNCTION;
    208 
    209 protected:
    210   DefinedOrUnknownSVal() {}
    211   explicit DefinedOrUnknownSVal(const void *d, bool isLoc, unsigned ValKind)
    212     : SVal(d, isLoc, ValKind) {}
    213 
    214   explicit DefinedOrUnknownSVal(BaseKind k, void *D = NULL)
    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 
    224 class UnknownVal : public DefinedOrUnknownSVal {
    225 public:
    226   explicit UnknownVal() : DefinedOrUnknownSVal(UnknownKind) {}
    227 
    228 private:
    229   friend class SVal;
    230   static bool isKind(const SVal &V) {
    231     return V.getBaseKind() == UnknownKind;
    232   }
    233 };
    234 
    235 class DefinedSVal : public DefinedOrUnknownSVal {
    236 private:
    237   // We want calling these methods to be a compiler error since they are
    238   // tautologically true/false.
    239   bool isUnknown() const LLVM_DELETED_FUNCTION;
    240   bool isUnknownOrUndef() const LLVM_DELETED_FUNCTION;
    241   bool isValid() const LLVM_DELETED_FUNCTION;
    242 protected:
    243   DefinedSVal() {}
    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 
    309 enum Kind { ConcreteIntKind, SymbolValKind,
    310             LocAsIntegerKind, CompoundValKind, LazyCompoundValKind };
    311 
    312 /// \brief Represents symbolic expression.
    313 class SymbolVal : public NonLoc {
    314 public:
    315   SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) {}
    316 
    317   SymbolRef getSymbol() const {
    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.
    348   SVal evalBinOp(SValBuilder &svalBuilder, BinaryOperator::Opcode Op,
    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 &&
    360            V.getSubKind() == ConcreteIntKind;
    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 
    384   Loc getPersistentLoc() const {
    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 &&
    402            V.getSubKind() == LocAsIntegerKind;
    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 
    420   typedef llvm::ImmutableList<SVal>::iterator iterator;
    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:
    442   const LazyCompoundValData *getCVData() const {
    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 &&
    453            V.getSubKind() == LazyCompoundValKind;
    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 
    468 enum Kind { GotoLabelKind, MemRegionKind, ConcreteIntKind };
    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.
    538   SVal evalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
    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 &&
    546            V.getSubKind() == ConcreteIntKind;
    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
    575