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_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