Author: Jan Svoboda Date: 2021-06-14T11:28:39+02:00 New Revision: 9223209be11e93c1b701054c6fff88d46ee54658
URL: https://github.com/llvm/llvm-project/commit/9223209be11e93c1b701054c6fff88d46ee54658 DIFF: https://github.com/llvm/llvm-project/commit/9223209be11e93c1b701054c6fff88d46ee54658.diff LOG: [clang][deps] Handle precompiled headers' AST files The `PreprocessOnlyAction` doesn't support loading the AST file of a precompiled header. This is problematic for dependency scanning, since the `#include` manufactured for the PCH is treated as textual. This means the PCH contents get scanned with each TU, which is redundant. Moreover, dependencies of the PCH end up being considered dependency of the TU. To handle AST file of PCH properly, this patch creates new `FrontendAction` that behaves the same way `PreprocessorOnlyAction` does, but treats the manufactured PCH `#include` as a normal compilation would (by not claiming it only uses a preprocessor and creating the default AST consumer). The AST file is now reported as a file dependency of the TU. Depends on D103519. Reviewed By: Bigcheese Differential Revision: https://reviews.llvm.org/D103524 Added: Modified: clang/include/clang/Frontend/FrontendActions.h clang/lib/Frontend/FrontendActions.cpp clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp clang/test/ClangScanDeps/modules-pch.c Removed: ################################################################################ diff --git a/clang/include/clang/Frontend/FrontendActions.h b/clang/include/clang/Frontend/FrontendActions.h index 25ca95980806..ff8d4417eaa4 100644 --- a/clang/include/clang/Frontend/FrontendActions.h +++ b/clang/include/clang/Frontend/FrontendActions.h @@ -34,6 +34,17 @@ class InitOnlyAction : public FrontendAction { bool usesPreprocessorOnly() const override { return false; } }; +/// Preprocessor-based frontend action that also loads PCH files. +class ReadPCHAndPreprocessAction : public FrontendAction { + void ExecuteAction() override; + + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; + +public: + bool usesPreprocessorOnly() const override { return false; } +}; + class DumpCompilerOptionsAction : public FrontendAction { std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override { diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index b3f6cfcf57e3..6df57cbb45ae 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -62,6 +62,27 @@ InitOnlyAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { void InitOnlyAction::ExecuteAction() { } +// Basically PreprocessOnlyAction::ExecuteAction. +void ReadPCHAndPreprocessAction::ExecuteAction() { + Preprocessor &PP = getCompilerInstance().getPreprocessor(); + + // Ignore unknown pragmas. + PP.IgnorePragmas(); + + Token Tok; + // Start parsing the specified input file. + PP.EnterMainSourceFile(); + do { + PP.Lex(Tok); + } while (Tok.isNot(tok::eof)); +} + +std::unique_ptr<ASTConsumer> +ReadPCHAndPreprocessAction::CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) { + return std::make_unique<ASTConsumer>(); +} + //===----------------------------------------------------------------------===// // AST Consumer Actions //===----------------------------------------------------------------------===// diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp index ecaeeed1a061..0df515a4c99f 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -73,6 +73,8 @@ class DependencyScanningAction : public tooling::ToolAction { if (!Compiler.hasDiagnostics()) return false; + Compiler.getPreprocessorOpts().AllowPCHWithDifferentModulesCachePath = true; + // Use the dependency scanning optimized file system if we can. if (DepFS) { const CompilerInvocation &CI = Compiler.getInvocation(); @@ -133,7 +135,7 @@ class DependencyScanningAction : public tooling::ToolAction { // the impact of strict context hashing. Compiler.getHeaderSearchOpts().ModulesStrictContextHash = true; - auto Action = std::make_unique<PreprocessOnlyAction>(); + auto Action = std::make_unique<ReadPCHAndPreprocessAction>(); const bool Result = Compiler.ExecuteAction(*Action); if (!DepFS) FileMgr->clearStatCache(); diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp index dfd853822327..3271075d9281 100644 --- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp +++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp @@ -156,6 +156,9 @@ void ModuleDepCollectorPP::EndOfMainFile() { MDC.MainFile = std::string( Instance.getSourceManager().getFileEntryForID(MainFileID)->getName()); + if (!Instance.getPreprocessorOpts().ImplicitPCHInclude.empty()) + MDC.FileDeps.push_back(Instance.getPreprocessorOpts().ImplicitPCHInclude); + for (const Module *M : DirectModularDeps) handleTopLevelModule(M); diff --git a/clang/test/ClangScanDeps/modules-pch.c b/clang/test/ClangScanDeps/modules-pch.c index ddb6949f5e6f..020818f74ed6 100644 --- a/clang/test/ClangScanDeps/modules-pch.c +++ b/clang/test/ClangScanDeps/modules-pch.c @@ -9,5 +9,52 @@ // Scan dependencies of the TU: // // RUN: sed "s|DIR|%/t|g" %S/Inputs/modules-pch/cdb_tu.json > %t/cdb.json +// RUN: echo -%t > %t/result_tu.json +// FIXME: Make this work with '-mode preprocess-minimized-sources'. // RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full \ -// RUN: -generate-modules-path-args -module-files-dir %t/build +// RUN: -generate-modules-path-args -module-files-dir %t/build -mode preprocess >> %t/result_tu.json +// RUN: cat %t/result_tu.json | sed 's:\\\\\?:/:g' | FileCheck %s -check-prefix=CHECK-TU +// +// CHECK-TU: -[[PREFIX:.*]] +// CHECK-TU-NEXT: { +// CHECK-TU-NEXT: "modules": [ +// CHECK-TU-NEXT: { +// CHECK-TU-NEXT: "clang-module-deps": [], +// CHECK-TU-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap", +// CHECK-TU-NEXT: "command-line": [ +// CHECK-TU-NEXT: "-cc1", +// CHECK-TU: "-emit-module", +// CHECK-TU: "-fmodule-name=ModTU", +// CHECK-TU: "-fno-implicit-modules", +// CHECK-TU: ], +// CHECK-TU-NEXT: "context-hash": "[[HASH_MOD_TU:.*]]", +// CHECK-TU-NEXT: "file-deps": [ +// CHECK-TU-NEXT: "[[PREFIX]]/mod_tu.h", +// CHECK-TU-NEXT: "[[PREFIX]]/module.modulemap" +// CHECK-TU-NEXT: ], +// CHECK-TU-NEXT: "name": "ModTU" +// CHECK-TU-NEXT: } +// CHECK-TU-NEXT: ], +// CHECK-TU-NEXT: "translation-units": [ +// CHECK-TU-NEXT: { +// CHECK-TU-NEXT: "clang-context-hash": "[[HASH_TU:.*]]", +// CHECK-TU-NEXT: "clang-module-deps": [ +// CHECK-TU-NEXT: { +// CHECK-TU-NEXT: "context-hash": "[[HASH_MOD_TU]]", +// CHECK-TU-NEXT: "module-name": "ModTU" +// CHECK-TU-NEXT: } +// CHECK-TU-NEXT: ], +// CHECK-TU-NEXT: "command-line": [ +// CHECK-TU-NEXT: "-fno-implicit-modules", +// CHECK-TU-NEXT: "-fno-implicit-module-maps", +// CHECK-TU-NEXT: "-fmodule-file=[[PREFIX]]/build/[[HASH_MOD_TU]]/ModTU-{{.*}}.pcm", +// CHECK-TU-NEXT: "-fmodule-map-file=[[PREFIX]]/module.modulemap" +// CHECK-TU-NEXT: ], +// CHECK-TU-NEXT: "file-deps": [ +// CHECK-TU-NEXT: "[[PREFIX]]/tu.c", +// CHECK-TU-NEXT: "[[PREFIX]]/pch.h.gch" +// CHECK-TU-NEXT: ], +// CHECK-TU-NEXT: "input-file": "[[PREFIX]]/tu.c" +// CHECK-TU-NEXT: } +// CHECK-TU-NEXT: ] +// CHECK-TU-NEXT: } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits