1 //===- UninitializedValues.cpp - Find Uninitialized Values ----------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements uninitialized values analysis for source-level CFGs. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "clang/Analysis/Analyses/UninitializedValues.h" 14 #include "clang/AST/Attr.h" 15 #include "clang/AST/Decl.h" 16 #include "clang/AST/DeclBase.h" 17 #include "clang/AST/Expr.h" 18 #include "clang/AST/OperationKinds.h" 19 #include "clang/AST/Stmt.h" 20 #include "clang/AST/StmtObjC.h" 21 #include "clang/AST/StmtVisitor.h" 22 #include "clang/AST/Type.h" 23 #include "clang/Analysis/Analyses/PostOrderCFGView.h" 24 #include "clang/Analysis/AnalysisDeclContext.h" 25 #include "clang/Analysis/CFG.h" 26 #include "clang/Analysis/DomainSpecific/ObjCNoReturn.h" 27 #include "clang/Analysis/FlowSensitive/DataflowWorklist.h" 28 #include "clang/Basic/LLVM.h" 29 #include "llvm/ADT/BitVector.h" 30 #include "llvm/ADT/DenseMap.h" 31 #include "llvm/ADT/None.h" 32 #include "llvm/ADT/Optional.h" 33 #include "llvm/ADT/PackedVector.h" 34 #include "llvm/ADT/SmallBitVector.h" 35 #include "llvm/ADT/SmallVector.h" 36 #include "llvm/Support/Casting.h" 37 #include <algorithm> 38 #include <cassert> 39 40 using namespace clang; 41 42 #define DEBUG_LOGGING 0 43 44 static bool isTrackedVar(const VarDecl *vd, const DeclContext *dc) { 45 if (vd->isLocalVarDecl() && !vd->hasGlobalStorage() && 46 !vd->isExceptionVariable() && !vd->isInitCapture() && 47 !vd->isImplicit() && vd->getDeclContext() == dc) { 48 QualType ty = vd->getType(); 49 return ty->isScalarType() || ty->isVectorType() || ty->isRecordType() || 50 ty->isRVVType(); 51 } 52 return false; 53 } 54 55 //------------------------------------------------------------------------====// 56 // DeclToIndex: a mapping from Decls we track to value indices. 57 //====------------------------------------------------------------------------// 58 59 namespace { 60 61 class DeclToIndex { 62 llvm::DenseMap<const VarDecl *, unsigned> map; 63 64 public: 65 DeclToIndex() = default; 66 67 /// Compute the actual mapping from declarations to bits. 68 void computeMap(const DeclContext &dc); 69 70 /// Return the number of declarations in the map. 71 unsigned size() const { return map.size(); } 72 73 /// Returns the bit vector index for a given declaration. 74 Optional<unsigned> getValueIndex(const VarDecl *d) const; 75 }; 76 77 } // namespace 78 79 void DeclToIndex::computeMap(const DeclContext &dc) { 80 unsigned count = 0; 81 DeclContext::specific_decl_iterator<VarDecl> I(dc.decls_begin()), 82 E(dc.decls_end()); 83 for ( ; I != E; ++I) { 84 const VarDecl *vd = *I; 85 if (isTrackedVar(vd, &dc)) 86 map[vd] = count++; 87 } 88 } 89 90 Optional<unsigned> DeclToIndex::getValueIndex(const VarDecl *d) const { 91 llvm::DenseMap<const VarDecl *, unsigned>::const_iterator I = map.find(d); 92 if (I == map.end()) 93 return std::nullopt; 94 return I->second; 95 } 96 97 //------------------------------------------------------------------------====// 98 // CFGBlockValues: dataflow values for CFG blocks. 99 //====------------------------------------------------------------------------// 100 101 // These values are defined in such a way that a merge can be done using 102 // a bitwise OR. 103 enum Value { Unknown = 0x0, /* 00 */ 104 Initialized = 0x1, /* 01 */ 105 Uninitialized = 0x2, /* 10 */ 106 MayUninitialized = 0x3 /* 11 */ }; 107 108 static bool isUninitialized(const Value v) { 109 return v >= Uninitialized; 110 } 111 112 static bool isAlwaysUninit(const Value v) { 113 return v == Uninitialized; 114 } 115 116 namespace { 117 118 using ValueVector = llvm::PackedVector<Value, 2, llvm::SmallBitVector>; 119 120 class CFGBlockValues { 121 const CFG &cfg; 122 SmallVector<ValueVector, 8> vals; 123 ValueVector scratch; 124 DeclToIndex declToIndex; 125 126 public: 127 CFGBlockValues(const CFG &cfg); 128 129 unsigned getNumEntries() const { return declToIndex.size(); } 130 131 void computeSetOfDeclarations(const DeclContext &dc); 132 133 ValueVector &getValueVector(const CFGBlock *block) { 134 return vals[block->getBlockID()]; 135 } 136 137 void setAllScratchValues(Value V); 138 void mergeIntoScratch(ValueVector const &source, bool isFirst); 139 bool updateValueVectorWithScratch(const CFGBlock *block); 140 141 bool hasNoDeclarations() const { 142 return declToIndex.size() == 0; 143 } 144 145 void resetScratch(); 146 147 ValueVector::reference operator[](const VarDecl *vd); 148 149 Value getValue(const CFGBlock *block, const CFGBlock *dstBlock, 150 const VarDecl *vd) { 151 const Optional<unsigned> &idx = declToIndex.getValueIndex(vd); 152 assert(idx); 153 return getValueVector(block)[idx.value()]; 154 } 155 }; 156 157 } // namespace 158 159 CFGBlockValues::CFGBlockValues(const CFG &c) : cfg(c), vals(0) {} 160 161 void CFGBlockValues::computeSetOfDeclarations(const DeclContext &dc) { 162 declToIndex.computeMap(dc); 163 unsigned decls = declToIndex.size(); 164 scratch.resize(decls); 165 unsigned n = cfg.getNumBlockIDs(); 166 if (!n) 167 return; 168 vals.resize(n); 169 for (auto &val : vals) 170 val.resize(decls); 171 } 172 173 #if DEBUG_LOGGING 174 static void printVector(const CFGBlock *block, ValueVector &bv, 175 unsigned num) { 176 llvm::errs() << block->getBlockID() << " :"; 177 for (const auto &i : bv) 178 llvm::errs() << ' ' << i; 179 llvm::errs() << " : " << num << '\n'; 180 } 181 #endif 182 183 void CFGBlockValues::setAllScratchValues(Value V) { 184 for (unsigned I = 0, E = scratch.size(); I != E; ++I) 185 scratch[I] = V; 186 } 187 188 void CFGBlockValues::mergeIntoScratch(ValueVector const &source, 189 bool isFirst) { 190 if (isFirst) 191 scratch = source; 192 else 193 scratch |= source; 194 } 195 196 bool CFGBlockValues::updateValueVectorWithScratch(const CFGBlock *block) { 197 ValueVector &dst = getValueVector(block); 198 bool changed = (dst != scratch); 199 if (changed) 200 dst = scratch; 201 #if DEBUG_LOGGING 202 printVector(block, scratch, 0); 203 #endif 204 return changed; 205 } 206 207 void CFGBlockValues::resetScratch() { 208 scratch.reset(); 209 } 210 211 ValueVector::reference CFGBlockValues::operator[](const VarDecl *vd) { 212 const Optional<unsigned> &idx = declToIndex.getValueIndex(vd); 213 assert(idx); 214 return scratch[idx.value()]; 215 } 216 217 //------------------------------------------------------------------------====// 218 // Classification of DeclRefExprs as use or initialization. 219 //====------------------------------------------------------------------------// 220 221 namespace { 222 223 class FindVarResult { 224 const VarDecl *vd; 225 const DeclRefExpr *dr; 226 227 public: 228 FindVarResult(const VarDecl *vd, const DeclRefExpr *dr) : vd(vd), dr(dr) {} 229 230 const DeclRefExpr *getDeclRefExpr() const { return dr; } 231 const VarDecl *getDecl() const { return vd; } 232 }; 233 234 } // namespace 235 236 static const Expr *stripCasts(ASTContext &C, const Expr *Ex) { 237 while (Ex) { 238 Ex = Ex->IgnoreParenNoopCasts(C); 239 if (const auto *CE = dyn_cast<CastExpr>(Ex)) { 240 if (CE->getCastKind() == CK_LValueBitCast) { 241 Ex = CE->getSubExpr(); 242 continue; 243 } 244 } 245 break; 246 } 247 return Ex; 248 } 249 250 /// If E is an expression comprising a reference to a single variable, find that 251 /// variable. 252 static FindVarResult findVar(const Expr *E, const DeclContext *DC) { 253 if (const auto *DRE = 254 dyn_cast<DeclRefExpr>(stripCasts(DC->getParentASTContext(), E))) 255 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) 256 if (isTrackedVar(VD, DC)) 257 return FindVarResult(VD, DRE); 258 return FindVarResult(nullptr, nullptr); 259 } 260 261 namespace { 262 263 /// Classify each DeclRefExpr as an initialization or a use. Any 264 /// DeclRefExpr which isn't explicitly classified will be assumed to have 265 /// escaped the analysis and will be treated as an initialization. 266 class ClassifyRefs : public StmtVisitor<ClassifyRefs> { 267 public: 268 enum Class { 269 Init, 270 Use, 271 SelfInit, 272 ConstRefUse, 273 Ignore 274 }; 275 276 private: 277 const DeclContext *DC; 278 llvm::DenseMap<const DeclRefExpr *, Class> Classification; 279 280 bool isTrackedVar(const VarDecl *VD) const { 281 return ::isTrackedVar(VD, DC); 282 } 283 284 void classify(const Expr *E, Class C); 285 286 public: 287 ClassifyRefs(AnalysisDeclContext &AC) : DC(cast<DeclContext>(AC.getDecl())) {} 288 289 void VisitDeclStmt(DeclStmt *DS); 290 void VisitUnaryOperator(UnaryOperator *UO); 291 void VisitBinaryOperator(BinaryOperator *BO); 292 void VisitCallExpr(CallExpr *CE); 293 void VisitCastExpr(CastExpr *CE); 294 void VisitOMPExecutableDirective(OMPExecutableDirective *ED); 295 296 void operator()(Stmt *S) { Visit(S); } 297 298 Class get(const DeclRefExpr *DRE) const { 299 llvm::DenseMap<const DeclRefExpr*, Class>::const_iterator I 300 = Classification.find(DRE); 301 if (I != Classification.end()) 302 return I->second; 303 304 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()); 305 if (!VD || !isTrackedVar(VD)) 306 return Ignore; 307 308 return Init; 309 } 310 }; 311 312 } // namespace 313 314 static const DeclRefExpr *getSelfInitExpr(VarDecl *VD) { 315 if (VD->getType()->isRecordType()) 316 return nullptr; 317 if (Expr *Init = VD->getInit()) { 318 const auto *DRE = 319 dyn_cast<DeclRefExpr>(stripCasts(VD->getASTContext(), Init)); 320 if (DRE && DRE->getDecl() == VD) 321 return DRE; 322 } 323 return nullptr; 324 } 325 326 void ClassifyRefs::classify(const Expr *E, Class C) { 327 // The result of a ?: could also be an lvalue. 328 E = E->IgnoreParens(); 329 if (const auto *CO = dyn_cast<ConditionalOperator>(E)) { 330 classify(CO->getTrueExpr(), C); 331 classify(CO->getFalseExpr(), C); 332 return; 333 } 334 335 if (const auto *BCO = dyn_cast<BinaryConditionalOperator>(E)) { 336 classify(BCO->getFalseExpr(), C); 337 return; 338 } 339 340 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(E)) { 341 classify(OVE->getSourceExpr(), C); 342 return; 343 } 344 345 if (const auto *ME = dyn_cast<MemberExpr>(E)) { 346 if (const auto *VD = dyn_cast<VarDecl>(ME->getMemberDecl())) { 347 if (!VD->isStaticDataMember()) 348 classify(ME->getBase(), C); 349 } 350 return; 351 } 352 353 if (const auto *BO = dyn_cast<BinaryOperator>(E)) { 354 switch (BO->getOpcode()) { 355 case BO_PtrMemD: 356 case BO_PtrMemI: 357 classify(BO->getLHS(), C); 358 return; 359 case BO_Comma: 360 classify(BO->getRHS(), C); 361 return; 362 default: 363 return; 364 } 365 } 366 367 FindVarResult Var = findVar(E, DC); 368 if (const DeclRefExpr *DRE = Var.getDeclRefExpr()) 369 Classification[DRE] = std::max(Classification[DRE], C); 370 } 371 372 void ClassifyRefs::VisitDeclStmt(DeclStmt *DS) { 373 for (auto *DI : DS->decls()) { 374 auto *VD = dyn_cast<VarDecl>(DI); 375 if (VD && isTrackedVar(VD)) 376 if (const DeclRefExpr *DRE = getSelfInitExpr(VD)) 377 Classification[DRE] = SelfInit; 378 } 379 } 380 381 void ClassifyRefs::VisitBinaryOperator(BinaryOperator *BO) { 382 // Ignore the evaluation of a DeclRefExpr on the LHS of an assignment. If this 383 // is not a compound-assignment, we will treat it as initializing the variable 384 // when TransferFunctions visits it. A compound-assignment does not affect 385 // whether a variable is uninitialized, and there's no point counting it as a 386 // use. 387 if (BO->isCompoundAssignmentOp()) 388 classify(BO->getLHS(), Use); 389 else if (BO->getOpcode() == BO_Assign || BO->getOpcode() == BO_Comma) 390 classify(BO->getLHS(), Ignore); 391 } 392 393 void ClassifyRefs::VisitUnaryOperator(UnaryOperator *UO) { 394 // Increment and decrement are uses despite there being no lvalue-to-rvalue 395 // conversion. 396 if (UO->isIncrementDecrementOp()) 397 classify(UO->getSubExpr(), Use); 398 } 399 400 void ClassifyRefs::VisitOMPExecutableDirective(OMPExecutableDirective *ED) { 401 for (Stmt *S : OMPExecutableDirective::used_clauses_children(ED->clauses())) 402 classify(cast<Expr>(S), Use); 403 } 404 405 static bool isPointerToConst(const QualType &QT) { 406 return QT->isAnyPointerType() && QT->getPointeeType().isConstQualified(); 407 } 408 409 static bool hasTrivialBody(CallExpr *CE) { 410 if (FunctionDecl *FD = CE->getDirectCallee()) { 411 if (FunctionTemplateDecl *FTD = FD->getPrimaryTemplate()) 412 return FTD->getTemplatedDecl()->hasTrivialBody(); 413 return FD->hasTrivialBody(); 414 } 415 return false; 416 } 417 418 void ClassifyRefs::VisitCallExpr(CallExpr *CE) { 419 // Classify arguments to std::move as used. 420 if (CE->isCallToStdMove()) { 421 // RecordTypes are handled in SemaDeclCXX.cpp. 422 if (!CE->getArg(0)->getType()->isRecordType()) 423 classify(CE->getArg(0), Use); 424 return; 425 } 426 bool isTrivialBody = hasTrivialBody(CE); 427 // If a value is passed by const pointer to a function, 428 // we should not assume that it is initialized by the call, and we 429 // conservatively do not assume that it is used. 430 // If a value is passed by const reference to a function, 431 // it should already be initialized. 432 for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end(); 433 I != E; ++I) { 434 if ((*I)->isGLValue()) { 435 if ((*I)->getType().isConstQualified()) 436 classify((*I), isTrivialBody ? Ignore : ConstRefUse); 437 } else if (isPointerToConst((*I)->getType())) { 438 const Expr *Ex = stripCasts(DC->getParentASTContext(), *I); 439 const auto *UO = dyn_cast<UnaryOperator>(Ex); 440 if (UO && UO->getOpcode() == UO_AddrOf) 441 Ex = UO->getSubExpr(); 442 classify(Ex, Ignore); 443 } 444 } 445 } 446 447 void ClassifyRefs::VisitCastExpr(CastExpr *CE) { 448 if (CE->getCastKind() == CK_LValueToRValue) 449 classify(CE->getSubExpr(), Use); 450 else if (const auto *CSE = dyn_cast<CStyleCastExpr>(CE)) { 451 if (CSE->getType()->isVoidType()) { 452 // Squelch any detected load of an uninitialized value if 453 // we cast it to void. 454 // e.g. (void) x; 455 classify(CSE->getSubExpr(), Ignore); 456 } 457 } 458 } 459 460 //------------------------------------------------------------------------====// 461 // Transfer function for uninitialized values analysis. 462 //====------------------------------------------------------------------------// 463 464 namespace { 465 466 class TransferFunctions : public StmtVisitor<TransferFunctions> { 467 CFGBlockValues &vals; 468 const CFG &cfg; 469 const CFGBlock *block; 470 AnalysisDeclContext ∾ 471 const ClassifyRefs &classification; 472 ObjCNoReturn objCNoRet; 473 UninitVariablesHandler &handler; 474 475 public: 476 TransferFunctions(CFGBlockValues &vals, const CFG &cfg, 477 const CFGBlock *block, AnalysisDeclContext &ac, 478 const ClassifyRefs &classification, 479 UninitVariablesHandler &handler) 480 : vals(vals), cfg(cfg), block(block), ac(ac), 481 classification(classification), objCNoRet(ac.getASTContext()), 482 handler(handler) {} 483 484 void reportUse(const Expr *ex, const VarDecl *vd); 485 void reportConstRefUse(const Expr *ex, const VarDecl *vd); 486 487 void VisitBinaryOperator(BinaryOperator *bo); 488 void VisitBlockExpr(BlockExpr *be); 489 void VisitCallExpr(CallExpr *ce); 490 void VisitDeclRefExpr(DeclRefExpr *dr); 491 void VisitDeclStmt(DeclStmt *ds); 492 void VisitGCCAsmStmt(GCCAsmStmt *as); 493 void VisitObjCForCollectionStmt(ObjCForCollectionStmt *FS); 494 void VisitObjCMessageExpr(ObjCMessageExpr *ME); 495 void VisitOMPExecutableDirective(OMPExecutableDirective *ED); 496 497 bool isTrackedVar(const VarDecl *vd) { 498 return ::isTrackedVar(vd, cast<DeclContext>(ac.getDecl())); 499 } 500 501 FindVarResult findVar(const Expr *ex) { 502 return ::findVar(ex, cast<DeclContext>(ac.getDecl())); 503 } 504 505 UninitUse getUninitUse(const Expr *ex, const VarDecl *vd, Value v) { 506 UninitUse Use(ex, isAlwaysUninit(v)); 507 508 assert(isUninitialized(v)); 509 if (Use.getKind() == UninitUse::Always) 510 return Use; 511 512 // If an edge which leads unconditionally to this use did not initialize 513 // the variable, we can say something stronger than 'may be uninitialized': 514 // we can say 'either it's used uninitialized or you have dead code'. 515 // 516 // We track the number of successors of a node which have been visited, and 517 // visit a node once we have visited all of its successors. Only edges where 518 // the variable might still be uninitialized are followed. Since a variable 519 // can't transfer from being initialized to being uninitialized, this will 520 // trace out the subgraph which inevitably leads to the use and does not 521 // initialize the variable. We do not want to skip past loops, since their 522 // non-termination might be correlated with the initialization condition. 523 // 524 // For example: 525 // 526 // void f(bool a, bool b) { 527 // block1: int n; 528 // if (a) { 529 // block2: if (b) 530 // block3: n = 1; 531 // block4: } else if (b) { 532 // block5: while (!a) { 533 // block6: do_work(&a); 534 // n = 2; 535 // } 536 // } 537 // block7: if (a) 538 // block8: g(); 539 // block9: return n; 540 // } 541 // 542 // Starting from the maybe-uninitialized use in block 9: 543 // * Block 7 is not visited because we have only visited one of its two 544 // successors. 545 // * Block 8 is visited because we've visited its only successor. 546 // From block 8: 547 // * Block 7 is visited because we've now visited both of its successors. 548 // From block 7: 549 // * Blocks 1, 2, 4, 5, and 6 are not visited because we didn't visit all 550 // of their successors (we didn't visit 4, 3, 5, 6, and 5, respectively). 551 // * Block 3 is not visited because it initializes 'n'. 552 // Now the algorithm terminates, having visited blocks 7 and 8, and having 553 // found the frontier is blocks 2, 4, and 5. 554 // 555 // 'n' is definitely uninitialized for two edges into block 7 (from blocks 2 556 // and 4), so we report that any time either of those edges is taken (in 557 // each case when 'b == false'), 'n' is used uninitialized. 558 SmallVector<const CFGBlock*, 32> Queue; 559 SmallVector<unsigned, 32> SuccsVisited(cfg.getNumBlockIDs(), 0); 560 Queue.push_back(block); 561 // Specify that we've already visited all successors of the starting block. 562 // This has the dual purpose of ensuring we never add it to the queue, and 563 // of marking it as not being a candidate element of the frontier. 564 SuccsVisited[block->getBlockID()] = block->succ_size(); 565 while (!Queue.empty()) { 566 const CFGBlock *B = Queue.pop_back_val(); 567 568 // If the use is always reached from the entry block, make a note of that. 569 if (B == &cfg.getEntry()) 570 Use.setUninitAfterCall(); 571 572 for (CFGBlock::const_pred_iterator I = B->pred_begin(), E = B->pred_end(); 573 I != E; ++I) { 574 const CFGBlock *Pred = *I; 575 if (!Pred) 576 continue; 577 578 Value AtPredExit = vals.getValue(Pred, B, vd); 579 if (AtPredExit == Initialized) 580 // This block initializes the variable. 581 continue; 582 if (AtPredExit == MayUninitialized && 583 vals.getValue(B, nullptr, vd) == Uninitialized) { 584 // This block declares the variable (uninitialized), and is reachable 585 // from a block that initializes the variable. We can't guarantee to 586 // give an earlier location for the diagnostic (and it appears that 587 // this code is intended to be reachable) so give a diagnostic here 588 // and go no further down this path. 589 Use.setUninitAfterDecl(); 590 continue; 591 } 592 593 if (AtPredExit == MayUninitialized) { 594 // If the predecessor's terminator is an "asm goto" that initializes 595 // the variable, then don't count it as "initialized" on the indirect 596 // paths. 597 CFGTerminator term = Pred->getTerminator(); 598 if (const auto *as = dyn_cast_or_null<GCCAsmStmt>(term.getStmt())) { 599 const CFGBlock *fallthrough = *Pred->succ_begin(); 600 if (as->isAsmGoto() && 601 llvm::any_of(as->outputs(), [&](const Expr *output) { 602 return vd == findVar(output).getDecl() && 603 llvm::any_of(as->labels(), 604 [&](const AddrLabelExpr *label) { 605 return label->getLabel()->getStmt() == B->Label && 606 B != fallthrough; 607 }); 608 })) { 609 Use.setUninitAfterDecl(); 610 continue; 611 } 612 } 613 } 614 615 unsigned &SV = SuccsVisited[Pred->getBlockID()]; 616 if (!SV) { 617 // When visiting the first successor of a block, mark all NULL 618 // successors as having been visited. 619 for (CFGBlock::const_succ_iterator SI = Pred->succ_begin(), 620 SE = Pred->succ_end(); 621 SI != SE; ++SI) 622 if (!*SI) 623 ++SV; 624 } 625 626 if (++SV == Pred->succ_size()) 627 // All paths from this block lead to the use and don't initialize the 628 // variable. 629 Queue.push_back(Pred); 630 } 631 } 632 633 // Scan the frontier, looking for blocks where the variable was 634 // uninitialized. 635 for (const auto *Block : cfg) { 636 unsigned BlockID = Block->getBlockID(); 637 const Stmt *Term = Block->getTerminatorStmt(); 638 if (SuccsVisited[BlockID] && SuccsVisited[BlockID] < Block->succ_size() && 639 Term) { 640 // This block inevitably leads to the use. If we have an edge from here 641 // to a post-dominator block, and the variable is uninitialized on that 642 // edge, we have found a bug. 643 for (CFGBlock::const_succ_iterator I = Block->succ_begin(), 644 E = Block->succ_end(); I != E; ++I) { 645 const CFGBlock *Succ = *I; 646 if (Succ && SuccsVisited[Succ->getBlockID()] >= Succ->succ_size() && 647 vals.getValue(Block, Succ, vd) == Uninitialized) { 648 // Switch cases are a special case: report the label to the caller 649 // as the 'terminator', not the switch statement itself. Suppress 650 // situations where no label matched: we can't be sure that's 651 // possible. 652 if (isa<SwitchStmt>(Term)) { 653 const Stmt *Label = Succ->getLabel(); 654 if (!Label || !isa<SwitchCase>(Label)) 655 // Might not be possible. 656 continue; 657 UninitUse::Branch Branch; 658 Branch.Terminator = Label; 659 Branch.Output = 0; // Ignored. 660 Use.addUninitBranch(Branch); 661 } else { 662 UninitUse::Branch Branch; 663 Branch.Terminator = Term; 664 Branch.Output = I - Block->succ_begin(); 665 Use.addUninitBranch(Branch); 666 } 667 } 668 } 669 } 670 } 671 672 return Use; 673 } 674 }; 675 676 } // namespace 677 678 void TransferFunctions::reportUse(const Expr *ex, const VarDecl *vd) { 679 Value v = vals[vd]; 680 if (isUninitialized(v)) 681 handler.handleUseOfUninitVariable(vd, getUninitUse(ex, vd, v)); 682 } 683 684 void TransferFunctions::reportConstRefUse(const Expr *ex, const VarDecl *vd) { 685 Value v = vals[vd]; 686 if (isAlwaysUninit(v)) 687 handler.handleConstRefUseOfUninitVariable(vd, getUninitUse(ex, vd, v)); 688 } 689 690 void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *FS) { 691 // This represents an initialization of the 'element' value. 692 if (const auto *DS = dyn_cast<DeclStmt>(FS->getElement())) { 693 const auto *VD = cast<VarDecl>(DS->getSingleDecl()); 694 if (isTrackedVar(VD)) 695 vals[VD] = Initialized; 696 } 697 } 698 699 void TransferFunctions::VisitOMPExecutableDirective( 700 OMPExecutableDirective *ED) { 701 for (Stmt *S : OMPExecutableDirective::used_clauses_children(ED->clauses())) { 702 assert(S && "Expected non-null used-in-clause child."); 703 Visit(S); 704 } 705 if (!ED->isStandaloneDirective()) 706 Visit(ED->getStructuredBlock()); 707 } 708 709 void TransferFunctions::VisitBlockExpr(BlockExpr *be) { 710 const BlockDecl *bd = be->getBlockDecl(); 711 for (const auto &I : bd->captures()) { 712 const VarDecl *vd = I.getVariable(); 713 if (!isTrackedVar(vd)) 714 continue; 715 if (I.isByRef()) { 716 vals[vd] = Initialized; 717 continue; 718 } 719 reportUse(be, vd); 720 } 721 } 722 723 void TransferFunctions::VisitCallExpr(CallExpr *ce) { 724 if (Decl *Callee = ce->getCalleeDecl()) { 725 if (Callee->hasAttr<ReturnsTwiceAttr>()) { 726 // After a call to a function like setjmp or vfork, any variable which is 727 // initialized anywhere within this function may now be initialized. For 728 // now, just assume such a call initializes all variables. FIXME: Only 729 // mark variables as initialized if they have an initializer which is 730 // reachable from here. 731 vals.setAllScratchValues(Initialized); 732 } 733 else if (Callee->hasAttr<AnalyzerNoReturnAttr>()) { 734 // Functions labeled like "analyzer_noreturn" are often used to denote 735 // "panic" functions that in special debug situations can still return, 736 // but for the most part should not be treated as returning. This is a 737 // useful annotation borrowed from the static analyzer that is useful for 738 // suppressing branch-specific false positives when we call one of these 739 // functions but keep pretending the path continues (when in reality the 740 // user doesn't care). 741 vals.setAllScratchValues(Unknown); 742 } 743 } 744 } 745 746 void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *dr) { 747 switch (classification.get(dr)) { 748 case ClassifyRefs::Ignore: 749 break; 750 case ClassifyRefs::Use: 751 reportUse(dr, cast<VarDecl>(dr->getDecl())); 752 break; 753 case ClassifyRefs::Init: 754 vals[cast<VarDecl>(dr->getDecl())] = Initialized; 755 break; 756 case ClassifyRefs::SelfInit: 757 handler.handleSelfInit(cast<VarDecl>(dr->getDecl())); 758 break; 759 case ClassifyRefs::ConstRefUse: 760 reportConstRefUse(dr, cast<VarDecl>(dr->getDecl())); 761 break; 762 } 763 } 764 765 void TransferFunctions::VisitBinaryOperator(BinaryOperator *BO) { 766 if (BO->getOpcode() == BO_Assign) { 767 FindVarResult Var = findVar(BO->getLHS()); 768 if (const VarDecl *VD = Var.getDecl()) 769 vals[VD] = Initialized; 770 } 771 } 772 773 void TransferFunctions::VisitDeclStmt(DeclStmt *DS) { 774 for (auto *DI : DS->decls()) { 775 auto *VD = dyn_cast<VarDecl>(DI); 776 if (VD && isTrackedVar(VD)) { 777 if (getSelfInitExpr(VD)) { 778 // If the initializer consists solely of a reference to itself, we 779 // explicitly mark the variable as uninitialized. This allows code 780 // like the following: 781 // 782 // int x = x; 783 // 784 // to deliberately leave a variable uninitialized. Different analysis 785 // clients can detect this pattern and adjust their reporting 786 // appropriately, but we need to continue to analyze subsequent uses 787 // of the variable. 788 vals[VD] = Uninitialized; 789 } else if (VD->getInit()) { 790 // Treat the new variable as initialized. 791 vals[VD] = Initialized; 792 } else { 793 // No initializer: the variable is now uninitialized. This matters 794 // for cases like: 795 // while (...) { 796 // int n; 797 // use(n); 798 // n = 0; 799 // } 800 // FIXME: Mark the variable as uninitialized whenever its scope is 801 // left, since its scope could be re-entered by a jump over the 802 // declaration. 803 vals[VD] = Uninitialized; 804 } 805 } 806 } 807 } 808 809 void TransferFunctions::VisitGCCAsmStmt(GCCAsmStmt *as) { 810 // An "asm goto" statement is a terminator that may initialize some variables. 811 if (!as->isAsmGoto()) 812 return; 813 814 ASTContext &C = ac.getASTContext(); 815 for (const Expr *O : as->outputs()) { 816 const Expr *Ex = stripCasts(C, O); 817 818 // Strip away any unary operators. Invalid l-values are reported by other 819 // semantic analysis passes. 820 while (const auto *UO = dyn_cast<UnaryOperator>(Ex)) 821 Ex = stripCasts(C, UO->getSubExpr()); 822 823 // Mark the variable as potentially uninitialized for those cases where 824 // it's used on an indirect path, where it's not guaranteed to be 825 // defined. 826 if (const VarDecl *VD = findVar(Ex).getDecl()) 827 vals[VD] = MayUninitialized; 828 } 829 } 830 831 void TransferFunctions::VisitObjCMessageExpr(ObjCMessageExpr *ME) { 832 // If the Objective-C message expression is an implicit no-return that 833 // is not modeled in the CFG, set the tracked dataflow values to Unknown. 834 if (objCNoRet.isImplicitNoReturn(ME)) { 835 vals.setAllScratchValues(Unknown); 836 } 837 } 838 839 //------------------------------------------------------------------------====// 840 // High-level "driver" logic for uninitialized values analysis. 841 //====------------------------------------------------------------------------// 842 843 static bool runOnBlock(const CFGBlock *block, const CFG &cfg, 844 AnalysisDeclContext &ac, CFGBlockValues &vals, 845 const ClassifyRefs &classification, 846 llvm::BitVector &wasAnalyzed, 847 UninitVariablesHandler &handler) { 848 wasAnalyzed[block->getBlockID()] = true; 849 vals.resetScratch(); 850 // Merge in values of predecessor blocks. 851 bool isFirst = true; 852 for (CFGBlock::const_pred_iterator I = block->pred_begin(), 853 E = block->pred_end(); I != E; ++I) { 854 const CFGBlock *pred = *I; 855 if (!pred) 856 continue; 857 if (wasAnalyzed[pred->getBlockID()]) { 858 vals.mergeIntoScratch(vals.getValueVector(pred), isFirst); 859 isFirst = false; 860 } 861 } 862 // Apply the transfer function. 863 TransferFunctions tf(vals, cfg, block, ac, classification, handler); 864 for (const auto &I : *block) { 865 if (Optional<CFGStmt> cs = I.getAs<CFGStmt>()) 866 tf.Visit(const_cast<Stmt *>(cs->getStmt())); 867 } 868 CFGTerminator terminator = block->getTerminator(); 869 if (auto *as = dyn_cast_or_null<GCCAsmStmt>(terminator.getStmt())) 870 if (as->isAsmGoto()) 871 tf.Visit(as); 872 return vals.updateValueVectorWithScratch(block); 873 } 874 875 namespace { 876 877 /// PruneBlocksHandler is a special UninitVariablesHandler that is used 878 /// to detect when a CFGBlock has any *potential* use of an uninitialized 879 /// variable. It is mainly used to prune out work during the final 880 /// reporting pass. 881 struct PruneBlocksHandler : public UninitVariablesHandler { 882 /// Records if a CFGBlock had a potential use of an uninitialized variable. 883 llvm::BitVector hadUse; 884 885 /// Records if any CFGBlock had a potential use of an uninitialized variable. 886 bool hadAnyUse = false; 887 888 /// The current block to scribble use information. 889 unsigned currentBlock = 0; 890 891 PruneBlocksHandler(unsigned numBlocks) : hadUse(numBlocks, false) {} 892 893 ~PruneBlocksHandler() override = default; 894 895 void handleUseOfUninitVariable(const VarDecl *vd, 896 const UninitUse &use) override { 897 hadUse[currentBlock] = true; 898 hadAnyUse = true; 899 } 900 901 void handleConstRefUseOfUninitVariable(const VarDecl *vd, 902 const UninitUse &use) override { 903 hadUse[currentBlock] = true; 904 hadAnyUse = true; 905 } 906 907 /// Called when the uninitialized variable analysis detects the 908 /// idiom 'int x = x'. All other uses of 'x' within the initializer 909 /// are handled by handleUseOfUninitVariable. 910 void handleSelfInit(const VarDecl *vd) override { 911 hadUse[currentBlock] = true; 912 hadAnyUse = true; 913 } 914 }; 915 916 } // namespace 917 918 void clang::runUninitializedVariablesAnalysis( 919 const DeclContext &dc, 920 const CFG &cfg, 921 AnalysisDeclContext &ac, 922 UninitVariablesHandler &handler, 923 UninitVariablesAnalysisStats &stats) { 924 CFGBlockValues vals(cfg); 925 vals.computeSetOfDeclarations(dc); 926 if (vals.hasNoDeclarations()) 927 return; 928 929 stats.NumVariablesAnalyzed = vals.getNumEntries(); 930 931 // Precompute which expressions are uses and which are initializations. 932 ClassifyRefs classification(ac); 933 cfg.VisitBlockStmts(classification); 934 935 // Mark all variables uninitialized at the entry. 936 const CFGBlock &entry = cfg.getEntry(); 937 ValueVector &vec = vals.getValueVector(&entry); 938 const unsigned n = vals.getNumEntries(); 939 for (unsigned j = 0; j < n; ++j) { 940 vec[j] = Uninitialized; 941 } 942 943 // Proceed with the workist. 944 ForwardDataflowWorklist worklist(cfg, ac); 945 llvm::BitVector previouslyVisited(cfg.getNumBlockIDs()); 946 worklist.enqueueSuccessors(&cfg.getEntry()); 947 llvm::BitVector wasAnalyzed(cfg.getNumBlockIDs(), false); 948 wasAnalyzed[cfg.getEntry().getBlockID()] = true; 949 PruneBlocksHandler PBH(cfg.getNumBlockIDs()); 950 951 while (const CFGBlock *block = worklist.dequeue()) { 952 PBH.currentBlock = block->getBlockID(); 953 954 // Did the block change? 955 bool changed = runOnBlock(block, cfg, ac, vals, 956 classification, wasAnalyzed, PBH); 957 ++stats.NumBlockVisits; 958 if (changed || !previouslyVisited[block->getBlockID()]) 959 worklist.enqueueSuccessors(block); 960 previouslyVisited[block->getBlockID()] = true; 961 } 962 963 if (!PBH.hadAnyUse) 964 return; 965 966 // Run through the blocks one more time, and report uninitialized variables. 967 for (const auto *block : cfg) 968 if (PBH.hadUse[block->getBlockID()]) { 969 runOnBlock(block, cfg, ac, vals, classification, wasAnalyzed, handler); 970 ++stats.NumBlockVisits; 971 } 972 } 973 974 UninitVariablesHandler::~UninitVariablesHandler() = default; 975