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