Skip to content

Commit a61d3f0

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 (cherry picked from commit 8e9f62e)
1 parent 1da456b commit a61d3f0

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
@@ -657,30 +657,40 @@ bool DependencyScanningWorker::computeDependencies(
657657

658658
Optional<std::vector<std::string>> ModifiedCommandLine;
659659
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> ModifiedFS;
660-
if (ModuleName) {
661-
ModifiedCommandLine = CommandLine;
662-
ModifiedCommandLine->emplace_back(*ModuleName);
663660

661+
// If we're scanning based on a module name alone, we don't expect the client
662+
// to provide us with an input file. However, the driver really wants to have
663+
// one. Let's just make it up to make the driver happy.
664+
if (ModuleName) {
664665
auto OverlayFS =
665666
llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(BaseFS);
666667
auto InMemoryFS =
667668
llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
668669
InMemoryFS->setCurrentWorkingDirectory(WorkingDirectory);
669-
InMemoryFS->addFile(*ModuleName, 0, llvm::MemoryBuffer::getMemBuffer(""));
670670
OverlayFS->pushOverlay(InMemoryFS);
671671
ModifiedFS = OverlayFS;
672+
673+
SmallString<128> FakeInputPath;
674+
// TODO: We should retry the creation if the path already exists.
675+
llvm::sys::fs::createUniquePath(*ModuleName + "-%%%%%%%%.input",
676+
FakeInputPath,
677+
/*MakeAbsolute=*/false);
678+
InMemoryFS->addFile(FakeInputPath, 0, llvm::MemoryBuffer::getMemBuffer(""));
679+
680+
ModifiedCommandLine = CommandLine;
681+
ModifiedCommandLine->emplace_back(FakeInputPath);
672682
}
673683

674684
const std::vector<std::string> &FinalCommandLine =
675685
ModifiedCommandLine ? *ModifiedCommandLine : CommandLine;
686+
auto &FinalFS = ModifiedFS ? ModifiedFS : BaseFS;
676687

677688
FileSystemOptions FSOpts;
678689
FSOpts.WorkingDir = WorkingDirectory.str();
679-
auto FileMgr = llvm::makeIntrusiveRefCnt<FileManager>(
680-
FSOpts, ModifiedFS ? ModifiedFS : BaseFS);
690+
auto FileMgr = llvm::makeIntrusiveRefCnt<FileManager>(FSOpts, FinalFS);
681691

682-
std::vector<const char *> FinalCCommandLine(CommandLine.size(), nullptr);
683-
llvm::transform(CommandLine, FinalCCommandLine.begin(),
692+
std::vector<const char *> FinalCCommandLine(FinalCommandLine.size(), nullptr);
693+
llvm::transform(FinalCommandLine, FinalCCommandLine.begin(),
684694
[](const std::string &Str) { return Str.c_str(); });
685695

686696
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)