Skip to content

Commit a36aad5

Browse files
committed
[clang][cas] Prefix-map paths in <module-includes>
When we generate <module-includes> for a system module that uses builtin clang headers, the clang headers show up with an absolute path since they are not relative to the module root directory. Prefix-map those paths so that we can get cache hits across different clang resource directory paths. rdar://108381336 (cherry picked from commit 6c3651b)
1 parent 9d6cbc5 commit a36aad5

File tree

4 files changed

+90
-15
lines changed

4 files changed

+90
-15
lines changed

clang/include/clang/Frontend/CompilerInstance.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "llvm/CAS/CASOutputBackend.h"
2626
#include "llvm/Support/BuryPointer.h"
2727
#include "llvm/Support/FileSystem.h"
28+
#include "llvm/Support/PrefixMapper.h"
2829
#include "llvm/Support/VirtualOutputBackend.h"
2930
#include <cassert>
3031
#include <list>
@@ -94,6 +95,9 @@ class CompilerInstance : public ModuleLoader {
9495
/// The \c ActionCache key for this compilation, if caching is enabled.
9596
Optional<cas::CASID> CompileJobCacheKey;
9697

98+
/// The prefix mapper; empty by default.
99+
llvm::PrefixMapper PrefixMapper;
100+
97101
/// The file manager.
98102
IntrusiveRefCntPtr<FileManager> FileMgr;
99103

@@ -362,6 +366,10 @@ class CompilerInstance : public ModuleLoader {
362366
}
363367
bool isSourceNonReproducible() const;
364368

369+
llvm::PrefixMapper &getPrefixMapper() { return PrefixMapper; }
370+
371+
void setPrefixMapper(llvm::PrefixMapper PM) { PrefixMapper = std::move(PM); }
372+
365373
/// }
366374
/// @name Diagnostics Engine
367375
/// {

clang/lib/Frontend/FrontendAction.cpp

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -307,15 +307,21 @@ operator+=(SmallVectorImpl<char> &Includes, StringRef RHS) {
307307
static void addHeaderInclude(StringRef HeaderName,
308308
SmallVectorImpl<char> &Includes,
309309
const LangOptions &LangOpts,
310-
bool IsExternC) {
310+
llvm::PrefixMapper &PrefixMapper, bool IsExternC) {
311311
if (IsExternC && LangOpts.CPlusPlus)
312312
Includes += "extern \"C\" {\n";
313313
if (LangOpts.ObjC)
314314
Includes += "#import \"";
315315
else
316316
Includes += "#include \"";
317317

318-
Includes += HeaderName;
318+
if (PrefixMapper.empty() || llvm::sys::path::is_relative(HeaderName)) {
319+
Includes += HeaderName;
320+
} else {
321+
SmallString<128> MappedPath;
322+
PrefixMapper.map(HeaderName, MappedPath);
323+
Includes += MappedPath;
324+
}
319325

320326
Includes += "\"\n";
321327
if (IsExternC && LangOpts.CPlusPlus)
@@ -330,8 +336,9 @@ static void addHeaderInclude(StringRef HeaderName,
330336
/// \param Includes Will be augmented with the set of \#includes or \#imports
331337
/// needed to load all of the named headers.
332338
static std::error_code collectModuleHeaderIncludes(
333-
const LangOptions &LangOpts, FileManager &FileMgr, DiagnosticsEngine &Diag,
334-
ModuleMap &ModMap, clang::Module *Module, SmallVectorImpl<char> &Includes) {
339+
const LangOptions &LangOpts, llvm::PrefixMapper &PrefixMapper,
340+
FileManager &FileMgr, DiagnosticsEngine &Diag, ModuleMap &ModMap,
341+
clang::Module *Module, SmallVectorImpl<char> &Includes) {
335342
// Don't collect any headers for unavailable modules.
336343
if (!Module->isAvailable())
337344
return std::error_code();
@@ -360,7 +367,7 @@ static std::error_code collectModuleHeaderIncludes(
360367
// the module map file) so this will find the same file that we found
361368
// while parsing the module map.
362369
addHeaderInclude(H.PathRelativeToRootModuleDirectory, Includes, LangOpts,
363-
Module->IsExternC);
370+
PrefixMapper, Module->IsExternC);
364371
}
365372
}
366373
// Note that Module->PrivateHeaders will not be a TopHeader.
@@ -370,7 +377,7 @@ static std::error_code collectModuleHeaderIncludes(
370377
if (Module->Parent)
371378
// Include the umbrella header for submodules.
372379
addHeaderInclude(UmbrellaHeader.PathRelativeToRootModuleDirectory,
373-
Includes, LangOpts, Module->IsExternC);
380+
Includes, LangOpts, PrefixMapper, Module->IsExternC);
374381
} else if (Module::DirectoryName UmbrellaDir = Module->getUmbrellaDir()) {
375382
// Add all of the headers we find in this subdirectory.
376383
std::error_code EC;
@@ -423,7 +430,8 @@ static std::error_code collectModuleHeaderIncludes(
423430
for (auto &H : Headers) {
424431
// Include this header as part of the umbrella directory.
425432
Module->addTopHeader(H.second);
426-
addHeaderInclude(H.first, Includes, LangOpts, Module->IsExternC);
433+
addHeaderInclude(H.first, Includes, LangOpts, PrefixMapper,
434+
Module->IsExternC);
427435
}
428436
}
429437

@@ -432,7 +440,7 @@ static std::error_code collectModuleHeaderIncludes(
432440
SubEnd = Module->submodule_end();
433441
Sub != SubEnd; ++Sub)
434442
if (std::error_code Err = collectModuleHeaderIncludes(
435-
LangOpts, FileMgr, Diag, ModMap, *Sub, Includes))
443+
LangOpts, PrefixMapper, FileMgr, Diag, ModMap, *Sub, Includes))
436444
return Err;
437445

438446
return std::error_code();
@@ -669,9 +677,10 @@ getInputBufferForModule(CompilerInstance &CI, Module *M) {
669677
std::error_code Err = std::error_code();
670678
if (Module::Header UmbrellaHeader = M->getUmbrellaHeader())
671679
addHeaderInclude(UmbrellaHeader.PathRelativeToRootModuleDirectory,
672-
HeaderContents, CI.getLangOpts(), M->IsExternC);
680+
HeaderContents, CI.getLangOpts(), CI.getPrefixMapper(),
681+
M->IsExternC);
673682
Err = collectModuleHeaderIncludes(
674-
CI.getLangOpts(), FileMgr, CI.getDiagnostics(),
683+
CI.getLangOpts(), CI.getPrefixMapper(), FileMgr, CI.getDiagnostics(),
675684
CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(), M,
676685
HeaderContents);
677686

clang/lib/Tooling/DependencyScanning/IncludeTreeActionController.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,8 @@ Error IncludeTreeActionController::initialize(
299299
return;
300300

301301
PreprocessorOptions &PPOpts = ScanInstance.getPreprocessorOpts();
302-
if (PPOpts.Includes.empty() && PPOpts.ImplicitPCHInclude.empty())
302+
if (PPOpts.Includes.empty() && PPOpts.ImplicitPCHInclude.empty() &&
303+
!ScanInstance.getLangOpts().Modules)
303304
return;
304305

305306
addReversePrefixMappingFileSystem(PrefixMapper, ScanInstance);
@@ -367,6 +368,7 @@ Error IncludeTreeActionController::initializeModuleBuild(
367368
return std::make_unique<LookupPCHModulesListener>(R);
368369
});
369370
ModuleScanInstance.addDependencyCollector(std::move(DC));
371+
ModuleScanInstance.setPrefixMapper(PrefixMapper);
370372

371373
return Error::success();
372374
}

