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_GR_RVALUE_H
00016 #define LLVM_CLANG_GR_RVALUE_H
00017 
00018 #include "clang/Basic/LLVM.h"
00019 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
00020 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.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 TypedRegion;
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 = NULL)
00067     : Data(D), Kind(k) {}
00068 
00069 public:
00070   explicit SVal() : Data(0), Kind(0) {}
00071   ~SVal() {}
00072 
00073   /// BufferTy - A temporary buffer to hold a set of SVals.
00074   typedef SmallVector<SVal,5> BufferTy;
00075 
00076   inline unsigned getRawKind() const { return Kind; }
00077   inline BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
00078   inline unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; }
00079 
00080   // This method is required for using SVal in a FoldingSetNode.  It
00081   // extracts a unique signature for this SVal object.
00082   inline void Profile(llvm::FoldingSetNodeID& ID) const {
00083     ID.AddInteger((unsigned) getRawKind());
00084     ID.AddPointer(Data);
00085   }
00086 
00087   inline bool operator==(const SVal& R) const {
00088     return getRawKind() == R.getRawKind() && Data == R.Data;
00089   }
00090 
00091   inline bool operator!=(const SVal& R) const {
00092     return !(*this == R);
00093   }
00094 
00095   inline bool isUnknown() const {
00096     return getRawKind() == UnknownKind;
00097   }
00098 
00099   inline bool isUndef() const {
00100     return getRawKind() == UndefinedKind;
00101   }
00102 
00103   inline bool isUnknownOrUndef() const {
00104     return getRawKind() <= UnknownKind;
00105   }
00106 
00107   inline bool isValid() const {
00108     return getRawKind() > UnknownKind;
00109   }
00110 
00111   bool isConstant() const;
00112 
00113   bool isConstant(int I) const;
00114 
00115   bool isZeroConstant() const;
00116 
00117   /// hasConjuredSymbol - If this SVal wraps a conjured symbol, return true;
00118   bool hasConjuredSymbol() const;
00119 
00120   /// getAsFunctionDecl - If this SVal is a MemRegionVal and wraps a
00121   /// CodeTextRegion wrapping a FunctionDecl, return that FunctionDecl.
00122   /// Otherwise return 0.
00123   const FunctionDecl *getAsFunctionDecl() const;
00124 
00125   /// If this SVal is a location (subclasses Loc) and
00126   /// wraps a symbol, return that SymbolRef.  Otherwise return 0.
00127   SymbolRef getAsLocSymbol() const;
00128 
00129   /// Get the symbol in the SVal or its base region.
00130   SymbolRef getLocSymbolInBase() const;
00131 
00132   /// If this SVal wraps a symbol return that SymbolRef.
00133   /// Otherwise, return 0.
00134   SymbolRef getAsSymbol() const;
00135 
00136   /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
00137   ///  return that expression.  Otherwise return NULL.
00138   const SymExpr *getAsSymbolicExpression() const;
00139 
00140   const SymExpr* getAsSymExpr() const;
00141 
00142   const MemRegion *getAsRegion() const;
00143 
00144   void dumpToStream(raw_ostream &OS) const;
00145   void dump() const;
00146 
00147   SymExpr::symbol_iterator symbol_begin() const {
00148     const SymExpr *SE = getAsSymbolicExpression();
00149     if (SE)
00150       return SE->symbol_begin();
00151     else
00152       return SymExpr::symbol_iterator();
00153   }
00154 
00155   SymExpr::symbol_iterator symbol_end() const { 
00156     return SymExpr::symbol_end();
00157   }
00158 
00159   // Implement isa<T> support.
00160   static inline bool classof(const SVal*) { return true; }
00161 };
00162 
00163 
00164 class UndefinedVal : public SVal {
00165 public:
00166   UndefinedVal() : SVal(UndefinedKind) {}
00167   UndefinedVal(const void *D) : SVal(UndefinedKind, D) {}
00168 
00169   static inline bool classof(const SVal* V) {
00170     return V->getBaseKind() == UndefinedKind;
00171   }
00172 
00173   const void *getData() const { return Data; }
00174 };
00175 
00176 class DefinedOrUnknownSVal : public SVal {
00177 private:
00178   // Do not implement.  We want calling these methods to be a compiler
00179   // error since they are tautologically false.
00180   bool isUndef() const;
00181   bool isValid() const;
00182   
00183 protected:
00184   explicit DefinedOrUnknownSVal(const void *d, bool isLoc, unsigned ValKind)
00185     : SVal(d, isLoc, ValKind) {}
00186   
00187   explicit DefinedOrUnknownSVal(BaseKind k, void *D = NULL)
00188     : SVal(k, D) {}
00189   
00190 public:
00191     // Implement isa<T> support.
00192   static inline bool classof(const SVal *V) {
00193     return !V->isUndef();
00194   }
00195 };
00196   
00197 class UnknownVal : public DefinedOrUnknownSVal {
00198 public:
00199   explicit UnknownVal() : DefinedOrUnknownSVal(UnknownKind) {}
00200   
00201   static inline bool classof(const SVal *V) {
00202     return V->getBaseKind() == UnknownKind;
00203   }
00204 };
00205 
00206 class DefinedSVal : public DefinedOrUnknownSVal {
00207 private:
00208   // Do not implement.  We want calling these methods to be a compiler
00209   // error since they are tautologically true/false.
00210   bool isUnknown() const;
00211   bool isUnknownOrUndef() const;
00212   bool isValid() const;  
00213 protected:
00214   explicit DefinedSVal(const void *d, bool isLoc, unsigned ValKind)
00215     : DefinedOrUnknownSVal(d, isLoc, ValKind) {}
00216 public:
00217   // Implement isa<T> support.
00218   static inline bool classof(const SVal *V) {
00219     return !V->isUnknownOrUndef();
00220   }
00221 };
00222 
00223 class NonLoc : public DefinedSVal {
00224 protected:
00225   explicit NonLoc(unsigned SubKind, const void *d)
00226     : DefinedSVal(d, false, SubKind) {}
00227 
00228 public:
00229   void dumpToStream(raw_ostream &Out) const;
00230 
00231   // Implement isa<T> support.
00232   static inline bool classof(const SVal* V) {
00233     return V->getBaseKind() == NonLocKind;
00234   }
00235 };
00236 
00237 class Loc : public DefinedSVal {
00238 protected:
00239   explicit Loc(unsigned SubKind, const void *D)
00240   : DefinedSVal(const_cast<void*>(D), true, SubKind) {}
00241 
00242 public:
00243   void dumpToStream(raw_ostream &Out) const;
00244 
00245   Loc(const Loc& X) : DefinedSVal(X.Data, true, X.getSubKind()) {}
00246 
00247   // Implement isa<T> support.
00248   static inline bool classof(const SVal* V) {
00249     return V->getBaseKind() == LocKind;
00250   }
00251 
00252   static inline bool isLocType(QualType T) {
00253     return T->isAnyPointerType() || T->isBlockPointerType() || 
00254            T->isReferenceType();
00255   }
00256 };
00257 
00258 //==------------------------------------------------------------------------==//
00259 //  Subclasses of NonLoc.
00260 //==------------------------------------------------------------------------==//
00261 
00262 namespace nonloc {
00263 
00264 enum Kind { ConcreteIntKind, SymbolValKind, SymExprValKind,
00265             LocAsIntegerKind, CompoundValKind, LazyCompoundValKind };
00266 
00267 /// \brief Represents symbolic expression.
00268 class SymbolVal : public NonLoc {
00269 public:
00270   SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) {}
00271 
00272   SymbolRef getSymbol() const {
00273     return (const SymExpr*) Data;
00274   }
00275 
00276   bool isExpression() {
00277     return !isa<SymbolData>(getSymbol());
00278   }
00279 
00280   static inline bool classof(const SVal* V) {
00281     return V->getBaseKind() == NonLocKind &&
00282            V->getSubKind() == SymbolValKind;
00283   }
00284 
00285   static inline bool classof(const NonLoc* V) {
00286     return V->getSubKind() == SymbolValKind;
00287   }
00288 };
00289 
00290 /// \brief Value representing integer constant.
00291 class ConcreteInt : public NonLoc {
00292 public:
00293   explicit ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {}
00294 
00295   const llvm::APSInt& getValue() const {
00296     return *static_cast<const llvm::APSInt*>(Data);
00297   }
00298 
00299   // Transfer functions for binary/unary operations on ConcreteInts.
00300   SVal evalBinOp(SValBuilder &svalBuilder, BinaryOperator::Opcode Op,
00301                  const ConcreteInt& R) const;
00302 
00303   ConcreteInt evalComplement(SValBuilder &svalBuilder) const;
00304 
00305   ConcreteInt evalMinus(SValBuilder &svalBuilder) const;
00306 
00307   // Implement isa<T> support.
00308   static inline bool classof(const SVal* V) {
00309     return V->getBaseKind() == NonLocKind &&
00310            V->getSubKind() == ConcreteIntKind;
00311   }
00312 
00313   static inline bool classof(const NonLoc* V) {
00314     return V->getSubKind() == ConcreteIntKind;
00315   }
00316 };
00317 
00318 class LocAsInteger : public NonLoc {
00319   friend class ento::SValBuilder;
00320 
00321   explicit LocAsInteger(const std::pair<SVal, uintptr_t>& data) :
00322     NonLoc(LocAsIntegerKind, &data) {
00323       assert (isa<Loc>(data.first));
00324     }
00325 
00326 public:
00327 
00328   Loc getLoc() const {
00329     return cast<Loc>(((std::pair<SVal, uintptr_t>*) Data)->first);
00330   }
00331 
00332   const Loc& getPersistentLoc() const {
00333     const SVal& V = ((std::pair<SVal, uintptr_t>*) Data)->first;
00334     return cast<Loc>(V);
00335   }
00336 
00337   unsigned getNumBits() const {
00338     return ((std::pair<SVal, unsigned>*) Data)->second;
00339   }
00340 
00341   // Implement isa<T> support.
00342   static inline bool classof(const SVal* V) {
00343     return V->getBaseKind() == NonLocKind &&
00344            V->getSubKind() == LocAsIntegerKind;
00345   }
00346 
00347   static inline bool classof(const NonLoc* V) {
00348     return V->getSubKind() == LocAsIntegerKind;
00349   }
00350 };
00351 
00352 class CompoundVal : public NonLoc {
00353   friend class ento::SValBuilder;
00354 
00355   explicit CompoundVal(const CompoundValData* D) : NonLoc(CompoundValKind, D) {}
00356 
00357 public:
00358   const CompoundValData* getValue() const {
00359     return static_cast<const CompoundValData*>(Data);
00360   }
00361 
00362   typedef llvm::ImmutableList<SVal>::iterator iterator;
00363   iterator begin() const;
00364   iterator end() const;
00365 
00366   static bool classof(const SVal* V) {
00367     return V->getBaseKind() == NonLocKind && V->getSubKind() == CompoundValKind;
00368   }
00369 
00370   static bool classof(const NonLoc* V) {
00371     return V->getSubKind() == CompoundValKind;
00372   }
00373 };
00374 
00375 class LazyCompoundVal : public NonLoc {
00376   friend class ento::SValBuilder;
00377 
00378   explicit LazyCompoundVal(const LazyCompoundValData *D)
00379     : NonLoc(LazyCompoundValKind, D) {}
00380 public:
00381   const LazyCompoundValData *getCVData() const {
00382     return static_cast<const LazyCompoundValData*>(Data);
00383   }
00384   const void *getStore() const;
00385   const TypedRegion *getRegion() const;
00386 
00387   static bool classof(const SVal *V) {
00388     return V->getBaseKind() == NonLocKind &&
00389            V->getSubKind() == LazyCompoundValKind;
00390   }
00391   static bool classof(const NonLoc *V) {
00392     return V->getSubKind() == LazyCompoundValKind;
00393   }
00394 };
00395 
00396 } // end namespace ento::nonloc
00397 
00398 //==------------------------------------------------------------------------==//
00399 //  Subclasses of Loc.
00400 //==------------------------------------------------------------------------==//
00401 
00402 namespace loc {
00403 
00404 enum Kind { GotoLabelKind, MemRegionKind, ConcreteIntKind, ObjCPropRefKind };
00405 
00406 class GotoLabel : public Loc {
00407 public:
00408   explicit GotoLabel(LabelDecl *Label) : Loc(GotoLabelKind, Label) {}
00409 
00410   const LabelDecl *getLabel() const {
00411     return static_cast<const LabelDecl*>(Data);
00412   }
00413 
00414   static inline bool classof(const SVal* V) {
00415     return V->getBaseKind() == LocKind && V->getSubKind() == GotoLabelKind;
00416   }
00417 
00418   static inline bool classof(const Loc* V) {
00419     return V->getSubKind() == GotoLabelKind;
00420   }
00421 };
00422 
00423 
00424 class MemRegionVal : public Loc {
00425 public:
00426   explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {}
00427 
00428   /// \brief Get the underlining region.
00429   const MemRegion* getRegion() const {
00430     return static_cast<const MemRegion*>(Data);
00431   }
00432 
00433   /// \brief Get the underlining region and strip casts.
00434   const MemRegion* stripCasts() const;
00435 
00436   template <typename REGION>
00437   const REGION* getRegionAs() const {
00438     return llvm::dyn_cast<REGION>(getRegion());
00439   }
00440 
00441   inline bool operator==(const MemRegionVal& R) const {
00442     return getRegion() == R.getRegion();
00443   }
00444 
00445   inline bool operator!=(const MemRegionVal& R) const {
00446     return getRegion() != R.getRegion();
00447   }
00448 
00449   // Implement isa<T> support.
00450   static inline bool classof(const SVal* V) {
00451     return V->getBaseKind() == LocKind &&
00452            V->getSubKind() == MemRegionKind;
00453   }
00454 
00455   static inline bool classof(const Loc* V) {
00456     return V->getSubKind() == MemRegionKind;
00457   }
00458 };
00459 
00460 class ConcreteInt : public Loc {
00461 public:
00462   explicit ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {}
00463 
00464   const llvm::APSInt& getValue() const {
00465     return *static_cast<const llvm::APSInt*>(Data);
00466   }
00467 
00468   // Transfer functions for binary/unary operations on ConcreteInts.
00469   SVal evalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
00470                  const ConcreteInt& R) const;
00471 
00472   // Implement isa<T> support.
00473   static inline bool classof(const SVal* V) {
00474     return V->getBaseKind() == LocKind &&
00475            V->getSubKind() == ConcreteIntKind;
00476   }
00477 
00478   static inline bool classof(const Loc* V) {
00479     return V->getSubKind() == ConcreteIntKind;
00480   }
00481 };
00482 
00483 /// \brief Pseudo-location SVal used by the ExprEngine to simulate a "load" or
00484 /// "store" of an ObjC property for the dot syntax.
00485 class ObjCPropRef : public Loc {
00486 public:
00487   explicit ObjCPropRef(const ObjCPropertyRefExpr *E)
00488     : Loc(ObjCPropRefKind, E) {}
00489 
00490   const ObjCPropertyRefExpr *getPropRefExpr() const {
00491     return static_cast<const ObjCPropertyRefExpr *>(Data);
00492   }
00493 
00494   // Implement isa<T> support.
00495   static inline bool classof(const SVal* V) {
00496     return V->getBaseKind() == LocKind &&
00497            V->getSubKind() == ObjCPropRefKind;
00498   }
00499 
00500   static inline bool classof(const Loc* V) {
00501     return V->getSubKind() == ObjCPropRefKind;
00502   }
00503 };
00504 
00505 } // end ento::loc namespace
00506 } // end GR namespace
00507 
00508 } // end clang namespace
00509 
00510 namespace llvm {
00511 static inline raw_ostream &operator<<(raw_ostream &os,
00512                                             clang::ento::SVal V) {
00513   V.dumpToStream(os);
00514   return os;
00515 }
00516 
00517 } // end llvm namespace
00518 
00519 #endif