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 SVal(const void * d,bool isLoc,unsigned ValKind)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) Data(D)67 : Data(D), Kind(k) {} 68 69 public: SVal()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> castAs()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> getAs()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 getRawKind()98 inline unsigned getRawKind() const { return Kind; } getBaseKind()99 inline BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); } getSubKind()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. Profile(llvm::FoldingSetNodeID & ID)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 isUnknown()117 inline bool isUnknown() const { 118 return getRawKind() == UnknownKind; 119 } 120 isUndef()121 inline bool isUndef() const { 122 return getRawKind() == UndefinedKind; 123 } 124 isUnknownOrUndef()125 inline bool isUnknownOrUndef() const { 126 return getRawKind() <= UnknownKind; 127 } 128 isValid()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 /// If this SVal is a location (subclasses Loc) and 148 /// wraps a symbol, return that SymbolRef. Otherwise return 0. 149 SymbolRef getAsLocSymbol() const; 150 151 /// Get the symbol in the SVal or its base region. 152 SymbolRef getLocSymbolInBase() const; 153 154 /// If this SVal wraps a symbol return that SymbolRef. 155 /// Otherwise, return 0. 156 SymbolRef getAsSymbol() const; 157 158 /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then 159 /// return that expression. Otherwise return NULL. 160 const SymExpr *getAsSymbolicExpression() const; 161 162 const SymExpr* getAsSymExpr() const; 163 164 const MemRegion *getAsRegion() const; 165 166 void dumpToStream(raw_ostream &OS) const; 167 void dump() const; 168 symbol_begin()169 SymExpr::symbol_iterator symbol_begin() const { 170 const SymExpr *SE = getAsSymbolicExpression(); 171 if (SE) 172 return SE->symbol_begin(); 173 else 174 return SymExpr::symbol_iterator(); 175 } 176 symbol_end()177 SymExpr::symbol_iterator symbol_end() const { 178 return SymExpr::symbol_end(); 179 } 180 }; 181 182 183 class UndefinedVal : public SVal { 184 public: UndefinedVal()185 UndefinedVal() : SVal(UndefinedKind) {} 186 187 private: 188 friend class SVal; isKind(const SVal & V)189 static bool isKind(const SVal& V) { 190 return V.getBaseKind() == UndefinedKind; 191 } 192 }; 193 194 class DefinedOrUnknownSVal : public SVal { 195 private: 196 // We want calling these methods to be a compiler error since they are 197 // tautologically false. 198 bool isUndef() const LLVM_DELETED_FUNCTION; 199 bool isValid() const LLVM_DELETED_FUNCTION; 200 201 protected: DefinedOrUnknownSVal()202 DefinedOrUnknownSVal() {} DefinedOrUnknownSVal(const void * d,bool isLoc,unsigned ValKind)203 explicit DefinedOrUnknownSVal(const void *d, bool isLoc, unsigned ValKind) 204 : SVal(d, isLoc, ValKind) {} 205 206 explicit DefinedOrUnknownSVal(BaseKind k, void *D = NULL) SVal(k,D)207 : SVal(k, D) {} 208 209 private: 210 friend class SVal; isKind(const SVal & V)211 static bool isKind(const SVal& V) { 212 return !V.isUndef(); 213 } 214 }; 215 216 class UnknownVal : public DefinedOrUnknownSVal { 217 public: UnknownVal()218 explicit UnknownVal() : DefinedOrUnknownSVal(UnknownKind) {} 219 220 private: 221 friend class SVal; isKind(const SVal & V)222 static bool isKind(const SVal &V) { 223 return V.getBaseKind() == UnknownKind; 224 } 225 }; 226 227 class DefinedSVal : public DefinedOrUnknownSVal { 228 private: 229 // We want calling these methods to be a compiler error since they are 230 // tautologically true/false. 231 bool isUnknown() const LLVM_DELETED_FUNCTION; 232 bool isUnknownOrUndef() const LLVM_DELETED_FUNCTION; 233 bool isValid() const LLVM_DELETED_FUNCTION; 234 protected: DefinedSVal()235 DefinedSVal() {} DefinedSVal(const void * d,bool isLoc,unsigned ValKind)236 explicit DefinedSVal(const void *d, bool isLoc, unsigned ValKind) 237 : DefinedOrUnknownSVal(d, isLoc, ValKind) {} 238 private: 239 friend class SVal; isKind(const SVal & V)240 static bool isKind(const SVal& V) { 241 return !V.isUnknownOrUndef(); 242 } 243 }; 244 245 246 /// \brief Represents an SVal that is guaranteed to not be UnknownVal. 247 class KnownSVal : public SVal { KnownSVal()248 KnownSVal() {} 249 friend class SVal; isKind(const SVal & V)250 static bool isKind(const SVal &V) { 251 return !V.isUnknown(); 252 } 253 public: KnownSVal(const DefinedSVal & V)254 KnownSVal(const DefinedSVal &V) : SVal(V) {} KnownSVal(const UndefinedVal & V)255 KnownSVal(const UndefinedVal &V) : SVal(V) {} 256 }; 257 258 class NonLoc : public DefinedSVal { 259 protected: NonLoc()260 NonLoc() {} NonLoc(unsigned SubKind,const void * d)261 explicit NonLoc(unsigned SubKind, const void *d) 262 : DefinedSVal(d, false, SubKind) {} 263 264 public: 265 void dumpToStream(raw_ostream &Out) const; 266 267 private: 268 friend class SVal; isKind(const SVal & V)269 static bool isKind(const SVal& V) { 270 return V.getBaseKind() == NonLocKind; 271 } 272 }; 273 274 class Loc : public DefinedSVal { 275 protected: Loc()276 Loc() {} Loc(unsigned SubKind,const void * D)277 explicit Loc(unsigned SubKind, const void *D) 278 : DefinedSVal(const_cast<void*>(D), true, SubKind) {} 279 280 public: 281 void dumpToStream(raw_ostream &Out) const; 282 isLocType(QualType T)283 static inline bool isLocType(QualType T) { 284 return T->isAnyPointerType() || T->isBlockPointerType() || 285 T->isReferenceType(); 286 } 287 288 private: 289 friend class SVal; isKind(const SVal & V)290 static bool isKind(const SVal& V) { 291 return V.getBaseKind() == LocKind; 292 } 293 }; 294 295 //==------------------------------------------------------------------------==// 296 // Subclasses of NonLoc. 297 //==------------------------------------------------------------------------==// 298 299 namespace nonloc { 300 301 enum Kind { ConcreteIntKind, SymbolValKind, 302 LocAsIntegerKind, CompoundValKind, LazyCompoundValKind }; 303 304 /// \brief Represents symbolic expression. 305 class SymbolVal : public NonLoc { 306 public: SymbolVal(SymbolRef sym)307 SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) {} 308 getSymbol()309 SymbolRef getSymbol() const { 310 return (const SymExpr*) Data; 311 } 312 isExpression()313 bool isExpression() const { 314 return !isa<SymbolData>(getSymbol()); 315 } 316 317 private: 318 friend class SVal; SymbolVal()319 SymbolVal() {} isKind(const SVal & V)320 static bool isKind(const SVal& V) { 321 return V.getBaseKind() == NonLocKind && 322 V.getSubKind() == SymbolValKind; 323 } 324 isKind(const NonLoc & V)325 static bool isKind(const NonLoc& V) { 326 return V.getSubKind() == SymbolValKind; 327 } 328 }; 329 330 /// \brief Value representing integer constant. 331 class ConcreteInt : public NonLoc { 332 public: ConcreteInt(const llvm::APSInt & V)333 explicit ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {} 334 getValue()335 const llvm::APSInt& getValue() const { 336 return *static_cast<const llvm::APSInt*>(Data); 337 } 338 339 // Transfer functions for binary/unary operations on ConcreteInts. 340 SVal evalBinOp(SValBuilder &svalBuilder, BinaryOperator::Opcode Op, 341 const ConcreteInt& R) const; 342 343 ConcreteInt evalComplement(SValBuilder &svalBuilder) const; 344 345 ConcreteInt evalMinus(SValBuilder &svalBuilder) const; 346 347 private: 348 friend class SVal; ConcreteInt()349 ConcreteInt() {} isKind(const SVal & V)350 static bool isKind(const SVal& V) { 351 return V.getBaseKind() == NonLocKind && 352 V.getSubKind() == ConcreteIntKind; 353 } 354 isKind(const NonLoc & V)355 static bool isKind(const NonLoc& V) { 356 return V.getSubKind() == ConcreteIntKind; 357 } 358 }; 359 360 class LocAsInteger : public NonLoc { 361 friend class ento::SValBuilder; 362 LocAsInteger(const std::pair<SVal,uintptr_t> & data)363 explicit LocAsInteger(const std::pair<SVal, uintptr_t> &data) 364 : NonLoc(LocAsIntegerKind, &data) { 365 assert (data.first.getAs<Loc>()); 366 } 367 368 public: 369 getLoc()370 Loc getLoc() const { 371 const std::pair<SVal, uintptr_t> *D = 372 static_cast<const std::pair<SVal, uintptr_t> *>(Data); 373 return D->first.castAs<Loc>(); 374 } 375 getPersistentLoc()376 Loc getPersistentLoc() const { 377 const std::pair<SVal, uintptr_t> *D = 378 static_cast<const std::pair<SVal, uintptr_t> *>(Data); 379 const SVal& V = D->first; 380 return V.castAs<Loc>(); 381 } 382 getNumBits()383 unsigned getNumBits() const { 384 const std::pair<SVal, uintptr_t> *D = 385 static_cast<const std::pair<SVal, uintptr_t> *>(Data); 386 return D->second; 387 } 388 389 private: 390 friend class SVal; LocAsInteger()391 LocAsInteger() {} isKind(const SVal & V)392 static bool isKind(const SVal& V) { 393 return V.getBaseKind() == NonLocKind && 394 V.getSubKind() == LocAsIntegerKind; 395 } 396 isKind(const NonLoc & V)397 static bool isKind(const NonLoc& V) { 398 return V.getSubKind() == LocAsIntegerKind; 399 } 400 }; 401 402 class CompoundVal : public NonLoc { 403 friend class ento::SValBuilder; 404 CompoundVal(const CompoundValData * D)405 explicit CompoundVal(const CompoundValData* D) : NonLoc(CompoundValKind, D) {} 406 407 public: getValue()408 const CompoundValData* getValue() const { 409 return static_cast<const CompoundValData*>(Data); 410 } 411 412 typedef llvm::ImmutableList<SVal>::iterator iterator; 413 iterator begin() const; 414 iterator end() const; 415 416 private: 417 friend class SVal; CompoundVal()418 CompoundVal() {} isKind(const SVal & V)419 static bool isKind(const SVal& V) { 420 return V.getBaseKind() == NonLocKind && V.getSubKind() == CompoundValKind; 421 } 422 isKind(const NonLoc & V)423 static bool isKind(const NonLoc& V) { 424 return V.getSubKind() == CompoundValKind; 425 } 426 }; 427 428 class LazyCompoundVal : public NonLoc { 429 friend class ento::SValBuilder; 430 LazyCompoundVal(const LazyCompoundValData * D)431 explicit LazyCompoundVal(const LazyCompoundValData *D) 432 : NonLoc(LazyCompoundValKind, D) {} 433 public: getCVData()434 const LazyCompoundValData *getCVData() const { 435 return static_cast<const LazyCompoundValData*>(Data); 436 } 437 const void *getStore() const; 438 const TypedValueRegion *getRegion() const; 439 440 private: 441 friend class SVal; LazyCompoundVal()442 LazyCompoundVal() {} isKind(const SVal & V)443 static bool isKind(const SVal& V) { 444 return V.getBaseKind() == NonLocKind && 445 V.getSubKind() == LazyCompoundValKind; 446 } isKind(const NonLoc & V)447 static bool isKind(const NonLoc& V) { 448 return V.getSubKind() == LazyCompoundValKind; 449 } 450 }; 451 452 } // end namespace ento::nonloc 453 454 //==------------------------------------------------------------------------==// 455 // Subclasses of Loc. 456 //==------------------------------------------------------------------------==// 457 458 namespace loc { 459 460 enum Kind { GotoLabelKind, MemRegionKind, ConcreteIntKind }; 461 462 class GotoLabel : public Loc { 463 public: GotoLabel(LabelDecl * Label)464 explicit GotoLabel(LabelDecl *Label) : Loc(GotoLabelKind, Label) {} 465 getLabel()466 const LabelDecl *getLabel() const { 467 return static_cast<const LabelDecl*>(Data); 468 } 469 470 private: 471 friend class SVal; GotoLabel()472 GotoLabel() {} isKind(const SVal & V)473 static bool isKind(const SVal& V) { 474 return V.getBaseKind() == LocKind && V.getSubKind() == GotoLabelKind; 475 } 476 isKind(const Loc & V)477 static bool isKind(const Loc& V) { 478 return V.getSubKind() == GotoLabelKind; 479 } 480 }; 481 482 483 class MemRegionVal : public Loc { 484 public: MemRegionVal(const MemRegion * r)485 explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {} 486 487 /// \brief Get the underlining region. getRegion()488 const MemRegion* getRegion() const { 489 return static_cast<const MemRegion*>(Data); 490 } 491 492 /// \brief Get the underlining region and strip casts. 493 const MemRegion* stripCasts(bool StripBaseCasts = true) const; 494 495 template <typename REGION> getRegionAs()496 const REGION* getRegionAs() const { 497 return dyn_cast<REGION>(getRegion()); 498 } 499 500 inline bool operator==(const MemRegionVal& R) const { 501 return getRegion() == R.getRegion(); 502 } 503 504 inline bool operator!=(const MemRegionVal& R) const { 505 return getRegion() != R.getRegion(); 506 } 507 508 private: 509 friend class SVal; MemRegionVal()510 MemRegionVal() {} isKind(const SVal & V)511 static bool isKind(const SVal& V) { 512 return V.getBaseKind() == LocKind && 513 V.getSubKind() == MemRegionKind; 514 } 515 isKind(const Loc & V)516 static bool isKind(const Loc& V) { 517 return V.getSubKind() == MemRegionKind; 518 } 519 }; 520 521 class ConcreteInt : public Loc { 522 public: ConcreteInt(const llvm::APSInt & V)523 explicit ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {} 524 getValue()525 const llvm::APSInt& getValue() const { 526 return *static_cast<const llvm::APSInt*>(Data); 527 } 528 529 // Transfer functions for binary/unary operations on ConcreteInts. 530 SVal evalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op, 531 const ConcreteInt& R) const; 532 533 private: 534 friend class SVal; ConcreteInt()535 ConcreteInt() {} isKind(const SVal & V)536 static bool isKind(const SVal& V) { 537 return V.getBaseKind() == LocKind && 538 V.getSubKind() == ConcreteIntKind; 539 } 540 isKind(const Loc & V)541 static bool isKind(const Loc& V) { 542 return V.getSubKind() == ConcreteIntKind; 543 } 544 }; 545 546 } // end ento::loc namespace 547 } // end GR namespace 548 549 } // end clang namespace 550 551 namespace llvm { 552 static inline raw_ostream &operator<<(raw_ostream &os, 553 clang::ento::SVal V) { 554 V.dumpToStream(os); 555 return os; 556 } 557 558 template <typename T> struct isPodLike; 559 template <> struct isPodLike<clang::ento::SVal> { 560 static const bool value = true; 561 }; 562 563 } // end llvm namespace 564 565 #endif 566