clang API Documentation
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