[modules] Instead of storing absolute paths in a .pcm file, store the path to
the root of the module and use paths relative to that directory wherever
possible. This is a step towards allowing explicit modules to be relocated
without being rebuilt, which is important for some kinds of distributed builds,
for good paths in diagnostics, and for appropriate .d output.
llvm-svn: 223443
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index b253704..7baeba7 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -1029,7 +1029,7 @@
/// \brief Read the line table in the source manager block.
/// \returns true if there was an error.
bool ASTReader::ParseLineTable(ModuleFile &F,
- SmallVectorImpl<uint64_t> &Record) {
+ const RecordData &Record) {
unsigned Idx = 0;
LineTableInfo &LineTable = SourceMgr.getLineTable();
@@ -1037,10 +1037,7 @@
std::map<int, int> FileIDs;
for (int I = 0, N = Record[Idx++]; I != N; ++I) {
// Extract the file name
- unsigned FilenameLen = Record[Idx++];
- std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen);
- Idx += FilenameLen;
- MaybeAddSystemRootToFilename(F, Filename);
+ auto Filename = ReadPath(F, Record, Idx);
FileIDs[I] = LineTable.getLineTableFilenameID(Filename);
}
@@ -1483,11 +1480,11 @@
unsigned HeaderFileInfoTrait::ComputeHash(internal_key_ref ikey) {
return llvm::hash_combine(ikey.Size, ikey.ModTime);
}
-
+
HeaderFileInfoTrait::internal_key_type
HeaderFileInfoTrait::GetInternalKey(const FileEntry *FE) {
internal_key_type ikey = { FE->getSize(), FE->getModificationTime(),
- FE->getName() };
+ FE->getName(), /*Imported*/false };
return ikey;
}
@@ -1495,14 +1492,24 @@
if (a.Size != b.Size || a.ModTime != b.ModTime)
return false;
- if (strcmp(a.Filename, b.Filename) == 0)
+ if (llvm::sys::path::is_absolute(a.Filename) &&
+ strcmp(a.Filename, b.Filename) == 0)
return true;
// Determine whether the actual files are equivalent.
FileManager &FileMgr = Reader.getFileManager();
- const FileEntry *FEA = FileMgr.getFile(a.Filename);
- const FileEntry *FEB = FileMgr.getFile(b.Filename);
- return (FEA && FEA == FEB);
+ auto GetFile = [&](const internal_key_type &Key) -> const FileEntry* {
+ if (!Key.Imported)
+ return FileMgr.getFile(Key.Filename);
+
+ std::string Resolved = Key.Filename;
+ Reader.ResolveImportedPath(M, Resolved);
+ return FileMgr.getFile(Resolved);
+ };
+
+ const FileEntry *FEA = GetFile(a);
+ const FileEntry *FEB = GetFile(b);
+ return FEA && FEA == FEB;
}
std::pair<unsigned, unsigned>
@@ -1520,6 +1527,7 @@
ikey.Size = off_t(endian::readNext<uint64_t, little, unaligned>(d));
ikey.ModTime = time_t(endian::readNext<uint64_t, little, unaligned>(d));
ikey.Filename = (const char *)d;
+ ikey.Imported = true;
return ikey;
}
@@ -1559,11 +1567,13 @@
FileManager &FileMgr = Reader.getFileManager();
ModuleMap &ModMap =
Reader.getPreprocessor().getHeaderSearchInfo().getModuleMap();
- // FIXME: This is wrong. We should track the filename as written; this
- // information should be propagated through the SUBMODULE_HEADER etc
- // records rather than from here.
+ // FIXME: This information should be propagated through the
+ // SUBMODULE_HEADER etc records rather than from here.
// FIXME: We don't ever mark excluded headers.
- Module::Header H = { key.Filename, FileMgr.getFile(key.Filename) };
+ std::string Filename = key.Filename;
+ if (key.Imported)
+ Reader.ResolveImportedPath(M, Filename);
+ Module::Header H = { key.Filename, FileMgr.getFile(Filename) };
ModMap.addHeader(Mod, H, HFI.getHeaderRole());
}
}
@@ -2084,14 +2094,14 @@
off_t StoredSize;
time_t StoredTime;
bool Overridden;
-
+
assert(Record[0] == ID && "Bogus stored ID or offset");
StoredSize = static_cast<off_t>(Record[1]);
StoredTime = static_cast<time_t>(Record[2]);
Overridden = static_cast<bool>(Record[3]);
Filename = Blob;
- MaybeAddSystemRootToFilename(F, Filename);
-
+ ResolveImportedPath(F, Filename);
+
InputFileInfo R = { std::move(Filename), StoredSize, StoredTime, Overridden };
return R;
}
@@ -2229,46 +2239,24 @@
return IF;
}
-const FileEntry *ASTReader::getFileEntry(StringRef filenameStrRef) {
- ModuleFile &M = ModuleMgr.getPrimaryModule();
- std::string Filename = filenameStrRef;
- MaybeAddSystemRootToFilename(M, Filename);
- const FileEntry *File = FileMgr.getFile(Filename);
- if (File == nullptr && !M.OriginalDir.empty() && !CurrentDir.empty() &&
- M.OriginalDir != CurrentDir) {
- std::string resolved = resolveFileRelativeToOriginalDir(Filename,
- M.OriginalDir,
- CurrentDir);
- if (!resolved.empty())
- File = FileMgr.getFile(resolved);
- }
-
- return File;
+/// \brief If we are loading a relocatable PCH or module file, and the filename
+/// is not an absolute path, add the system or module root to the beginning of
+/// the file name.
+void ASTReader::ResolveImportedPath(ModuleFile &M, std::string &Filename) {
+ // Resolve relative to the base directory, if we have one.
+ if (!M.BaseDirectory.empty())
+ return ResolveImportedPath(Filename, M.BaseDirectory);
}
-/// \brief If we are loading a relocatable PCH file, and the filename is
-/// not an absolute path, add the system root to the beginning of the file
-/// name.
-void ASTReader::MaybeAddSystemRootToFilename(ModuleFile &M,
- std::string &Filename) {
- // If this is not a relocatable PCH file, there's nothing to do.
- if (!M.RelocatablePCH)
- return;
-
+void ASTReader::ResolveImportedPath(std::string &Filename, StringRef Prefix) {
if (Filename.empty() || llvm::sys::path::is_absolute(Filename))
return;
- if (isysroot.empty()) {
- // If no system root was given, default to '/'
- Filename.insert(Filename.begin(), '/');
- return;
- }
-
- unsigned Length = isysroot.size();
- if (isysroot[Length - 1] != '/')
+ unsigned Length = Prefix.size();
+ if (Prefix[Length - 1] != '/')
Filename.insert(Filename.begin(), '/');
- Filename.insert(Filename.begin(), isysroot.begin(), isysroot.end());
+ Filename.insert(Filename.begin(), Prefix.begin(), Prefix.end());
}
ASTReader::ASTReadResult
@@ -2388,6 +2376,9 @@
}
F.RelocatablePCH = Record[4];
+ // Relative paths in a relocatable PCH are relative to our sysroot.
+ if (F.RelocatablePCH)
+ F.BaseDirectory = isysroot.empty() ? "/" : isysroot;
const std::string &CurBranch = getClangFullRepositoryVersion();
StringRef ASTBranch = Blob;
@@ -2418,10 +2409,7 @@
off_t StoredSize = (off_t)Record[Idx++];
time_t StoredModTime = (time_t)Record[Idx++];
ASTFileSignature StoredSignature = Record[Idx++];
- unsigned Length = Record[Idx++];
- SmallString<128> ImportedFile(Record.begin() + Idx,
- Record.begin() + Idx + Length);
- Idx += Length;
+ auto ImportedFile = ReadPath(F, Record, Idx);
// Load the AST file.
switch(ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F, Loaded,
@@ -2505,7 +2493,7 @@
F.OriginalSourceFileID = FileID::get(Record[0]);
F.ActualOriginalSourceFileName = Blob;
F.OriginalSourceFileName = F.ActualOriginalSourceFileName;
- MaybeAddSystemRootToFilename(F, F.OriginalSourceFileName);
+ ResolveImportedPath(F, F.OriginalSourceFileName);
break;
case ORIGINAL_FILE_ID:
@@ -2522,6 +2510,10 @@
Listener->ReadModuleName(F.ModuleName);
break;
+ case MODULE_DIRECTORY:
+ F.BaseDirectory = Blob;
+ break;
+
case MODULE_MAP_FILE:
if (ASTReadResult Result =
ReadModuleMapFileBlock(Record, F, ImportedBy, ClientLoadCapabilities))
@@ -3342,7 +3334,7 @@
const ModuleFile *ImportedBy,
unsigned ClientLoadCapabilities) {
unsigned Idx = 0;
- F.ModuleMapPath = ReadString(Record, Idx);
+ F.ModuleMapPath = ReadPath(F, Record, Idx);
if (F.Kind == MK_ExplicitModule) {
// For an explicitly-loaded module, we don't care whether the original
@@ -3389,7 +3381,7 @@
llvm::SmallPtrSet<const FileEntry *, 1> AdditionalStoredMaps;
for (unsigned I = 0, N = Record[Idx++]; I < N; ++I) {
// FIXME: we should use input files rather than storing names.
- std::string Filename = ReadString(Record, Idx);
+ std::string Filename = ReadPath(F, Record, Idx);
const FileEntry *F =
FileMgr.getFile(Filename, false, false);
if (F == nullptr) {
@@ -4256,6 +4248,7 @@
// Scan for ORIGINAL_FILE inside the control block.
RecordData Record;
+ std::string ModuleDir;
while (1) {
llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
if (Entry.Kind == llvm::BitstreamEntry::EndBlock)
@@ -4280,9 +4273,14 @@
case MODULE_NAME:
Listener.ReadModuleName(Blob);
break;
+ case MODULE_DIRECTORY:
+ ModuleDir = Blob;
+ break;
case MODULE_MAP_FILE: {
unsigned Idx = 0;
- Listener.ReadModuleMapFile(ReadString(Record, Idx));
+ auto Path = ReadString(Record, Idx);
+ ResolveImportedPath(Path, ModuleDir);
+ Listener.ReadModuleMapFile(Path);
break;
}
case LANGUAGE_OPTIONS:
@@ -4344,7 +4342,10 @@
switch ((InputFileRecordTypes)Cursor.readRecord(Code, Record, &Blob)) {
case INPUT_FILE:
bool Overridden = static_cast<bool>(Record[3]);
- shouldContinue = Listener.visitInputFile(Blob, isSystemFile, Overridden);
+ std::string Filename = Blob;
+ ResolveImportedPath(Filename, ModuleDir);
+ shouldContinue =
+ Listener.visitInputFile(Filename, isSystemFile, Overridden);
break;
}
if (!shouldContinue)
@@ -4361,11 +4362,9 @@
while (Idx < N) {
// Read information about the AST file.
Idx += 5; // ImportLoc, Size, ModTime, Signature
- unsigned Length = Record[Idx++];
- SmallString<128> ImportedFile(Record.begin() + Idx,
- Record.begin() + Idx + Length);
- Idx += Length;
- Listener.visitImport(ImportedFile);
+ std::string Filename = ReadString(Record, Idx);
+ ResolveImportedPath(Filename, ModuleDir);
+ Listener.visitImport(Filename);
}
break;
}
@@ -8050,6 +8049,13 @@
return Result;
}
+std::string ASTReader::ReadPath(ModuleFile &F, const RecordData &Record,
+ unsigned &Idx) {
+ std::string Filename = ReadString(Record, Idx);
+ ResolveImportedPath(F, Filename);
+ return Filename;
+}
+
VersionTuple ASTReader::ReadVersionTuple(const RecordData &Record,
unsigned &Idx) {
unsigned Major = Record[Idx++];