SVals.h revision da9ae6088b9543134a6561a412b79530e290408d
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_ANALYSIS_RVALUE_H 16#define LLVM_CLANG_ANALYSIS_RVALUE_H 17 18#include "clang/Analysis/PathSensitive/SymbolManager.h" 19#include "llvm/Support/Casting.h" 20#include "llvm/ADT/ImmutableList.h" 21 22//==------------------------------------------------------------------------==// 23// Base SVal types. 24//==------------------------------------------------------------------------==// 25 26namespace clang { 27 28class CompoundValData; 29class BasicValueFactory; 30class MemRegion; 31class MemRegionManager; 32class GRStateManager; 33 34class SVal { 35public: 36 enum BaseKind { UndefinedKind, UnknownKind, LocKind, NonLocKind }; 37 enum { BaseBits = 2, BaseMask = 0x3 }; 38 39protected: 40 void* Data; 41 unsigned Kind; 42 43protected: 44 SVal(const void* d, bool isLoc, unsigned ValKind) 45 : Data(const_cast<void*>(d)), 46 Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {} 47 48 explicit SVal(BaseKind k, void* D = NULL) 49 : Data(D), Kind(k) {} 50 51public: 52 SVal() : Data(0), Kind(0) {} 53 ~SVal() {}; 54 55 /// BufferTy - A temporary buffer to hold a set of SVals. 56 typedef llvm::SmallVector<SVal,5> BufferTy; 57 58 inline unsigned getRawKind() const { return Kind; } 59 inline BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); } 60 inline unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; } 61 62 inline void Profile(llvm::FoldingSetNodeID& ID) const { 63 ID.AddInteger((unsigned) getRawKind()); 64 ID.AddPointer(reinterpret_cast<void*>(Data)); 65 } 66 67 inline bool operator==(const SVal& R) const { 68 return getRawKind() == R.getRawKind() && Data == R.Data; 69 } 70 71 inline bool operator!=(const SVal& R) const { 72 return !(*this == R); 73 } 74 75 /// GetRValueSymbolVal - make a unique symbol for value of R. 76 static SVal GetRValueSymbolVal(SymbolManager& SymMgr, MemRegionManager& MRMgr, 77 const MemRegion* R); 78 79 static SVal GetConjuredSymbolVal(SymbolManager& SymMgr, const Expr *E, 80 unsigned Count); 81 82 inline bool isUnknown() const { 83 return getRawKind() == UnknownKind; 84 } 85 86 inline bool isUndef() const { 87 return getRawKind() == UndefinedKind; 88 } 89 90 inline bool isUnknownOrUndef() const { 91 return getRawKind() <= UnknownKind; 92 } 93 94 inline bool isValid() const { 95 return getRawKind() > UnknownKind; 96 } 97 98 static SVal MakeZero(BasicValueFactory &BasicVals, QualType T); 99 100 bool isZeroConstant() const; 101 102 /// getAsLocSymbol - If this SVal is a location (subclasses Loc) and 103 /// wraps a symbol, return that SymbolRef. Otherwise return a SymbolData* 104 SymbolRef getAsLocSymbol() const; 105 106 /// getAsSymbol - If this Sval wraps a symbol return that SymbolRef. 107 /// Otherwise return a SymbolRef where 'isValid()' returns false. 108 SymbolRef getAsSymbol() const; 109 110 /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then 111 /// return that expression. Otherwise return NULL. 112 const SymExpr *getAsSymbolicExpression() const; 113 114 void print(std::ostream& OS) const; 115 void print(llvm::raw_ostream& OS) const; 116 void printStdErr() const; 117 118 // Iterators. 119 class symbol_iterator { 120 llvm::SmallVector<const SymExpr*, 5> itr; 121 void expand(); 122 public: 123 symbol_iterator() {} 124 symbol_iterator(const SymExpr* SE); 125 126 symbol_iterator& operator++(); 127 SymbolRef operator*(); 128 129 bool operator==(const symbol_iterator& X) const; 130 bool operator!=(const symbol_iterator& X) const; 131 }; 132 133 symbol_iterator symbol_begin() const { 134 const SymExpr *SE = getAsSymbolicExpression(); 135 if (SE) 136 return symbol_iterator(SE); 137 else 138 return symbol_iterator(); 139 } 140 141 symbol_iterator symbol_end() const { return symbol_iterator(); } 142 143 // Implement isa<T> support. 144 static inline bool classof(const SVal*) { return true; } 145}; 146 147class UnknownVal : public SVal { 148public: 149 UnknownVal() : SVal(UnknownKind) {} 150 151 static inline bool classof(const SVal* V) { 152 return V->getBaseKind() == UnknownKind; 153 } 154}; 155 156class UndefinedVal : public SVal { 157public: 158 UndefinedVal() : SVal(UndefinedKind) {} 159 UndefinedVal(void* D) : SVal(UndefinedKind, D) {} 160 161 static inline bool classof(const SVal* V) { 162 return V->getBaseKind() == UndefinedKind; 163 } 164 165 void* getData() const { return Data; } 166}; 167 168class NonLoc : public SVal { 169protected: 170 NonLoc(unsigned SubKind, const void* d) : SVal(d, false, SubKind) {} 171 172public: 173 void print(llvm::raw_ostream& Out) const; 174 175 // Utility methods to create NonLocs. 176 static NonLoc MakeVal(SymbolRef sym); 177 178 static NonLoc MakeVal(SymbolManager& SymMgr, const SymExpr *lhs, 179 BinaryOperator::Opcode op, const llvm::APSInt& rhs, 180 QualType T); 181 182 static NonLoc MakeVal(SymbolManager& SymMgr, const SymExpr *lhs, 183 BinaryOperator::Opcode op, const SymExpr *rhs, 184 QualType T); 185 186 static NonLoc MakeIntVal(BasicValueFactory& BasicVals, uint64_t X, 187 bool isUnsigned); 188 189 static NonLoc MakeVal(BasicValueFactory& BasicVals, uint64_t X, 190 unsigned BitWidth, bool isUnsigned); 191 192 static NonLoc MakeVal(BasicValueFactory& BasicVals, uint64_t X, QualType T); 193 194 static NonLoc MakeVal(BasicValueFactory& BasicVals, IntegerLiteral* I); 195 196 static NonLoc MakeVal(BasicValueFactory& BasicVals, const llvm::APInt& I, 197 bool isUnsigned); 198 199 static NonLoc MakeVal(BasicValueFactory& BasicVals, const llvm::APSInt& I); 200 201 static NonLoc MakeIntTruthVal(BasicValueFactory& BasicVals, bool b); 202 203 static NonLoc MakeCompoundVal(QualType T, llvm::ImmutableList<SVal> Vals, 204 BasicValueFactory& BasicVals); 205 206 // Implement isa<T> support. 207 static inline bool classof(const SVal* V) { 208 return V->getBaseKind() == NonLocKind; 209 } 210}; 211 212class Loc : public SVal { 213protected: 214 Loc(unsigned SubKind, const void* D) 215 : SVal(const_cast<void*>(D), true, SubKind) {} 216 217public: 218 void print(llvm::raw_ostream& Out) const; 219 220 Loc(const Loc& X) : SVal(X.Data, true, X.getSubKind()) {} 221 Loc& operator=(const Loc& X) { memcpy(this, &X, sizeof(Loc)); return *this; } 222 223 static Loc MakeVal(const MemRegion* R); 224 225 static Loc MakeVal(AddrLabelExpr* E); 226 227 static Loc MakeVal(SymbolRef sym); 228 229 static Loc MakeNull(BasicValueFactory &BasicVals); 230 231 // Implement isa<T> support. 232 static inline bool classof(const SVal* V) { 233 return V->getBaseKind() == LocKind; 234 } 235 236 static inline bool IsLocType(QualType T) { 237 return T->isPointerType() || T->isObjCQualifiedIdType() 238 || T->isBlockPointerType(); 239 } 240}; 241 242//==------------------------------------------------------------------------==// 243// Subclasses of NonLoc. 244//==------------------------------------------------------------------------==// 245 246namespace nonloc { 247 248enum Kind { ConcreteIntKind, SymbolValKind, SymExprValKind, 249 LocAsIntegerKind, CompoundValKind }; 250 251class SymbolVal : public NonLoc { 252public: 253 SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) {} 254 255 SymbolRef getSymbol() const { 256 return (const SymbolData*) Data; 257 } 258 259 static inline bool classof(const SVal* V) { 260 return V->getBaseKind() == NonLocKind && 261 V->getSubKind() == SymbolValKind; 262 } 263 264 static inline bool classof(const NonLoc* V) { 265 return V->getSubKind() == SymbolValKind; 266 } 267}; 268 269class SymExprVal : public NonLoc { 270public: 271 SymExprVal(const SymExpr *SE) 272 : NonLoc(SymExprValKind, reinterpret_cast<const void*>(SE)) {} 273 274 const SymExpr *getSymbolicExpression() const { 275 return reinterpret_cast<SymExpr*>(Data); 276 } 277 278 static inline bool classof(const SVal* V) { 279 return V->getBaseKind() == NonLocKind && 280 V->getSubKind() == SymExprValKind; 281 } 282 283 static inline bool classof(const NonLoc* V) { 284 return V->getSubKind() == SymExprValKind; 285 } 286}; 287 288class ConcreteInt : public NonLoc { 289public: 290 ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {} 291 292 const llvm::APSInt& getValue() const { 293 return *static_cast<llvm::APSInt*>(Data); 294 } 295 296 // Transfer functions for binary/unary operations on ConcreteInts. 297 SVal EvalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op, 298 const ConcreteInt& R) const; 299 300 ConcreteInt EvalComplement(BasicValueFactory& BasicVals) const; 301 302 ConcreteInt EvalMinus(BasicValueFactory& BasicVals, UnaryOperator* U) const; 303 304 // Implement isa<T> support. 305 static inline bool classof(const SVal* V) { 306 return V->getBaseKind() == NonLocKind && 307 V->getSubKind() == ConcreteIntKind; 308 } 309 310 static inline bool classof(const NonLoc* V) { 311 return V->getSubKind() == ConcreteIntKind; 312 } 313}; 314 315class LocAsInteger : public NonLoc { 316 LocAsInteger(const std::pair<SVal, uintptr_t>& data) : 317 NonLoc(LocAsIntegerKind, &data) { 318 assert (isa<Loc>(data.first)); 319 } 320 321public: 322 323 Loc getLoc() const { 324 return cast<Loc>(((std::pair<SVal, uintptr_t>*) Data)->first); 325 } 326 327 const Loc& getPersistentLoc() const { 328 const SVal& V = ((std::pair<SVal, uintptr_t>*) Data)->first; 329 return cast<Loc>(V); 330 } 331 332 unsigned getNumBits() const { 333 return ((std::pair<SVal, unsigned>*) Data)->second; 334 } 335 336 // Implement isa<T> support. 337 static inline bool classof(const SVal* V) { 338 return V->getBaseKind() == NonLocKind && 339 V->getSubKind() == LocAsIntegerKind; 340 } 341 342 static inline bool classof(const NonLoc* V) { 343 return V->getSubKind() == LocAsIntegerKind; 344 } 345 346 static LocAsInteger Make(BasicValueFactory& Vals, Loc V, unsigned Bits); 347}; 348 349class CompoundVal : public NonLoc { 350 friend class NonLoc; 351 352 CompoundVal(const CompoundValData* D) : NonLoc(CompoundValKind, D) {} 353 354public: 355 const CompoundValData* getValue() const { 356 return static_cast<CompoundValData*>(Data); 357 } 358 359 typedef llvm::ImmutableList<SVal>::iterator iterator; 360 iterator begin() const; 361 iterator end() const; 362 363 static bool classof(const SVal* V) { 364 return V->getBaseKind() == NonLocKind && V->getSubKind() == CompoundValKind; 365 } 366 367 static bool classof(const NonLoc* V) { 368 return V->getSubKind() == CompoundValKind; 369 } 370}; 371 372} // end namespace clang::nonloc 373 374//==------------------------------------------------------------------------==// 375// Subclasses of Loc. 376//==------------------------------------------------------------------------==// 377 378namespace loc { 379 380enum Kind { SymbolValKind, GotoLabelKind, MemRegionKind, FuncValKind, 381 ConcreteIntKind }; 382 383class SymbolVal : public Loc { 384public: 385 SymbolVal(SymbolRef sym) : Loc(SymbolValKind, sym) {} 386 387 SymbolRef getSymbol() const { return (SymbolRef) Data; } 388 389 static inline bool classof(const SVal* V) { 390 return V->getBaseKind() == LocKind && 391 V->getSubKind() == SymbolValKind; 392 } 393 394 static inline bool classof(const Loc* V) { 395 return V->getSubKind() == SymbolValKind; 396 } 397}; 398 399class GotoLabel : public Loc { 400public: 401 GotoLabel(LabelStmt* Label) : Loc(GotoLabelKind, Label) {} 402 403 LabelStmt* getLabel() const { 404 return static_cast<LabelStmt*>(Data); 405 } 406 407 static inline bool classof(const SVal* V) { 408 return V->getBaseKind() == LocKind && 409 V->getSubKind() == GotoLabelKind; 410 } 411 412 static inline bool classof(const Loc* V) { 413 return V->getSubKind() == GotoLabelKind; 414 } 415}; 416 417 418class MemRegionVal : public Loc { 419public: 420 MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {} 421 422 const MemRegion* getRegion() const { 423 return static_cast<MemRegion*>(Data); 424 } 425 426 template <typename REGION> 427 const REGION* getRegionAs() const { 428 return llvm::dyn_cast<REGION>(getRegion()); 429 } 430 431 inline bool operator==(const MemRegionVal& R) const { 432 return getRegion() == R.getRegion(); 433 } 434 435 inline bool operator!=(const MemRegionVal& R) const { 436 return getRegion() != R.getRegion(); 437 } 438 439 // Implement isa<T> support. 440 static inline bool classof(const SVal* V) { 441 return V->getBaseKind() == LocKind && 442 V->getSubKind() == MemRegionKind; 443 } 444 445 static inline bool classof(const Loc* V) { 446 return V->getSubKind() == MemRegionKind; 447 } 448}; 449 450class FuncVal : public Loc { 451public: 452 FuncVal(const FunctionDecl* fd) : Loc(FuncValKind, fd) {} 453 454 FunctionDecl* getDecl() const { 455 return static_cast<FunctionDecl*>(Data); 456 } 457 458 inline bool operator==(const FuncVal& R) const { 459 return getDecl() == R.getDecl(); 460 } 461 462 inline bool operator!=(const FuncVal& R) const { 463 return getDecl() != R.getDecl(); 464 } 465 466 // Implement isa<T> support. 467 static inline bool classof(const SVal* V) { 468 return V->getBaseKind() == LocKind && 469 V->getSubKind() == FuncValKind; 470 } 471 472 static inline bool classof(const Loc* V) { 473 return V->getSubKind() == FuncValKind; 474 } 475}; 476 477class ConcreteInt : public Loc { 478public: 479 ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {} 480 481 const llvm::APSInt& getValue() const { 482 return *static_cast<llvm::APSInt*>(Data); 483 } 484 485 // Transfer functions for binary/unary operations on ConcreteInts. 486 SVal EvalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op, 487 const ConcreteInt& R) const; 488 489 // Implement isa<T> support. 490 static inline bool classof(const SVal* V) { 491 return V->getBaseKind() == LocKind && 492 V->getSubKind() == ConcreteIntKind; 493 } 494 495 static inline bool classof(const Loc* V) { 496 return V->getSubKind() == ConcreteIntKind; 497 } 498}; 499 500} // end clang::loc namespace 501} // end clang namespace 502 503#endif 504