1 //===--- AnalysisConsumer.cpp - ASTConsumer for running Analyses ----------===// 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 // "Meta" ASTConsumer for running different source analyses. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h" 14 #include "ModelInjector.h" 15 #include "clang/AST/Decl.h" 16 #include "clang/AST/DeclCXX.h" 17 #include "clang/AST/DeclObjC.h" 18 #include "clang/AST/DynamicRecursiveASTVisitor.h" 19 #include "clang/Analysis/Analyses/LiveVariables.h" 20 #include "clang/Analysis/CFG.h" 21 #include "clang/Analysis/CallGraph.h" 22 #include "clang/Analysis/CodeInjector.h" 23 #include "clang/Analysis/MacroExpansionContext.h" 24 #include "clang/Analysis/PathDiagnostic.h" 25 #include "clang/Basic/SourceManager.h" 26 #include "clang/CrossTU/CrossTranslationUnit.h" 27 #include "clang/Frontend/CompilerInstance.h" 28 #include "clang/Lex/Preprocessor.h" 29 #include "clang/Rewrite/Core/Rewriter.h" 30 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" 31 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 32 #include "clang/StaticAnalyzer/Core/CheckerManager.h" 33 #include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h" 34 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 35 #include "clang/StaticAnalyzer/Core/PathSensitive/EntryPointStats.h" 36 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 37 #include "llvm/ADT/PostOrderIterator.h" 38 #include "llvm/ADT/ScopeExit.h" 39 #include "llvm/Support/TimeProfiler.h" 40 #include "llvm/Support/Timer.h" 41 #include "llvm/Support/raw_ostream.h" 42 #include <memory> 43 #include <utility> 44 45 using namespace clang; 46 using namespace ento; 47 48 #define DEBUG_TYPE "AnalysisConsumer" 49 50 STAT_COUNTER(NumFunctionTopLevel, "The # of functions at top level."); 51 ALWAYS_ENABLED_STATISTIC(NumFunctionsAnalyzed, 52 "The # of functions and blocks analyzed (as top level " 53 "with inlining turned on)."); 54 ALWAYS_ENABLED_STATISTIC(NumBlocksInAnalyzedFunctions, 55 "The # of basic blocks in the analyzed functions."); 56 ALWAYS_ENABLED_STATISTIC( 57 NumVisitedBlocksInAnalyzedFunctions, 58 "The # of visited basic blocks in the analyzed functions."); 59 ALWAYS_ENABLED_STATISTIC(PercentReachableBlocks, 60 "The % of reachable basic blocks."); 61 STAT_MAX(MaxCFGSize, "The maximum number of basic blocks in a function."); 62 //===----------------------------------------------------------------------===// 63 // AnalysisConsumer declaration. 64 //===----------------------------------------------------------------------===// 65 66 namespace { 67 68 class AnalysisConsumer : public AnalysisASTConsumer, 69 public DynamicRecursiveASTVisitor { 70 enum { 71 AM_None = 0, 72 AM_Syntax = 0x1, 73 AM_Path = 0x2 74 }; 75 typedef unsigned AnalysisMode; 76 77 /// Mode of the analyzes while recursively visiting Decls. 78 AnalysisMode RecVisitorMode; 79 /// Bug Reporter to use while recursively visiting Decls. 80 BugReporter *RecVisitorBR; 81 82 std::vector<std::function<void(CheckerRegistry &)>> CheckerRegistrationFns; 83 84 public: 85 ASTContext *Ctx; 86 Preprocessor &PP; 87 const std::string OutDir; 88 AnalyzerOptions &Opts; 89 ArrayRef<std::string> Plugins; 90 std::unique_ptr<CodeInjector> Injector; 91 cross_tu::CrossTranslationUnitContext CTU; 92 93 /// Stores the declarations from the local translation unit. 94 /// Note, we pre-compute the local declarations at parse time as an 95 /// optimization to make sure we do not deserialize everything from disk. 96 /// The local declaration to all declarations ratio might be very small when 97 /// working with a PCH file. 98 SetOfDecls LocalTUDecls; 99 100 MacroExpansionContext MacroExpansions; 101 102 // Set of PathDiagnosticConsumers. Owned by AnalysisManager. 103 PathDiagnosticConsumers PathConsumers; 104 105 StoreManagerCreator CreateStoreMgr; 106 ConstraintManagerCreator CreateConstraintMgr; 107 108 std::unique_ptr<CheckerManager> checkerMgr; 109 std::unique_ptr<AnalysisManager> Mgr; 110 111 /// Time the analyzes time of each translation unit. 112 std::unique_ptr<llvm::TimerGroup> AnalyzerTimers; 113 std::unique_ptr<llvm::Timer> SyntaxCheckTimer; 114 std::unique_ptr<llvm::Timer> ExprEngineTimer; 115 std::unique_ptr<llvm::Timer> BugReporterTimer; 116 117 /// The information about analyzed functions shared throughout the 118 /// translation unit. 119 FunctionSummariesTy FunctionSummaries; 120 121 AnalysisConsumer(CompilerInstance &CI, const std::string &outdir, 122 AnalyzerOptions &opts, ArrayRef<std::string> plugins, 123 std::unique_ptr<CodeInjector> injector) 124 : RecVisitorMode(0), RecVisitorBR(nullptr), Ctx(nullptr), 125 PP(CI.getPreprocessor()), OutDir(outdir), Opts(opts), Plugins(plugins), 126 Injector(std::move(injector)), CTU(CI), 127 MacroExpansions(CI.getLangOpts()) { 128 EntryPointStat::lockRegistry(); 129 DigestAnalyzerOptions(); 130 131 if (Opts.AnalyzerDisplayProgress || Opts.PrintStats || 132 Opts.ShouldSerializeStats) { 133 AnalyzerTimers = std::make_unique<llvm::TimerGroup>( 134 "analyzer", "Analyzer timers"); 135 SyntaxCheckTimer = std::make_unique<llvm::Timer>( 136 "syntaxchecks", "Syntax-based analysis time", *AnalyzerTimers); 137 ExprEngineTimer = std::make_unique<llvm::Timer>( 138 "exprengine", "Path exploration time", *AnalyzerTimers); 139 BugReporterTimer = std::make_unique<llvm::Timer>( 140 "bugreporter", "Path-sensitive report post-processing time", 141 *AnalyzerTimers); 142 } 143 144 if (Opts.PrintStats || Opts.ShouldSerializeStats) { 145 llvm::EnableStatistics(/* DoPrintOnExit= */ false); 146 } 147 148 if (Opts.ShouldDisplayMacroExpansions) 149 MacroExpansions.registerForPreprocessor(PP); 150 151 // Visitor options. 152 ShouldWalkTypesOfTypeLocs = false; 153 } 154 155 ~AnalysisConsumer() override { 156 if (Opts.PrintStats) { 157 llvm::PrintStatistics(); 158 } 159 } 160 161 void DigestAnalyzerOptions() { 162 switch (Opts.AnalysisDiagOpt) { 163 case PD_NONE: 164 break; 165 #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN) \ 166 case PD_##NAME: \ 167 CREATEFN(Opts.getDiagOpts(), PathConsumers, OutDir, PP, CTU, \ 168 MacroExpansions); \ 169 break; 170 #include "clang/StaticAnalyzer/Core/Analyses.def" 171 default: 172 llvm_unreachable("Unknown analyzer output type!"); 173 } 174 175 // Create the analyzer component creators. 176 CreateStoreMgr = &CreateRegionStoreManager; 177 178 switch (Opts.AnalysisConstraintsOpt) { 179 default: 180 llvm_unreachable("Unknown constraint manager."); 181 #define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN) \ 182 case NAME##Model: CreateConstraintMgr = CREATEFN; break; 183 #include "clang/StaticAnalyzer/Core/Analyses.def" 184 } 185 } 186 187 void DisplayTime(llvm::TimeRecord &Time) { 188 if (!Opts.AnalyzerDisplayProgress) { 189 return; 190 } 191 llvm::errs() << " : " << llvm::format("%1.1f", Time.getWallTime() * 1000) 192 << " ms\n"; 193 } 194 195 void DisplayFunction(const Decl *D, AnalysisMode Mode, 196 ExprEngine::InliningModes IMode) { 197 if (!Opts.AnalyzerDisplayProgress) 198 return; 199 200 SourceManager &SM = Mgr->getASTContext().getSourceManager(); 201 PresumedLoc Loc = SM.getPresumedLoc(D->getLocation()); 202 if (Loc.isValid()) { 203 llvm::errs() << "ANALYZE"; 204 205 if (Mode == AM_Syntax) 206 llvm::errs() << " (Syntax)"; 207 else if (Mode == AM_Path) { 208 llvm::errs() << " (Path, "; 209 switch (IMode) { 210 case ExprEngine::Inline_Minimal: 211 llvm::errs() << " Inline_Minimal"; 212 break; 213 case ExprEngine::Inline_Regular: 214 llvm::errs() << " Inline_Regular"; 215 break; 216 } 217 llvm::errs() << ")"; 218 } else 219 assert(Mode == (AM_Syntax | AM_Path) && "Unexpected mode!"); 220 221 llvm::errs() << ": " << Loc.getFilename() << ' ' 222 << AnalysisDeclContext::getFunctionName(D); 223 } 224 } 225 226 /// Store the top level decls in the set to be processed later on. 227 /// (Doing this pre-processing avoids deserialization of data from PCH.) 228 bool HandleTopLevelDecl(DeclGroupRef D) override; 229 void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override; 230 231 void HandleTranslationUnit(ASTContext &C) override; 232 233 /// Determine which inlining mode should be used when this function is 234 /// analyzed. This allows to redefine the default inlining policies when 235 /// analyzing a given function. 236 ExprEngine::InliningModes 237 getInliningModeForFunction(const Decl *D, const SetOfConstDecls &Visited); 238 239 /// Build the call graph for all the top level decls of this TU and 240 /// use it to define the order in which the functions should be visited. 241 void HandleDeclsCallGraph(const unsigned LocalTUDeclsSize); 242 243 /// Run analyzes(syntax or path sensitive) on the given function. 244 /// \param Mode - determines if we are requesting syntax only or path 245 /// sensitive only analysis. 246 /// \param VisitedCallees - The output parameter, which is populated with the 247 /// set of functions which should be considered analyzed after analyzing the 248 /// given root function. 249 void HandleCode(Decl *D, AnalysisMode Mode, 250 ExprEngine::InliningModes IMode = ExprEngine::Inline_Minimal, 251 SetOfConstDecls *VisitedCallees = nullptr); 252 253 void RunPathSensitiveChecks(Decl *D, 254 ExprEngine::InliningModes IMode, 255 SetOfConstDecls *VisitedCallees); 256 257 /// Handle callbacks for arbitrary Decls. 258 bool VisitDecl(Decl *D) override { 259 AnalysisMode Mode = getModeForDecl(D, RecVisitorMode); 260 if (Mode & AM_Syntax) { 261 if (SyntaxCheckTimer) 262 SyntaxCheckTimer->startTimer(); 263 checkerMgr->runCheckersOnASTDecl(D, *Mgr, *RecVisitorBR); 264 if (SyntaxCheckTimer) 265 SyntaxCheckTimer->stopTimer(); 266 } 267 return true; 268 } 269 270 bool VisitVarDecl(VarDecl *VD) override { 271 if (!Opts.IsNaiveCTUEnabled) 272 return true; 273 274 if (VD->hasExternalStorage() || VD->isStaticDataMember()) { 275 if (!cross_tu::shouldImport(VD, *Ctx)) 276 return true; 277 } else { 278 // Cannot be initialized in another TU. 279 return true; 280 } 281 282 if (VD->getAnyInitializer()) 283 return true; 284 285 llvm::Expected<const VarDecl *> CTUDeclOrError = 286 CTU.getCrossTUDefinition(VD, Opts.CTUDir, Opts.CTUIndexName, 287 Opts.DisplayCTUProgress); 288 289 if (!CTUDeclOrError) { 290 handleAllErrors(CTUDeclOrError.takeError(), 291 [&](const cross_tu::IndexError &IE) { 292 CTU.emitCrossTUDiagnostics(IE); 293 }); 294 } 295 296 return true; 297 } 298 299 bool VisitFunctionDecl(FunctionDecl *FD) override { 300 IdentifierInfo *II = FD->getIdentifier(); 301 if (II && II->getName().starts_with("__inline")) 302 return true; 303 304 // We skip function template definitions, as their semantics is 305 // only determined when they are instantiated. 306 if (FD->isThisDeclarationADefinition() && 307 !FD->isDependentContext()) { 308 assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() == false); 309 HandleCode(FD, RecVisitorMode); 310 } 311 return true; 312 } 313 314 bool VisitObjCMethodDecl(ObjCMethodDecl *MD) override { 315 if (MD->isThisDeclarationADefinition()) { 316 assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() == false); 317 HandleCode(MD, RecVisitorMode); 318 } 319 return true; 320 } 321 322 bool VisitBlockDecl(BlockDecl *BD) override { 323 if (BD->hasBody()) { 324 assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() == false); 325 // Since we skip function template definitions, we should skip blocks 326 // declared in those functions as well. 327 if (!BD->isDependentContext()) { 328 HandleCode(BD, RecVisitorMode); 329 } 330 } 331 return true; 332 } 333 334 void AddDiagnosticConsumer( 335 std::unique_ptr<PathDiagnosticConsumer> Consumer) override { 336 PathConsumers.push_back(std::move(Consumer)); 337 } 338 339 void AddCheckerRegistrationFn(std::function<void(CheckerRegistry&)> Fn) override { 340 CheckerRegistrationFns.push_back(std::move(Fn)); 341 } 342 343 private: 344 void storeTopLevelDecls(DeclGroupRef DG); 345 346 /// Check if we should skip (not analyze) the given function. 347 AnalysisMode getModeForDecl(Decl *D, AnalysisMode Mode); 348 void runAnalysisOnTranslationUnit(ASTContext &C); 349 350 /// Print \p S to stderr if \c Opts.AnalyzerDisplayProgress is set. 351 void reportAnalyzerProgress(StringRef S); 352 }; 353 354 std::string timeTraceScopeDeclName(StringRef FunName, const Decl *D) { 355 if (llvm::timeTraceProfilerEnabled()) { 356 if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) 357 return (FunName + " " + ND->getQualifiedNameAsString()).str(); 358 return (FunName + " <anonymous> ").str(); 359 } 360 return ""; 361 } 362 363 llvm::TimeTraceMetadata timeTraceScopeDeclMetadata(const Decl *D) { 364 // If time-trace profiler is not enabled, this function is never called. 365 assert(llvm::timeTraceProfilerEnabled()); 366 if (const auto &Loc = D->getBeginLoc(); Loc.isValid()) { 367 const auto &SM = D->getASTContext().getSourceManager(); 368 std::string DeclName = AnalysisDeclContext::getFunctionName(D); 369 return llvm::TimeTraceMetadata{ 370 std::move(DeclName), SM.getFilename(Loc).str(), 371 static_cast<int>(SM.getExpansionLineNumber(Loc))}; 372 } 373 return llvm::TimeTraceMetadata{"", ""}; 374 } 375 376 void flushReports(llvm::Timer *BugReporterTimer, BugReporter &BR) { 377 llvm::TimeTraceScope TCS{"Flushing reports"}; 378 // Display warnings. 379 if (BugReporterTimer) 380 BugReporterTimer->startTimer(); 381 BR.FlushReports(); 382 if (BugReporterTimer) 383 BugReporterTimer->stopTimer(); 384 } 385 } // namespace 386 387 //===----------------------------------------------------------------------===// 388 // AnalysisConsumer implementation. 389 //===----------------------------------------------------------------------===// 390 bool AnalysisConsumer::HandleTopLevelDecl(DeclGroupRef DG) { 391 storeTopLevelDecls(DG); 392 return true; 393 } 394 395 void AnalysisConsumer::HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) { 396 storeTopLevelDecls(DG); 397 } 398 399 void AnalysisConsumer::storeTopLevelDecls(DeclGroupRef DG) { 400 for (auto &I : DG) { 401 402 // Skip ObjCMethodDecl, wait for the objc container to avoid 403 // analyzing twice. 404 if (isa<ObjCMethodDecl>(I)) 405 continue; 406 407 LocalTUDecls.push_back(I); 408 } 409 } 410 411 static bool shouldSkipFunction(const Decl *D, 412 const SetOfConstDecls &Visited, 413 const SetOfConstDecls &VisitedAsTopLevel) { 414 if (VisitedAsTopLevel.count(D)) 415 return true; 416 417 // Skip analysis of inheriting constructors as top-level functions. These 418 // constructors don't even have a body written down in the code, so even if 419 // we find a bug, we won't be able to display it. 420 if (const auto *CD = dyn_cast<CXXConstructorDecl>(D)) 421 if (CD->isInheritingConstructor()) 422 return true; 423 424 // We want to re-analyse the functions as top level in the following cases: 425 // - The 'init' methods should be reanalyzed because 426 // ObjCNonNilReturnValueChecker assumes that '[super init]' never returns 427 // 'nil' and unless we analyze the 'init' functions as top level, we will 428 // not catch errors within defensive code. 429 // - We want to reanalyze all ObjC methods as top level to report Retain 430 // Count naming convention errors more aggressively. 431 if (isa<ObjCMethodDecl>(D)) 432 return false; 433 // We also want to reanalyze all C++ copy and move assignment operators to 434 // separately check the two cases where 'this' aliases with the parameter and 435 // where it may not. (cplusplus.SelfAssignmentChecker) 436 if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) { 437 if (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()) 438 return false; 439 } 440 441 // Otherwise, if we visited the function before, do not reanalyze it. 442 return Visited.count(D); 443 } 444 445 ExprEngine::InliningModes 446 AnalysisConsumer::getInliningModeForFunction(const Decl *D, 447 const SetOfConstDecls &Visited) { 448 // We want to reanalyze all ObjC methods as top level to report Retain 449 // Count naming convention errors more aggressively. But we should tune down 450 // inlining when reanalyzing an already inlined function. 451 if (Visited.count(D) && isa<ObjCMethodDecl>(D)) { 452 const ObjCMethodDecl *ObjCM = cast<ObjCMethodDecl>(D); 453 if (ObjCM->getMethodFamily() != OMF_init) 454 return ExprEngine::Inline_Minimal; 455 } 456 457 return ExprEngine::Inline_Regular; 458 } 459 460 void AnalysisConsumer::HandleDeclsCallGraph(const unsigned LocalTUDeclsSize) { 461 // Build the Call Graph by adding all the top level declarations to the graph. 462 // Note: CallGraph can trigger deserialization of more items from a pch 463 // (though HandleInterestingDecl); triggering additions to LocalTUDecls. 464 // We rely on random access to add the initially processed Decls to CG. 465 CallGraph CG; 466 for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) { 467 CG.addToCallGraph(LocalTUDecls[i]); 468 } 469 470 // Walk over all of the call graph nodes in topological order, so that we 471 // analyze parents before the children. Skip the functions inlined into 472 // the previously processed functions. Use external Visited set to identify 473 // inlined functions. The topological order allows the "do not reanalyze 474 // previously inlined function" performance heuristic to be triggered more 475 // often. 476 SetOfConstDecls Visited; 477 SetOfConstDecls VisitedAsTopLevel; 478 llvm::ReversePostOrderTraversal<clang::CallGraph*> RPOT(&CG); 479 for (auto &N : RPOT) { 480 NumFunctionTopLevel++; 481 482 Decl *D = N->getDecl(); 483 484 // Skip the abstract root node. 485 if (!D) 486 continue; 487 488 // Skip the functions which have been processed already or previously 489 // inlined. 490 if (shouldSkipFunction(D, Visited, VisitedAsTopLevel)) 491 continue; 492 493 // The CallGraph might have declarations as callees. However, during CTU 494 // the declaration might form a declaration chain with the newly imported 495 // definition from another TU. In this case we don't want to analyze the 496 // function definition as toplevel. 497 if (const auto *FD = dyn_cast<FunctionDecl>(D)) { 498 // Calling 'hasBody' replaces 'FD' in place with the FunctionDecl 499 // that has the body. 500 FD->hasBody(FD); 501 if (CTU.isImportedAsNew(FD)) 502 continue; 503 } 504 505 // Analyze the function. 506 SetOfConstDecls VisitedCallees; 507 508 HandleCode(D, AM_Path, getInliningModeForFunction(D, Visited), 509 (Mgr->options.InliningMode == All ? nullptr : &VisitedCallees)); 510 511 // Add the visited callees to the global visited set. 512 for (const Decl *Callee : VisitedCallees) 513 // Decls from CallGraph are already canonical. But Decls coming from 514 // CallExprs may be not. We should canonicalize them manually. 515 Visited.insert(isa<ObjCMethodDecl>(Callee) ? Callee 516 : Callee->getCanonicalDecl()); 517 VisitedAsTopLevel.insert(D); 518 } 519 } 520 521 static bool fileContainsString(StringRef Substring, ASTContext &C) { 522 const SourceManager &SM = C.getSourceManager(); 523 FileID FID = SM.getMainFileID(); 524 StringRef Buffer = SM.getBufferOrFake(FID).getBuffer(); 525 return Buffer.contains(Substring); 526 } 527 528 static void reportAnalyzerFunctionMisuse(const AnalyzerOptions &Opts, 529 const ASTContext &Ctx) { 530 llvm::errs() << "Every top-level function was skipped.\n"; 531 532 if (!Opts.AnalyzerDisplayProgress) 533 llvm::errs() << "Pass the -analyzer-display-progress for tracking which " 534 "functions are analyzed.\n"; 535 536 bool HasBrackets = 537 Opts.AnalyzeSpecificFunction.find("(") != std::string::npos; 538 539 if (Ctx.getLangOpts().CPlusPlus && !HasBrackets) { 540 llvm::errs() 541 << "For analyzing C++ code you need to pass the function parameter " 542 "list: -analyze-function=\"foobar(int, _Bool)\"\n"; 543 } else if (!Ctx.getLangOpts().CPlusPlus && HasBrackets) { 544 llvm::errs() << "For analyzing C code you shouldn't pass the function " 545 "parameter list, only the name of the function: " 546 "-analyze-function=foobar\n"; 547 } 548 } 549 550 void AnalysisConsumer::runAnalysisOnTranslationUnit(ASTContext &C) { 551 BugReporter BR(*Mgr); 552 const TranslationUnitDecl *TU = C.getTranslationUnitDecl(); 553 BR.setAnalysisEntryPoint(TU); 554 if (SyntaxCheckTimer) 555 SyntaxCheckTimer->startTimer(); 556 checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR); 557 if (SyntaxCheckTimer) 558 SyntaxCheckTimer->stopTimer(); 559 560 // Run the AST-only checks using the order in which functions are defined. 561 // If inlining is not turned on, use the simplest function order for path 562 // sensitive analyzes as well. 563 RecVisitorMode = AM_Syntax; 564 if (!Mgr->shouldInlineCall()) 565 RecVisitorMode |= AM_Path; 566 RecVisitorBR = &BR; 567 568 // Process all the top level declarations. 569 // 570 // Note: TraverseDecl may modify LocalTUDecls, but only by appending more 571 // entries. Thus we don't use an iterator, but rely on LocalTUDecls 572 // random access. By doing so, we automatically compensate for iterators 573 // possibly being invalidated, although this is a bit slower. 574 const unsigned LocalTUDeclsSize = LocalTUDecls.size(); 575 for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) { 576 TraverseDecl(LocalTUDecls[i]); 577 } 578 579 if (Mgr->shouldInlineCall()) 580 HandleDeclsCallGraph(LocalTUDeclsSize); 581 582 // After all decls handled, run checkers on the entire TranslationUnit. 583 checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR); 584 585 BR.FlushReports(); 586 RecVisitorBR = nullptr; 587 588 // If the user wanted to analyze a specific function and the number of basic 589 // blocks analyzed is zero, than the user might not specified the function 590 // name correctly. 591 // FIXME: The user might have analyzed the requested function in Syntax mode, 592 // but we are unaware of that. 593 if (!Opts.AnalyzeSpecificFunction.empty() && NumFunctionsAnalyzed == 0) 594 reportAnalyzerFunctionMisuse(Opts, *Ctx); 595 } 596 597 void AnalysisConsumer::reportAnalyzerProgress(StringRef S) { 598 if (Opts.AnalyzerDisplayProgress) 599 llvm::errs() << S; 600 } 601 602 void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) { 603 // Don't run the actions if an error has occurred with parsing the file. 604 DiagnosticsEngine &Diags = PP.getDiagnostics(); 605 if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) 606 return; 607 608 Ctx = &C; 609 checkerMgr = std::make_unique<CheckerManager>(*Ctx, Opts, PP, Plugins, 610 CheckerRegistrationFns); 611 612 Mgr = std::make_unique<AnalysisManager>( 613 *Ctx, PP, std::move(PathConsumers), CreateStoreMgr, CreateConstraintMgr, 614 checkerMgr.get(), Opts, std::move(Injector)); 615 616 // Explicitly destroy the PathDiagnosticConsumer. This will flush its output. 617 // FIXME: This should be replaced with something that doesn't rely on 618 // side-effects in PathDiagnosticConsumer's destructor. This is required when 619 // used with option -disable-free. 620 const auto DiagFlusherScopeExit = 621 llvm::make_scope_exit([this] { Mgr.reset(); }); 622 623 if (Opts.ShouldIgnoreBisonGeneratedFiles && 624 fileContainsString("/* A Bison parser, made by", C)) { 625 reportAnalyzerProgress("Skipping bison-generated file\n"); 626 return; 627 } 628 629 if (Opts.ShouldIgnoreFlexGeneratedFiles && 630 fileContainsString("/* A lexical scanner generated by flex", C)) { 631 reportAnalyzerProgress("Skipping flex-generated file\n"); 632 return; 633 } 634 635 // Don't analyze if the user explicitly asked for no checks to be performed 636 // on this file. 637 if (Opts.DisableAllCheckers) { 638 reportAnalyzerProgress("All checks are disabled using a supplied option\n"); 639 return; 640 } 641 642 // Otherwise, just run the analysis. 643 runAnalysisOnTranslationUnit(C); 644 645 // Count how many basic blocks we have not covered. 646 NumBlocksInAnalyzedFunctions = FunctionSummaries.getTotalNumBasicBlocks(); 647 NumVisitedBlocksInAnalyzedFunctions = 648 FunctionSummaries.getTotalNumVisitedBasicBlocks(); 649 if (NumBlocksInAnalyzedFunctions > 0) 650 PercentReachableBlocks = 651 (FunctionSummaries.getTotalNumVisitedBasicBlocks() * 100) / 652 NumBlocksInAnalyzedFunctions; 653 654 if (!Opts.DumpEntryPointStatsToCSV.empty()) { 655 EntryPointStat::dumpStatsAsCSV(Opts.DumpEntryPointStatsToCSV); 656 } 657 } 658 659 AnalysisConsumer::AnalysisMode 660 AnalysisConsumer::getModeForDecl(Decl *D, AnalysisMode Mode) { 661 if (!Opts.AnalyzeSpecificFunction.empty() && 662 AnalysisDeclContext::getFunctionName(D) != Opts.AnalyzeSpecificFunction) 663 return AM_None; 664 665 // Unless -analyze-all is specified, treat decls differently depending on 666 // where they came from: 667 // - Main source file: run both path-sensitive and non-path-sensitive checks. 668 // - Header files: run non-path-sensitive checks only. 669 // - System headers: don't run any checks. 670 if (Opts.AnalyzeAll) 671 return Mode; 672 673 const SourceManager &SM = Ctx->getSourceManager(); 674 675 const SourceLocation Loc = [&SM](Decl *D) -> SourceLocation { 676 const Stmt *Body = D->getBody(); 677 SourceLocation SL = Body ? Body->getBeginLoc() : D->getLocation(); 678 return SM.getExpansionLoc(SL); 679 }(D); 680 681 // Ignore system headers. 682 if (Loc.isInvalid() || SM.isInSystemHeader(Loc)) 683 return AM_None; 684 685 // Disable path sensitive analysis in user-headers. 686 if (!Mgr->isInCodeFile(Loc)) 687 return Mode & ~AM_Path; 688 689 return Mode; 690 } 691 692 static UnsignedEPStat PathRunningTime("PathRunningTime"); 693 694 void AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode, 695 ExprEngine::InliningModes IMode, 696 SetOfConstDecls *VisitedCallees) { 697 llvm::TimeTraceScope TCS(timeTraceScopeDeclName("HandleCode", D), 698 [D]() { return timeTraceScopeDeclMetadata(D); }); 699 if (!D->hasBody()) 700 return; 701 Mode = getModeForDecl(D, Mode); 702 if (Mode == AM_None) 703 return; 704 705 // Clear the AnalysisManager of old AnalysisDeclContexts. 706 Mgr->ClearContexts(); 707 // Ignore autosynthesized code. 708 if (Mgr->getAnalysisDeclContext(D)->isBodyAutosynthesized()) 709 return; 710 711 CFG *DeclCFG = Mgr->getCFG(D); 712 if (DeclCFG) 713 MaxCFGSize.updateMax(DeclCFG->size()); 714 715 DisplayFunction(D, Mode, IMode); 716 BugReporter BR(*Mgr); 717 BR.setAnalysisEntryPoint(D); 718 719 if (Mode & AM_Syntax) { 720 llvm::TimeRecord CheckerStartTime; 721 if (SyntaxCheckTimer) { 722 CheckerStartTime = SyntaxCheckTimer->getTotalTime(); 723 SyntaxCheckTimer->startTimer(); 724 } 725 checkerMgr->runCheckersOnASTBody(D, *Mgr, BR); 726 if (SyntaxCheckTimer) { 727 SyntaxCheckTimer->stopTimer(); 728 llvm::TimeRecord CheckerEndTime = SyntaxCheckTimer->getTotalTime(); 729 CheckerEndTime -= CheckerStartTime; 730 DisplayTime(CheckerEndTime); 731 } 732 } 733 734 BR.FlushReports(); 735 736 if ((Mode & AM_Path) && checkerMgr->hasPathSensitiveCheckers()) { 737 RunPathSensitiveChecks(D, IMode, VisitedCallees); 738 EntryPointStat::takeSnapshot(D); 739 if (IMode != ExprEngine::Inline_Minimal) 740 NumFunctionsAnalyzed++; 741 } 742 } 743 744 //===----------------------------------------------------------------------===// 745 // Path-sensitive checking. 746 //===----------------------------------------------------------------------===// 747 748 void AnalysisConsumer::RunPathSensitiveChecks(Decl *D, 749 ExprEngine::InliningModes IMode, 750 SetOfConstDecls *VisitedCallees) { 751 // Construct the analysis engine. First check if the CFG is valid. 752 // FIXME: Inter-procedural analysis will need to handle invalid CFGs. 753 if (!Mgr->getCFG(D)) 754 return; 755 756 // See if the LiveVariables analysis scales. 757 if (!Mgr->getAnalysisDeclContext(D)->getAnalysis<RelaxedLiveVariables>()) 758 return; 759 760 ExprEngine Eng(CTU, *Mgr, VisitedCallees, &FunctionSummaries, IMode); 761 762 // Execute the worklist algorithm. 763 llvm::TimeRecord ExprEngineStartTime; 764 if (ExprEngineTimer) { 765 ExprEngineStartTime = ExprEngineTimer->getTotalTime(); 766 ExprEngineTimer->startTimer(); 767 } 768 Eng.ExecuteWorkList(Mgr->getAnalysisDeclContextManager().getStackFrame(D), 769 Mgr->options.MaxNodesPerTopLevelFunction); 770 if (ExprEngineTimer) { 771 ExprEngineTimer->stopTimer(); 772 llvm::TimeRecord ExprEngineEndTime = ExprEngineTimer->getTotalTime(); 773 ExprEngineEndTime -= ExprEngineStartTime; 774 DisplayTime(ExprEngineEndTime); 775 } 776 777 if (!Mgr->options.DumpExplodedGraphTo.empty()) 778 Eng.DumpGraph(Mgr->options.TrimGraph, Mgr->options.DumpExplodedGraphTo); 779 780 // Visualize the exploded graph. 781 if (Mgr->options.visualizeExplodedGraphWithGraphViz) 782 Eng.ViewGraph(Mgr->options.TrimGraph); 783 784 flushReports(BugReporterTimer.get(), Eng.getBugReporter()); 785 } 786 787 //===----------------------------------------------------------------------===// 788 // AnalysisConsumer creation. 789 //===----------------------------------------------------------------------===// 790 791 std::unique_ptr<AnalysisASTConsumer> 792 ento::CreateAnalysisConsumer(CompilerInstance &CI) { 793 // Disable the effects of '-Werror' when using the AnalysisConsumer. 794 CI.getPreprocessor().getDiagnostics().setWarningsAsErrors(false); 795 796 AnalyzerOptions &analyzerOpts = CI.getAnalyzerOpts(); 797 bool hasModelPath = analyzerOpts.Config.count("model-path") > 0; 798 799 return std::make_unique<AnalysisConsumer>( 800 CI, CI.getFrontendOpts().OutputFile, analyzerOpts, 801 CI.getFrontendOpts().Plugins, 802 hasModelPath ? std::make_unique<ModelInjector>(CI) : nullptr); 803 } 804