Index: include/clang/CrossTU/CrossTranslationUnit.h =================================================================== --- include/clang/CrossTU/CrossTranslationUnit.h +++ include/clang/CrossTU/CrossTranslationUnit.h @@ -108,7 +108,7 @@ /// Note that the AST files should also be in the \p CrossTUDir. llvm::Expected getCrossTUDefinition(const FunctionDecl *FD, StringRef CrossTUDir, - StringRef IndexName); + StringRef IndexName, bool DisplayCTUProgress = false); /// This function loads a function definition from an external AST /// file. @@ -124,7 +124,8 @@ /// Note that the AST files should also be in the \p CrossTUDir. llvm::Expected loadExternalAST(StringRef LookupName, StringRef CrossTUDir, - StringRef IndexName); + StringRef IndexName, + bool DisplayCTUProgress = false); /// This function merges a definition from a separate AST Unit into /// the current one which was created by the compiler instance that Index: include/clang/Driver/CC1Options.td =================================================================== --- include/clang/Driver/CC1Options.td +++ include/clang/Driver/CC1Options.td @@ -84,6 +84,9 @@ HelpText<"Dump exploded graph to the specified file">; def analyzer_dump_egraph_EQ : Joined<["-"], "analyzer-dump-egraph=">, Alias; +def analyzer_display_ctu_progress : Flag<["-"], "analyzer-display-ctu-progress">, + HelpText<"Emit verbose output about the analyzer's progress related to ctu">; + def analyzer_inline_max_stack_depth : Separate<["-"], "analyzer-inline-max-stack-depth">, HelpText<"Bound on stack depth while inlining (4 by default)">; def analyzer_inline_max_stack_depth_EQ : Joined<["-"], "analyzer-inline-max-stack-depth=">, Index: include/clang/StaticAnalyzer/Core/AnalyzerOptions.h =================================================================== --- include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -200,6 +200,7 @@ unsigned ShowConfigOptionsList : 1; unsigned AnalyzeAll : 1; unsigned AnalyzerDisplayProgress : 1; + unsigned AnalyzerDisplayCTUProgress : 1; unsigned AnalyzeNestedBlocks : 1; unsigned eagerlyAssumeBinOpBifurcation : 1; @@ -251,9 +252,10 @@ : DisableAllChecks(false), ShowCheckerHelp(false), ShowEnabledCheckerList(false), ShowConfigOptionsList(false), AnalyzeAll(false), AnalyzerDisplayProgress(false), - AnalyzeNestedBlocks(false), eagerlyAssumeBinOpBifurcation(false), - TrimGraph(false), visualizeExplodedGraphWithGraphViz(false), - UnoptimizedCFG(false), PrintStats(false), NoRetryExhausted(false) {} + AnalyzerDisplayCTUProgress(false), AnalyzeNestedBlocks(false), + eagerlyAssumeBinOpBifurcation(false), TrimGraph(false), + visualizeExplodedGraphWithGraphViz(false), UnoptimizedCFG(false), + PrintStats(false), NoRetryExhausted(false) {} /// Interprets an option's string value as a boolean. The "true" string is /// interpreted as true and the "false" string is interpreted as false. Index: lib/CrossTU/CrossTranslationUnit.cpp =================================================================== --- lib/CrossTU/CrossTranslationUnit.cpp +++ lib/CrossTU/CrossTranslationUnit.cpp @@ -149,14 +149,15 @@ llvm::Expected CrossTranslationUnitContext::getCrossTUDefinition(const FunctionDecl *FD, StringRef CrossTUDir, - StringRef IndexName) { + StringRef IndexName, + bool DisplayCTUProgress) { assert(!FD->hasBody() && "FD has a definition in current translation unit!"); const std::string LookupFnName = getLookupName(FD); if (LookupFnName.empty()) return llvm::make_error( index_error_code::failed_to_generate_usr); llvm::Expected ASTUnitOrError = - loadExternalAST(LookupFnName, CrossTUDir, IndexName); + loadExternalAST(LookupFnName, CrossTUDir, IndexName, DisplayCTUProgress); if (!ASTUnitOrError) return ASTUnitOrError.takeError(); ASTUnit *Unit = *ASTUnitOrError; @@ -193,7 +194,8 @@ } llvm::Expected CrossTranslationUnitContext::loadExternalAST( - StringRef LookupName, StringRef CrossTUDir, StringRef IndexName) { + StringRef LookupName, StringRef CrossTUDir, StringRef IndexName, + bool DisplayCTUProgress) { // FIXME: The current implementation only supports loading functions with // a lookup name from a single translation unit. If multiple // translation units contains functions with the same lookup name an @@ -233,6 +235,10 @@ ASTUnit::LoadEverything, Diags, CI.getFileSystemOpts())); Unit = LoadedUnit.get(); FileASTUnitMap[ASTFileName] = std::move(LoadedUnit); + if (DisplayCTUProgress) { + llvm::errs() << "ANALYZE CTU loaded AST file: " + << ASTFileName << "\n"; + } } else { Unit = ASTCacheEntry->second.get(); } Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -289,6 +289,8 @@ Opts.NoRetryExhausted = Args.hasArg(OPT_analyzer_disable_retry_exhausted); Opts.AnalyzeAll = Args.hasArg(OPT_analyzer_opt_analyze_headers); Opts.AnalyzerDisplayProgress = Args.hasArg(OPT_analyzer_display_progress); + Opts.AnalyzerDisplayCTUProgress = + Args.hasArg(OPT_analyzer_display_ctu_progress); Opts.AnalyzeNestedBlocks = Args.hasArg(OPT_analyzer_opt_analyze_nested_blocks); Opts.AnalyzeSpecificFunction = Args.getLastArgValue(OPT_analyze_function); Index: lib/StaticAnalyzer/Core/CallEvent.cpp =================================================================== --- lib/StaticAnalyzer/Core/CallEvent.cpp +++ lib/StaticAnalyzer/Core/CallEvent.cpp @@ -560,7 +560,8 @@ cross_tu::CrossTranslationUnitContext &CTUCtx = *Engine->getCrossTranslationUnitContext(); llvm::Expected CTUDeclOrError = - CTUCtx.getCrossTUDefinition(FD, Opts.getCTUDir(), Opts.getCTUIndexName()); + CTUCtx.getCrossTUDefinition(FD, Opts.getCTUDir(), Opts.getCTUIndexName(), + Opts.AnalyzerDisplayCTUProgress); if (!CTUDeclOrError) { handleAllErrors(CTUDeclOrError.takeError(), Index: test/Analysis/ctu-main.cpp =================================================================== --- test/Analysis/ctu-main.cpp +++ test/Analysis/ctu-main.cpp @@ -3,6 +3,10 @@ // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o %T/ctudir/ctu-chain.cpp.ast %S/Inputs/ctu-chain.cpp // RUN: cp %S/Inputs/externalFnMap.txt %T/ctudir/ // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%T/ctudir -verify %s +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%T/ctudir -analyzer-display-ctu-progress 2>&1 %s | FileCheck %s + +// CHECK: ANALYZE (CTU loaded AST for source file): {{.*}}/ctu-other.cpp +// CHECK: ANALYZE (CTU loaded AST for source file): {{.*}}/ctu-chain.cpp #include "ctu-hdr.h"