[clang] 8e9f62e - [clang][deps] Give the fake file a unique name in by-module-name scans

Jan Svoboda via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 1 13:46:37 PST 2023


Author: Jan Svoboda
Date: 2023-02-01T13:46:26-08:00
New Revision: 8e9f62e5f833cb89b57bf4c9e80e850bcac7e15e

URL: https://github.com/llvm/llvm-project/commit/8e9f62e5f833cb89b57bf4c9e80e850bcac7e15e
DIFF: https://github.com/llvm/llvm-project/commit/8e9f62e5f833cb89b57bf4c9e80e850bcac7e15e.diff

LOG: [clang][deps] Give the fake file a unique name in by-module-name scans

When scanning dependencies of a module, the command line we're given doesn't have an input file, which the driver needs to be happy. We've been creating a fake in-memory input file named after the module. However, this can hide files/directories on the actual filesystem, leading to errors.

This patch works around that issue by generating a unique file name, which won't collide with the actual file system.

We could also change the driver APIs so that we're able to specify an "assumed" input file. This would be more work, though, since the driver assumes the input name comes from the actual command-line.

Depends on D140176.

Reviewed By: artemcm

Differential Revision: https://reviews.llvm.org/D140177

Added: 
    clang/test/ClangScanDeps/modules-full-by-mod-name.c

Modified: 
    clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp

Removed: 
    clang/test/ClangScanDeps/Inputs/modules_cdb_by_mod_name.json
    clang/test/ClangScanDeps/Inputs/modules_cdb_clangcl_by_mod_name.json
    clang/test/ClangScanDeps/modules-full-by-mod-name.cpp


