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

Reply via email to