clang API Documentation
00001 //==- UninitializedValues.cpp - Find Uninitialized Values -------*- 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 implements uninitialized values analysis for source-level CFGs. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "clang/AST/ASTContext.h" 00015 #include "clang/AST/Attr.h" 00016 #include "clang/AST/Decl.h" 00017 #include "clang/AST/StmtVisitor.h" 00018 #include "clang/Analysis/Analyses/PostOrderCFGView.h" 00019 #include "clang/Analysis/Analyses/UninitializedValues.h" 00020 #include "clang/Analysis/AnalysisContext.h" 00021 #include "clang/Analysis/CFG.h" 00022 #include "clang/Analysis/DomainSpecific/ObjCNoReturn.h" 00023 #include "llvm/ADT/DenseMap.h" 00024 #include "llvm/ADT/Optional.h" 00025 #include "llvm/ADT/PackedVector.h" 00026 #include "llvm/ADT/SmallBitVector.h" 00027 #include "llvm/ADT/SmallVector.h" 00028 #include "llvm/Support/SaveAndRestore.h" 00029 #include <utility> 00030 00031 using namespace clang; 00032 00033 #define DEBUG_LOGGING 0 00034 00035 static bool isTrackedVar(const VarDecl *vd, const DeclContext *dc) { 00036 if (vd->isLocalVarDecl() && !vd->hasGlobalStorage() && 00037 !vd->isExceptionVariable() && !vd->isInitCapture() && 00038 vd->getDeclContext() == dc) { 00039 QualType ty = vd->getType(); 00040 return ty->isScalarType() || ty->isVectorType(); 00041 } 00042 return false; 00043 } 00044 00045 //------------------------------------------------------------------------====// 00046 // DeclToIndex: a mapping from Decls we track to value indices. 00047 //====------------------------------------------------------------------------// 00048 00049 namespace { 00050 class DeclToIndex { 00051 llvm::DenseMap<const VarDecl *, unsigned> map; 00052 public: 00053 DeclToIndex() {} 00054 00055 /// Compute the actual mapping from declarations to bits. 00056 void computeMap(const DeclContext &dc); 00057 00058 /// Return the number of declarations in the map. 00059 unsigned size() const { return map.size(); } 00060 00061 /// Returns the bit vector index for a given declaration. 00062 Optional<unsigned> getValueIndex(const VarDecl *d) const; 00063 }; 00064 } 00065 00066 void DeclToIndex::computeMap(const DeclContext &dc) { 00067 unsigned count = 0; 00068 DeclContext::specific_decl_iterator<VarDecl> I(dc.decls_begin()), 00069 E(dc.decls_end()); 00070 for ( ; I != E; ++I) { 00071 const VarDecl *vd = *I; 00072 if (isTrackedVar(vd, &dc)) 00073 map[vd] = count++; 00074 } 00075 } 00076 00077 Optional<unsigned> DeclToIndex::getValueIndex(const VarDecl *d) const { 00078 llvm::DenseMap<const VarDecl *, unsigned>::const_iterator I = map.find(d); 00079 if (I == map.end()) 00080 return None; 00081 return I->second; 00082 } 00083 00084 //------------------------------------------------------------------------====// 00085 // CFGBlockValues: dataflow values for CFG blocks. 00086 //====------------------------------------------------------------------------// 00087 00088 // These values are defined in such a way that a merge can be done using 00089 // a bitwise OR. 00090 enum Value { Unknown = 0x0, /* 00 */ 00091 Initialized = 0x1, /* 01 */ 00092 Uninitialized = 0x2, /* 10 */ 00093 MayUninitialized = 0x3 /* 11 */ }; 00094 00095 static bool isUninitialized(const Value v) { 00096 return v >= Uninitialized; 00097 } 00098 static bool isAlwaysUninit(const Value v) { 00099 return v == Uninitialized; 00100 } 00101 00102 namespace { 00103 00104 typedef llvm::PackedVector<Value, 2, llvm::SmallBitVector> ValueVector; 00105 00106 class CFGBlockValues { 00107 const CFG &cfg; 00108 SmallVector<ValueVector, 8> vals; 00109 ValueVector scratch; 00110 DeclToIndex declToIndex; 00111 public: 00112 CFGBlockValues(const CFG &cfg); 00113 00114 unsigned getNumEntries() const { return declToIndex.size(); } 00115 00116 void computeSetOfDeclarations(const DeclContext &dc); 00117 ValueVector &getValueVector(const CFGBlock *block) { 00118 return vals[block->getBlockID()]; 00119 } 00120 00121 void setAllScratchValues(Value V); 00122 void mergeIntoScratch(ValueVector const &source, bool isFirst); 00123 bool updateValueVectorWithScratch(const CFGBlock *block); 00124 00125 bool hasNoDeclarations() const { 00126 return declToIndex.size() == 0; 00127 } 00128 00129 void resetScratch(); 00130 00131 ValueVector::reference operator[](const VarDecl *vd); 00132 00133 Value getValue(const CFGBlock *block, const CFGBlock *dstBlock, 00134 const VarDecl *vd) { 00135 const Optional<unsigned> &idx = declToIndex.getValueIndex(vd); 00136 assert(idx.hasValue()); 00137 return getValueVector(block)[idx.getValue()]; 00138 } 00139 }; 00140 } // end anonymous namespace 00141 00142 CFGBlockValues::CFGBlockValues(const CFG &c) : cfg(c), vals(0) {} 00143 00144 void CFGBlockValues::computeSetOfDeclarations(const DeclContext &dc) { 00145 declToIndex.computeMap(dc); 00146 unsigned decls = declToIndex.size(); 00147 scratch.resize(decls); 00148 unsigned n = cfg.getNumBlockIDs(); 00149 if (!n) 00150 return; 00151 vals.resize(n); 00152 for (unsigned i = 0; i < n; ++i) 00153 vals[i].resize(decls); 00154 } 00155 00156 #if DEBUG_LOGGING 00157 static void printVector(const CFGBlock *block, ValueVector &bv, 00158 unsigned num) { 00159 llvm::errs() << block->getBlockID() << " :"; 00160 for (unsigned i = 0; i < bv.size(); ++i) { 00161 llvm::errs() << ' ' << bv[i]; 00162 } 00163 llvm::errs() << " : " << num << '\n'; 00164 } 00165 #endif 00166 00167 void CFGBlockValues::setAllScratchValues(Value V) { 00168 for (unsigned I = 0, E = scratch.size(); I != E; ++I) 00169 scratch[I] = V; 00170 } 00171 00172 void CFGBlockValues::mergeIntoScratch(ValueVector const &source, 00173 bool isFirst) { 00174 if (isFirst) 00175 scratch = source; 00176 else 00177 scratch |= source; 00178 } 00179 00180 bool CFGBlockValues::updateValueVectorWithScratch(const CFGBlock *block) { 00181 ValueVector &dst = getValueVector(block); 00182 bool changed = (dst != scratch); 00183 if (changed) 00184 dst = scratch; 00185 #if DEBUG_LOGGING 00186 printVector(block, scratch, 0); 00187 #endif 00188 return changed; 00189 } 00190 00191 void CFGBlockValues::resetScratch() { 00192 scratch.reset(); 00193 } 00194 00195 ValueVector::reference CFGBlockValues::operator[](const VarDecl *vd) { 00196 const Optional<unsigned> &idx = declToIndex.getValueIndex(vd); 00197 assert(idx.hasValue()); 00198 return scratch[idx.getValue()]; 00199 } 00200 00201 //------------------------------------------------------------------------====// 00202 // Worklist: worklist for dataflow analysis. 00203 //====------------------------------------------------------------------------// 00204 00205 namespace { 00206 class DataflowWorklist { 00207 PostOrderCFGView::iterator PO_I, PO_E; 00208 SmallVector<const CFGBlock *, 20> worklist; 00209 llvm::BitVector enqueuedBlocks; 00210 public: 00211 DataflowWorklist(const CFG &cfg, PostOrderCFGView &view) 00212 : PO_I(view.begin()), PO_E(view.end()), 00213 enqueuedBlocks(cfg.getNumBlockIDs(), true) { 00214 // Treat the first block as already analyzed. 00215 if (PO_I != PO_E) { 00216 assert(*PO_I == &cfg.getEntry()); 00217 enqueuedBlocks[(*PO_I)->getBlockID()] = false; 00218 ++PO_I; 00219 } 00220 } 00221 00222 void enqueueSuccessors(const CFGBlock *block); 00223 const CFGBlock *dequeue(); 00224 }; 00225 } 00226 00227 void DataflowWorklist::enqueueSuccessors(const clang::CFGBlock *block) { 00228 for (CFGBlock::const_succ_iterator I = block->succ_begin(), 00229 E = block->succ_end(); I != E; ++I) { 00230 const CFGBlock *Successor = *I; 00231 if (!Successor || enqueuedBlocks[Successor->getBlockID()]) 00232 continue; 00233 worklist.push_back(Successor); 00234 enqueuedBlocks[Successor->getBlockID()] = true; 00235 } 00236 } 00237 00238 const CFGBlock *DataflowWorklist::dequeue() { 00239 const CFGBlock *B = nullptr; 00240 00241 // First dequeue from the worklist. This can represent 00242 // updates along backedges that we want propagated as quickly as possible. 00243 if (!worklist.empty()) 00244 B = worklist.pop_back_val(); 00245 00246 // Next dequeue from the initial reverse post order. This is the 00247 // theoretical ideal in the presence of no back edges. 00248 else if (PO_I != PO_E) { 00249 B = *PO_I; 00250 ++PO_I; 00251 } 00252 else { 00253 return nullptr; 00254 } 00255 00256 assert(enqueuedBlocks[B->getBlockID()] == true); 00257 enqueuedBlocks[B->getBlockID()] = false; 00258 return B; 00259 } 00260 00261 //------------------------------------------------------------------------====// 00262 // Classification of DeclRefExprs as use or initialization. 00263 //====------------------------------------------------------------------------// 00264 00265 namespace { 00266 class FindVarResult { 00267 const VarDecl *vd; 00268 const DeclRefExpr *dr; 00269 public: 00270 FindVarResult(const VarDecl *vd, const DeclRefExpr *dr) : vd(vd), dr(dr) {} 00271 00272 const DeclRefExpr *getDeclRefExpr() const { return dr; } 00273 const VarDecl *getDecl() const { return vd; } 00274 }; 00275 00276 static const Expr *stripCasts(ASTContext &C, const Expr *Ex) { 00277 while (Ex) { 00278 Ex = Ex->IgnoreParenNoopCasts(C); 00279 if (const CastExpr *CE = dyn_cast<CastExpr>(Ex)) { 00280 if (CE->getCastKind() == CK_LValueBitCast) { 00281 Ex = CE->getSubExpr(); 00282 continue; 00283 } 00284 } 00285 break; 00286 } 00287 return Ex; 00288 } 00289 00290 /// If E is an expression comprising a reference to a single variable, find that 00291 /// variable. 00292 static FindVarResult findVar(const Expr *E, const DeclContext *DC) { 00293 if (const DeclRefExpr *DRE = 00294 dyn_cast<DeclRefExpr>(stripCasts(DC->getParentASTContext(), E))) 00295 if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) 00296 if (isTrackedVar(VD, DC)) 00297 return FindVarResult(VD, DRE); 00298 return FindVarResult(nullptr, nullptr); 00299 } 00300 00301 /// \brief Classify each DeclRefExpr as an initialization or a use. Any 00302 /// DeclRefExpr which isn't explicitly classified will be assumed to have 00303 /// escaped the analysis and will be treated as an initialization. 00304 class ClassifyRefs : public StmtVisitor<ClassifyRefs> { 00305 public: 00306 enum Class { 00307 Init, 00308 Use, 00309 SelfInit, 00310 Ignore 00311 }; 00312 00313 private: 00314 const DeclContext *DC; 00315 llvm::DenseMap<const DeclRefExpr*, Class> Classification; 00316 00317 bool isTrackedVar(const VarDecl *VD) const { 00318 return ::isTrackedVar(VD, DC); 00319 } 00320 00321 void classify(const Expr *E, Class C); 00322 00323 public: 00324 ClassifyRefs(AnalysisDeclContext &AC) : DC(cast<DeclContext>(AC.getDecl())) {} 00325 00326 void VisitDeclStmt(DeclStmt *DS); 00327 void VisitUnaryOperator(UnaryOperator *UO); 00328 void VisitBinaryOperator(BinaryOperator *BO); 00329 void VisitCallExpr(CallExpr *CE); 00330 void VisitCastExpr(CastExpr *CE); 00331 00332 void operator()(Stmt *S) { Visit(S); } 00333 00334 Class get(const DeclRefExpr *DRE) const { 00335 llvm::DenseMap<const DeclRefExpr*, Class>::const_iterator I 00336 = Classification.find(DRE); 00337 if (I != Classification.end()) 00338 return I->second; 00339 00340 const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()); 00341 if (!VD || !isTrackedVar(VD)) 00342 return Ignore; 00343 00344 return Init; 00345 } 00346 }; 00347 } 00348 00349 static const DeclRefExpr *getSelfInitExpr(VarDecl *VD) { 00350 if (Expr *Init = VD->getInit()) { 00351 const DeclRefExpr *DRE 00352 = dyn_cast<DeclRefExpr>(stripCasts(VD->getASTContext(), Init)); 00353 if (DRE && DRE->getDecl() == VD) 00354 return DRE; 00355 } 00356 return nullptr; 00357 } 00358 00359 void ClassifyRefs::classify(const Expr *E, Class C) { 00360 // The result of a ?: could also be an lvalue. 00361 E = E->IgnoreParens(); 00362 if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) { 00363 classify(CO->getTrueExpr(), C); 00364 classify(CO->getFalseExpr(), C); 00365 return; 00366 } 00367 00368 if (const BinaryConditionalOperator *BCO = 00369 dyn_cast<BinaryConditionalOperator>(E)) { 00370 classify(BCO->getFalseExpr(), C); 00371 return; 00372 } 00373 00374 if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) { 00375 classify(OVE->getSourceExpr(), C); 00376 return; 00377 } 00378 00379 if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) { 00380 if (BO->getOpcode() == BO_Comma) 00381 classify(BO->getRHS(), C); 00382 return; 00383 } 00384 00385 FindVarResult Var = findVar(E, DC); 00386 if (const DeclRefExpr *DRE = Var.getDeclRefExpr()) 00387 Classification[DRE] = std::max(Classification[DRE], C); 00388 } 00389 00390 void ClassifyRefs::VisitDeclStmt(DeclStmt *DS) { 00391 for (auto *DI : DS->decls()) { 00392 VarDecl *VD = dyn_cast<VarDecl>(DI); 00393 if (VD && isTrackedVar(VD)) 00394 if (const DeclRefExpr *DRE = getSelfInitExpr(VD)) 00395 Classification[DRE] = SelfInit; 00396 } 00397 } 00398 00399 void ClassifyRefs::VisitBinaryOperator(BinaryOperator *BO) { 00400 // Ignore the evaluation of a DeclRefExpr on the LHS of an assignment. If this 00401 // is not a compound-assignment, we will treat it as initializing the variable 00402 // when TransferFunctions visits it. A compound-assignment does not affect 00403 // whether a variable is uninitialized, and there's no point counting it as a 00404 // use. 00405 if (BO->isCompoundAssignmentOp()) 00406 classify(BO->getLHS(), Use); 00407 else if (BO->getOpcode() == BO_Assign) 00408 classify(BO->getLHS(), Ignore); 00409 } 00410 00411 void ClassifyRefs::VisitUnaryOperator(UnaryOperator *UO) { 00412 // Increment and decrement are uses despite there being no lvalue-to-rvalue 00413 // conversion. 00414 if (UO->isIncrementDecrementOp()) 00415 classify(UO->getSubExpr(), Use); 00416 } 00417 00418 void ClassifyRefs::VisitCallExpr(CallExpr *CE) { 00419 // Classify arguments to std::move as used. 00420 if (CE->getNumArgs() == 1) { 00421 if (FunctionDecl *FD = CE->getDirectCallee()) { 00422 if (FD->getIdentifier() && FD->getIdentifier()->isStr("move")) { 00423 classify(CE->getArg(0), Use); 00424 return; 00425 } 00426 } 00427 } 00428 00429 // If a value is passed by const reference to a function, we should not assume 00430 // that it is initialized by the call, and we conservatively do not assume 00431 // that it is used. 00432 for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end(); 00433 I != E; ++I) 00434 if ((*I)->getType().isConstQualified() && (*I)->isGLValue()) 00435 classify(*I, Ignore); 00436 } 00437 00438 void ClassifyRefs::VisitCastExpr(CastExpr *CE) { 00439 if (CE->getCastKind() == CK_LValueToRValue) 00440 classify(CE->getSubExpr(), Use); 00441 else if (CStyleCastExpr *CSE = dyn_cast<CStyleCastExpr>(CE)) { 00442 if (CSE->getType()->isVoidType()) { 00443 // Squelch any detected load of an uninitialized value if 00444 // we cast it to void. 00445 // e.g. (void) x; 00446 classify(CSE->getSubExpr(), Ignore); 00447 } 00448 } 00449 } 00450 00451 //------------------------------------------------------------------------====// 00452 // Transfer function for uninitialized values analysis. 00453 //====------------------------------------------------------------------------// 00454 00455 namespace { 00456 class TransferFunctions : public StmtVisitor<TransferFunctions> { 00457 CFGBlockValues &vals; 00458 const CFG &cfg; 00459 const CFGBlock *block; 00460 AnalysisDeclContext ∾ 00461 const ClassifyRefs &classification; 00462 ObjCNoReturn objCNoRet; 00463 UninitVariablesHandler &handler; 00464 00465 public: 00466 TransferFunctions(CFGBlockValues &vals, const CFG &cfg, 00467 const CFGBlock *block, AnalysisDeclContext &ac, 00468 const ClassifyRefs &classification, 00469 UninitVariablesHandler &handler) 00470 : vals(vals), cfg(cfg), block(block), ac(ac), 00471 classification(classification), objCNoRet(ac.getASTContext()), 00472 handler(handler) {} 00473 00474 void reportUse(const Expr *ex, const VarDecl *vd); 00475 00476 void VisitBinaryOperator(BinaryOperator *bo); 00477 void VisitBlockExpr(BlockExpr *be); 00478 void VisitCallExpr(CallExpr *ce); 00479 void VisitDeclRefExpr(DeclRefExpr *dr); 00480 void VisitDeclStmt(DeclStmt *ds); 00481 void VisitObjCForCollectionStmt(ObjCForCollectionStmt *FS); 00482 void VisitObjCMessageExpr(ObjCMessageExpr *ME); 00483 00484 bool isTrackedVar(const VarDecl *vd) { 00485 return ::isTrackedVar(vd, cast<DeclContext>(ac.getDecl())); 00486 } 00487 00488 FindVarResult findVar(const Expr *ex) { 00489 return ::findVar(ex, cast<DeclContext>(ac.getDecl())); 00490 } 00491 00492 UninitUse getUninitUse(const Expr *ex, const VarDecl *vd, Value v) { 00493 UninitUse Use(ex, isAlwaysUninit(v)); 00494 00495 assert(isUninitialized(v)); 00496 if (Use.getKind() == UninitUse::Always) 00497 return Use; 00498 00499 // If an edge which leads unconditionally to this use did not initialize 00500 // the variable, we can say something stronger than 'may be uninitialized': 00501 // we can say 'either it's used uninitialized or you have dead code'. 00502 // 00503 // We track the number of successors of a node which have been visited, and 00504 // visit a node once we have visited all of its successors. Only edges where 00505 // the variable might still be uninitialized are followed. Since a variable 00506 // can't transfer from being initialized to being uninitialized, this will 00507 // trace out the subgraph which inevitably leads to the use and does not 00508 // initialize the variable. We do not want to skip past loops, since their 00509 // non-termination might be correlated with the initialization condition. 00510 // 00511 // For example: 00512 // 00513 // void f(bool a, bool b) { 00514 // block1: int n; 00515 // if (a) { 00516 // block2: if (b) 00517 // block3: n = 1; 00518 // block4: } else if (b) { 00519 // block5: while (!a) { 00520 // block6: do_work(&a); 00521 // n = 2; 00522 // } 00523 // } 00524 // block7: if (a) 00525 // block8: g(); 00526 // block9: return n; 00527 // } 00528 // 00529 // Starting from the maybe-uninitialized use in block 9: 00530 // * Block 7 is not visited because we have only visited one of its two 00531 // successors. 00532 // * Block 8 is visited because we've visited its only successor. 00533 // From block 8: 00534 // * Block 7 is visited because we've now visited both of its successors. 00535 // From block 7: 00536 // * Blocks 1, 2, 4, 5, and 6 are not visited because we didn't visit all 00537 // of their successors (we didn't visit 4, 3, 5, 6, and 5, respectively). 00538 // * Block 3 is not visited because it initializes 'n'. 00539 // Now the algorithm terminates, having visited blocks 7 and 8, and having 00540 // found the frontier is blocks 2, 4, and 5. 00541 // 00542 // 'n' is definitely uninitialized for two edges into block 7 (from blocks 2 00543 // and 4), so we report that any time either of those edges is taken (in 00544 // each case when 'b == false'), 'n' is used uninitialized. 00545 SmallVector<const CFGBlock*, 32> Queue; 00546 SmallVector<unsigned, 32> SuccsVisited(cfg.getNumBlockIDs(), 0); 00547 Queue.push_back(block); 00548 // Specify that we've already visited all successors of the starting block. 00549 // This has the dual purpose of ensuring we never add it to the queue, and 00550 // of marking it as not being a candidate element of the frontier. 00551 SuccsVisited[block->getBlockID()] = block->succ_size(); 00552 while (!Queue.empty()) { 00553 const CFGBlock *B = Queue.pop_back_val(); 00554 00555 // If the use is always reached from the entry block, make a note of that. 00556 if (B == &cfg.getEntry()) 00557 Use.setUninitAfterCall(); 00558 00559 for (CFGBlock::const_pred_iterator I = B->pred_begin(), E = B->pred_end(); 00560 I != E; ++I) { 00561 const CFGBlock *Pred = *I; 00562 if (!Pred) 00563 continue; 00564 00565 Value AtPredExit = vals.getValue(Pred, B, vd); 00566 if (AtPredExit == Initialized) 00567 // This block initializes the variable. 00568 continue; 00569 if (AtPredExit == MayUninitialized && 00570 vals.getValue(B, nullptr, vd) == Uninitialized) { 00571 // This block declares the variable (uninitialized), and is reachable 00572 // from a block that initializes the variable. We can't guarantee to 00573 // give an earlier location for the diagnostic (and it appears that 00574 // this code is intended to be reachable) so give a diagnostic here 00575 // and go no further down this path. 00576 Use.setUninitAfterDecl(); 00577 continue; 00578 } 00579 00580 unsigned &SV = SuccsVisited[Pred->getBlockID()]; 00581 if (!SV) { 00582 // When visiting the first successor of a block, mark all NULL 00583 // successors as having been visited. 00584 for (CFGBlock::const_succ_iterator SI = Pred->succ_begin(), 00585 SE = Pred->succ_end(); 00586 SI != SE; ++SI) 00587 if (!*SI) 00588 ++SV; 00589 } 00590 00591 if (++SV == Pred->succ_size()) 00592 // All paths from this block lead to the use and don't initialize the 00593 // variable. 00594 Queue.push_back(Pred); 00595 } 00596 } 00597 00598 // Scan the frontier, looking for blocks where the variable was 00599 // uninitialized. 00600 for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI) { 00601 const CFGBlock *Block = *BI; 00602 unsigned BlockID = Block->getBlockID(); 00603 const Stmt *Term = Block->getTerminator(); 00604 if (SuccsVisited[BlockID] && SuccsVisited[BlockID] < Block->succ_size() && 00605 Term) { 00606 // This block inevitably leads to the use. If we have an edge from here 00607 // to a post-dominator block, and the variable is uninitialized on that 00608 // edge, we have found a bug. 00609 for (CFGBlock::const_succ_iterator I = Block->succ_begin(), 00610 E = Block->succ_end(); I != E; ++I) { 00611 const CFGBlock *Succ = *I; 00612 if (Succ && SuccsVisited[Succ->getBlockID()] >= Succ->succ_size() && 00613 vals.getValue(Block, Succ, vd) == Uninitialized) { 00614 // Switch cases are a special case: report the label to the caller 00615 // as the 'terminator', not the switch statement itself. Suppress 00616 // situations where no label matched: we can't be sure that's 00617 // possible. 00618 if (isa<SwitchStmt>(Term)) { 00619 const Stmt *Label = Succ->getLabel(); 00620 if (!Label || !isa<SwitchCase>(Label)) 00621 // Might not be possible. 00622 continue; 00623 UninitUse::Branch Branch; 00624 Branch.Terminator = Label; 00625 Branch.Output = 0; // Ignored. 00626 Use.addUninitBranch(Branch); 00627 } else { 00628 UninitUse::Branch Branch; 00629 Branch.Terminator = Term; 00630 Branch.Output = I - Block->succ_begin(); 00631 Use.addUninitBranch(Branch); 00632 } 00633 } 00634 } 00635 } 00636 } 00637 00638 return Use; 00639 } 00640 }; 00641 } 00642 00643 void TransferFunctions::reportUse(const Expr *ex, const VarDecl *vd) { 00644 Value v = vals[vd]; 00645 if (isUninitialized(v)) 00646 handler.handleUseOfUninitVariable(vd, getUninitUse(ex, vd, v)); 00647 } 00648 00649 void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *FS) { 00650 // This represents an initialization of the 'element' value. 00651 if (DeclStmt *DS = dyn_cast<DeclStmt>(FS->getElement())) { 00652 const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl()); 00653 if (isTrackedVar(VD)) 00654 vals[VD] = Initialized; 00655 } 00656 } 00657 00658 void TransferFunctions::VisitBlockExpr(BlockExpr *be) { 00659 const BlockDecl *bd = be->getBlockDecl(); 00660 for (const auto &I : bd->captures()) { 00661 const VarDecl *vd = I.getVariable(); 00662 if (!isTrackedVar(vd)) 00663 continue; 00664 if (I.isByRef()) { 00665 vals[vd] = Initialized; 00666 continue; 00667 } 00668 reportUse(be, vd); 00669 } 00670 } 00671 00672 void TransferFunctions::VisitCallExpr(CallExpr *ce) { 00673 if (Decl *Callee = ce->getCalleeDecl()) { 00674 if (Callee->hasAttr<ReturnsTwiceAttr>()) { 00675 // After a call to a function like setjmp or vfork, any variable which is 00676 // initialized anywhere within this function may now be initialized. For 00677 // now, just assume such a call initializes all variables. FIXME: Only 00678 // mark variables as initialized if they have an initializer which is 00679 // reachable from here. 00680 vals.setAllScratchValues(Initialized); 00681 } 00682 else if (Callee->hasAttr<AnalyzerNoReturnAttr>()) { 00683 // Functions labeled like "analyzer_noreturn" are often used to denote 00684 // "panic" functions that in special debug situations can still return, 00685 // but for the most part should not be treated as returning. This is a 00686 // useful annotation borrowed from the static analyzer that is useful for 00687 // suppressing branch-specific false positives when we call one of these 00688 // functions but keep pretending the path continues (when in reality the 00689 // user doesn't care). 00690 vals.setAllScratchValues(Unknown); 00691 } 00692 } 00693 } 00694 00695 void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *dr) { 00696 switch (classification.get(dr)) { 00697 case ClassifyRefs::Ignore: 00698 break; 00699 case ClassifyRefs::Use: 00700 reportUse(dr, cast<VarDecl>(dr->getDecl())); 00701 break; 00702 case ClassifyRefs::Init: 00703 vals[cast<VarDecl>(dr->getDecl())] = Initialized; 00704 break; 00705 case ClassifyRefs::SelfInit: 00706 handler.handleSelfInit(cast<VarDecl>(dr->getDecl())); 00707 break; 00708 } 00709 } 00710 00711 void TransferFunctions::VisitBinaryOperator(BinaryOperator *BO) { 00712 if (BO->getOpcode() == BO_Assign) { 00713 FindVarResult Var = findVar(BO->getLHS()); 00714 if (const VarDecl *VD = Var.getDecl()) 00715 vals[VD] = Initialized; 00716 } 00717 } 00718 00719 void TransferFunctions::VisitDeclStmt(DeclStmt *DS) { 00720 for (auto *DI : DS->decls()) { 00721 VarDecl *VD = dyn_cast<VarDecl>(DI); 00722 if (VD && isTrackedVar(VD)) { 00723 if (getSelfInitExpr(VD)) { 00724 // If the initializer consists solely of a reference to itself, we 00725 // explicitly mark the variable as uninitialized. This allows code 00726 // like the following: 00727 // 00728 // int x = x; 00729 // 00730 // to deliberately leave a variable uninitialized. Different analysis 00731 // clients can detect this pattern and adjust their reporting 00732 // appropriately, but we need to continue to analyze subsequent uses 00733 // of the variable. 00734 vals[VD] = Uninitialized; 00735 } else if (VD->getInit()) { 00736 // Treat the new variable as initialized. 00737 vals[VD] = Initialized; 00738 } else { 00739 // No initializer: the variable is now uninitialized. This matters 00740 // for cases like: 00741 // while (...) { 00742 // int n; 00743 // use(n); 00744 // n = 0; 00745 // } 00746 // FIXME: Mark the variable as uninitialized whenever its scope is 00747 // left, since its scope could be re-entered by a jump over the 00748 // declaration. 00749 vals[VD] = Uninitialized; 00750 } 00751 } 00752 } 00753 } 00754 00755 void TransferFunctions::VisitObjCMessageExpr(ObjCMessageExpr *ME) { 00756 // If the Objective-C message expression is an implicit no-return that 00757 // is not modeled in the CFG, set the tracked dataflow values to Unknown. 00758 if (objCNoRet.isImplicitNoReturn(ME)) { 00759 vals.setAllScratchValues(Unknown); 00760 } 00761 } 00762 00763 //------------------------------------------------------------------------====// 00764 // High-level "driver" logic for uninitialized values analysis. 00765 //====------------------------------------------------------------------------// 00766 00767 static bool runOnBlock(const CFGBlock *block, const CFG &cfg, 00768 AnalysisDeclContext &ac, CFGBlockValues &vals, 00769 const ClassifyRefs &classification, 00770 llvm::BitVector &wasAnalyzed, 00771 UninitVariablesHandler &handler) { 00772 wasAnalyzed[block->getBlockID()] = true; 00773 vals.resetScratch(); 00774 // Merge in values of predecessor blocks. 00775 bool isFirst = true; 00776 for (CFGBlock::const_pred_iterator I = block->pred_begin(), 00777 E = block->pred_end(); I != E; ++I) { 00778 const CFGBlock *pred = *I; 00779 if (!pred) 00780 continue; 00781 if (wasAnalyzed[pred->getBlockID()]) { 00782 vals.mergeIntoScratch(vals.getValueVector(pred), isFirst); 00783 isFirst = false; 00784 } 00785 } 00786 // Apply the transfer function. 00787 TransferFunctions tf(vals, cfg, block, ac, classification, handler); 00788 for (CFGBlock::const_iterator I = block->begin(), E = block->end(); 00789 I != E; ++I) { 00790 if (Optional<CFGStmt> cs = I->getAs<CFGStmt>()) 00791 tf.Visit(const_cast<Stmt*>(cs->getStmt())); 00792 } 00793 return vals.updateValueVectorWithScratch(block); 00794 } 00795 00796 /// PruneBlocksHandler is a special UninitVariablesHandler that is used 00797 /// to detect when a CFGBlock has any *potential* use of an uninitialized 00798 /// variable. It is mainly used to prune out work during the final 00799 /// reporting pass. 00800 namespace { 00801 struct PruneBlocksHandler : public UninitVariablesHandler { 00802 PruneBlocksHandler(unsigned numBlocks) 00803 : hadUse(numBlocks, false), hadAnyUse(false), 00804 currentBlock(0) {} 00805 00806 virtual ~PruneBlocksHandler() {} 00807 00808 /// Records if a CFGBlock had a potential use of an uninitialized variable. 00809 llvm::BitVector hadUse; 00810 00811 /// Records if any CFGBlock had a potential use of an uninitialized variable. 00812 bool hadAnyUse; 00813 00814 /// The current block to scribble use information. 00815 unsigned currentBlock; 00816 00817 void handleUseOfUninitVariable(const VarDecl *vd, 00818 const UninitUse &use) override { 00819 hadUse[currentBlock] = true; 00820 hadAnyUse = true; 00821 } 00822 00823 /// Called when the uninitialized variable analysis detects the 00824 /// idiom 'int x = x'. All other uses of 'x' within the initializer 00825 /// are handled by handleUseOfUninitVariable. 00826 void handleSelfInit(const VarDecl *vd) override { 00827 hadUse[currentBlock] = true; 00828 hadAnyUse = true; 00829 } 00830 }; 00831 } 00832 00833 void clang::runUninitializedVariablesAnalysis( 00834 const DeclContext &dc, 00835 const CFG &cfg, 00836 AnalysisDeclContext &ac, 00837 UninitVariablesHandler &handler, 00838 UninitVariablesAnalysisStats &stats) { 00839 CFGBlockValues vals(cfg); 00840 vals.computeSetOfDeclarations(dc); 00841 if (vals.hasNoDeclarations()) 00842 return; 00843 00844 stats.NumVariablesAnalyzed = vals.getNumEntries(); 00845 00846 // Precompute which expressions are uses and which are initializations. 00847 ClassifyRefs classification(ac); 00848 cfg.VisitBlockStmts(classification); 00849 00850 // Mark all variables uninitialized at the entry. 00851 const CFGBlock &entry = cfg.getEntry(); 00852 ValueVector &vec = vals.getValueVector(&entry); 00853 const unsigned n = vals.getNumEntries(); 00854 for (unsigned j = 0; j < n ; ++j) { 00855 vec[j] = Uninitialized; 00856 } 00857 00858 // Proceed with the workist. 00859 DataflowWorklist worklist(cfg, *ac.getAnalysis<PostOrderCFGView>()); 00860 llvm::BitVector previouslyVisited(cfg.getNumBlockIDs()); 00861 worklist.enqueueSuccessors(&cfg.getEntry()); 00862 llvm::BitVector wasAnalyzed(cfg.getNumBlockIDs(), false); 00863 wasAnalyzed[cfg.getEntry().getBlockID()] = true; 00864 PruneBlocksHandler PBH(cfg.getNumBlockIDs()); 00865 00866 while (const CFGBlock *block = worklist.dequeue()) { 00867 PBH.currentBlock = block->getBlockID(); 00868 00869 // Did the block change? 00870 bool changed = runOnBlock(block, cfg, ac, vals, 00871 classification, wasAnalyzed, PBH); 00872 ++stats.NumBlockVisits; 00873 if (changed || !previouslyVisited[block->getBlockID()]) 00874 worklist.enqueueSuccessors(block); 00875 previouslyVisited[block->getBlockID()] = true; 00876 } 00877 00878 if (!PBH.hadAnyUse) 00879 return; 00880 00881 // Run through the blocks one more time, and report uninitialized variables. 00882 for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI) { 00883 const CFGBlock *block = *BI; 00884 if (PBH.hadUse[block->getBlockID()]) { 00885 runOnBlock(block, cfg, ac, vals, classification, wasAnalyzed, handler); 00886 ++stats.NumBlockVisits; 00887 } 00888 } 00889 } 00890 00891 UninitVariablesHandler::~UninitVariablesHandler() {}