clang API Documentation

SVals.h
Go to the documentation of this file.
00001 //== SVals.h - Abstract Values for Static Analysis ---------*- C++ -*--==//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 //  This file defines SVal, Loc, and NonLoc, classes that represent
00011 //  abstract r-values for use with path-sensitive value tracking.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H
00016 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H
00017 
00018 #include "clang/Basic/LLVM.h"
00019 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
00020 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
00021 #include "llvm/ADT/ImmutableList.h"
00022 
00023 //==------------------------------------------------------------------------==//
00024 //  Base SVal types.
00025 //==------------------------------------------------------------------------==//
00026 
00027 namespace clang {
00028 
00029 namespace ento {
00030 
00031 class CompoundValData;
00032 class LazyCompoundValData;
00033 class ProgramState;
00034 class BasicValueFactory;
00035 class MemRegion;
00036 class TypedValueRegion;
00037 class MemRegionManager;
00038 class ProgramStateManager;
00039 class SValBuilder;
00040 
00041 /// SVal - This represents a symbolic expression, which can be either
00042 ///  an L-value or an R-value.
00043 ///
00044 class SVal {
00045 public:
00046   enum BaseKind {
00047     // The enumerators must be representable using 2 bits.
00048     UndefinedKind = 0,  // for subclass UndefinedVal (an uninitialized value)
00049     UnknownKind = 1,    // for subclass UnknownVal (a void value)
00050     LocKind = 2,        // for subclass Loc (an L-value)
00051     NonLocKind = 3      // for subclass NonLoc (an R-value that's not
00052                         //   an L-value)
00053   };
00054   enum { BaseBits = 2, BaseMask = 0x3 };
00055 
00056 protected:
00057   const void *Data;
00058 
00059   /// The lowest 2 bits are a BaseKind (0 -- 3).
00060   ///  The higher bits are an unsigned "kind" value.
00061   unsigned Kind;
00062 
00063   explicit SVal(const void *d, bool isLoc, unsigned ValKind)
00064   : Data(d), Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {}
00065 
00066   explicit SVal(BaseKind k, const void *D = nullptr)
00067     : Data(D), Kind(k) {}
00068 
00069 public:
00070   explicit SVal() : Data(nullptr), Kind(0) {}
00071 
00072   /// \brief Convert to the specified SVal type, asserting that this SVal is of
00073   /// the desired type.
00074   template<typename T>
00075   T castAs() const {
00076     assert(T::isKind(*this));
00077     T t;
00078     SVal& sv = t;
00079     sv = *this;
00080     return t;
00081   }
00082 
00083   /// \brief Convert to the specified SVal type, returning None if this SVal is
00084   /// not of the desired type.
00085   template<typename T>
00086   Optional<T> getAs() const {
00087     if (!T::isKind(*this))
00088       return None;
00089     T t;
00090     SVal& sv = t;
00091     sv = *this;
00092     return t;
00093   }
00094 
00095   /// BufferTy - A temporary buffer to hold a set of SVals.
00096   typedef SmallVector<SVal,5> BufferTy;
00097 
00098   inline unsigned getRawKind() const { return Kind; }
00099   inline BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
00100   inline unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; }
00101 
00102   // This method is required for using SVal in a FoldingSetNode.  It
00103   // extracts a unique signature for this SVal object.
00104   inline void Profile(llvm::FoldingSetNodeID& ID) const {
00105     ID.AddInteger((unsigned) getRawKind());
00106     ID.AddPointer(Data);
00107   }
00108 
00109   inline bool operator==(const SVal& R) const {
00110     return getRawKind() == R.getRawKind() && Data == R.Data;
00111   }
00112 
00113   inline bool operator!=(const SVal& R) const {
00114     return !(*this == R);
00115   }
00116 
00117   inline bool isUnknown() const {
00118     return getRawKind() == UnknownKind;
00119   }
00120 
00121   inline bool isUndef() const {
00122     return getRawKind() == UndefinedKind;
00123   }
00124 
00125   inline bool isUnknownOrUndef() const {
00126     return getRawKind() <= UnknownKind;
00127   }
00128 
00129   inline bool isValid() const {
00130     return getRawKind() > UnknownKind;
00131   }
00132 
00133   bool isConstant() const;
00134 
00135   bool isConstant(int I) const;
00136 
00137   bool isZeroConstant() const;
00138 
00139   /// hasConjuredSymbol - If this SVal wraps a conjured symbol, return true;
00140   bool hasConjuredSymbol() const;
00141 
00142   /// getAsFunctionDecl - If this SVal is a MemRegionVal and wraps a
00143   /// CodeTextRegion wrapping a FunctionDecl, return that FunctionDecl.
00144   /// Otherwise return 0.
00145   const FunctionDecl *getAsFunctionDecl() const;
00146 
00147   /// \brief If this SVal is a location and wraps a symbol, return that
00148   ///  SymbolRef. Otherwise return 0.
00149   ///
00150   /// Casts are ignored during lookup.
00151   /// \param IncludeBaseRegions The boolean that controls whether the search
00152   /// should continue to the base regions if the region is not symbolic.
00153   SymbolRef getAsLocSymbol(bool IncludeBaseRegions = false) const;
00154 
00155   /// Get the symbol in the SVal or its base region.
00156   SymbolRef getLocSymbolInBase() const;
00157 
00158   /// \brief If this SVal wraps a symbol return that SymbolRef.
00159   /// Otherwise, return 0.
00160   ///
00161   /// Casts are ignored during lookup.
00162   /// \param IncludeBaseRegions The boolean that controls whether the search
00163   /// should continue to the base regions if the region is not symbolic.
00164   SymbolRef getAsSymbol(bool IncludeBaseRegions = false) const;
00165 
00166   /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
00167   ///  return that expression.  Otherwise return NULL.
00168   const SymExpr *getAsSymbolicExpression() const;
00169 
00170   const SymExpr* getAsSymExpr() const;
00171 
00172   const MemRegion *getAsRegion() const;
00173 
00174   void dumpToStream(raw_ostream &OS) const;
00175   void dump() const;
00176 
00177   SymExpr::symbol_iterator symbol_begin() const {
00178     const SymExpr *SE = getAsSymbolicExpression();
00179     if (SE)
00180       return SE->symbol_begin();
00181     else
00182       return SymExpr::symbol_iterator();
00183   }
00184 
00185   SymExpr::symbol_iterator symbol_end() const { 
00186     return SymExpr::symbol_end();
00187   }
00188 };
00189 
00190 
00191 class UndefinedVal : public SVal {
00192 public:
00193   UndefinedVal() : SVal(UndefinedKind) {}
00194 
00195 private:
00196   friend class SVal;
00197   static bool isKind(const SVal& V) {
00198     return V.getBaseKind() == UndefinedKind;
00199   }
00200 };
00201 
00202 class DefinedOrUnknownSVal : public SVal {
00203 private:
00204   // We want calling these methods to be a compiler error since they are
00205   // tautologically false.
00206   bool isUndef() const LLVM_DELETED_FUNCTION;
00207   bool isValid() const LLVM_DELETED_FUNCTION;
00208   
00209 protected:
00210   DefinedOrUnknownSVal() {}
00211   explicit DefinedOrUnknownSVal(const void *d, bool isLoc, unsigned ValKind)
00212     : SVal(d, isLoc, ValKind) {}
00213   
00214   explicit DefinedOrUnknownSVal(BaseKind k, void *D = nullptr)
00215     : SVal(k, D) {}
00216   
00217 private:
00218   friend class SVal;
00219   static bool isKind(const SVal& V) {
00220     return !V.isUndef();
00221   }
00222 };
00223   
00224 class UnknownVal : public DefinedOrUnknownSVal {
00225 public:
00226   explicit UnknownVal() : DefinedOrUnknownSVal(UnknownKind) {}
00227   
00228 private:
00229   friend class SVal;
00230   static bool isKind(const SVal &V) {
00231     return V.getBaseKind() == UnknownKind;
00232   }
00233 };
00234 
00235 class DefinedSVal : public DefinedOrUnknownSVal {
00236 private:
00237   // We want calling these methods to be a compiler error since they are
00238   // tautologically true/false.
00239   bool isUnknown() const LLVM_DELETED_FUNCTION;
00240   bool isUnknownOrUndef() const LLVM_DELETED_FUNCTION;
00241   bool isValid() const LLVM_DELETED_FUNCTION;
00242 protected:
00243   DefinedSVal() {}
00244   explicit DefinedSVal(const void *d, bool isLoc, unsigned ValKind)
00245     : DefinedOrUnknownSVal(d, isLoc, ValKind) {}
00246 private:
00247   friend class SVal;
00248   static bool isKind(const SVal& V) {
00249     return !V.isUnknownOrUndef();
00250   }
00251 };
00252 
00253 
00254 /// \brief Represents an SVal that is guaranteed to not be UnknownVal.
00255 class KnownSVal : public SVal {
00256   KnownSVal() {}
00257   friend class SVal;
00258   static bool isKind(const SVal &V) {
00259     return !V.isUnknown();
00260   }
00261 public:
00262   KnownSVal(const DefinedSVal &V) : SVal(V) {}
00263   KnownSVal(const UndefinedVal &V) : SVal(V) {}
00264 };
00265 
00266 class NonLoc : public DefinedSVal {
00267 protected:
00268   NonLoc() {}
00269   explicit NonLoc(unsigned SubKind, const void *d)
00270     : DefinedSVal(d, false, SubKind) {}
00271 
00272 public:
00273   void dumpToStream(raw_ostream &Out) const;
00274 
00275 private:
00276   friend class SVal;
00277   static bool isKind(const SVal& V) {
00278     return V.getBaseKind() == NonLocKind;
00279   }
00280 };
00281 
00282 class Loc : public DefinedSVal {
00283 protected:
00284   Loc() {}
00285   explicit Loc(unsigned SubKind, const void *D)
00286   : DefinedSVal(const_cast<void*>(D), true, SubKind) {}
00287 
00288 public:
00289   void dumpToStream(raw_ostream &Out) const;
00290 
00291   static inline bool isLocType(QualType T) {
00292     return T->isAnyPointerType() || T->isBlockPointerType() || 
00293            T->isReferenceType() || T->isNullPtrType();
00294   }
00295 
00296 private:
00297   friend class SVal;
00298   static bool isKind(const SVal& V) {
00299     return V.getBaseKind() == LocKind;
00300   }
00301 };
00302 
00303 //==------------------------------------------------------------------------==//
00304 //  Subclasses of NonLoc.
00305 //==------------------------------------------------------------------------==//
00306 
00307 namespace nonloc {
00308 
00309 enum Kind { ConcreteIntKind, SymbolValKind,
00310             LocAsIntegerKind, CompoundValKind, LazyCompoundValKind };
00311 
00312 /// \brief Represents symbolic expression.
00313 class SymbolVal : public NonLoc {
00314 public:
00315   SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) {}
00316 
00317   SymbolRef getSymbol() const {
00318     return (const SymExpr*) Data;
00319   }
00320 
00321   bool isExpression() const {
00322     return !isa<SymbolData>(getSymbol());
00323   }
00324 
00325 private:
00326   friend class SVal;
00327   SymbolVal() {}
00328   static bool isKind(const SVal& V) {
00329     return V.getBaseKind() == NonLocKind &&
00330            V.getSubKind() == SymbolValKind;
00331   }
00332 
00333   static bool isKind(const NonLoc& V) {
00334     return V.getSubKind() == SymbolValKind;
00335   }
00336 };
00337 
00338 /// \brief Value representing integer constant.
00339 class ConcreteInt : public NonLoc {
00340 public:
00341   explicit ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {}
00342 
00343   const llvm::APSInt& getValue() const {
00344     return *static_cast<const llvm::APSInt*>(Data);
00345   }
00346 
00347   // Transfer functions for binary/unary operations on ConcreteInts.
00348   SVal evalBinOp(SValBuilder &svalBuilder, BinaryOperator::Opcode Op,
00349                  const ConcreteInt& R) const;
00350 
00351   ConcreteInt evalComplement(SValBuilder &svalBuilder) const;
00352 
00353   ConcreteInt evalMinus(SValBuilder &svalBuilder) const;
00354 
00355 private:
00356   friend class SVal;
00357   ConcreteInt() {}
00358   static bool isKind(const SVal& V) {
00359     return V.getBaseKind() == NonLocKind &&
00360            V.getSubKind() == ConcreteIntKind;
00361   }
00362 
00363   static bool isKind(const NonLoc& V) {
00364     return V.getSubKind() == ConcreteIntKind;
00365   }
00366 };
00367 
00368 class LocAsInteger : public NonLoc {
00369   friend class ento::SValBuilder;
00370 
00371   explicit LocAsInteger(const std::pair<SVal, uintptr_t> &data)
00372       : NonLoc(LocAsIntegerKind, &data) {
00373     assert (data.first.getAs<Loc>());
00374   }
00375 
00376 public:
00377 
00378   Loc getLoc() const {
00379     const std::pair<SVal, uintptr_t> *D =
00380       static_cast<const std::pair<SVal, uintptr_t> *>(Data);
00381     return D->first.castAs<Loc>();
00382   }
00383 
00384   Loc getPersistentLoc() const {
00385     const std::pair<SVal, uintptr_t> *D =
00386       static_cast<const std::pair<SVal, uintptr_t> *>(Data);
00387     const SVal& V = D->first;
00388     return V.castAs<Loc>();
00389   }
00390 
00391   unsigned getNumBits() const {
00392     const std::pair<SVal, uintptr_t> *D =
00393       static_cast<const std::pair<SVal, uintptr_t> *>(Data);
00394     return D->second;
00395   }
00396 
00397 private:
00398   friend class SVal;
00399   LocAsInteger() {}
00400   static bool isKind(const SVal& V) {
00401     return V.getBaseKind() == NonLocKind &&
00402            V.getSubKind() == LocAsIntegerKind;
00403   }
00404 
00405   static bool isKind(const NonLoc& V) {
00406     return V.getSubKind() == LocAsIntegerKind;
00407   }
00408 };
00409 
00410 class CompoundVal : public NonLoc {
00411   friend class ento::SValBuilder;
00412 
00413   explicit CompoundVal(const CompoundValData* D) : NonLoc(CompoundValKind, D) {}
00414 
00415 public:
00416   const CompoundValData* getValue() const {
00417     return static_cast<const CompoundValData*>(Data);
00418   }
00419 
00420   typedef llvm::ImmutableList<SVal>::iterator iterator;
00421   iterator begin() const;
00422   iterator end() const;
00423 
00424 private:
00425   friend class SVal;
00426   CompoundVal() {}
00427   static bool isKind(const SVal& V) {
00428     return V.getBaseKind() == NonLocKind && V.getSubKind() == CompoundValKind;
00429   }
00430 
00431   static bool isKind(const NonLoc& V) {
00432     return V.getSubKind() == CompoundValKind;
00433   }
00434 };
00435 
00436 class LazyCompoundVal : public NonLoc {
00437   friend class ento::SValBuilder;
00438 
00439   explicit LazyCompoundVal(const LazyCompoundValData *D)
00440     : NonLoc(LazyCompoundValKind, D) {}
00441 public:
00442   const LazyCompoundValData *getCVData() const {
00443     return static_cast<const LazyCompoundValData*>(Data);
00444   }
00445   const void *getStore() const;
00446   const TypedValueRegion *getRegion() const;
00447 
00448 private:
00449   friend class SVal;
00450   LazyCompoundVal() {}
00451   static bool isKind(const SVal& V) {
00452     return V.getBaseKind() == NonLocKind &&
00453            V.getSubKind() == LazyCompoundValKind;
00454   }
00455   static bool isKind(const NonLoc& V) {
00456     return V.getSubKind() == LazyCompoundValKind;
00457   }
00458 };
00459 
00460 } // end namespace ento::nonloc
00461 
00462 //==------------------------------------------------------------------------==//
00463 //  Subclasses of Loc.
00464 //==------------------------------------------------------------------------==//
00465 
00466 namespace loc {
00467 
00468 enum Kind { GotoLabelKind, MemRegionKind, ConcreteIntKind };
00469 
00470 class GotoLabel : public Loc {
00471 public:
00472   explicit GotoLabel(LabelDecl *Label) : Loc(GotoLabelKind, Label) {}
00473 
00474   const LabelDecl *getLabel() const {
00475     return static_cast<const LabelDecl*>(Data);
00476   }
00477 
00478 private:
00479   friend class SVal;
00480   GotoLabel() {}
00481   static bool isKind(const SVal& V) {
00482     return V.getBaseKind() == LocKind && V.getSubKind() == GotoLabelKind;
00483   }
00484 
00485   static bool isKind(const Loc& V) {
00486     return V.getSubKind() == GotoLabelKind;
00487   }
00488 };
00489 
00490 
00491 class MemRegionVal : public Loc {
00492 public:
00493   explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {}
00494 
00495   /// \brief Get the underlining region.
00496   const MemRegion* getRegion() const {
00497     return static_cast<const MemRegion*>(Data);
00498   }
00499 
00500   /// \brief Get the underlining region and strip casts.
00501   const MemRegion* stripCasts(bool StripBaseCasts = true) const;
00502 
00503   template <typename REGION>
00504   const REGION* getRegionAs() const {
00505     return dyn_cast<REGION>(getRegion());
00506   }
00507 
00508   inline bool operator==(const MemRegionVal& R) const {
00509     return getRegion() == R.getRegion();
00510   }
00511 
00512   inline bool operator!=(const MemRegionVal& R) const {
00513     return getRegion() != R.getRegion();
00514   }
00515 
00516 private:
00517   friend class SVal;
00518   MemRegionVal() {}
00519   static bool isKind(const SVal& V) {
00520     return V.getBaseKind() == LocKind &&
00521            V.getSubKind() == MemRegionKind;
00522   }
00523 
00524   static bool isKind(const Loc& V) {
00525     return V.getSubKind() == MemRegionKind;
00526   }
00527 };
00528 
00529 class ConcreteInt : public Loc {
00530 public:
00531   explicit ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {}
00532 
00533   const llvm::APSInt& getValue() const {
00534     return *static_cast<const llvm::APSInt*>(Data);
00535   }
00536 
00537   // Transfer functions for binary/unary operations on ConcreteInts.
00538   SVal evalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
00539                  const ConcreteInt& R) const;
00540 
00541 private:
00542   friend class SVal;
00543   ConcreteInt() {}
00544   static bool isKind(const SVal& V) {
00545     return V.getBaseKind() == LocKind &&
00546            V.getSubKind() == ConcreteIntKind;
00547   }
00548 
00549   static bool isKind(const Loc& V) {
00550     return V.getSubKind() == ConcreteIntKind;
00551   }
00552 };
00553 
00554 } // end ento::loc namespace
00555 
00556 } // end ento namespace
00557 
00558 } // end clang namespace
00559 
00560 namespace llvm {
00561 static inline raw_ostream &operator<<(raw_ostream &os,
00562                                             clang::ento::SVal V) {
00563   V.dumpToStream(os);
00564   return os;
00565 }
00566 
00567 template <typename T> struct isPodLike;
00568 template <> struct isPodLike<clang::ento::SVal> {
00569   static const bool value = true;
00570 };
00571 
00572 } // end llvm namespace
00573 
00574 #endif