UninitializedValues.cpp revision 6cfa78f6bd4e7d5e23366a0907f8f8792366bc4c
1//==- UninitializedValues.cpp - Find Uninitialized 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 implements uninitialized values analysis for source-level CFGs. 11// 12//===----------------------------------------------------------------------===// 13 14#include <utility> 15#include "llvm/ADT/Optional.h" 16#include "llvm/ADT/SmallVector.h" 17#include "llvm/ADT/PackedVector.h" 18#include "llvm/ADT/DenseMap.h" 19#include "clang/AST/ASTContext.h" 20#include "clang/AST/Decl.h" 21#include "clang/Analysis/CFG.h" 22#include "clang/Analysis/AnalysisContext.h" 23#include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h" 24#include "clang/Analysis/Analyses/UninitializedValues.h" 25#include "llvm/Support/SaveAndRestore.h" 26 27using namespace clang; 28 29#define DEBUG_LOGGING 0 30 31static bool isTrackedVar(const VarDecl *vd, const DeclContext *dc) { 32 if (vd->isLocalVarDecl() && !vd->hasGlobalStorage() && 33 !vd->isExceptionVariable() && 34 vd->getDeclContext() == dc) { 35 QualType ty = vd->getType(); 36 return ty->isScalarType() || ty->isVectorType(); 37 } 38 return false; 39} 40 41//------------------------------------------------------------------------====// 42// DeclToIndex: a mapping from Decls we track to value indices. 43//====------------------------------------------------------------------------// 44 45namespace { 46class DeclToIndex { 47 llvm::DenseMap<const VarDecl *, unsigned> map; 48public: 49 DeclToIndex() {} 50 51 /// Compute the actual mapping from declarations to bits. 52 void computeMap(const DeclContext &dc); 53 54 /// Return the number of declarations in the map. 55 unsigned size() const { return map.size(); } 56 57 /// Returns the bit vector index for a given declaration. 58 llvm::Optional<unsigned> getValueIndex(const VarDecl *d) const; 59}; 60} 61 62void DeclToIndex::computeMap(const DeclContext &dc) { 63 unsigned count = 0; 64 DeclContext::specific_decl_iterator<VarDecl> I(dc.decls_begin()), 65 E(dc.decls_end()); 66 for ( ; I != E; ++I) { 67 const VarDecl *vd = *I; 68 if (isTrackedVar(vd, &dc)) 69 map[vd] = count++; 70 } 71} 72 73llvm::Optional<unsigned> DeclToIndex::getValueIndex(const VarDecl *d) const { 74 llvm::DenseMap<const VarDecl *, unsigned>::const_iterator I = map.find(d); 75 if (I == map.end()) 76 return llvm::Optional<unsigned>(); 77 return I->second; 78} 79 80//------------------------------------------------------------------------====// 81// CFGBlockValues: dataflow values for CFG blocks. 82//====------------------------------------------------------------------------// 83 84// These values are defined in such a way that a merge can be done using 85// a bitwise OR. 86enum Value { Unknown = 0x0, /* 00 */ 87 Initialized = 0x1, /* 01 */ 88 Uninitialized = 0x2, /* 10 */ 89 MayUninitialized = 0x3 /* 11 */ }; 90 91static bool isUninitialized(const Value v) { 92 return v >= Uninitialized; 93} 94static bool isAlwaysUninit(const Value v) { 95 return v == Uninitialized; 96} 97 98namespace { 99 100typedef llvm::PackedVector<Value, 2> ValueVector; 101typedef std::pair<ValueVector *, ValueVector *> BVPair; 102 103class CFGBlockValues { 104 const CFG &cfg; 105 BVPair *vals; 106 ValueVector scratch; 107 DeclToIndex declToIndex; 108 109 ValueVector &lazyCreate(ValueVector *&bv); 110public: 111 CFGBlockValues(const CFG &cfg); 112 ~CFGBlockValues(); 113 114 unsigned getNumEntries() const { return declToIndex.size(); } 115 116 void computeSetOfDeclarations(const DeclContext &dc); 117 ValueVector &getValueVector(const CFGBlock *block, 118 const CFGBlock *dstBlock); 119 120 BVPair &getValueVectors(const CFGBlock *block, bool shouldLazyCreate); 121 122 void setAllScratchValues(Value V); 123 void mergeIntoScratch(ValueVector const &source, bool isFirst); 124 bool updateValueVectorWithScratch(const CFGBlock *block); 125 bool updateValueVectors(const CFGBlock *block, const BVPair &newVals); 126 127 bool hasNoDeclarations() const { 128 return declToIndex.size() == 0; 129 } 130 131 void resetScratch(); 132 ValueVector &getScratch() { return scratch; } 133 134 ValueVector::reference operator[](const VarDecl *vd); 135 136 Value getValue(const CFGBlock *block, const CFGBlock *dstBlock, 137 const VarDecl *vd) { 138 const llvm::Optional<unsigned> &idx = declToIndex.getValueIndex(vd); 139 assert(idx.hasValue()); 140 return getValueVector(block, dstBlock)[idx.getValue()]; 141 } 142}; 143} // end anonymous namespace 144 145CFGBlockValues::CFGBlockValues(const CFG &c) : cfg(c), vals(0) { 146 unsigned n = cfg.getNumBlockIDs(); 147 if (!n) 148 return; 149 vals = new std::pair<ValueVector*, ValueVector*>[n]; 150 memset((void*)vals, 0, sizeof(*vals) * n); 151} 152 153CFGBlockValues::~CFGBlockValues() { 154 unsigned n = cfg.getNumBlockIDs(); 155 if (n == 0) 156 return; 157 for (unsigned i = 0; i < n; ++i) { 158 delete vals[i].first; 159 delete vals[i].second; 160 } 161 delete [] vals; 162} 163 164void CFGBlockValues::computeSetOfDeclarations(const DeclContext &dc) { 165 declToIndex.computeMap(dc); 166 scratch.resize(declToIndex.size()); 167} 168 169ValueVector &CFGBlockValues::lazyCreate(ValueVector *&bv) { 170 if (!bv) 171 bv = new ValueVector(declToIndex.size()); 172 return *bv; 173} 174 175/// This function pattern matches for a '&&' or '||' that appears at 176/// the beginning of a CFGBlock that also (1) has a terminator and 177/// (2) has no other elements. If such an expression is found, it is returned. 178static const BinaryOperator *getLogicalOperatorInChain(const CFGBlock *block) { 179 if (block->empty()) 180 return 0; 181 182 CFGElement front = block->front(); 183 const CFGStmt *cstmt = front.getAs<CFGStmt>(); 184 if (!cstmt) 185 return 0; 186 187 const BinaryOperator *b = dyn_cast_or_null<BinaryOperator>(cstmt->getStmt()); 188 189 if (!b || !b->isLogicalOp()) 190 return 0; 191 192 if (block->pred_size() == 2) { 193 if (block->getTerminatorCondition() == b) { 194 if (block->succ_size() == 2) 195 return b; 196 } 197 else if (block->size() == 1) 198 return b; 199 } 200 201 return 0; 202} 203 204ValueVector &CFGBlockValues::getValueVector(const CFGBlock *block, 205 const CFGBlock *dstBlock) { 206 unsigned idx = block->getBlockID(); 207 if (dstBlock && getLogicalOperatorInChain(block)) { 208 if (*block->succ_begin() == dstBlock) 209 return lazyCreate(vals[idx].first); 210 assert(*(block->succ_begin()+1) == dstBlock); 211 return lazyCreate(vals[idx].second); 212 } 213 214 assert(vals[idx].second == 0); 215 return lazyCreate(vals[idx].first); 216} 217 218BVPair &CFGBlockValues::getValueVectors(const clang::CFGBlock *block, 219 bool shouldLazyCreate) { 220 unsigned idx = block->getBlockID(); 221 lazyCreate(vals[idx].first); 222 if (shouldLazyCreate) 223 lazyCreate(vals[idx].second); 224 return vals[idx]; 225} 226 227#if DEBUG_LOGGING 228static void printVector(const CFGBlock *block, ValueVector &bv, 229 unsigned num) { 230 llvm::errs() << block->getBlockID() << " :"; 231 for (unsigned i = 0; i < bv.size(); ++i) { 232 llvm::errs() << ' ' << bv[i]; 233 } 234 llvm::errs() << " : " << num << '\n'; 235} 236#endif 237 238void CFGBlockValues::setAllScratchValues(Value V) { 239 for (unsigned I = 0, E = scratch.size(); I != E; ++I) 240 scratch[I] = V; 241} 242 243void CFGBlockValues::mergeIntoScratch(ValueVector const &source, 244 bool isFirst) { 245 if (isFirst) 246 scratch = source; 247 else 248 scratch |= source; 249} 250 251bool CFGBlockValues::updateValueVectorWithScratch(const CFGBlock *block) { 252 ValueVector &dst = getValueVector(block, 0); 253 bool changed = (dst != scratch); 254 if (changed) 255 dst = scratch; 256#if DEBUG_LOGGING 257 printVector(block, scratch, 0); 258#endif 259 return changed; 260} 261 262bool CFGBlockValues::updateValueVectors(const CFGBlock *block, 263 const BVPair &newVals) { 264 BVPair &vals = getValueVectors(block, true); 265 bool changed = *newVals.first != *vals.first || 266 *newVals.second != *vals.second; 267 *vals.first = *newVals.first; 268 *vals.second = *newVals.second; 269#if DEBUG_LOGGING 270 printVector(block, *vals.first, 1); 271 printVector(block, *vals.second, 2); 272#endif 273 return changed; 274} 275 276void CFGBlockValues::resetScratch() { 277 scratch.reset(); 278} 279 280ValueVector::reference CFGBlockValues::operator[](const VarDecl *vd) { 281 const llvm::Optional<unsigned> &idx = declToIndex.getValueIndex(vd); 282 assert(idx.hasValue()); 283 return scratch[idx.getValue()]; 284} 285 286//------------------------------------------------------------------------====// 287// Worklist: worklist for dataflow analysis. 288//====------------------------------------------------------------------------// 289 290namespace { 291class DataflowWorklist { 292 SmallVector<const CFGBlock *, 20> worklist; 293 llvm::BitVector enqueuedBlocks; 294public: 295 DataflowWorklist(const CFG &cfg) : enqueuedBlocks(cfg.getNumBlockIDs()) {} 296 297 void enqueueSuccessors(const CFGBlock *block); 298 const CFGBlock *dequeue(); 299}; 300} 301 302void DataflowWorklist::enqueueSuccessors(const clang::CFGBlock *block) { 303 unsigned OldWorklistSize = worklist.size(); 304 for (CFGBlock::const_succ_iterator I = block->succ_begin(), 305 E = block->succ_end(); I != E; ++I) { 306 const CFGBlock *Successor = *I; 307 if (!Successor || enqueuedBlocks[Successor->getBlockID()]) 308 continue; 309 worklist.push_back(Successor); 310 enqueuedBlocks[Successor->getBlockID()] = true; 311 } 312 if (OldWorklistSize == 0 || OldWorklistSize == worklist.size()) 313 return; 314 315 // Rotate the newly added blocks to the start of the worklist so that it forms 316 // a proper queue when we pop off the end of the worklist. 317 std::rotate(worklist.begin(), worklist.begin() + OldWorklistSize, 318 worklist.end()); 319} 320 321const CFGBlock *DataflowWorklist::dequeue() { 322 if (worklist.empty()) 323 return 0; 324 const CFGBlock *b = worklist.back(); 325 worklist.pop_back(); 326 enqueuedBlocks[b->getBlockID()] = false; 327 return b; 328} 329 330//------------------------------------------------------------------------====// 331// Classification of DeclRefExprs as use or initialization. 332//====------------------------------------------------------------------------// 333 334namespace { 335class FindVarResult { 336 const VarDecl *vd; 337 const DeclRefExpr *dr; 338public: 339 FindVarResult(const VarDecl *vd, const DeclRefExpr *dr) : vd(vd), dr(dr) {} 340 341 const DeclRefExpr *getDeclRefExpr() const { return dr; } 342 const VarDecl *getDecl() const { return vd; } 343}; 344 345static const Expr *stripCasts(ASTContext &C, const Expr *Ex) { 346 while (Ex) { 347 Ex = Ex->IgnoreParenNoopCasts(C); 348 if (const CastExpr *CE = dyn_cast<CastExpr>(Ex)) { 349 if (CE->getCastKind() == CK_LValueBitCast) { 350 Ex = CE->getSubExpr(); 351 continue; 352 } 353 } 354 break; 355 } 356 return Ex; 357} 358 359/// If E is an expression comprising a reference to a single variable, find that 360/// variable. 361static FindVarResult findVar(const Expr *E, const DeclContext *DC) { 362 if (const DeclRefExpr *DRE = 363 dyn_cast<DeclRefExpr>(stripCasts(DC->getParentASTContext(), E))) 364 if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) 365 if (isTrackedVar(VD, DC)) 366 return FindVarResult(VD, DRE); 367 return FindVarResult(0, 0); 368} 369 370/// \brief Classify each DeclRefExpr as an initialization or a use. Any 371/// DeclRefExpr which isn't explicitly classified will be assumed to have 372/// escaped the analysis and will be treated as an initialization. 373class ClassifyRefs : public StmtVisitor<ClassifyRefs> { 374public: 375 enum Class { 376 Init, 377 Use, 378 SelfInit, 379 Ignore 380 }; 381 382private: 383 const DeclContext *DC; 384 llvm::DenseMap<const DeclRefExpr*, Class> Classification; 385 386 bool isTrackedVar(const VarDecl *VD) const { 387 return ::isTrackedVar(VD, DC); 388 } 389 390 void classify(const Expr *E, Class C); 391 392public: 393 ClassifyRefs(AnalysisDeclContext &AC) : DC(cast<DeclContext>(AC.getDecl())) {} 394 395 void VisitDeclStmt(DeclStmt *DS); 396 void VisitUnaryOperator(UnaryOperator *UO); 397 void VisitBinaryOperator(BinaryOperator *BO); 398 void VisitCallExpr(CallExpr *CE); 399 void VisitCastExpr(CastExpr *CE); 400 401 void operator()(Stmt *S) { Visit(S); } 402 403 Class get(const DeclRefExpr *DRE) const { 404 llvm::DenseMap<const DeclRefExpr*, Class>::const_iterator I 405 = Classification.find(DRE); 406 if (I != Classification.end()) 407 return I->second; 408 409 const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()); 410 if (!VD || !isTrackedVar(VD)) 411 return Ignore; 412 413 return Init; 414 } 415}; 416} 417 418static const DeclRefExpr *getSelfInitExpr(VarDecl *VD) { 419 if (Expr *Init = VD->getInit()) { 420 const DeclRefExpr *DRE 421 = dyn_cast<DeclRefExpr>(stripCasts(VD->getASTContext(), Init)); 422 if (DRE && DRE->getDecl() == VD) 423 return DRE; 424 } 425 return 0; 426} 427 428void ClassifyRefs::classify(const Expr *E, Class C) { 429 FindVarResult Var = findVar(E, DC); 430 if (const DeclRefExpr *DRE = Var.getDeclRefExpr()) 431 Classification[DRE] = std::max(Classification[DRE], C); 432} 433 434void ClassifyRefs::VisitDeclStmt(DeclStmt *DS) { 435 for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end(); 436 DI != DE; ++DI) { 437 VarDecl *VD = dyn_cast<VarDecl>(*DI); 438 if (VD && isTrackedVar(VD)) 439 if (const DeclRefExpr *DRE = getSelfInitExpr(VD)) 440 Classification[DRE] = SelfInit; 441 } 442} 443 444void ClassifyRefs::VisitBinaryOperator(BinaryOperator *BO) { 445 // Ignore the evaluation of a DeclRefExpr on the LHS of an assignment. If this 446 // is not a compound-assignment, we will treat it as initializing the variable 447 // when TransferFunctions visits it. A compound-assignment does not affect 448 // whether a variable is uninitialized, and there's no point counting it as a 449 // use. 450 if (BO->isCompoundAssignmentOp()) 451 classify(BO->getLHS(), Use); 452 else if (BO->getOpcode() == BO_Assign) 453 classify(BO->getLHS(), Ignore); 454} 455 456void ClassifyRefs::VisitUnaryOperator(UnaryOperator *UO) { 457 // Increment and decrement are uses despite there being no lvalue-to-rvalue 458 // conversion. 459 if (UO->isIncrementDecrementOp()) 460 classify(UO->getSubExpr(), Use); 461} 462 463void ClassifyRefs::VisitCallExpr(CallExpr *CE) { 464 // If a value is passed by const reference to a function, we should not assume 465 // that it is initialized by the call, and we conservatively do not assume 466 // that it is used. 467 for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end(); 468 I != E; ++I) 469 if ((*I)->getType().isConstQualified() && (*I)->isGLValue()) 470 classify(*I, Ignore); 471} 472 473void ClassifyRefs::VisitCastExpr(CastExpr *CE) { 474 if (CE->getCastKind() == CK_LValueToRValue) 475 classify(CE->getSubExpr(), Use); 476 else if (CStyleCastExpr *CSE = dyn_cast<CStyleCastExpr>(CE)) { 477 if (CSE->getType()->isVoidType()) { 478 // Squelch any detected load of an uninitialized value if 479 // we cast it to void. 480 // e.g. (void) x; 481 classify(CSE->getSubExpr(), Ignore); 482 } 483 } 484} 485 486//------------------------------------------------------------------------====// 487// Transfer function for uninitialized values analysis. 488//====------------------------------------------------------------------------// 489 490namespace { 491class TransferFunctions : public StmtVisitor<TransferFunctions> { 492 CFGBlockValues &vals; 493 const CFG &cfg; 494 const CFGBlock *block; 495 AnalysisDeclContext ∾ 496 const ClassifyRefs &classification; 497 UninitVariablesHandler *handler; 498 499public: 500 TransferFunctions(CFGBlockValues &vals, const CFG &cfg, 501 const CFGBlock *block, AnalysisDeclContext &ac, 502 const ClassifyRefs &classification, 503 UninitVariablesHandler *handler) 504 : vals(vals), cfg(cfg), block(block), ac(ac), 505 classification(classification), handler(handler) {} 506 507 void reportUse(const Expr *ex, const VarDecl *vd); 508 509 void VisitObjCForCollectionStmt(ObjCForCollectionStmt *FS); 510 void VisitBlockExpr(BlockExpr *be); 511 void VisitCallExpr(CallExpr *ce); 512 void VisitDeclStmt(DeclStmt *ds); 513 void VisitDeclRefExpr(DeclRefExpr *dr); 514 void VisitBinaryOperator(BinaryOperator *bo); 515 516 bool isTrackedVar(const VarDecl *vd) { 517 return ::isTrackedVar(vd, cast<DeclContext>(ac.getDecl())); 518 } 519 520 FindVarResult findVar(const Expr *ex) { 521 return ::findVar(ex, cast<DeclContext>(ac.getDecl())); 522 } 523 524 UninitUse getUninitUse(const Expr *ex, const VarDecl *vd, Value v) { 525 UninitUse Use(ex, isAlwaysUninit(v)); 526 527 assert(isUninitialized(v)); 528 if (Use.getKind() == UninitUse::Always) 529 return Use; 530 531 // If an edge which leads unconditionally to this use did not initialize 532 // the variable, we can say something stronger than 'may be uninitialized': 533 // we can say 'either it's used uninitialized or you have dead code'. 534 // 535 // We track the number of successors of a node which have been visited, and 536 // visit a node once we have visited all of its successors. Only edges where 537 // the variable might still be uninitialized are followed. Since a variable 538 // can't transfer from being initialized to being uninitialized, this will 539 // trace out the subgraph which inevitably leads to the use and does not 540 // initialize the variable. We do not want to skip past loops, since their 541 // non-termination might be correlated with the initialization condition. 542 // 543 // For example: 544 // 545 // void f(bool a, bool b) { 546 // block1: int n; 547 // if (a) { 548 // block2: if (b) 549 // block3: n = 1; 550 // block4: } else if (b) { 551 // block5: while (!a) { 552 // block6: do_work(&a); 553 // n = 2; 554 // } 555 // } 556 // block7: if (a) 557 // block8: g(); 558 // block9: return n; 559 // } 560 // 561 // Starting from the maybe-uninitialized use in block 9: 562 // * Block 7 is not visited because we have only visited one of its two 563 // successors. 564 // * Block 8 is visited because we've visited its only successor. 565 // From block 8: 566 // * Block 7 is visited because we've now visited both of its successors. 567 // From block 7: 568 // * Blocks 1, 2, 4, 5, and 6 are not visited because we didn't visit all 569 // of their successors (we didn't visit 4, 3, 5, 6, and 5, respectively). 570 // * Block 3 is not visited because it initializes 'n'. 571 // Now the algorithm terminates, having visited blocks 7 and 8, and having 572 // found the frontier is blocks 2, 4, and 5. 573 // 574 // 'n' is definitely uninitialized for two edges into block 7 (from blocks 2 575 // and 4), so we report that any time either of those edges is taken (in 576 // each case when 'b == false'), 'n' is used uninitialized. 577 llvm::SmallVector<const CFGBlock*, 32> Queue; 578 llvm::SmallVector<unsigned, 32> SuccsVisited(cfg.getNumBlockIDs(), 0); 579 Queue.push_back(block); 580 // Specify that we've already visited all successors of the starting block. 581 // This has the dual purpose of ensuring we never add it to the queue, and 582 // of marking it as not being a candidate element of the frontier. 583 SuccsVisited[block->getBlockID()] = block->succ_size(); 584 while (!Queue.empty()) { 585 const CFGBlock *B = Queue.back(); 586 Queue.pop_back(); 587 for (CFGBlock::const_pred_iterator I = B->pred_begin(), E = B->pred_end(); 588 I != E; ++I) { 589 const CFGBlock *Pred = *I; 590 if (vals.getValue(Pred, B, vd) == Initialized) 591 // This block initializes the variable. 592 continue; 593 594 unsigned &SV = SuccsVisited[Pred->getBlockID()]; 595 if (!SV) { 596 // When visiting the first successor of a block, mark all NULL 597 // successors as having been visited. 598 for (CFGBlock::const_succ_iterator SI = Pred->succ_begin(), 599 SE = Pred->succ_end(); 600 SI != SE; ++SI) 601 if (!*SI) 602 ++SV; 603 } 604 605 if (++SV == Pred->succ_size()) 606 // All paths from this block lead to the use and don't initialize the 607 // variable. 608 Queue.push_back(Pred); 609 } 610 } 611 612 // Scan the frontier, looking for blocks where the variable was 613 // uninitialized. 614 for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI) { 615 const CFGBlock *Block = *BI; 616 unsigned BlockID = Block->getBlockID(); 617 const Stmt *Term = Block->getTerminator(); 618 if (SuccsVisited[BlockID] && SuccsVisited[BlockID] < Block->succ_size() && 619 Term) { 620 // This block inevitably leads to the use. If we have an edge from here 621 // to a post-dominator block, and the variable is uninitialized on that 622 // edge, we have found a bug. 623 for (CFGBlock::const_succ_iterator I = Block->succ_begin(), 624 E = Block->succ_end(); I != E; ++I) { 625 const CFGBlock *Succ = *I; 626 if (Succ && SuccsVisited[Succ->getBlockID()] >= Succ->succ_size() && 627 vals.getValue(Block, Succ, vd) == Uninitialized) { 628 // Switch cases are a special case: report the label to the caller 629 // as the 'terminator', not the switch statement itself. Suppress 630 // situations where no label matched: we can't be sure that's 631 // possible. 632 if (isa<SwitchStmt>(Term)) { 633 const Stmt *Label = Succ->getLabel(); 634 if (!Label || !isa<SwitchCase>(Label)) 635 // Might not be possible. 636 continue; 637 UninitUse::Branch Branch; 638 Branch.Terminator = Label; 639 Branch.Output = 0; // Ignored. 640 Use.addUninitBranch(Branch); 641 } else { 642 UninitUse::Branch Branch; 643 Branch.Terminator = Term; 644 Branch.Output = I - Block->succ_begin(); 645 Use.addUninitBranch(Branch); 646 } 647 } 648 } 649 } 650 } 651 652 return Use; 653 } 654}; 655} 656 657void TransferFunctions::reportUse(const Expr *ex, const VarDecl *vd) { 658 if (!handler) 659 return; 660 Value v = vals[vd]; 661 if (isUninitialized(v)) 662 handler->handleUseOfUninitVariable(vd, getUninitUse(ex, vd, v)); 663} 664 665void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *FS) { 666 // This represents an initialization of the 'element' value. 667 if (DeclStmt *DS = dyn_cast<DeclStmt>(FS->getElement())) { 668 const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl()); 669 if (isTrackedVar(VD)) 670 vals[VD] = Initialized; 671 } 672} 673 674void TransferFunctions::VisitBlockExpr(BlockExpr *be) { 675 const BlockDecl *bd = be->getBlockDecl(); 676 for (BlockDecl::capture_const_iterator i = bd->capture_begin(), 677 e = bd->capture_end() ; i != e; ++i) { 678 const VarDecl *vd = i->getVariable(); 679 if (!isTrackedVar(vd)) 680 continue; 681 if (i->isByRef()) { 682 vals[vd] = Initialized; 683 continue; 684 } 685 reportUse(be, vd); 686 } 687} 688 689void TransferFunctions::VisitCallExpr(CallExpr *ce) { 690 // After a call to a function like setjmp or vfork, any variable which is 691 // initialized anywhere within this function may now be initialized. For now, 692 // just assume such a call initializes all variables. 693 // FIXME: Only mark variables as initialized if they have an initializer which 694 // is reachable from here. 695 Decl *Callee = ce->getCalleeDecl(); 696 if (Callee && Callee->hasAttr<ReturnsTwiceAttr>()) 697 vals.setAllScratchValues(Initialized); 698} 699 700void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *dr) { 701 switch (classification.get(dr)) { 702 case ClassifyRefs::Ignore: 703 break; 704 case ClassifyRefs::Use: 705 reportUse(dr, cast<VarDecl>(dr->getDecl())); 706 break; 707 case ClassifyRefs::Init: 708 vals[cast<VarDecl>(dr->getDecl())] = Initialized; 709 break; 710 case ClassifyRefs::SelfInit: 711 if (handler) 712 handler->handleSelfInit(cast<VarDecl>(dr->getDecl())); 713 break; 714 } 715} 716 717void TransferFunctions::VisitBinaryOperator(BinaryOperator *BO) { 718 if (BO->getOpcode() == BO_Assign) { 719 FindVarResult Var = findVar(BO->getLHS()); 720 if (const VarDecl *VD = Var.getDecl()) 721 vals[VD] = Initialized; 722 } 723} 724 725void TransferFunctions::VisitDeclStmt(DeclStmt *DS) { 726 for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end(); 727 DI != DE; ++DI) { 728 VarDecl *VD = dyn_cast<VarDecl>(*DI); 729 if (VD && isTrackedVar(VD)) { 730 if (getSelfInitExpr(VD)) { 731 // If the initializer consists solely of a reference to itself, we 732 // explicitly mark the variable as uninitialized. This allows code 733 // like the following: 734 // 735 // int x = x; 736 // 737 // to deliberately leave a variable uninitialized. Different analysis 738 // clients can detect this pattern and adjust their reporting 739 // appropriately, but we need to continue to analyze subsequent uses 740 // of the variable. 741 vals[VD] = Uninitialized; 742 } else if (VD->getInit()) { 743 // Treat the new variable as initialized. 744 vals[VD] = Initialized; 745 } else { 746 // No initializer: the variable is now uninitialized. This matters 747 // for cases like: 748 // while (...) { 749 // int n; 750 // use(n); 751 // n = 0; 752 // } 753 // FIXME: Mark the variable as uninitialized whenever its scope is 754 // left, since its scope could be re-entered by a jump over the 755 // declaration. 756 vals[VD] = Uninitialized; 757 } 758 } 759 } 760} 761 762//------------------------------------------------------------------------====// 763// High-level "driver" logic for uninitialized values analysis. 764//====------------------------------------------------------------------------// 765 766static bool runOnBlock(const CFGBlock *block, const CFG &cfg, 767 AnalysisDeclContext &ac, CFGBlockValues &vals, 768 const ClassifyRefs &classification, 769 llvm::BitVector &wasAnalyzed, 770 UninitVariablesHandler *handler = 0) { 771 772 wasAnalyzed[block->getBlockID()] = true; 773 774 if (const BinaryOperator *b = getLogicalOperatorInChain(block)) { 775 CFGBlock::const_pred_iterator itr = block->pred_begin(); 776 BVPair vA = vals.getValueVectors(*itr, false); 777 ++itr; 778 BVPair vB = vals.getValueVectors(*itr, false); 779 780 BVPair valsAB; 781 782 if (b->getOpcode() == BO_LAnd) { 783 // Merge the 'F' bits from the first and second. 784 vals.mergeIntoScratch(*(vA.second ? vA.second : vA.first), true); 785 vals.mergeIntoScratch(*(vB.second ? vB.second : vB.first), false); 786 valsAB.first = vA.first; 787 valsAB.second = &vals.getScratch(); 788 } else { 789 // Merge the 'T' bits from the first and second. 790 assert(b->getOpcode() == BO_LOr); 791 vals.mergeIntoScratch(*vA.first, true); 792 vals.mergeIntoScratch(*vB.first, false); 793 valsAB.first = &vals.getScratch(); 794 valsAB.second = vA.second ? vA.second : vA.first; 795 } 796 return vals.updateValueVectors(block, valsAB); 797 } 798 799 // Default behavior: merge in values of predecessor blocks. 800 vals.resetScratch(); 801 bool isFirst = true; 802 for (CFGBlock::const_pred_iterator I = block->pred_begin(), 803 E = block->pred_end(); I != E; ++I) { 804 const CFGBlock *pred = *I; 805 if (wasAnalyzed[pred->getBlockID()]) { 806 vals.mergeIntoScratch(vals.getValueVector(pred, block), isFirst); 807 isFirst = false; 808 } 809 } 810 // Apply the transfer function. 811 TransferFunctions tf(vals, cfg, block, ac, classification, handler); 812 for (CFGBlock::const_iterator I = block->begin(), E = block->end(); 813 I != E; ++I) { 814 if (const CFGStmt *cs = dyn_cast<CFGStmt>(&*I)) { 815 tf.Visit(const_cast<Stmt*>(cs->getStmt())); 816 } 817 } 818 return vals.updateValueVectorWithScratch(block); 819} 820 821void clang::runUninitializedVariablesAnalysis( 822 const DeclContext &dc, 823 const CFG &cfg, 824 AnalysisDeclContext &ac, 825 UninitVariablesHandler &handler, 826 UninitVariablesAnalysisStats &stats) { 827 CFGBlockValues vals(cfg); 828 vals.computeSetOfDeclarations(dc); 829 if (vals.hasNoDeclarations()) 830 return; 831#if DEBUG_LOGGING 832 cfg.dump(dc.getParentASTContext().getLangOpts(), true); 833#endif 834 835 stats.NumVariablesAnalyzed = vals.getNumEntries(); 836 837 // Precompute which expressions are uses and which are initializations. 838 ClassifyRefs classification(ac); 839 cfg.VisitBlockStmts(classification); 840 841 // Mark all variables uninitialized at the entry. 842 const CFGBlock &entry = cfg.getEntry(); 843 for (CFGBlock::const_succ_iterator i = entry.succ_begin(), 844 e = entry.succ_end(); i != e; ++i) { 845 if (const CFGBlock *succ = *i) { 846 ValueVector &vec = vals.getValueVector(&entry, succ); 847 const unsigned n = vals.getNumEntries(); 848 for (unsigned j = 0; j < n ; ++j) { 849 vec[j] = Uninitialized; 850 } 851 } 852 } 853 854 // Proceed with the workist. 855 DataflowWorklist worklist(cfg); 856 llvm::BitVector previouslyVisited(cfg.getNumBlockIDs()); 857 worklist.enqueueSuccessors(&cfg.getEntry()); 858 llvm::BitVector wasAnalyzed(cfg.getNumBlockIDs(), false); 859 wasAnalyzed[cfg.getEntry().getBlockID()] = true; 860 861 while (const CFGBlock *block = worklist.dequeue()) { 862 // Did the block change? 863 bool changed = runOnBlock(block, cfg, ac, vals, 864 classification, wasAnalyzed); 865 ++stats.NumBlockVisits; 866 if (changed || !previouslyVisited[block->getBlockID()]) 867 worklist.enqueueSuccessors(block); 868 previouslyVisited[block->getBlockID()] = true; 869 } 870 871 // Run through the blocks one more time, and report uninitialized variabes. 872 for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI) { 873 const CFGBlock *block = *BI; 874 if (wasAnalyzed[block->getBlockID()]) { 875 runOnBlock(block, cfg, ac, vals, classification, wasAnalyzed, &handler); 876 ++stats.NumBlockVisits; 877 } 878 } 879} 880 881UninitVariablesHandler::~UninitVariablesHandler() {} 882