clang/test/ClangScanDeps/modules-include-tree-prefix-map.c

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
// RUN: rm -rf %t
44
// RUN: split-file %s %t/dir1
55
// RUN: cp -r %t/dir1 %t/dir2
6-
// RUN: sed "s|DIR|%/t/dir1|g" %t/dir1/cdb.json.template > %t/cdb1.json
7-
// RUN: sed "s|DIR|%/t/dir2|g" %t/dir1/cdb.json.template > %t/cdb2.json
6+
// RUN: sed -e "s|DIR|%/t/dir1|g" -e "s|CLANG|%clang|g" %t/dir1/cdb.json.template > %t/cdb1.json
7+
// RUN: sed -e "s|DIR|%/t/dir2|g" -e "s|CLANG|%clang|g" %t/dir1/cdb.json.template > %t/cdb2.json
88

99
// RUN: clang-scan-deps -compilation-database %t/cdb1.json \
1010
// RUN: -cas-path %t/cas -module-files-dir %t/dir1/outputs \
@@ -16,12 +16,14 @@
1616
// RUN: %deps-to-rsp %t/deps.json --module-name Top > %t/Top.rsp
1717
// RUN: %deps-to-rsp %t/deps.json --module-name Left > %t/Left.rsp
1818
// RUN: %deps-to-rsp %t/deps.json --module-name Right > %t/Right.rsp
19+
// RUN: %deps-to-rsp %t/deps.json --module-name System > %t/System.rsp
1920
// RUN: %deps-to-rsp %t/deps.json --tu-index 0 > %t/tu.rsp
2021

