1 //== SymbolManager.h - Management of Symbolic Values ------------*- 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 SymbolManager, a class that manages symbolic values 11 // created for use by ExprEngine and related classes. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" 16 #include "clang/Analysis/Analyses/LiveVariables.h" 17 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" 18 #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" 19 #include "llvm/Support/raw_ostream.h" 20 21 using namespace clang; 22 using namespace ento; 23 24 void SymExpr::dump() const { 25 dumpToStream(llvm::errs()); 26 } 27 28 static void print(raw_ostream &os, BinaryOperator::Opcode Op) { 29 switch (Op) { 30 default: 31 llvm_unreachable("operator printing not implemented"); 32 case BO_Mul: os << '*' ; break; 33 case BO_Div: os << '/' ; break; 34 case BO_Rem: os << '%' ; break; 35 case BO_Add: os << '+' ; break; 36 case BO_Sub: os << '-' ; break; 37 case BO_Shl: os << "<<" ; break; 38 case BO_Shr: os << ">>" ; break; 39 case BO_LT: os << "<" ; break; 40 case BO_GT: os << '>' ; break; 41 case BO_LE: os << "<=" ; break; 42 case BO_GE: os << ">=" ; break; 43 case BO_EQ: os << "==" ; break; 44 case BO_NE: os << "!=" ; break; 45 case BO_And: os << '&' ; break; 46 case BO_Xor: os << '^' ; break; 47 case BO_Or: os << '|' ; break; 48 } 49 } 50 51 void SymIntExpr::dumpToStream(raw_ostream &os) const { 52 os << '('; 53 getLHS()->dumpToStream(os); 54 os << ") "; 55 print(os, getOpcode()); 56 os << ' ' << getRHS().getZExtValue(); 57 if (getRHS().isUnsigned()) os << 'U'; 58 } 59 60 void SymSymExpr::dumpToStream(raw_ostream &os) const { 61 os << '('; 62 getLHS()->dumpToStream(os); 63 os << ") "; 64 os << '('; 65 getRHS()->dumpToStream(os); 66 os << ')'; 67 } 68 69 void SymbolCast::dumpToStream(raw_ostream &os) const { 70 os << '(' << ToTy.getAsString() << ") ("; 71 Operand->dumpToStream(os); 72 os << ')'; 73 } 74 75 void SymbolConjured::dumpToStream(raw_ostream &os) const { 76 os << "conj_$" << getSymbolID() << '{' << T.getAsString() << '}'; 77 } 78 79 void SymbolDerived::dumpToStream(raw_ostream &os) const { 80 os << "derived_$" << getSymbolID() << '{' 81 << getParentSymbol() << ',' << getRegion() << '}'; 82 } 83 84 void SymbolExtent::dumpToStream(raw_ostream &os) const { 85 os << "extent_$" << getSymbolID() << '{' << getRegion() << '}'; 86 } 87 88 void SymbolMetadata::dumpToStream(raw_ostream &os) const { 89 os << "meta_$" << getSymbolID() << '{' 90 << getRegion() << ',' << T.getAsString() << '}'; 91 } 92 93 void SymbolRegionValue::dumpToStream(raw_ostream &os) const { 94 os << "reg_$" << getSymbolID() << "<" << R << ">"; 95 } 96 97 bool SymExpr::symbol_iterator::operator==(const symbol_iterator &X) const { 98 return itr == X.itr; 99 } 100 101 bool SymExpr::symbol_iterator::operator!=(const symbol_iterator &X) const { 102 return itr != X.itr; 103 } 104 105 SymExpr::symbol_iterator::symbol_iterator(const SymExpr *SE) { 106 itr.push_back(SE); 107 while (!isa<SymbolData>(itr.back())) expand(); 108 } 109 110 SymExpr::symbol_iterator &SymExpr::symbol_iterator::operator++() { 111 assert(!itr.empty() && "attempting to iterate on an 'end' iterator"); 112 assert(isa<SymbolData>(itr.back())); 113 itr.pop_back(); 114 if (!itr.empty()) 115 while (!isa<SymbolData>(itr.back())) expand(); 116 return *this; 117 } 118 119 SymbolRef SymExpr::symbol_iterator::operator*() { 120 assert(!itr.empty() && "attempting to dereference an 'end' iterator"); 121 return cast<SymbolData>(itr.back()); 122 } 123 124 void SymExpr::symbol_iterator::expand() { 125 const SymExpr *SE = itr.back(); 126 itr.pop_back(); 127 128 if (const SymbolCast *SC = dyn_cast<SymbolCast>(SE)) { 129 itr.push_back(SC->getOperand()); 130 return; 131 } 132 if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) { 133 itr.push_back(SIE->getLHS()); 134 return; 135 } 136 else if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(SE)) { 137 itr.push_back(SSE->getLHS()); 138 itr.push_back(SSE->getRHS()); 139 return; 140 } 141 142 llvm_unreachable("unhandled expansion case"); 143 } 144 145 const SymbolRegionValue* 146 SymbolManager::getRegionValueSymbol(const TypedValueRegion* R) { 147 llvm::FoldingSetNodeID profile; 148 SymbolRegionValue::Profile(profile, R); 149 void *InsertPos; 150 SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); 151 if (!SD) { 152 SD = (SymExpr*) BPAlloc.Allocate<SymbolRegionValue>(); 153 new (SD) SymbolRegionValue(SymbolCounter, R); 154 DataSet.InsertNode(SD, InsertPos); 155 ++SymbolCounter; 156 } 157 158 return cast<SymbolRegionValue>(SD); 159 } 160 161 const SymbolConjured* 162 SymbolManager::getConjuredSymbol(const Stmt *E, QualType T, unsigned Count, 163 const void *SymbolTag) { 164 165 llvm::FoldingSetNodeID profile; 166 SymbolConjured::Profile(profile, E, T, Count, SymbolTag); 167 void *InsertPos; 168 SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); 169 if (!SD) { 170 SD = (SymExpr*) BPAlloc.Allocate<SymbolConjured>(); 171 new (SD) SymbolConjured(SymbolCounter, E, T, Count, SymbolTag); 172 DataSet.InsertNode(SD, InsertPos); 173 ++SymbolCounter; 174 } 175 176 return cast<SymbolConjured>(SD); 177 } 178 179 const SymbolDerived* 180 SymbolManager::getDerivedSymbol(SymbolRef parentSymbol, 181 const TypedValueRegion *R) { 182 183 llvm::FoldingSetNodeID profile; 184 SymbolDerived::Profile(profile, parentSymbol, R); 185 void *InsertPos; 186 SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); 187 if (!SD) { 188 SD = (SymExpr*) BPAlloc.Allocate<SymbolDerived>(); 189 new (SD) SymbolDerived(SymbolCounter, parentSymbol, R); 190 DataSet.InsertNode(SD, InsertPos); 191 ++SymbolCounter; 192 } 193 194 return cast<SymbolDerived>(SD); 195 } 196 197 const SymbolExtent* 198 SymbolManager::getExtentSymbol(const SubRegion *R) { 199 llvm::FoldingSetNodeID profile; 200 SymbolExtent::Profile(profile, R); 201 void *InsertPos; 202 SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); 203 if (!SD) { 204 SD = (SymExpr*) BPAlloc.Allocate<SymbolExtent>(); 205 new (SD) SymbolExtent(SymbolCounter, R); 206 DataSet.InsertNode(SD, InsertPos); 207 ++SymbolCounter; 208 } 209 210 return cast<SymbolExtent>(SD); 211 } 212 213 const SymbolMetadata* 214 SymbolManager::getMetadataSymbol(const MemRegion* R, const Stmt *S, QualType T, 215 unsigned Count, const void *SymbolTag) { 216 217 llvm::FoldingSetNodeID profile; 218 SymbolMetadata::Profile(profile, R, S, T, Count, SymbolTag); 219 void *InsertPos; 220 SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); 221 if (!SD) { 222 SD = (SymExpr*) BPAlloc.Allocate<SymbolMetadata>(); 223 new (SD) SymbolMetadata(SymbolCounter, R, S, T, Count, SymbolTag); 224 DataSet.InsertNode(SD, InsertPos); 225 ++SymbolCounter; 226 } 227 228 return cast<SymbolMetadata>(SD); 229 } 230 231 const SymbolCast* 232 SymbolManager::getCastSymbol(const SymExpr *Op, 233 QualType From, QualType To) { 234 llvm::FoldingSetNodeID ID; 235 SymbolCast::Profile(ID, Op, From, To); 236 void *InsertPos; 237 SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos); 238 if (!data) { 239 data = (SymbolCast*) BPAlloc.Allocate<SymbolCast>(); 240 new (data) SymbolCast(Op, From, To); 241 DataSet.InsertNode(data, InsertPos); 242 } 243 244 return cast<SymbolCast>(data); 245 } 246 247 const SymIntExpr *SymbolManager::getSymIntExpr(const SymExpr *lhs, 248 BinaryOperator::Opcode op, 249 const llvm::APSInt& v, 250 QualType t) { 251 llvm::FoldingSetNodeID ID; 252 SymIntExpr::Profile(ID, lhs, op, v, t); 253 void *InsertPos; 254 SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos); 255 256 if (!data) { 257 data = (SymIntExpr*) BPAlloc.Allocate<SymIntExpr>(); 258 new (data) SymIntExpr(lhs, op, v, t); 259 DataSet.InsertNode(data, InsertPos); 260 } 261 262 return cast<SymIntExpr>(data); 263 } 264 265 const SymSymExpr *SymbolManager::getSymSymExpr(const SymExpr *lhs, 266 BinaryOperator::Opcode op, 267 const SymExpr *rhs, 268 QualType t) { 269 llvm::FoldingSetNodeID ID; 270 SymSymExpr::Profile(ID, lhs, op, rhs, t); 271 void *InsertPos; 272 SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos); 273 274 if (!data) { 275 data = (SymSymExpr*) BPAlloc.Allocate<SymSymExpr>(); 276 new (data) SymSymExpr(lhs, op, rhs, t); 277 DataSet.InsertNode(data, InsertPos); 278 } 279 280 return cast<SymSymExpr>(data); 281 } 282 283 QualType SymbolConjured::getType(ASTContext&) const { 284 return T; 285 } 286 287 QualType SymbolDerived::getType(ASTContext &Ctx) const { 288 return R->getValueType(); 289 } 290 291 QualType SymbolExtent::getType(ASTContext &Ctx) const { 292 return Ctx.getSizeType(); 293 } 294 295 QualType SymbolMetadata::getType(ASTContext&) const { 296 return T; 297 } 298 299 QualType SymbolRegionValue::getType(ASTContext &C) const { 300 return R->getValueType(); 301 } 302 303 SymbolManager::~SymbolManager() { 304 for (SymbolDependTy::const_iterator I = SymbolDependencies.begin(), 305 E = SymbolDependencies.end(); I != E; ++I) { 306 delete I->second; 307 } 308 309 } 310 311 bool SymbolManager::canSymbolicate(QualType T) { 312 T = T.getCanonicalType(); 313 314 if (Loc::isLocType(T)) 315 return true; 316 317 if (T->isIntegerType()) 318 return T->isScalarType(); 319 320 if (T->isRecordType() && !T->isUnionType()) 321 return true; 322 323 return false; 324 } 325 326 void SymbolManager::addSymbolDependency(const SymbolRef Primary, 327 const SymbolRef Dependent) { 328 SymbolDependTy::iterator I = SymbolDependencies.find(Primary); 329 SymbolRefSmallVectorTy *dependencies = 0; 330 if (I == SymbolDependencies.end()) { 331 dependencies = new SymbolRefSmallVectorTy(); 332 SymbolDependencies[Primary] = dependencies; 333 } else { 334 dependencies = I->second; 335 } 336 dependencies->push_back(Dependent); 337 } 338 339 const SymbolRefSmallVectorTy *SymbolManager::getDependentSymbols( 340 const SymbolRef Primary) { 341 SymbolDependTy::const_iterator I = SymbolDependencies.find(Primary); 342 if (I == SymbolDependencies.end()) 343 return 0; 344 return I->second; 345 } 346 347 void SymbolReaper::markDependentsLive(SymbolRef sym) { 348 // Do not mark dependents more then once. 349 SymbolMapTy::iterator LI = TheLiving.find(sym); 350 assert(LI != TheLiving.end() && "The primary symbol is not live."); 351 if (LI->second == HaveMarkedDependents) 352 return; 353 LI->second = HaveMarkedDependents; 354 355 if (const SymbolRefSmallVectorTy *Deps = SymMgr.getDependentSymbols(sym)) { 356 for (SymbolRefSmallVectorTy::const_iterator I = Deps->begin(), 357 E = Deps->end(); I != E; ++I) { 358 if (TheLiving.find(*I) != TheLiving.end()) 359 continue; 360 markLive(*I); 361 } 362 } 363 } 364 365 void SymbolReaper::markLive(SymbolRef sym) { 366 TheLiving[sym] = NotProcessed; 367 TheDead.erase(sym); 368 markDependentsLive(sym); 369 } 370 371 void SymbolReaper::markLive(const MemRegion *region) { 372 RegionRoots.insert(region); 373 } 374 375 void SymbolReaper::markInUse(SymbolRef sym) { 376 if (isa<SymbolMetadata>(sym)) 377 MetadataInUse.insert(sym); 378 } 379 380 bool SymbolReaper::maybeDead(SymbolRef sym) { 381 if (isLive(sym)) 382 return false; 383 384 TheDead.insert(sym); 385 return true; 386 } 387 388 bool SymbolReaper::isLiveRegion(const MemRegion *MR) { 389 if (RegionRoots.count(MR)) 390 return true; 391 392 MR = MR->getBaseRegion(); 393 394 if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR)) 395 return isLive(SR->getSymbol()); 396 397 if (const VarRegion *VR = dyn_cast<VarRegion>(MR)) 398 return isLive(VR, true); 399 400 // FIXME: This is a gross over-approximation. What we really need is a way to 401 // tell if anything still refers to this region. Unlike SymbolicRegions, 402 // AllocaRegions don't have associated symbols, though, so we don't actually 403 // have a way to track their liveness. 404 if (isa<AllocaRegion>(MR)) 405 return true; 406 407 if (isa<CXXThisRegion>(MR)) 408 return true; 409 410 if (isa<MemSpaceRegion>(MR)) 411 return true; 412 413 return false; 414 } 415 416 bool SymbolReaper::isLive(SymbolRef sym) { 417 if (TheLiving.count(sym)) { 418 markDependentsLive(sym); 419 return true; 420 } 421 422 if (const SymbolDerived *derived = dyn_cast<SymbolDerived>(sym)) { 423 if (isLive(derived->getParentSymbol())) { 424 markLive(sym); 425 return true; 426 } 427 return false; 428 } 429 430 if (const SymbolExtent *extent = dyn_cast<SymbolExtent>(sym)) { 431 if (isLiveRegion(extent->getRegion())) { 432 markLive(sym); 433 return true; 434 } 435 return false; 436 } 437 438 if (const SymbolMetadata *metadata = dyn_cast<SymbolMetadata>(sym)) { 439 if (MetadataInUse.count(sym)) { 440 if (isLiveRegion(metadata->getRegion())) { 441 markLive(sym); 442 MetadataInUse.erase(sym); 443 return true; 444 } 445 } 446 return false; 447 } 448 449 // Interogate the symbol. It may derive from an input value to 450 // the analyzed function/method. 451 return isa<SymbolRegionValue>(sym); 452 } 453 454 bool SymbolReaper::isLive(const Stmt *ExprVal) const { 455 return LCtx->getAnalysis<RelaxedLiveVariables>()->isLive(Loc, ExprVal); 456 } 457 458 bool SymbolReaper::isLive(const VarRegion *VR, bool includeStoreBindings) const{ 459 const StackFrameContext *VarContext = VR->getStackFrame(); 460 const StackFrameContext *CurrentContext = LCtx->getCurrentStackFrame(); 461 462 if (VarContext == CurrentContext) { 463 if (LCtx->getAnalysis<RelaxedLiveVariables>()->isLive(Loc, VR->getDecl())) 464 return true; 465 466 if (!includeStoreBindings) 467 return false; 468 469 unsigned &cachedQuery = 470 const_cast<SymbolReaper*>(this)->includedRegionCache[VR]; 471 472 if (cachedQuery) { 473 return cachedQuery == 1; 474 } 475 476 // Query the store to see if the region occurs in any live bindings. 477 if (Store store = reapedStore.getStore()) { 478 bool hasRegion = 479 reapedStore.getStoreManager().includedInBindings(store, VR); 480 cachedQuery = hasRegion ? 1 : 2; 481 return hasRegion; 482 } 483 484 return false; 485 } 486 487 return VarContext->isParentOf(CurrentContext); 488 } 489 490 SymbolVisitor::~SymbolVisitor() {} 491