[clang] [clang][AST] Add path prefix mapping support for PCH/PCM files. (PR #203662)
Vladimir Vereschaka via cfe-commits
cfe-commits at lists.llvm.org
Fri Jun 12 20:01:58 PDT 2026
https://github.com/vvereschaka created https://github.com/llvm/llvm-project/pull/203662
This commit extends a path prefix mapping provided by `-ffile-prefix-map` (`-fmacro-prefix-map`) options to PCH/PCM files in order to support the reproducable builds. It uses the prefix map passedvia `-fmacro-prefix-map` option to remap the pathes stored within those files.
These changes affect `ORIGINAL_FILE`, `INPUT_FILE` and `MODULE_DIRECTORY` AST entries within the PCH/PCM files.
The same prefix maps must be used when emitting the PCH/PCM files (`--emit-pch`/`--emit-module`) and during their usage (`--include-pch`/ `-fmodule-file`).
Also updated `LangOptions::remapPathPrefix()` method to support a reverse mapping for the path prefixes.
>From af1990ff20c05be5844bdda439ed5abc554a755b Mon Sep 17 00:00:00 2001
From: Vladimir Vereschaka <vvereschaka at accesssoftek.com>
Date: Wed, 3 Jun 2026 17:17:03 -0700
Subject: [PATCH] [clang][AST] Add path prefix mapping support for PCH/PCM
files.
This commit extends a path prefix mapping provided by `-ffile-prefix-map`
(`-fmacro-prefix-map`) options to PCH/PCM files in order to support
the reproducable builds. It uses the prefix map passedvia `-fmacro-prefix-map`
option to remap the pathes stored within those files.
These changes affect `ORIGINAL_FILE`, `INPUT_FILE` and `MODULE_DIRECTORY`
AST entries within the PCH/PCM files.
The same prefix maps must be used when emitting the PCH/PCM files
(`--emit-pch`/`--emit-module`) and during their usage (`--include-pch`/
`-fmodule-file`).
Also updated `LangOptions::remapPathPrefix()` method to support a reverse
mapping for the path prefixes.
---
clang/include/clang/Basic/LangOptions.h | 7 +-
clang/include/clang/Serialization/ASTReader.h | 37 ++++++--
clang/lib/Basic/LangOptions.cpp | 13 ++-
.../DependencyScannerImpl.cpp | 4 +-
clang/lib/Frontend/ASTUnit.cpp | 2 +-
clang/lib/Frontend/CompilerInstance.cpp | 2 +-
clang/lib/Frontend/FrontendActions.cpp | 2 +-
clang/lib/Serialization/ASTReader.cpp | 86 +++++++++++++------
clang/lib/Serialization/ASTWriter.cpp | 9 +-
clang/test/Modules/module-path-prefix-map.cpp | 45 ++++++++++
clang/test/PCH/pch-path-prefix-map.cpp | 48 +++++++++++
11 files changed, 207 insertions(+), 48 deletions(-)
create mode 100644 clang/test/Modules/module-path-prefix-map.cpp
create mode 100644 clang/test/PCH/pch-path-prefix-map.cpp
diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h
index 9af036156b1ad..b4ca32b42bcc1 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -796,8 +796,11 @@ class LangOptions : public LangOptionsBase {
bool allowArrayReturnTypes() const { return HLSL; }
- /// Remap path prefix according to -fmacro-prefix-path option.
- void remapPathPrefix(SmallVectorImpl<char> &Path) const;
+ /// Remap path prefix according to -fmacro-prefix-map option.
+ /// If 'reverse' is true the swapped prefix pair will be used.
+ /// Returns true if Path was changed.
+ bool remapPathPrefix(SmallVectorImpl<char> &Path,
+ const bool reverse = false) const;
RoundingMode getDefaultRoundingMode() const {
return RoundingMath ? RoundingMode::Dynamic
diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h
index 61bd3d0748988..2809ac2b4e9b5 100644
--- a/clang/include/clang/Serialization/ASTReader.h
+++ b/clang/include/clang/Serialization/ASTReader.h
@@ -1460,15 +1460,35 @@ class ASTReader : public ExternalPreprocessorSource,
/// value must go out of scope before the next call to \c ResolveImportedPath.
static TemporarilyOwnedStringRef
ResolveImportedPath(SmallString<0> &Buf, StringRef Path, StringRef Prefix);
+ /// Resolve \c Path in the context of module file \c M with substitution
+ /// of the path prefixes in case provided them by `-ffile-prefix-map` or
+ /// `-fmacro-prefix-map` options.
+ /// The return value must go out of scope before the next call to
+ /// \c ResolveImportedPath.
+ static TemporarilyOwnedStringRef
+ ResolveImportedPath(SmallString<0> &Buf, StringRef Path, ModuleFile &ModF,
+ const LangOptions &LangOpts);
+ /// Resolve \c Path in the context of the \c Prefix directory with
+ /// substitution of the path prefixes in case provided them by
+ /// `-ffile-prefix-map` or `-fmacro-prefix-map` options.
+ /// The return value must go out of scope before the next call to
+ /// \c ResolveImportedPath.
+ static TemporarilyOwnedStringRef
+ ResolveImportedPath(SmallString<0> &Buf, StringRef Path, StringRef Prefix,
+ const LangOptions &LangOpts);
/// Resolve \c Path in the context of module file \c M.
- static std::string ResolveImportedPathAndAllocate(SmallString<0> &Buf,
- StringRef Path,
- ModuleFile &ModF);
+ /// The module path could be remapped with the path prefixes provided by
+ /// `-ffile-prefix-map` or `-fmacro-prefix-map` options.
+ static std::string
+ ResolveImportedPathAndAllocate(SmallString<0> &Buf, StringRef Path,
+ ModuleFile &ModF, const LangOptions &LangOpts);
/// Resolve \c Path in the context of the \c Prefix directory.
- static std::string ResolveImportedPathAndAllocate(SmallString<0> &Buf,
- StringRef Path,
- StringRef Prefix);
+ /// The path could be remapped with the path prefixes provided by
+ /// `-ffile-prefix-map` or `-fmacro-prefix-map` options.
+ static std::string
+ ResolveImportedPathAndAllocate(SmallString<0> &Buf, StringRef Path,
+ StringRef Prefix, const LangOptions &LangOpts);
/// Returns the first key declaration for the given declaration. This
/// is one that is formerly-canonical (or still canonical) and whose module
@@ -1998,8 +2018,9 @@ class ASTReader : public ExternalPreprocessorSource,
/// \returns true if an error occurred, false otherwise.
static bool readASTFileControlBlock(
StringRef Filename, FileManager &FileMgr, const ModuleCache &ModCache,
- const PCHContainerReader &PCHContainerRdr, bool FindModuleFileExtensions,
- ASTReaderListener &Listener, bool ValidateDiagnosticOptions,
+ const PCHContainerReader &PCHContainerRdr, const LangOptions &LangOpts,
+ bool FindModuleFileExtensions, ASTReaderListener &Listener,
+ bool ValidateDiagnosticOptions,
unsigned ClientLoadCapabilities = ARR_ConfigurationMismatch |
ARR_OutOfDate);
diff --git a/clang/lib/Basic/LangOptions.cpp b/clang/lib/Basic/LangOptions.cpp
index 7e75bf1221eb7..3c351ea7a985c 100644
--- a/clang/lib/Basic/LangOptions.cpp
+++ b/clang/lib/Basic/LangOptions.cpp
@@ -74,10 +74,15 @@ unsigned LangOptions::getOpenCLCompatibleVersion() const {
llvm_unreachable("Unknown OpenCL version");
}
-void LangOptions::remapPathPrefix(SmallVectorImpl<char> &Path) const {
- for (const auto &Entry : MacroPrefixMap)
- if (llvm::sys::path::replace_path_prefix(Path, Entry.first, Entry.second))
- break;
+bool LangOptions::remapPathPrefix(SmallVectorImpl<char> &Path,
+ const bool reverse /*=false*/) const {
+ for (const auto &Entry : MacroPrefixMap) {
+ const std::string& From = reverse ? Entry.second : Entry.first;
+ const std::string& To = reverse ? Entry.first : Entry.second;
+ if (llvm::sys::path::replace_path_prefix(Path, From, To))
+ return true;
+ }
+ return false;
}
std::string LangOptions::getOpenCLVersionString() const {
diff --git a/clang/lib/DependencyScanning/DependencyScannerImpl.cpp b/clang/lib/DependencyScanning/DependencyScannerImpl.cpp
index dc3dbe3603c01..eb34ae2656f09 100644
--- a/clang/lib/DependencyScanning/DependencyScannerImpl.cpp
+++ b/clang/lib/DependencyScanning/DependencyScannerImpl.cpp
@@ -189,7 +189,7 @@ static bool visitPrebuiltModule(StringRef PrebuiltModuleFilename,
/*DirectlyImported=*/true);
if (ASTReader::readASTFileControlBlock(
PrebuiltModuleFilename, CI.getFileManager(), CI.getModuleCache(),
- CI.getPCHContainerReader(),
+ CI.getPCHContainerReader(), CI.getLangOpts(),
/*FindModuleFileExtensions=*/false, Listener,
/*ValidateDiagnosticOptions=*/false, ASTReader::ARR_OutOfDate))
return true;
@@ -205,7 +205,7 @@ static bool visitPrebuiltModule(StringRef PrebuiltModuleFilename,
/*DirectlyImported=*/false);
if (ASTReader::readASTFileControlBlock(
Worklist.pop_back_val(), CI.getFileManager(), CI.getModuleCache(),
- CI.getPCHContainerReader(),
+ CI.getPCHContainerReader(), CI.getLangOpts(),
/*FindModuleFileExtensions=*/false, Listener,
/*ValidateDiagnosticOptions=*/false))
return true;
diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp
index 2974cf2660184..01cefc1f18ede 100644
--- a/clang/lib/Frontend/ASTUnit.cpp
+++ b/clang/lib/Frontend/ASTUnit.cpp
@@ -734,7 +734,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
*AST->LangOpts, *AST->CodeGenOpts,
*AST->TargetOpts, Counter);
if (ASTReader::readASTFileControlBlock(
- Filename, TmpFileMgr, *AST->ModCache, PCHContainerRdr,
+ Filename, TmpFileMgr, *AST->ModCache, PCHContainerRdr, *AST->LangOpts,
/*FindModuleFileExtensions=*/true, Collector,
/*ValidateDiagnosticOptions=*/true, ASTReader::ARR_None)) {
AST->getDiagnostics().Report(diag::err_fe_unable_to_load_ast_file);
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 8aee45b5dc644..1f19e7ac252f8 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -265,7 +265,7 @@ static void collectIncludePCH(CompilerInstance &CI,
// but only to check whether this is a file containing an AST.
if (!ASTReader::readASTFileControlBlock(
Dir->path(), FileMgr, CI.getModuleCache(),
- CI.getPCHContainerReader(),
+ CI.getPCHContainerReader(), CI.getLangOpts(),
/*FindModuleFileExtensions=*/false, Validator,
/*ValidateDiagnosticOptions=*/false))
MDC->addFile(Dir->path());
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp
index ba3487d52e380..fac3088a5ad91 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -1010,7 +1010,7 @@ void DumpModuleInfoAction::ExecuteAction() {
// FileCcontrolBlock is (re-)parsed.
ASTReader::readASTFileControlBlock(
getCurrentFile(), FileMgr, CI.getModuleCache(),
- CI.getPCHContainerReader(),
+ CI.getPCHContainerReader(), CI.getLangOpts(),
/*FindModuleFileExtensions=*/true, Listener,
HSOpts.ModulesValidateDiagnosticOptions);
}
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index f8a6a38bb9b5c..6e2ce4ead79df 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -2341,8 +2341,8 @@ HeaderFileInfoTrait::getFile(const internal_key_type &Key) {
if (!Key.Imported)
return FileMgr.getOptionalFileRef(Key.Filename);
- auto Resolved =
- ASTReader::ResolveImportedPath(Reader.getPathBuf(), Key.Filename, M);
+ auto Resolved = Reader.ResolveImportedPath(
+ Reader.getPathBuf(), Key.Filename, M, Reader.getContext().getLangOpts());
return FileMgr.getOptionalFileRef(*Resolved);
}
@@ -2872,8 +2872,8 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
time_t StoredTime = FI.StoredTime;
bool Overridden = FI.Overridden;
bool Transient = FI.Transient;
- auto Filename =
- ResolveImportedPath(PathBuf, FI.UnresolvedImportedFilenameAsRequested, F);
+ auto Filename = ResolveImportedPath(
+ PathBuf, FI.UnresolvedImportedFilenameAsRequested, F, PP.getLangOpts());
uint64_t StoredContentHash = FI.ContentHash;
// For standard C++ modules, we don't need to check the inputs.
@@ -3056,16 +3056,36 @@ ASTReader::ResolveImportedPath(SmallString<0> &Buf, StringRef Path,
return {ResolvedPath, Buf};
}
-std::string ASTReader::ResolveImportedPathAndAllocate(SmallString<0> &Buf,
- StringRef P,
- ModuleFile &ModF) {
- return ResolveImportedPathAndAllocate(Buf, P, ModF.BaseDirectory);
+ASTReader::TemporarilyOwnedStringRef
+ASTReader::ResolveImportedPath(SmallString<0> &Buf, StringRef Path,
+ StringRef Prefix, const LangOptions &LangOpts) {
+ auto Resolved = ResolveImportedPath(Buf, Path, Prefix);
+
+ Buf.assign(*Resolved);
+ if (LangOpts.remapPathPrefix(Buf, true))
+ return {StringRef{Buf.data(), Buf.size()}, Buf};
+
+ return Resolved;
+}
+
+ASTReader::TemporarilyOwnedStringRef
+ASTReader::ResolveImportedPath(SmallString<0> &Buf, StringRef Path,
+ ModuleFile &ModF, const LangOptions &LangOpts) {
+ return ResolveImportedPath(Buf, Path, ModF.BaseDirectory, LangOpts);
}
-std::string ASTReader::ResolveImportedPathAndAllocate(SmallString<0> &Buf,
- StringRef P,
- StringRef Prefix) {
- auto ResolvedPath = ResolveImportedPath(Buf, P, Prefix);
+std::string
+ASTReader::ResolveImportedPathAndAllocate(SmallString<0> &Buf, StringRef P,
+ ModuleFile &ModF,
+ const LangOptions &LangOpts) {
+ return ResolveImportedPathAndAllocate(Buf, P, ModF.BaseDirectory, LangOpts);
+}
+
+std::string
+ASTReader::ResolveImportedPathAndAllocate(SmallString<0> &Buf, StringRef P,
+ StringRef Prefix,
+ const LangOptions &LangOpts) {
+ auto ResolvedPath = ResolveImportedPath(Buf, P, Prefix, LangOpts);
return ResolvedPath->str();
}
@@ -3339,7 +3359,8 @@ ASTReader::ReadControlBlock(ModuleFile &F,
bool IsSystem = I >= NumUserInputs;
InputFileInfo FI = getInputFileInfo(F, I + 1);
auto FilenameAsRequested = ResolveImportedPath(
- PathBuf, FI.UnresolvedImportedFilenameAsRequested, F);
+ PathBuf, FI.UnresolvedImportedFilenameAsRequested, F,
+ PP.getLangOpts());
Listener->visitInputFile(
*FilenameAsRequested, IsSystem, FI.Overridden,
F.Kind == MK_ExplicitModule || F.Kind == MK_PrebuiltModule);
@@ -3417,6 +3438,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
// Read and process a record.
Record.clear();
StringRef Blob;
+ SmallString<0> RPath;
Expected<unsigned> MaybeRecordType =
Stream.readRecord(Entry.ID, Record, &Blob);
if (!MaybeRecordType) {
@@ -3603,7 +3625,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
F.OriginalSourceFileID = FileID::get(Record[0]);
F.ActualOriginalSourceFileName = std::string(Blob);
F.OriginalSourceFileName = ResolveImportedPathAndAllocate(
- PathBuf, F.ActualOriginalSourceFileName, F);
+ PathBuf, F.ActualOriginalSourceFileName, F, PP.getLangOpts());
break;
case ORIGINAL_FILE_ID:
@@ -3627,10 +3649,15 @@ ASTReader::ReadControlBlock(ModuleFile &F,
case MODULE_DIRECTORY: {
// Save the BaseDirectory as written in the PCM for computing the module
- // filename for the ModuleCache.
+ // filename for the ModuleCache. Remap path prefixes if specified.
+ RPath.assign(Blob.begin(), Blob.end());
+ if (PP.getLangOpts().remapPathPrefix(RPath, true))
+ Blob = StringRef(RPath.begin(), RPath.size());
+
BaseDirectoryAsWritten = Blob;
assert(!F.ModuleName.empty() &&
"MODULE_DIRECTORY found before MODULE_NAME");
+
F.BaseDirectory = std::string(Blob);
auto [MaybeM, IgnoreError] =
@@ -4032,8 +4059,7 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F,
case MODULAR_CODEGEN_DECLS:
// FIXME: Skip reading this record if our ASTConsumer doesn't care about
// them (ie: if we're not codegenerating this module).
- if (F.Kind == MK_MainFile ||
- getContext().getLangOpts().BuildingPCHWithObjectFile)
+ if (F.Kind == MK_MainFile || PP.getLangOpts().BuildingPCHWithObjectFile)
for (unsigned I = 0, N = Record.size(); I != N; /*in loop*/)
EagerlyDeserializedDecls.push_back(ReadDeclID(F, Record, I));
break;
@@ -5974,9 +6000,9 @@ namespace {
bool ASTReader::readASTFileControlBlock(
StringRef Filename, FileManager &FileMgr, const ModuleCache &ModCache,
- const PCHContainerReader &PCHContainerRdr, bool FindModuleFileExtensions,
- ASTReaderListener &Listener, bool ValidateDiagnosticOptions,
- unsigned ClientLoadCapabilities) {
+ const PCHContainerReader &PCHContainerRdr, const LangOptions &LangOpts,
+ bool FindModuleFileExtensions, ASTReaderListener &Listener,
+ bool ValidateDiagnosticOptions, unsigned ClientLoadCapabilities) {
// Open the AST file.
off_t Size;
time_t ModTime;
@@ -6124,7 +6150,7 @@ bool ASTReader::readASTFileControlBlock(
case MODULE_MAP_FILE: {
unsigned Idx = 0;
std::string PathStr = ReadString(Record, Idx);
- auto Path = ResolveImportedPath(PathBuf, PathStr, ModuleDir);
+ auto Path = ResolveImportedPath(PathBuf, PathStr, ModuleDir, LangOpts);
Listener.ReadModuleMapFile(*Path);
break;
}
@@ -6176,13 +6202,13 @@ bool ASTReader::readASTFileControlBlock(
auto [UnresolvedFilenameAsRequested, UnresolvedFilename] =
getUnresolvedInputFilenames(Record, Blob);
auto FilenameAsRequestedBuf = ResolveImportedPath(
- PathBuf, UnresolvedFilenameAsRequested, ModuleDir);
+ PathBuf, UnresolvedFilenameAsRequested, ModuleDir, LangOpts);
StringRef Filename;
if (UnresolvedFilename.empty())
Filename = *FilenameAsRequestedBuf;
else {
auto FilenameBuf = ResolveImportedPath(
- AdditionalPathBuf, UnresolvedFilename, ModuleDir);
+ AdditionalPathBuf, UnresolvedFilename, ModuleDir, LangOpts);
Filename = *FilenameBuf;
}
shouldContinue = Listener.visitInputFileAsRequested(
@@ -6226,7 +6252,8 @@ bool ASTReader::readASTFileControlBlock(
Blob = Blob.substr(ASTFileSignature::size);
StringRef FilenameStr = ReadStringBlob(Record, Idx, Blob);
- auto Filename = ResolveImportedPath(PathBuf, FilenameStr, ModuleDir);
+ auto Filename =
+ ResolveImportedPath(PathBuf, FilenameStr, ModuleDir, LangOpts);
Listener.visitImport(ModuleName, *Filename);
break;
}
@@ -6313,6 +6340,7 @@ bool ASTReader::isAcceptableASTFile(
SpecificModuleCachePath, FileMgr,
RequireStrictOptionMatches);
return !readASTFileControlBlock(Filename, FileMgr, ModCache, PCHContainerRdr,
+ LangOpts,
/*FindModuleFileExtensions=*/false, validator,
/*ValidateDiagnosticOptions=*/true);
}
@@ -6548,13 +6576,13 @@ Module *ASTReader::getSubmodule(uint32_t GlobalID) {
break;
case SUBMODULE_TOPHEADER: {
- auto HeaderName = ResolveImportedPath(PathBuf, Blob, F);
+ auto HeaderName = ResolveImportedPath(PathBuf, Blob, F, PP.getLangOpts());
CurrentModule->addTopHeaderFilename(*HeaderName);
break;
}
case SUBMODULE_UMBRELLA_DIR: {
- auto Dirname = ResolveImportedPath(PathBuf, Blob, F);
+ auto Dirname = ResolveImportedPath(PathBuf, Blob, F, PP.getLangOpts());
if (auto Umbrella =
PP.getFileManager().getOptionalDirectoryRef(*Dirname)) {
if (!CurrentModule->getUmbrellaDirAsWritten()) {
@@ -10464,14 +10492,16 @@ std::string ASTReader::ReadPath(ModuleFile &F, const RecordData &Record,
std::string ASTReader::ReadPath(StringRef BaseDirectory,
const RecordData &Record, unsigned &Idx) {
std::string Filename = ReadString(Record, Idx);
- return ResolveImportedPathAndAllocate(PathBuf, Filename, BaseDirectory);
+ return ResolveImportedPathAndAllocate(PathBuf, Filename, BaseDirectory,
+ PP.getLangOpts());
}
std::string ASTReader::ReadPathBlob(StringRef BaseDirectory,
const RecordData &Record, unsigned &Idx,
StringRef &Blob) {
StringRef Filename = ReadStringBlob(Record, Idx, Blob);
- return ResolveImportedPathAndAllocate(PathBuf, Filename, BaseDirectory);
+ return ResolveImportedPathAndAllocate(PathBuf, Filename, BaseDirectory,
+ PP.getLangOpts());
}
VersionTuple ASTReader::ReadVersionTuple(const RecordData &Record,
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 21dda6f3733e4..1a43aba60ed41 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -1505,7 +1505,12 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, StringRef isysroot) {
unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));
RecordData::value_type Record[] = {MODULE_DIRECTORY};
- Stream.EmitRecordWithBlob(AbbrevCode, Record, *BaseDir);
+
+ // Remap the path with the prefixes if specified. Write out only
+ // remapped directory, but keep working with the unmodified path.
+ SmallString<0> RPath(*BaseDir);
+ getLangOpts().remapPathPrefix(RPath);
+ Stream.EmitRecordWithBlob(AbbrevCode, Record, RPath);
}
// Write out all other paths relative to the base directory if possible.
@@ -5417,6 +5422,8 @@ bool ASTWriter::PreparePathForOutput(SmallVectorImpl<char> &Path) {
Path.erase(Path.begin(), Path.begin() + (PathPtr - PathBegin));
Changed = true;
}
+ // Remap with the path prefixes if provided.
+ Changed |= getLangOpts().remapPathPrefix(Path);
return Changed;
}
diff --git a/clang/test/Modules/module-path-prefix-map.cpp b/clang/test/Modules/module-path-prefix-map.cpp
new file mode 100644
index 0000000000000..475e82dbe8f49
--- /dev/null
+++ b/clang/test/Modules/module-path-prefix-map.cpp
@@ -0,0 +1,45 @@
+//NOTE: this test reuses the existing include/module files.
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t/merge-vtable-codegen
+// RUN: cp -r %S/Inputs/merge-vtable-codegen %t/
+
+// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fimplicit-module-maps -fmodule-name=b -fmodules-cache-path=%t -o %t/b1.pcm \
+// RUN: -emit-module %t/merge-vtable-codegen/merge-vtable-codegen.modulemap \
+// RUN: -I%t//merge-vtable-codegen -fmacro-prefix-map=%S=x:/PREFIX-MAP-IN -fmacro-prefix-map=%t=x:/PREFIX-MAP-OUT
+// RUN: llvm-bcanalyzer -dump --disable-histogram %t/b1.pcm | FileCheck -check-prefix=CHECK-PREFIX-MAP-OUT %s
+
+// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fimplicit-module-maps -fmodule-name=b -fmodules-cache-path=%t -o %t/b1.pcm \
+// RUN: -emit-module %t/merge-vtable-codegen/merge-vtable-codegen.modulemap \
+// RUN: -I%t/./merge-vtable-codegen -fmacro-prefix-map=%S=x:/PREFIX-MAP-IN -fmacro-prefix-map=%t=x:/PREFIX-MAP-OUT
+// RUN: llvm-bcanalyzer -dump --disable-histogram %t/b1.pcm | FileCheck -check-prefix=CHECK-PREFIX-MAP-OUT %s
+
+// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fimplicit-module-maps -fmodule-name=b -fmodules-cache-path=%t -o %t/b1.pcm \
+// RUN: -emit-module %t/merge-vtable-codegen/merge-vtable-codegen.modulemap \
+// RUN: -I%t/../merge-vtable-codegen -fmacro-prefix-map=%S=x:/PREFIX-MAP-IN -fmacro-prefix-map=%t=x:/PREFIX-MAP-OUT
+// RUN: llvm-bcanalyzer -dump --disable-histogram %t/b1.pcm | FileCheck -check-prefix=CHECK-PREFIX-MAP-OUT %s
+
+
+// First, build two modules that both re-export the same header.
+// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fimplicit-module-maps -fmodule-name=b -o %t/b.pcm \
+// RUN: -emit-module %S/Inputs/merge-vtable-codegen/merge-vtable-codegen.modulemap \
+// RUN: -I%S/Inputs/merge-vtable-codegen -fmacro-prefix-map=%S=x:/PREFIX-MAP-IN -fmacro-prefix-map=%t=x:/PREFIX-MAP-OUT
+// RUN: llvm-bcanalyzer -dump --disable-histogram %t/b.pcm | FileCheck -check-prefix=CHECK-PREFIX-MAP-IN %s
+
+// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fimplicit-module-maps -fmodule-name=c -o %t/c.pcm \
+// RUN: -emit-module %S/Inputs/merge-vtable-codegen/merge-vtable-codegen.modulemap \
+// RUN: -I%S/Inputs/merge-vtable-codegen -fmacro-prefix-map=%S=x:/PREFIX-MAP-IN -fmacro-prefix-map=%t=x:/PREFIX-MAP-OUT
+// RUN: llvm-bcanalyzer -dump --disable-histogram %t/c.pcm | FileCheck -check-prefix=CHECK-PREFIX-MAP-IN %s
+
+// Use the two modules in a single compile.
+// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fimplicit-module-maps -fmodule-file=%t/b.pcm -fmodule-file=%t/c.pcm \
+// RUN: -fmodule-map-file=%S/Inputs/merge-vtable-codegen/merge-vtable-codegen.modulemap -fmacro-prefix-map=%S=x:/PREFIX-MAP-IN -fmacro-prefix-map=%t=x:/PREFIX-MAP-OUT \
+// RUN: -emit-llvm -o %t/test.o %s
+
+
+// CHECK-PREFIX-MAP-IN: <MODULE_DIRECTORY {{.*}}/> blob data = 'x:/PREFIX-MAP-IN{{[/\\]}}Inputs{{[/\\]}}merge-vtable-codegen'
+
+// CHECK-PREFIX-MAP-OUT: <MODULE_DIRECTORY {{.*}}/> blob data = 'x:/PREFIX-MAP-OUT{{[/\\]}}merge-vtable-codegen'
+
+#include "Inputs/merge-vtable-codegen/c.h"
+#include "Inputs/merge-vtable-codegen/b.h"
diff --git a/clang/test/PCH/pch-path-prefix-map.cpp b/clang/test/PCH/pch-path-prefix-map.cpp
new file mode 100644
index 0000000000000..eeb520691dace
--- /dev/null
+++ b/clang/test/PCH/pch-path-prefix-map.cpp
@@ -0,0 +1,48 @@
+//NOTE: this test reuses the existing include files.
+
+// Create PCH with mappend path prefixes
+// RUN: mkdir -p %t-dir
+// RUN: cp %S/Inputs/pch-through3.h %t-dir
+// RUN: cp %S/Inputs/pch-through4.h %t-dir
+
+// RUN: %clang_cc1 -I %S -I %t-dir -x c++-header -emit-pch -fmacro-prefix-map=%S=x:/PREFIX-MAP-IN -fmacro-prefix-map=%t-dir=x:/PREFIX-MAP-OUT \
+// RUN: -o %t.pch %s
+// RUN: llvm-bcanalyzer -dump --disable-histogram %t.pch | FileCheck -check-prefix=CHECK-PREFIX-MAP-ORIGINAL %s
+// RUN: llvm-bcanalyzer -dump --disable-histogram %t.pch | FileCheck -check-prefix=CHECK-PREFIX-MAP-IN %s
+// RUN: rm -f %t.pch
+
+// RUN: %clang_cc1 -I %S -I %t-dir -x c++-header -emit-pch -fmacro-prefix-map=%S=x:/PREFIX-MAP-IN -fmacro-prefix-map=%t-dir=x:/PREFIX-MAP-OUT \
+// RUN: -include %S/cmdline-include1.h -include cmdline-include2.h -o %t.pch %s
+// RUN: llvm-bcanalyzer -dump --disable-histogram %t.pch | FileCheck -check-prefix=CHECK-PREFIX-MAP-ORIGINAL %s
+// RUN: llvm-bcanalyzer -dump --disable-histogram %t.pch | FileCheck -check-prefix=CHECK-PREFIX-MAP-IN-CMD %s
+
+// Use PCH with mapped path prefixes.
+// RUN: %clang_cc1 -I %S -I %t-dir -include-pch %t.pch -fmacro-prefix-map=%S=x:/PREFIX-MAP-IN -fmacro-prefix-map=%t-dir=x:/PREFIX-MAP-OUT %s
+// RUN: rm -f %t.pch
+
+// RUN: %clang_cl -Werror /I %S /I %t-dir /Yc%s /FI%s /c /Fo%t.pch.obj /Fp%t.pch /pathmap:%S=x:/PREFIX-MAP-IN /pathmap:%t-dir=x:/PREFIX-MAP-OUT -- %s
+// RUN: llvm-bcanalyzer -dump --disable-histogram %t.pch | FileCheck -check-prefix=CHECK-PREFIX-MAP-ORIGINAL %s
+// RUN: llvm-bcanalyzer -dump --disable-histogram %t.pch | FileCheck -check-prefix=CHECK-PREFIX-MAP-IN %s
+
+// use {{[/\\]}} to follow LLVM_WINDOWS_PREFER_FORWARD_SLASH=ON|OFF on Windows.
+
+// CHECK-PREFIX-MAP-ORIGINAL: <ORIGINAL_FILE {{.*}}/> blob data = 'x:/PREFIX-MAP-IN{{[/\\]}}pch-path-prefix-map.cpp'
+// CHECK-PREFIX-MAP-IN: <INPUT_FILE {{.*}}/> blob data = 'x:/PREFIX-MAP-IN{{[/\\]}}pch-path-prefix-map.cpp'
+// CHECK-PREFIX-MAP-IN: <INPUT_FILE {{.*}}/> blob data = 'x:/PREFIX-MAP-IN{{[/\\]}}Inputs{{[/\\]}}pch-through{{[12]}}.h'
+// CHECK-PREFIX-MAP-IN: <INPUT_FILE {{.*}}/> blob data = 'x:/PREFIX-MAP-IN{{[/\\]}}Inputs{{[/\\]}}pch-through{{[12]}}.h'
+// CHECK-PREFIX-MAP-IN: <INPUT_FILE {{.*}}/> blob data = 'x:/PREFIX-MAP-OUT{{[/\\]}}pch-through{{[34]}}.h'
+// CHECK-PREFIX-MAP-IN: <INPUT_FILE {{.*}}/> blob data = 'x:/PREFIX-MAP-OUT{{[/\\]}}pch-through{{[34]}}.h'
+
+// CHECK-PREFIX-MAP-IN-CMD: <INPUT_FILE {{.*}}/> blob data = 'x:/PREFIX-MAP-IN{{[/\\]}}pch-path-prefix-map.cpp'
+// CHECK-PREFIX-MAP-IN-CMD: <INPUT_FILE {{.*}}/> blob data = 'x:/PREFIX-MAP-IN{{[/\\]}}cmdline-include{{[12]}}.h'
+// CHECK-PREFIX-MAP-IN-CMD: <INPUT_FILE {{.*}}/> blob data = 'x:/PREFIX-MAP-IN{{[/\\]}}cmdline-include{{[12]}}.h'
+// CHECK-PREFIX-MAP-IN-CMD: <INPUT_FILE {{.*}}/> blob data = 'x:/PREFIX-MAP-IN{{[/\\]}}Inputs{{[/\\]}}pch-through{{[12]}}.h'
+// CHECK-PREFIX-MAP-IN-CMD: <INPUT_FILE {{.*}}/> blob data = 'x:/PREFIX-MAP-IN{{[/\\]}}Inputs{{[/\\]}}pch-through{{[12]}}.h'
+// CHECK-PREFIX-MAP-IN-CMD: <INPUT_FILE {{.*}}/> blob data = 'x:/PREFIX-MAP-OUT{{[/\\]}}pch-through{{[34]}}.h'
+// CHECK-PREFIX-MAP-IN-CMD: <INPUT_FILE {{.*}}/> blob data = 'x:/PREFIX-MAP-OUT{{[/\\]}}pch-through{{[34]}}.h'
+
+#include "Inputs/pch-through1.h"
+#include "Inputs/pch-through2.h"
+#include "pch-through3.h"
+#include <pch-through4.h>
+
More information about the cfe-commits
mailing list