2122
// Extract include-tree casids
2223
// RUN: cat %t/Top.rsp | sed -E 's|.*"-fcas-include-tree" "(llvmcas://[[:xdigit:]]+)".*|\1|' > %t/Top.casid
2324
// RUN: cat %t/Left.rsp | sed -E 's|.*"-fcas-include-tree" "(llvmcas://[[:xdigit:]]+)".*|\1|' > %t/Left.casid
2425
// RUN: cat %t/Right.rsp | sed -E 's|.*"-fcas-include-tree" "(llvmcas://[[:xdigit:]]+)".*|\1|' > %t/Right.casid
26+
// RUN: cat %t/System.rsp | sed -E 's|.*"-fcas-include-tree" "(llvmcas://[[:xdigit:]]+)".*|\1|' > %t/System.casid
2527
// RUN: cat %t/tu.rsp | sed -E 's|.*"-fcas-include-tree" "(llvmcas://[[:xdigit:]]+)".*|\1|' > %t/tu.casid
2628

2729
// RUN: echo "MODULE Top" > %t/result.txt
@@ -33,6 +35,10 @@
3335
// RUN: echo "TRANSLATION UNIT" >> %t/result.txt
3436
// RUN: clang-cas-test -cas %t/cas -print-include-tree @%t/tu.casid >> %t/result.txt
3537

38+
// RUN: clang-cas-test -cas %t/cas -print-include-tree @%t/System.casid | grep '<module-includes>' | sed 's|.* llvmcas|llvmcas|' > %t/system-module-includes.casid
39+
// RUN: echo "System module-includes" >> %t/result.txt
40+
// RUN: llvm-cas -cas %t/cas -cat-blob @%t/system-module-includes.casid >> %t/result.txt
41+
3642
// RUN: FileCheck %s -input-file %t/result.txt -DPREFIX=%/t -check-prefix=NO_PATHS
3743
// NO_PATHS-NOT: [[PREFIX]]
3844

@@ -97,7 +103,11 @@
97103
// CHECK: /^src/Top.h llvmcas://{{[[:xdigit:]]+}}
98104
// CHECK: /^src/Right.h llvmcas://{{[[:xdigit:]]+}}
99105

100-
// CHECK: {
106+
// CHECK-LABEL: System module-includes
107+
// CHECK-NEXT: #import "sys.h"
108+
// CHECK-NEXT: #import "/^tc/{{.*}}/stdbool.h"
109+
110+
// CHECK-NEXT: {
101111
// CHECK-NEXT "modules": [
102112
// CHECK-NEXT {
103113
// CHECK: "cas-include-tree-id": "[[LEFT_TREE:llvmcas://[[:xdigit:]]+]]"
@@ -170,6 +180,33 @@
170180
// CHECK: "name": "Right"
171181
// CHECK: }
172182
// CHECK-NEXT: {
183+
// CHECK: "cas-include-tree-id": "[[SYS_TREE:llvmcas://[[:xdigit:]]+]]"
184+
// CHECK: "clang-module-deps": []
185+
// CHECK: "clang-modulemap-file": "[[PREFIX]]/dir1/System/module.modulemap"
186+
// CHECK: "command-line": [
187+
// CHECK-NEXT: "-cc1"
188+
// CHECK: "-fcas-path"
189+
// CHECK-NEXT: "[[PREFIX]]/cas"
190+
// CHECK: "-o"
191+
// CHECK-NEXT: "[[PREFIX]]/dir1/outputs/{{.*}}/System-{{.*}}.pcm"
192+
// CHECK: "-disable-free"
193+
// CHECK: "-fno-pch-timestamp"
194+
// CHECK: "-fcas-include-tree"
195+
// CHECK-NEXT: "[[SYS_TREE]]"
196+
// CHECK: "-fcache-compile-job"
197+
// CHECK: "-emit-module"
198+
// CHECK: "-fmodules"
199+
// CHECK: "-fmodule-name=System"
200+
// CHECK: "-fno-implicit-modules"
201+
// CHECK: ]
202+
// CHECK: "file-deps": [
203+
// CHECK-DAG: "{{.*}}/stdbool.h"
204+
// CHECK-DAG: "[[PREFIX]]/dir1/System/module.modulemap"
205+
// CHECK-DAG: "[[PREFIX]]/dir1/System/sys.h"
206+
// CHECK: ]
207+
// CHECK: "name": "System"
208+
// CHECK: }
209+
// CHECK-NEXT: {
173210
// CHECK: "cas-include-tree-id": "[[TOP_TREE:llvmcas://[[:xdigit:]]+]]"
174211
// CHECK: "clang-module-deps": []
175212
// CHECK: "clang-modulemap-file": "[[PREFIX]]/dir1/module.modulemap"
@@ -208,6 +245,9 @@
208245
// CHECK-NEXT: {
209246
// CHECK: "module-name": "Right"
210247
// CHECK: }
248+
// CHECK-NEXT: {
249+
// CHECK: "module-name": "System"
250+
// CHECK: }
211251
// CHECK-NEXT: ]
212252
// CHECK: "command-line": [
213253
// CHECK-NEXT: "-cc1"
@@ -244,6 +284,7 @@
244284
// RUN: %clang @%t/Top.rsp 2>&1 | FileCheck %s -check-prefix=CACHE_MISS
245285
// RUN: %clang @%t/Left.rsp 2>&1 | FileCheck %s -check-prefix=CACHE_MISS
246286
// RUN: %clang @%t/Right.rsp 2>&1 | FileCheck %s -check-prefix=CACHE_MISS
287+
// RUN: %clang @%t/System.rsp 2>&1 | FileCheck %s -check-prefix=CACHE_MISS
247288
// RUN: %clang @%t/tu.rsp 2>&1 | FileCheck %s -check-prefix=CACHE_MISS
248289