################################################################################
diff  --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
index b54b8de9157ef..f14de94025798 100644
--- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
+++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
@@ -393,30 +393,40 @@ bool DependencyScanningWorker::computeDependencies(
 
   std::optional<std::vector<std::string>> ModifiedCommandLine;
   llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> ModifiedFS;
-  if (ModuleName) {
-    ModifiedCommandLine = CommandLine;
-    ModifiedCommandLine->emplace_back(*ModuleName);
 
+  // If we're scanning based on a module name alone, we don't expect the client
+  // to provide us with an input file. However, the driver really wants to have
+  // one. Let's just make it up to make the driver happy.
+  if (ModuleName) {
     auto OverlayFS =
         llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(BaseFS);
     auto InMemoryFS =
         llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
     InMemoryFS->setCurrentWorkingDirectory(WorkingDirectory);
-    InMemoryFS->addFile(*ModuleName, 0, llvm::MemoryBuffer::getMemBuffer(""));
     OverlayFS->pushOverlay(InMemoryFS);
     ModifiedFS = OverlayFS;
+
+    SmallString<128> FakeInputPath;
+    // TODO: We should retry the creation if the path already exists.
+    llvm::sys::fs::createUniquePath(*ModuleName + "-%%%%%%%%.input",
+                                    FakeInputPath,
+                                    /*MakeAbsolute=*/false);
+    InMemoryFS->addFile(FakeInputPath, 0, llvm::MemoryBuffer::getMemBuffer(""));
+
+    ModifiedCommandLine = CommandLine;
+    ModifiedCommandLine->emplace_back(FakeInputPath);
   }
 
   const std::vector<std::string> &FinalCommandLine =
       ModifiedCommandLine ? *ModifiedCommandLine : CommandLine;
+  auto &FinalFS = ModifiedFS ? ModifiedFS : BaseFS;
 
   FileSystemOptions FSOpts;
   FSOpts.WorkingDir = WorkingDirectory.str();
-  auto FileMgr = llvm::makeIntrusiveRefCnt<FileManager>(
-      FSOpts, ModifiedFS ? ModifiedFS : BaseFS);
+  auto FileMgr = llvm::makeIntrusiveRefCnt<FileManager>(FSOpts, FinalFS);
 
-  std::vector<const char *> FinalCCommandLine(CommandLine.size(), nullptr);
-  llvm::transform(CommandLine, FinalCCommandLine.begin(),
+  std::vector<const char *> FinalCCommandLine(FinalCommandLine.size(), nullptr);
+  llvm::transform(FinalCommandLine, FinalCCommandLine.begin(),
                   [](const std::string &Str) { return Str.c_str(); });
 
   auto DiagOpts = CreateAndPopulateDiagOpts(FinalCCommandLine);

diff  --git a/clang/test/ClangScanDeps/Inputs/modules_cdb_by_mod_name.json b/clang/test/ClangScanDeps/Inputs/modules_cdb_by_mod_name.json
deleted file mode 100644
index f95749f11be2a..0000000000000
--- a/clang/test/ClangScanDeps/Inputs/modules_cdb_by_mod_name.json
+++ /dev/null
@@ -1,12 +0,0 @@
-[
-{
-  "directory": "DIR",
-  "command": "clang -E -IInputs -D INCLUDE_HEADER2 -MD -MF DIR/modules_cdb2.d -fmodules -fcxx-modules -fmodules-cache-path=DIR/module-cache -fimplicit-modules -fimplicit-module-maps -gmodules -x c++",
-  "file": ""
-},
-{
-  "directory": "DIR",
-  "command": "clang -E -IInputs -fmodules -fcxx-modules -fmodules-cache-path=DIR/module-cache -fimplicit-modules -fimplicit-module-maps -x c++",
-  "file": ""
-},
-]

diff  --git a/clang/test/ClangScanDeps/Inputs/modules_cdb_clangcl_by_mod_name.json b/clang/test/ClangScanDeps/Inputs/modules_cdb_clangcl_by_mod_name.json
deleted file mode 100644
index ef44985a8f915..0000000000000
--- a/clang/test/ClangScanDeps/Inputs/modules_cdb_clangcl_by_mod_name.json
+++ /dev/null
@@ -1,12 +0,0 @@
-[
-{
-  "directory": "DIR",
-  "command": "clang-cl /E /IInputs /D INCLUDE_HEADER2 /clang:-MD /clang:-MF /clang:DIR/modules_cdb2_clangcl.d /clang:-fmodules /clang:-fcxx-modules /clang:-fmodules-cache-path=DIR/module-cache_clangcl /clang:-fimplicit-modules /clang:-fimplicit-module-maps /clang:-x /clang:c++ --",
-  "file": ""
-},
-{
-  "directory": "DIR",
-  "command": "clang-cl /E /IInputs /clang:-fmodules /clang:-fcxx-modules /clang:-fmodules-cache-path=DIR/module-cache_clangcl /clang:-fimplicit-modules /clang:-fimplicit-module-maps /clang:-x /clang:c++ --",
-  "file": ""
-},
-]

diff  --git a/clang/test/ClangScanDeps/modules-full-by-mod-name.c b/clang/test/ClangScanDeps/modules-full-by-mod-name.c
new file mode 100644
index 0000000000000..054ff5494753c
--- /dev/null
+++ b/clang/test/ClangScanDeps/modules-full-by-mod-name.c
@@ -0,0 +1,84 @@
+// UNSUPPORTED: target=powerpc64-ibm-aix{{.*}}
+
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+
+//--- module.modulemap
+module root { header "root.h" }
+module direct { header "direct.h" }
+module transitive { header "transitive.h" }
+//--- root.h
+#include "direct.h"
+#include "root/textual.h"
+//--- direct.h
+#include "transitive.h"
+//--- transitive.h
+// empty
+
+//--- root/textual.h
+// This is here to verify that the "root" directory doesn't clash with name of
+// the "root" module.
+
+//--- cdb.json.template
+[{
+  "file": "",
+  "directory": "DIR",
+  "command": "clang -fmodules -fmodules-cache-path=DIR/cache -I DIR -x c"
+}]
+
+// RUN: sed "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json
+// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full -module-name=root > %t/result.json
+// RUN: cat %t/result.json | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t %s
+
+// CHECK:      {
+// CHECK-NEXT:   "modules": [
+// CHECK-NEXT:     {
+// CHECK-NEXT:       "clang-module-deps": [
+// CHECK-NEXT:         {
+// CHECK-NEXT:           "context-hash": "{{.*}}",
+// CHECK-NEXT:           "module-name": "transitive"
+// CHECK-NEXT:         }
+// CHECK-NEXT:       ],
+// CHECK-NEXT:       "clang-modulemap-file": "[[PREFIX]]/module.modulemap",
+// CHECK-NEXT:       "command-line": [
+// CHECK:            ],
+// CHECK-NEXT:       "context-hash": "{{.*}}",
+// CHECK-NEXT:       "file-deps": [
+// CHECK-NEXT:         "[[PREFIX]]/direct.h"
+// CHECK-NEXT:         "[[PREFIX]]/module.modulemap"
+// CHECK-NEXT:       ],
+// CHECK-NEXT:       "name": "direct"
+// CHECK-NEXT:     },
+// CHECK-NEXT:     {
+// CHECK-NEXT:       "clang-module-deps": [
+// CHECK-NEXT:         {
+// CHECK-NEXT:           "context-hash": "{{.*}}",
+// CHECK-NEXT:           "module-name": "direct"
+// CHECK-NEXT:         }
+// CHECK-NEXT:       ],
+// CHECK-NEXT:       "clang-modulemap-file": "[[PREFIX]]/module.modulemap",
+// CHECK-NEXT:       "command-line": [
+// CHECK:            ],
+// CHECK-NEXT:       "context-hash": "{{.*}}",
+// CHECK-NEXT:       "file-deps": [
+// CHECK-NEXT:         "[[PREFIX]]/module.modulemap"
+// CHECK-NEXT:         "[[PREFIX]]/root.h"
+// CHECK-NEXT:         "[[PREFIX]]/root/textual.h"
+// CHECK-NEXT:       ],
+// CHECK-NEXT:       "name": "root"
+// CHECK-NEXT:     },
+// CHECK-NEXT:     {
+// CHECK-NEXT:       "clang-module-deps": [],
+// CHECK-NEXT:       "clang-modulemap-file": "[[PREFIX]]/module.modulemap",
+// CHECK-NEXT:       "command-line": [
+// CHECK:            ],
+// CHECK-NEXT:       "context-hash": "{{.*}}",
+// CHECK-NEXT:       "file-deps": [
+// CHECK-NEXT:         "[[PREFIX]]/module.modulemap"
+// CHECK-NEXT:         "[[PREFIX]]/transitive.h"
+// CHECK-NEXT:       ],
+// CHECK-NEXT:       "name": "transitive"
+// CHECK-NEXT:     }
+// CHECK-NEXT:   ],
+// CHECK-NEXT:   "translation-units": []
+// CHECK-NEXT: }

diff  --git a/clang/test/ClangScanDeps/modules-full-by-mod-name.cpp b/clang/test/ClangScanDeps/modules-full-by-mod-name.cpp
deleted file mode 100644
index 4109747bf48e1..0000000000000
--- a/clang/test/ClangScanDeps/modules-full-by-mod-name.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-// UNSUPPORTED: target=powerpc64-ibm-aix{{.*}}
-// RUN: rm -rf %t.dir
-// RUN: rm -rf %t.cdb
-// RUN: mkdir -p %t.dir
-// RUN: cp %s %t.dir/modules_cdb_input.cpp
-// RUN: cp %s %t.dir/modules_cdb_input2.cpp
-// RUN: mkdir %t.dir/Inputs
-// RUN: cp %S/Inputs/header.h %t.dir/Inputs/header.h
-// RUN: cp %S/Inputs/header2.h %t.dir/Inputs/header2.h
-// RUN: cp %S/Inputs/module.modulemap %t.dir/Inputs/module.modulemap
-// RUN: sed -e "s|DIR|%/t.dir|g" %S/Inputs/modules_cdb_by_mod_name.json > %t.cdb
-// RUN: sed -e "s|DIR|%/t.dir|g" %S/Inputs/modules_cdb_clangcl_by_mod_name.json > %t_clangcl.cdb
-//
-// RUN: clang-scan-deps -compilation-database %t.cdb -j 1 -format experimental-full \
-// RUN:   -mode preprocess-dependency-directives -module-name=header1 > %t.result
-// RUN: cat %t.result | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t.dir --check-prefixes=CHECK %s
-//
-// RUN: clang-scan-deps -compilation-database %t_clangcl.cdb -j 4 -format experimental-full \
-// RUN:   -mode preprocess-dependency-directives -module-name=header1 > %t_clangcl.result
-// RUN: cat %t_clangcl.result | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t.dir --check-prefixes=CHECK %s
-
-// CHECK:      {
-// CHECK-NEXT:   "modules": [
-// CHECK-NEXT:     {
-// CHECK-NEXT:       "clang-module-deps": [
-// CHECK-NEXT:         {
-// CHECK-NEXT:           "context-hash": "[[HASH_H2_DINCLUDE:[A-Z0-9]+]]",
-// CHECK-NEXT:           "module-name": "header2"
-// CHECK-NEXT:         }
-// CHECK-NEXT:       ],
-// CHECK-NEXT:       "clang-modulemap-file": "[[PREFIX]]/Inputs/module.modulemap",
-// CHECK-NEXT:       "command-line": [
-// CHECK-NEXT:         "-cc1"
-// CHECK:              "-emit-module"
-// CHECK:              "-fmodule-name=header1"
-// CHECK:              "-fno-implicit-modules"
-// CHECK:            ],
-// CHECK-NEXT:       "context-hash": "[[HASH_H1_DINCLUDE:[A-Z0-9]+]]",
-// CHECK-NEXT:       "file-deps": [
-// CHECK-NEXT:         "[[PREFIX]]/Inputs/header.h",
-// CHECK-NEXT:         "[[PREFIX]]/Inputs/module.modulemap"
-// CHECK-NEXT:       ],
-// CHECK-NEXT:       "name": "header1"
-// CHECK-NEXT:     },
-// CHECK-NEXT:     {
-// CHECK-NEXT:       "clang-module-deps": [],
-// CHECK-NEXT:       "clang-modulemap-file": "[[PREFIX]]/Inputs/module.modulemap",
-// CHECK-NEXT:       "command-line": [
-// CHECK-NEXT:         "-cc1",
-// CHECK:              "-emit-module",
-// CHECK:              "-fmodule-name=header1",
-// CHECK:              "-fno-implicit-modules",
-// CHECK:            ],
-// CHECK-NEXT:       "context-hash": "[[HASH_H1:[A-Z0-9]+]]",
-// CHECK-NEXT:       "file-deps": [
-// CHECK-NEXT:         "[[PREFIX]]/Inputs/header.h",
-// CHECK-NEXT:         "[[PREFIX]]/Inputs/module.modulemap"
-// CHECK-NEXT:       ],
-// CHECK-NEXT:       "name": "header1"
-// CHECK-NEXT:     },
-// CHECK-NEXT:     {
-// CHECK-NEXT:       "clang-module-deps": [],
-// CHECK-NEXT:       "clang-modulemap-file": "[[PREFIX]]/Inputs/module.modulemap",
-// CHECK-NEXT:       "command-line": [
-// CHECK-NEXT:         "-cc1",
-// CHECK:              "-emit-module",
-// CHECK:              "-fmodule-name=header2",
-// CHECK:              "-fno-implicit-modules",
-// CHECK:            ],
-// CHECK-NEXT:       "context-hash": "[[HASH_H2_DINCLUDE]]",
-// CHECK-NEXT:       "file-deps": [
-// CHECK-NEXT:         "[[PREFIX]]/Inputs/header2.h",
-// CHECK-NEXT:         "[[PREFIX]]/Inputs/module.modulemap"
-// CHECK-NEXT:       ],
-// CHECK-NEXT:       "name": "header2"
-// CHECK-NEXT:     }
-// CHECK-NEXT:   ],
-// CHECK-NEXT:   "translation-units": []
-// CHECK-NEXT: }


        


More information about the cfe-commits mailing list