Skip to content

Commit 8e9f62e

Browse files
committed
[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
1 parent ba55666 commit 8e9f62e

File tree

5 files changed

+102
-111
lines changed

5 files changed

+102
-111
lines changed

clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -393,30 +393,40 @@ bool DependencyScanningWorker::computeDependencies(
393393

394394
std::optional<std::vector<std::string>> ModifiedCommandLine;
395395
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> ModifiedFS;
396-
if (ModuleName) {
397-
ModifiedCommandLine = CommandLine;
398-
ModifiedCommandLine->emplace_back(*ModuleName);
399396

397+
// If we're scanning based on a module name alone, we don't expect the client
398+
// to provide us with an input file. However, the driver really wants to have
399+
// one. Let's just make it up to make the driver happy.
400+
if (ModuleName) {
400401
auto OverlayFS =
401402
llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(BaseFS);
402403
auto InMemoryFS =
403404
llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
404405
InMemoryFS->setCurrentWorkingDirectory(WorkingDirectory);
405-
InMemoryFS->addFile(*ModuleName, 0, llvm::MemoryBuffer::getMemBuffer(""));
406406
OverlayFS->pushOverlay(InMemoryFS);
407407
ModifiedFS = OverlayFS;
408+
409+
SmallString<128> FakeInputPath;
410+
// TODO: We should retry the creation if the path already exists.
411+
llvm::sys::fs::createUniquePath(*ModuleName + "-%%%%%%%%.input",
412+
FakeInputPath,
413+
/*MakeAbsolute=*/false);
414+
InMemoryFS->addFile(FakeInputPath, 0, llvm::MemoryBuffer::getMemBuffer(""));
415+
416+
ModifiedCommandLine = CommandLine;
417+
ModifiedCommandLine->emplace_back(FakeInputPath);
408418
}
409419

410420
const std::vector<std::string> &FinalCommandLine =
411421
ModifiedCommandLine ? *ModifiedCommandLine : CommandLine;
422+
auto &FinalFS = ModifiedFS ? ModifiedFS : BaseFS;
412423

413424
FileSystemOptions FSOpts;
414425
FSOpts.WorkingDir = WorkingDirectory.str();
415-
auto FileMgr = llvm::makeIntrusiveRefCnt<FileManager>(
416-
FSOpts, ModifiedFS ? ModifiedFS : BaseFS);
426+
auto FileMgr = llvm::makeIntrusiveRefCnt<FileManager>(FSOpts, FinalFS);
417427

418-
std::vector<const char *> FinalCCommandLine(CommandLine.size(), nullptr);
419-
llvm::transform(CommandLine, FinalCCommandLine.begin(),
428+
std::vector<const char *> FinalCCommandLine(FinalCommandLine.size(), nullptr);
429+
llvm::transform(FinalCommandLine, FinalCCommandLine.begin(),
420430
[](const std::string &Str) { return Str.c_str(); });
421431

422432
auto DiagOpts = CreateAndPopulateDiagOpts(FinalCCommandLine);

clang/test/ClangScanDeps/Inputs/modules_cdb_by_mod_name.json

Lines changed: 0 additions & 12 deletions
This file was deleted.

clang/test/ClangScanDeps/Inputs/modules_cdb_clangcl_by_mod_name.json

Lines changed: 0 additions & 12 deletions
This file was deleted.
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// UNSUPPORTED: target=powerpc64-ibm-aix{{.*}}
2+
3+
// RUN: rm -rf %t
4+
// RUN: split-file %s %t
5+
6+
//--- module.modulemap
7+
module root { header "root.h" }
8+
module direct { header "direct.h" }
9+
module transitive { header "transitive.h" }
10+
//--- root.h
11+
#include "direct.h"
12+
#include "root/textual.h"
13+
//--- direct.h
14+
#include "transitive.h"
15+
//--- transitive.h
16+
// empty
17+
18+
//--- root/textual.h
19+
// This is here to verify that the "root" directory doesn't clash with name of
20+
// the "root" module.
21+
22+
//--- cdb.json.template
23+
[{
24+
"file": "",
25+
"directory": "DIR",
26+
"command": "clang -fmodules -fmodules-cache-path=DIR/cache -I DIR -x c"
27+
}]
28+
29+
// RUN: sed "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json
30+
// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full -module-name=root > %t/result.json
31+
// RUN: cat %t/result.json | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t %s
32+
33+
// CHECK: {
34+
// CHECK-NEXT: "modules": [
35+
// CHECK-NEXT: {
36+
// CHECK-NEXT: "clang-module-deps": [
37+
// CHECK-NEXT: {
38+
// CHECK-NEXT: "context-hash": "{{.*}}",
39+
// CHECK-NEXT: "module-name": "transitive"
40+
// CHECK-NEXT: }
41+
// CHECK-NEXT: ],
42+
// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap",
43+
// CHECK-NEXT: "command-line": [
44+
// CHECK: ],
45+
// CHECK-NEXT: "context-hash": "{{.*}}",
46+
// CHECK-NEXT: "file-deps": [
47+
// CHECK-NEXT: "[[PREFIX]]/direct.h"
48+
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
49+
// CHECK-NEXT: ],
50+
// CHECK-NEXT: "name": "direct"
51+
// CHECK-NEXT: },
52+
// CHECK-NEXT: {
53+
// CHECK-NEXT: "clang-module-deps": [
54+
// CHECK-NEXT: {
55+
// CHECK-NEXT: "context-hash": "{{.*}}",
56+
// CHECK-NEXT: "module-name": "direct"
57+
// CHECK-NEXT: }
58+
// CHECK-NEXT: ],
59+
// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap",
60+
// CHECK-NEXT: "command-line": [
61+
// CHECK: ],
62+
// CHECK-NEXT: "context-hash": "{{.*}}",
63+
// CHECK-NEXT: "file-deps": [
64+
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
65+
// CHECK-NEXT: "[[PREFIX]]/root.h"
66+
// CHECK-NEXT: "[[PREFIX]]/root/textual.h"
67+
// CHECK-NEXT: ],
68+
// CHECK-NEXT: "name": "root"
69+
// CHECK-NEXT: },
70+
// CHECK-NEXT: {
71+
// CHECK-NEXT: "clang-module-deps": [],
72+
// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap",
73+
// CHECK-NEXT: "command-line": [
74+
// CHECK: ],
75+
// CHECK-NEXT: "context-hash": "{{.*}}",
76+
// CHECK-NEXT: "file-deps": [
77+
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
78+
// CHECK-NEXT: "[[PREFIX]]/transitive.h"
79+
// CHECK-NEXT: ],
80+
// CHECK-NEXT: "name": "transitive"
81+
// CHECK-NEXT: }
82+
// CHECK-NEXT: ],
83+
// CHECK-NEXT: "translation-units": []
84+
// CHECK-NEXT: }

clang/test/ClangScanDeps/modules-full-by-mod-name.cpp

Lines changed: 0 additions & 79 deletions
This file was deleted.

0 commit comments

Comments
 (0)