249290
// Scan in a different directory
@@ -256,12 +297,14 @@
256297
// RUN: %deps-to-rsp %t/deps2.json --module-name Top > %t/Top2.rsp
257298
// RUN: %deps-to-rsp %t/deps2.json --module-name Left > %t/Left2.rsp
258299
// RUN: %deps-to-rsp %t/deps2.json --module-name Right > %t/Right2.rsp
300+
// RUN: %deps-to-rsp %t/deps2.json --module-name System > %t/System2.rsp
259301
// RUN: %deps-to-rsp %t/deps2.json --tu-index 0 > %t/tu2.rsp
260302

261303
// Check cache hits
262304
// RUN: %clang @%t/Top2.rsp 2>&1 | FileCheck %s -check-prefix=CACHE_HIT
263305
// RUN: %clang @%t/Left2.rsp 2>&1 | FileCheck %s -check-prefix=CACHE_HIT
264306
// RUN: %clang @%t/Right2.rsp 2>&1 | FileCheck %s -check-prefix=CACHE_HIT
307+
// RUN: %clang @%t/System2.rsp 2>&1 | FileCheck %s -check-prefix=CACHE_HIT
265308
// RUN: %clang @%t/tu2.rsp 2>&1 | FileCheck %s -check-prefix=CACHE_HIT
266309

267310
// CACHE_MISS: compile job cache miss
@@ -271,7 +314,7 @@
271314
[{
272315
"file": "DIR/tu.m",
273316
"directory": "DIR",
274-
"command": "clang -fsyntax-only DIR/tu.m -I DIR -fmodules -fimplicit-modules -fimplicit-module-maps -fmodules-cache-path=DIR/module-cache -Rcompile-job-cache"
317+
"command": "CLANG -fsyntax-only DIR/tu.m -I DIR -isystem DIR/System -fmodules -fimplicit-modules -fimplicit-module-maps -fmodules-cache-path=DIR/module-cache -Rcompile-job-cache"
275318
}]
276319

277320
//--- module.modulemap
@@ -294,12 +337,25 @@ void left(void);
294337
#include "Top.h"
295338
void right(void);
296339

340+
//--- System/module.modulemap
341+
module System [system] {
342+
header "sys.h"
343+
header "stdbool.h"
344+
}
345+
346+
//--- System/sys.h
347+
#include <stdbool.h>
348+
bool sys(void);
349+
297350
//--- tu.m
298351
#import "Left.h"
299352
#import <Right.h>
353+
#import <sys.h>
300354

301355
void tu(void) {
302356
top();
303357
left();
304358
right();
359+
bool b = sys();
360+
(void)b;
305361
}

0 commit comments

Comments
 (0)