<br><br><div class="gmail_quote">On Fri Dec 05 2014 at 3:36:24 AM Richard Smith <<a href="mailto:richard-llvm@metafoo.co.uk">richard-llvm@metafoo.co.uk</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rsmith<br>
Date: Thu Dec 4 20:33:27 2014<br>
New Revision: 223443<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=223443&view=rev" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project?rev=223443&view=rev</a><br>
Log:<br>
[modules] Instead of storing absolute paths in a .pcm file, store the path to<br>
the root of the module and use paths relative to that directory wherever<br>
possible. This is a step towards allowing explicit modules to be relocated<br>
without being rebuilt, which is important for some kinds of distributed builds,<br>
for good paths in diagnostics, and for appropriate .d output.<br>
<br>
Modified:<br>
cfe/trunk/include/clang/<u></u>Serialization/ASTBitCodes.h<br>
cfe/trunk/include/clang/<u></u>Serialization/ASTReader.h<br>
cfe/trunk/include/clang/<u></u>Serialization/ASTWriter.h<br>
cfe/trunk/include/clang/<u></u>Serialization/Module.h<br>
cfe/trunk/lib/Serialization/<u></u>ASTReader.cpp<br>
cfe/trunk/lib/Serialization/<u></u>ASTReaderInternals.h<br>
cfe/trunk/lib/Serialization/<u></u>ASTWriter.cpp<br>
<br>
Modified: cfe/trunk/include/clang/<u></u>Serialization/ASTBitCodes.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=223443&r1=223442&r2=223443&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/cfe/trunk/include/<u></u>clang/Serialization/<u></u>ASTBitCodes.h?rev=223443&r1=<u></u>223442&r2=223443&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- cfe/trunk/include/clang/<u></u>Serialization/ASTBitCodes.h (original)<br>
+++ cfe/trunk/include/clang/<u></u>Serialization/ASTBitCodes.h Thu Dec 4 20:33:27 2014<br>
@@ -291,7 +291,10 @@ namespace clang {<br>
MODULE_MAP_FILE = 14,<br>
<br>
/// \brief Record code for the signature that identifiers this AST file.<br>
- SIGNATURE = 15<br>
+ SIGNATURE = 15,<br>
+<br>
+ /// \brief Record code for the module build directory.<br>
+ MODULE_DIRECTORY = 16,<br>
};<br>
<br>
/// \brief Record types that occur within the input-files block<br>
<br>
Modified: cfe/trunk/include/clang/<u></u>Serialization/ASTReader.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=223443&r1=223442&r2=223443&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/cfe/trunk/include/<u></u>clang/Serialization/ASTReader.<u></u>h?rev=223443&r1=223442&r2=<u></u>223443&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- cfe/trunk/include/clang/<u></u>Serialization/ASTReader.h (original)<br>
+++ cfe/trunk/include/clang/<u></u>Serialization/ASTReader.h Thu Dec 4 20:33:27 2014<br>
@@ -1113,12 +1113,11 @@ private:<br>
serialization::InputFile getInputFile(ModuleFile &F, unsigned ID,<br>
bool Complain = true);<br>
<br>
- /// \brief Get a FileEntry out of stored-in-PCH filename, making sure we take<br>
- /// into account all the necessary relocations.<br>
- const FileEntry *getFileEntry(StringRef filename);<br>
-<br>
- void MaybeAddSystemRootToFilename(<u></u>ModuleFile &M, std::string &Filename);<br>
+public:<br>
+ void ResolveImportedPath(ModuleFile &M, std::string &Filename);<br>
+ static void ResolveImportedPath(std::<u></u>string &Filename, StringRef Prefix);<br>
<br>
+private:<br>
struct ImportedModule {<br>
ModuleFile *Mod;<br>
ModuleFile *ImportedBy;<br>
@@ -1141,7 +1140,7 @@ private:<br>
const ModuleFile *ImportedBy,<br>
unsigned ClientLoadCapabilities);<br>
ASTReadResult ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities);<br>
- bool ParseLineTable(ModuleFile &F, SmallVectorImpl<uint64_t> &Record);<br>
+ bool ParseLineTable(ModuleFile &F, const RecordData &Record);<br>
bool ReadSourceManagerBlock(<u></u>ModuleFile &F);<br>
llvm::BitstreamCursor &SLocCursorForID(int ID);<br>
SourceLocation getImportLocation(ModuleFile *F);<br>
@@ -2045,6 +2044,9 @@ public:<br>
// \brief Read a string<br>
static std::string ReadString(const RecordData &Record, unsigned &Idx);<br>
<br>
+ // \brief Read a path<br>
+ std::string ReadPath(ModuleFile &F, const RecordData &Record, unsigned &Idx);<br>
+<br>
/// \brief Read a version tuple.<br>
static VersionTuple ReadVersionTuple(const RecordData &Record, unsigned &Idx);<br>
<br>
<br>
Modified: cfe/trunk/include/clang/<u></u>Serialization/ASTWriter.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=223443&r1=223442&r2=223443&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/cfe/trunk/include/<u></u>clang/Serialization/ASTWriter.<u></u>h?rev=223443&r1=223442&r2=<u></u>223443&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- cfe/trunk/include/clang/<u></u>Serialization/ASTWriter.h (original)<br>
+++ cfe/trunk/include/clang/<u></u>Serialization/ASTWriter.h Thu Dec 4 20:33:27 2014<br>
@@ -111,7 +111,10 @@ private:<br>
<br>
/// \brief The module we're currently writing, if any.<br>
Module *WritingModule;<br>
-<br>
+<br>
+ /// \brief The base directory for any relative paths we emit.<br>
+ std::string BaseDirectory;<br>
+<br>
/// \brief Indicates when the AST writing is actively performing<br>
/// serialization, rather than just queueing updates.<br>
bool WritingAST;<br>
@@ -457,13 +460,11 @@ private:<br>
StringRef isysroot, const std::string &OutputFile);<br>
void WriteInputFiles(SourceManager &SourceMgr,<br>
HeaderSearchOptions &HSOpts,<br>
- StringRef isysroot,<br>
bool Modules);<br>
void WriteSourceManagerBlock(<u></u>SourceManager &SourceMgr,<br>
- const Preprocessor &PP,<br>
- StringRef isysroot);<br>
+ const Preprocessor &PP);<br>
void WritePreprocessor(const Preprocessor &PP, bool IsModule);<br>
- void WriteHeaderSearch(const HeaderSearch &HS, StringRef isysroot);<br>
+ void WriteHeaderSearch(const HeaderSearch &HS);<br>
void WritePreprocessorDetail(<u></u>PreprocessingRecord &PPRec);<br>
void WriteSubmodules(Module *WritingModule);<br>
<br>
@@ -539,7 +540,8 @@ public:<br>
/// writing a precompiled header.<br>
///<br>
/// \param isysroot if non-empty, write a relocatable file whose headers<br>
- /// are relative to the given system root.<br>
+ /// are relative to the given system root. If we're writing a module, its<br>
+ /// build directory will be used in preference to this if both are available.<br>
void WriteAST(Sema &SemaRef,<br>
const std::string &OutputFile,<br>
Module *WritingModule, StringRef isysroot,<br>
@@ -686,6 +688,17 @@ public:<br>
/// \brief Add a string to the given record.<br>
void AddString(StringRef Str, RecordDataImpl &Record);<br>
<br>
+ /// \brief Convert a path from this build process into one that is appropriate<br>
+ /// for emission in the module file.<br>
+ bool PreparePathForOutput(<u></u>SmallVectorImpl<char> &Path);<br>
+<br>
+ /// \brief Add a path to the given record.<br>
+ void AddPath(StringRef Path, RecordDataImpl &Record);<br>
+<br>
+ /// \brief Emit the current record with the given path as a blob.<br>
+ void EmitRecordWithPath(unsigned Abbrev, RecordDataImpl &Record,<br>
+ StringRef Path);<br>
+<br>
/// \brief Add a version tuple to the given record<br>
void AddVersionTuple(const VersionTuple &Version, RecordDataImpl &Record);<br>
<br>
<br>
Modified: cfe/trunk/include/clang/<u></u>Serialization/Module.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/Module.h?rev=223443&r1=223442&r2=223443&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/cfe/trunk/include/<u></u>clang/Serialization/Module.h?<u></u>rev=223443&r1=223442&r2=<u></u>223443&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- cfe/trunk/include/clang/<u></u>Serialization/Module.h (original)<br>
+++ cfe/trunk/include/clang/<u></u>Serialization/Module.h Thu Dec 4 20:33:27 2014<br>
@@ -125,6 +125,9 @@ public:<br>
/// \brief The name of the module.<br>
std::string ModuleName;<br>
<br>
+ /// \brief The base directory of the module.<br>
+ std::string BaseDirectory;<br>
+<br>
std::string getTimestampFilename() const {<br>
return FileName + ".timestamp";<br>
}<br>
<br>
Modified: cfe/trunk/lib/Serialization/<u></u>ASTReader.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=223443&r1=223442&r2=223443&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/cfe/trunk/lib/<u></u>Serialization/ASTReader.cpp?<u></u>rev=223443&r1=223442&r2=<u></u>223443&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- cfe/trunk/lib/Serialization/<u></u>ASTReader.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/<u></u>ASTReader.cpp Thu Dec 4 20:33:27 2014<br>
@@ -1029,7 +1029,7 @@ void ASTReader::Error(unsigned DiagID,<br>
/// \brief Read the line table in the source manager block.<br>
/// \returns true if there was an error.<br>
bool ASTReader::ParseLineTable(<u></u>ModuleFile &F,<br>
- SmallVectorImpl<uint64_t> &Record) {<br>
+ const RecordData &Record) {<br>
unsigned Idx = 0;<br>
LineTableInfo &LineTable = SourceMgr.getLineTable();<br>
<br>
@@ -1037,10 +1037,7 @@ bool ASTReader::ParseLineTable(<u></u>ModuleFil<br>
std::map<int, int> FileIDs;<br>
for (int I = 0, N = Record[Idx++]; I != N; ++I) {<br>
// Extract the file name<br>
- unsigned FilenameLen = Record[Idx++];<br>
- std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen);<br>
- Idx += FilenameLen;<br>
- MaybeAddSystemRootToFilename(<u></u>F, Filename);<br>
+ auto Filename = ReadPath(F, Record, Idx);<br>
FileIDs[I] = LineTable.<u></u>getLineTableFilenameID(<u></u>Filename);<br>
}<br>
<br>
@@ -1483,11 +1480,11 @@ ASTReader::<u></u>getGlobalPreprocessedEntityID<br>
unsigned HeaderFileInfoTrait::<u></u>ComputeHash(internal_key_ref ikey) {<br>
return llvm::hash_combine(ikey.Size, ikey.ModTime);<br>
}<br>
-<br>
+<br>
HeaderFileInfoTrait::internal_<u></u>key_type<br>
HeaderFileInfoTrait::<u></u>GetInternalKey(const FileEntry *FE) {<br>
internal_key_type ikey = { FE->getSize(), FE->getModificationTime(),<br>
- FE->getName() };<br>
+ FE->getName(), /*Imported*/false };<br>
return ikey;<br>
}<br>
<br>
@@ -1495,14 +1492,24 @@ bool HeaderFileInfoTrait::EqualKey(<u></u>inter<br>
if (a.Size != b.Size || a.ModTime != b.ModTime)<br>
return false;<br>
<br>
- if (strcmp(a.Filename, b.Filename) == 0)<br>
+ if (llvm::sys::path::is_absolute(<u></u>a.Filename) &&<br>
+ strcmp(a.Filename, b.Filename) == 0)<br>
return true;<br>
<br>
// Determine whether the actual files are equivalent.<br>
FileManager &FileMgr = Reader.getFileManager();<br>
- const FileEntry *FEA = FileMgr.getFile(a.Filename);<br>
- const FileEntry *FEB = FileMgr.getFile(b.Filename);<br>
- return (FEA && FEA == FEB);<br>
+ auto GetFile = [&](const internal_key_type &Key) -> const FileEntry* {<br>
+ if (!Key.Imported)<br>
+ return FileMgr.getFile(Key.Filename);<br>
+<br>
+ std::string Resolved = Key.Filename;<br>
+ Reader.ResolveImportedPath(M, Resolved);<br>
+ return FileMgr.getFile(Resolved);<br>
+ };<br>
+<br>
+ const FileEntry *FEA = GetFile(a);<br>
+ const FileEntry *FEB = GetFile(b);<br>
+ return FEA && FEA == FEB;<br>
}<br>
<br>
std::pair<unsigned, unsigned><br>
@@ -1520,6 +1527,7 @@ HeaderFileInfoTrait::ReadKey(<u></u>const unsig<br>
ikey.Size = off_t(endian::readNext<uint64_<u></u>t, little, unaligned>(d));<br>
ikey.ModTime = time_t(endian::readNext<<u></u>uint64_t, little, unaligned>(d));<br>
ikey.Filename = (const char *)d;<br>
+ ikey.Imported = true;<br>
return ikey;<br>
}<br>
<br>
@@ -1559,11 +1567,13 @@ HeaderFileInfoTrait::ReadData(<u></u>internal_k<br>
FileManager &FileMgr = Reader.getFileManager();<br>
ModuleMap &ModMap =<br>
Reader.getPreprocessor().<u></u>getHeaderSearchInfo().<u></u>getModuleMap();<br>
- // FIXME: This is wrong. We should track the filename as written; this<br>
- // information should be propagated through the SUBMODULE_HEADER etc<br>
- // records rather than from here.<br>
+ // FIXME: This information should be propagated through the<br>
+ // SUBMODULE_HEADER etc records rather than from here.<br>
// FIXME: We don't ever mark excluded headers.<br>
- Module::Header H = { key.Filename, FileMgr.getFile(key.Filename) };<br>
+ std::string Filename = key.Filename;<br>
+ if (key.Imported)<br>
+ Reader.ResolveImportedPath(M, Filename);<br>
+ Module::Header H = { key.Filename, FileMgr.getFile(Filename) };<br>
ModMap.addHeader(Mod, H, HFI.getHeaderRole());<br>
}<br>
}<br>
@@ -2084,14 +2094,14 @@ ASTReader::readInputFileInfo(<u></u>ModuleFile<br>
off_t StoredSize;<br>
time_t StoredTime;<br>
bool Overridden;<br>
-<br>
+<br>
assert(Record[0] == ID && "Bogus stored ID or offset");<br>
StoredSize = static_cast<off_t>(Record[1]);<br>
StoredTime = static_cast<time_t>(Record[2])<u></u>;<br>
Overridden = static_cast<bool>(Record[3]);<br>
Filename = Blob;<br>
- MaybeAddSystemRootToFilename(<u></u>F, Filename);<br>
-<br>
+ ResolveImportedPath(F, Filename);<br>
+<br>
InputFileInfo R = { std::move(Filename), StoredSize, StoredTime, Overridden };<br>
return R;<br>
}<br>
@@ -2229,46 +2239,24 @@ InputFile ASTReader::getInputFile(Module<br>
return IF;<br>
}<br>
<br>
-const FileEntry *ASTReader::getFileEntry(<u></u>StringRef filenameStrRef) {<br>
- ModuleFile &M = ModuleMgr.getPrimaryModule();<br>
- std::string Filename = filenameStrRef;<br>
- MaybeAddSystemRootToFilename(<u></u>M, Filename);<br>
- const FileEntry *File = FileMgr.getFile(Filename);<br>
- if (File == nullptr && !M.OriginalDir.empty() && !CurrentDir.empty() &&<br>
- M.OriginalDir != CurrentDir) {<br>
- std::string resolved = resolveFileRelativeToOriginalD<u></u>ir(Filename,<br>
- M.OriginalDir,<br>
- CurrentDir);<br>
- if (!resolved.empty())<br>
- File = FileMgr.getFile(resolved);<br>
- }<br>
-<br>
- return File;<br>
+/// \brief If we are loading a relocatable PCH or module file, and the filename<br>
+/// is not an absolute path, add the system or module root to the beginning of<br>
+/// the file name.<br>
+void ASTReader::<u></u>ResolveImportedPath(ModuleFile &M, std::string &Filename) {<br>
+ // Resolve relative to the base directory, if we have one.<br>
+ if (!M.BaseDirectory.empty())<br>
+ return ResolveImportedPath(Filename, M.BaseDirectory);<br>
}<br>
<br>
-/// \brief If we are loading a relocatable PCH file, and the filename is<br>
-/// not an absolute path, add the system root to the beginning of the file<br>
-/// name.<br>
-void ASTReader::<u></u>MaybeAddSystemRootToFilename(<u></u>ModuleFile &M,<br>
- std::string &Filename) {<br>
- // If this is not a relocatable PCH file, there's nothing to do.<br>
- if (!M.RelocatablePCH)<br>
- return;<br>
-<br>
+void ASTReader::<u></u>ResolveImportedPath(std::<u></u>string &Filename, StringRef Prefix) {<br>
if (Filename.empty() || llvm::sys::path::is_absolute(<u></u>Filename))<br>
return;<br>
<br>
- if (isysroot.empty()) {<br>
- // If no system root was given, default to '/'<br>
- Filename.insert(Filename.<u></u>begin(), '/');<br>
- return;<br>
- }<br>
-<br>
- unsigned Length = isysroot.size();<br>
- if (isysroot[Length - 1] != '/')<br>
+ unsigned Length = Prefix.size();<br>
+ if (Prefix[Length - 1] != '/')<br>
Filename.insert(Filename.<u></u>begin(), '/');<br>
<br>
- Filename.insert(Filename.<u></u>begin(), isysroot.begin(), isysroot.end());<br>
+ Filename.insert(Filename.<u></u>begin(), Prefix.begin(), Prefix.end());</blockquote><div><br></div><div>Isn't that basically llvm::sys::path::append?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> </blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
}<br>
<br>
ASTReader::ASTReadResult<br>
@@ -2388,6 +2376,9 @@ ASTReader::ReadControlBlock(<u></u>ModuleFile &<br>
}<br>
<br>
F.RelocatablePCH = Record[4];<br>
+ // Relative paths in a relocatable PCH are relative to our sysroot.<br>
+ if (F.RelocatablePCH)<br>
+ F.BaseDirectory = isysroot.empty() ? "/" : isysroot;<br>
<br>
const std::string &CurBranch = getClangFullRepositoryVersion(<u></u>);<br>
StringRef ASTBranch = Blob;<br>
@@ -2418,10 +2409,7 @@ ASTReader::ReadControlBlock(<u></u>ModuleFile &<br>
off_t StoredSize = (off_t)Record[Idx++];<br>
time_t StoredModTime = (time_t)Record[Idx++];<br>
ASTFileSignature StoredSignature = Record[Idx++];<br>
- unsigned Length = Record[Idx++];<br>
- SmallString<128> ImportedFile(Record.begin() + Idx,<br>
- Record.begin() + Idx + Length);<br>
- Idx += Length;<br>
+ auto ImportedFile = ReadPath(F, Record, Idx);<br>
<br>
// Load the AST file.<br>
switch(ReadASTCore(<u></u>ImportedFile, ImportedKind, ImportLoc, &F, Loaded,<br>
@@ -2505,7 +2493,7 @@ ASTReader::ReadControlBlock(<u></u>ModuleFile &<br>
F.OriginalSourceFileID = FileID::get(Record[0]);<br>
F.ActualOriginalSourceFileName = Blob;<br>
F.OriginalSourceFileName = F.<u></u>ActualOriginalSourceFileName;<br>
- MaybeAddSystemRootToFilename(<u></u>F, F.OriginalSourceFileName);<br>
+ ResolveImportedPath(F, F.OriginalSourceFileName);<br>
break;<br>
<br>
case ORIGINAL_FILE_ID:<br>
@@ -2522,6 +2510,10 @@ ASTReader::ReadControlBlock(<u></u>ModuleFile &<br>
Listener->ReadModuleName(F.<u></u>ModuleName);<br>
break;<br>
<br>
+ case MODULE_DIRECTORY:<br>
+ F.BaseDirectory = Blob;<br>
+ break;<br>
+<br>
case MODULE_MAP_FILE:<br>
if (ASTReadResult Result =<br>
ReadModuleMapFileBlock(Record, F, ImportedBy, ClientLoadCapabilities))<br>
@@ -3342,7 +3334,7 @@ ASTReader::<u></u>ReadModuleMapFileBlock(Record<br>
const ModuleFile *ImportedBy,<br>
unsigned ClientLoadCapabilities) {<br>
unsigned Idx = 0;<br>
- F.ModuleMapPath = ReadString(Record, Idx);<br>
+ F.ModuleMapPath = ReadPath(F, Record, Idx);<br>
<br>
if (F.Kind == MK_ExplicitModule) {<br>
// For an explicitly-loaded module, we don't care whether the original<br>
@@ -3389,7 +3381,7 @@ ASTReader::<u></u>ReadModuleMapFileBlock(Record<br>
llvm::SmallPtrSet<const FileEntry *, 1> AdditionalStoredMaps;<br>
for (unsigned I = 0, N = Record[Idx++]; I < N; ++I) {<br>
// FIXME: we should use input files rather than storing names.<br>
- std::string Filename = ReadString(Record, Idx);<br>
+ std::string Filename = ReadPath(F, Record, Idx);<br>
const FileEntry *F =<br>
FileMgr.getFile(Filename, false, false);<br>
if (F == nullptr) {<br>
@@ -4256,6 +4248,7 @@ bool ASTReader::<u></u>readASTFileControlBlock(<br>
<br>
// Scan for ORIGINAL_FILE inside the control block.<br>
RecordData Record;<br>
+ std::string ModuleDir;<br>
while (1) {<br>
llvm::BitstreamEntry Entry = Stream.<u></u>advanceSkippingSubblocks();<br>
if (Entry.Kind == llvm::BitstreamEntry::<u></u>EndBlock)<br>
@@ -4280,9 +4273,14 @@ bool ASTReader::<u></u>readASTFileControlBlock(<br>
case MODULE_NAME:<br>
Listener.ReadModuleName(Blob);<br>
break;<br>
+ case MODULE_DIRECTORY:<br>
+ ModuleDir = Blob;<br>
+ break;<br>
case MODULE_MAP_FILE: {<br>
unsigned Idx = 0;<br>
- Listener.ReadModuleMapFile(<u></u>ReadString(Record, Idx));<br>
+ auto Path = ReadString(Record, Idx);<br>
+ ResolveImportedPath(Path, ModuleDir);<br>
+ Listener.ReadModuleMapFile(<u></u>Path);<br>
break;<br>
}<br>
case LANGUAGE_OPTIONS:<br>
@@ -4344,7 +4342,10 @@ bool ASTReader::<u></u>readASTFileControlBlock(<br>
switch ((InputFileRecordTypes)Cursor.<u></u>readRecord(Code, Record, &Blob)) {<br>
case INPUT_FILE:<br>
bool Overridden = static_cast<bool>(Record[3]);<br>
- shouldContinue = Listener.visitInputFile(Blob, isSystemFile, Overridden);<br>
+ std::string Filename = Blob;<br>
+ ResolveImportedPath(Filename, ModuleDir);<br>
+ shouldContinue =<br>
+ Listener.visitInputFile(<u></u>Filename, isSystemFile, Overridden);<br>
break;<br>
}<br>
if (!shouldContinue)<br>
@@ -4361,11 +4362,9 @@ bool ASTReader::<u></u>readASTFileControlBlock(<br>
while (Idx < N) {<br>
// Read information about the AST file.<br>
Idx += 5; // ImportLoc, Size, ModTime, Signature<br>
- unsigned Length = Record[Idx++];<br>
- SmallString<128> ImportedFile(Record.begin() + Idx,<br>
- Record.begin() + Idx + Length);<br>
- Idx += Length;<br>
- Listener.visitImport(<u></u>ImportedFile);<br>
+ std::string Filename = ReadString(Record, Idx);<br>
+ ResolveImportedPath(Filename, ModuleDir);<br>
+ Listener.visitImport(Filename)<u></u>;<br>
}<br>
break;<br>
}<br>
@@ -8050,6 +8049,13 @@ std::string ASTReader::ReadString(const<br>
return Result;<br>
}<br>
<br>
+std::string ASTReader::ReadPath(ModuleFile &F, const RecordData &Record,<br>
+ unsigned &Idx) {<br>
+ std::string Filename = ReadString(Record, Idx);<br>
+ ResolveImportedPath(F, Filename);<br>
+ return Filename;<br>
+}<br>
+<br>
VersionTuple ASTReader::ReadVersionTuple(<u></u>const RecordData &Record,<br>
unsigned &Idx) {<br>
unsigned Major = Record[Idx++];<br>
<br>
Modified: cfe/trunk/lib/Serialization/<u></u>ASTReaderInternals.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderInternals.h?rev=223443&r1=223442&r2=223443&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/cfe/trunk/lib/<u></u>Serialization/<u></u>ASTReaderInternals.h?rev=<u></u>223443&r1=223442&r2=223443&<u></u>view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- cfe/trunk/lib/Serialization/<u></u>ASTReaderInternals.h (original)<br>
+++ cfe/trunk/lib/Serialization/<u></u>ASTReaderInternals.h Thu Dec 4 20:33:27 2014<br>
@@ -194,8 +194,8 @@ typedef llvm::OnDiskChainedHashTable<<u></u>AST<br>
///<br>
/// The on-disk hash table contains a mapping from each header path to<br>
/// information about that header (how many times it has been included, its<br>
-/// controlling macro, etc.). Note that we actually hash based on the<br>
-/// filename, and support "deep" comparisons of file names based on current<br>
+/// controlling macro, etc.). Note that we actually hash based on the size<br>
+/// and mtime, and support "deep" comparisons of file names based on current<br>
/// inode numbers, so that the search can cope with non-normalized path names<br>
/// and symlinks.<br>
class HeaderFileInfoTrait {<br>
@@ -211,6 +211,7 @@ public:<br>
off_t Size;<br>
time_t ModTime;<br>
const char *Filename;<br>
+ bool Imported;<br>
};<br>
typedef const internal_key_type &internal_key_ref;<br>
<br>
<br>
Modified: cfe/trunk/lib/Serialization/<u></u>ASTWriter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=223443&r1=223442&r2=223443&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/cfe/trunk/lib/<u></u>Serialization/ASTWriter.cpp?<u></u>rev=223443&r1=223442&r2=<u></u>223443&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- cfe/trunk/lib/Serialization/<u></u>ASTWriter.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/<u></u>ASTWriter.cpp Thu Dec 4 20:33:27 2014<br>
@@ -1063,33 +1063,44 @@ void ASTWriter::<u></u>WriteBlockInfoBlock() {<br>
///<br>
/// \param Filename the file name to adjust.<br>
///<br>
-/// \param isysroot When non-NULL, the PCH file is a relocatable PCH file and<br>
-/// the returned filename will be adjusted by this system root.<br>
+/// \param BaseDir When non-NULL, the PCH file is a relocatable AST file and<br>
+/// the returned filename will be adjusted by this root directory.<br>
///<br>
/// \returns either the original filename (if it needs no adjustment) or the<br>
/// adjusted filename (which points into the @p Filename parameter).<br>
static const char *<br>
-<u></u>adjustFilenameForRelocatablePC<u></u>H(const char *Filename, StringRef isysroot) {<br>
+<u></u>adjustFilenameForRelocatableAS<u></u>T(const char *Filename, StringRef BaseDir) {<br>
assert(Filename && "No file name to adjust?");<br>
<br>
- if (isysroot.empty())<br>
+ if (BaseDir.empty())<br>
return Filename;<br>
<br>
// Verify that the filename and the system root have the same prefix.<br>
unsigned Pos = 0;<br>
- for (; Filename[Pos] && Pos < isysroot.size(); ++Pos)<br>
- if (Filename[Pos] != isysroot[Pos])<br>
+ for (; Filename[Pos] && Pos < BaseDir.size(); ++Pos)<br>
+ if (Filename[Pos] != BaseDir[Pos])<br>
return Filename; // Prefixes don't match.<br>
<br>
// We hit the end of the filename before we hit the end of the system root.<br>
if (!Filename[Pos])<br>
return Filename;<br>
<br>
- // If the file name has a '/' at the current position, skip over the '/'.<br>
- // We distinguish sysroot-based includes from absolute includes by the<br>
- // absence of '/' at the beginning of sysroot-based includes.<br>
- if (Filename[Pos] == '/')<br>
+ // If there's not a path separator at the end of the base directory nor<br>
+ // immediately after it, then this isn't within the base directory.<br>
+ if (!llvm::sys::path::is_<u></u>separator(Filename[Pos])) {<br>
+ if (!llvm::sys::path::is_<u></u>separator(BaseDir.back()))<br>
+ return Filename;<br>
+ } else {<br>
+ // If the file name has a '/' at the current position, skip over the '/'.<br>
+ // We distinguish relative paths from absolute paths by the<br>
+ // absence of '/' at the beginning of relative paths.<br>
+ //<br>
+ // FIXME: This is wrong. We distinguish them by asking if the path is<br>
+ // absolute, which isn't the same thing. And there might be multiple '/'s<br>
+ // in a row. Use a better mechanism to indicate whether we have emitted an<br>
+ // absolute or relative path.<br>
++Pos;<br>
+ }<br>
<br>
return Filename + Pos;<br>
}<br>
@@ -1126,6 +1137,8 @@ void ASTWriter::WriteControlBlock(<u></u>Prepro<br>
Record.push_back(VERSION_<u></u>MINOR);<br>
Record.push_back(CLANG_<u></u>VERSION_MAJOR);<br>
Record.push_back(CLANG_<u></u>VERSION_MINOR);<br>
+ assert((!WritingModule || isysroot.empty()) &&<br>
+ "writing module as a relocatable PCH?");<br>
Record.push_back(!isysroot.<u></u>empty());<br>
Record.push_back(<u></u>ASTHasCompilerErrors);<br>
Stream.EmitRecordWithBlob(<u></u>MetadataAbbrevCode, Record,<br>
@@ -1136,8 +1149,8 @@ void ASTWriter::WriteControlBlock(<u></u>Prepro<br>
Record.push_back(getSignature(<u></u>));<br>
Stream.EmitRecord(SIGNATURE, Record);<br>
<br>
- // Module name<br>
if (WritingModule) {<br>
+ // Module name<br>
BitCodeAbbrev *Abbrev = new BitCodeAbbrev();<br>
Abbrev->Add(BitCodeAbbrevOp(<u></u>MODULE_NAME));<br>
Abbrev->Add(BitCodeAbbrevOp(<u></u>BitCodeAbbrevOp::Blob)); // Name<br>
@@ -1147,25 +1160,42 @@ void ASTWriter::WriteControlBlock(<u></u>Prepro<br>
Stream.EmitRecordWithBlob(<u></u>AbbrevCode, Record, WritingModule->Name);<br>
}<br>
<br>
+ if (WritingModule && WritingModule->Directory) {<br>
+ // Module directory.<br>
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();<br>
+ Abbrev->Add(BitCodeAbbrevOp(<u></u>MODULE_DIRECTORY));<br>
+ Abbrev->Add(BitCodeAbbrevOp(<u></u>BitCodeAbbrevOp::Blob)); // Directory<br>
+ unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev);<br>
+ RecordData Record;<br>
+ Record.push_back(MODULE_<u></u>DIRECTORY);<br>
+<br>
+ SmallString<128> BaseDir(WritingModule-><u></u>Directory->getName());<br>
+ Context.getSourceManager().<u></u>getFileManager().<u></u>FixupRelativePath(BaseDir);<br>
+ llvm::sys::fs::make_absolute(<u></u>BaseDir);<br>
+ Stream.EmitRecordWithBlob(<u></u>AbbrevCode, Record, BaseDir);<br>
+<br>
+ // Write out all other paths relative to the base directory if possible.<br>
+ BaseDirectory.assign(BaseDir.<u></u>begin(), BaseDir.end());<br>
+ } else if (!isysroot.empty()) {<br>
+ // Write out paths relative to the sysroot if possible.<br>
+ BaseDirectory = isysroot;<br>
+ }<br>
+<br>
// Module map file<br>
if (WritingModule) {<br>
Record.clear();<br>
- auto addModMap = [&](const FileEntry *F) {<br>
- SmallString<128> ModuleMap(F->getName());<br>
- llvm::sys::fs::make_absolute(<u></u>ModuleMap);<br>
- AddString(ModuleMap.str(), Record);<br>
- };<br>
<br>
auto &Map = PP.getHeaderSearchInfo().<u></u>getModuleMap();<br>
<br>
// Primary module map file.<br>
- addModMap(Map.<u></u>getModuleMapFileForUniquing(<u></u>WritingModule));<br>
+ AddPath(Map.<u></u>getModuleMapFileForUniquing(<u></u>WritingModule)->getName(), Record);<br>
<br>
// Additional module map files.<br>
- if (auto *AdditionalModMaps = Map.<u></u>getAdditionalModuleMapFiles(<u></u>WritingModule)) {<br>
+ if (auto *AdditionalModMaps =<br>
+ Map.<u></u>getAdditionalModuleMapFiles(<u></u>WritingModule)) {<br>
Record.push_back(<u></u>AdditionalModMaps->size());<br>
for (const FileEntry *F : *AdditionalModMaps)<br>
- addModMap(F);<br>
+ AddPath(F->getName(), Record);<br>
} else {<br>
Record.push_back(0);<br>
}<br>
@@ -1189,9 +1219,7 @@ void ASTWriter::WriteControlBlock(<u></u>Prepro<br>
Record.push_back((*M)->File-><u></u>getSize());<br>
Record.push_back((*M)->File-><u></u>getModificationTime());<br>
Record.push_back((*M)-><u></u>Signature);<br>
- const std::string &FileName = (*M)->FileName;<br>
- Record.push_back(FileName.<u></u>size());<br>
- Record.append(FileName.begin()<u></u>, FileName.end());<br>
+ AddPath((*M)->FileName, Record);<br>
}<br>
Stream.EmitRecord(IMPORTS, Record);<br>
}<br>
@@ -1339,17 +1367,10 @@ void ASTWriter::WriteControlBlock(<u></u>Prepro<br>
FileAbbrev->Add(<u></u>BitCodeAbbrevOp(<u></u>BitCodeAbbrevOp::Blob)); // File name<br>
unsigned FileAbbrevCode = Stream.EmitAbbrev(FileAbbrev);<br>
<br>
- SmallString<128> MainFilePath(MainFile-><u></u>getName());<br>
-<br>
- llvm::sys::fs::make_absolute(<u></u>MainFilePath);<br>
-<br>
- const char *MainFileNameStr = MainFilePath.c_str();<br>
- MainFileNameStr = adjustFilenameForRelocatablePC<u></u>H(MainFileNameStr,<br>
- isysroot);<br>
Record.clear();<br>
Record.push_back(ORIGINAL_<u></u>FILE);<br>
Record.push_back(SM.<u></u>getMainFileID().<u></u>getOpaqueValue());<br>
- Stream.EmitRecordWithBlob(<u></u>FileAbbrevCode, Record, MainFileNameStr);<br>
+ EmitRecordWithPath(<u></u>FileAbbrevCode, Record, MainFile->getName());<br>
}<br>
<br>
Record.clear();<br>
@@ -1375,7 +1396,6 @@ void ASTWriter::WriteControlBlock(<u></u>Prepro<br>
<br>
WriteInputFiles(Context.<u></u>SourceMgr,<br>
PP.getHeaderSearchInfo().<u></u>getHeaderSearchOpts(),<br>
- isysroot,<br>
PP.getLangOpts().Modules);<br>
Stream.ExitBlock();<br>
}<br>
@@ -1391,7 +1411,6 @@ namespace {<br>
<br>
void ASTWriter::WriteInputFiles(<u></u>SourceManager &SourceMgr,<br>
HeaderSearchOptions &HSOpts,<br>
- StringRef isysroot,<br>
bool Modules) {<br>
using namespace llvm;<br>
Stream.EnterSubblock(INPUT_<u></u>FILES_BLOCK_ID, 4);<br>
@@ -1462,23 +1481,8 @@ void ASTWriter::WriteInputFiles(<u></u>SourceMa<br>
// Whether this file was overridden.<br>
Record.push_back(Entry.<u></u>BufferOverridden);<br>
<br>
- // Turn the file name into an absolute path, if it isn't already.<br>
- const char *Filename = Entry.File->getName();<br>
- SmallString<128> FilePath(Filename);<br>
-<br>
- // Ask the file manager to fixup the relative path for us. This will<br>
- // honor the working directory.<br>
- SourceMgr.getFileManager().<u></u>FixupRelativePath(FilePath);<br>
-<br>
- // FIXME: This call to make_absolute shouldn't be necessary, the<br>
- // call to FixupRelativePath should always return an absolute path.<br>
- llvm::sys::fs::make_absolute(<u></u>FilePath);<br>
- Filename = FilePath.c_str();<br>
-<br>
- Filename = adjustFilenameForRelocatablePC<u></u>H(Filename, isysroot);<br>
-<br>
- Stream.EmitRecordWithBlob(<u></u>IFAbbrevCode, Record, Filename);<br>
- }<br>
+ EmitRecordWithPath(<u></u>IFAbbrevCode, Record, Entry.File->getName());<br>
+ }<br>
<br>
Stream.ExitBlock();<br>
<br>
@@ -1588,6 +1592,9 @@ namespace {<br>
// The hash is based only on size/time of the file, so that the reader can<br>
// match even when symlinking or excess path elements ("foo/../", "../")<br>
// change the form of the name. However, complete path is still the key.<br>
+ //<br>
+ // FIXME: Using the mtime here will cause problems for explicit module<br>
+ // imports.<br>
return llvm::hash_combine(key.FE-><u></u>getSize(),<br>
key.FE->getModificationTime())<u></u>;<br>
}<br>
@@ -1668,7 +1675,7 @@ namespace {<br>
/// \brief Write the header search block for the list of files that<br>
///<br>
/// \param HS The header search structure to save.<br>
-void ASTWriter::WriteHeaderSearch(<u></u>const HeaderSearch &HS, StringRef isysroot) {<br>
+void ASTWriter::WriteHeaderSearch(<u></u>const HeaderSearch &HS) {<br>
SmallVector<const FileEntry *, 16> FilesByUID;<br>
HS.getFileMgr().<u></u>GetUniqueIDMapping(FilesByUID)<u></u>;<br>
<br>
@@ -1692,17 +1699,16 @@ void ASTWriter::WriteHeaderSearch(<u></u>const<br>
(HFI.isModuleHeader && !HFI.isCompilingModuleHeader))<br>
continue;<br>
<br>
- // Turn the file name into an absolute path, if it isn't already.<br>
+ // Massage the file path into an appropriate form.<br>
const char *Filename = File->getName();<br>
- Filename = adjustFilenameForRelocatablePC<u></u>H(Filename, isysroot);<br>
-<br>
- // If we performed any translation on the file name at all, we need to<br>
- // save this string, since the generator will refer to it later.<br>
- if (Filename != File->getName()) {<br>
- Filename = strdup(Filename);<br>
+ SmallString<128> FilenameTmp(Filename);<br>
+ if (PreparePathForOutput(<u></u>FilenameTmp)) {<br>
+ // If we performed any translation on the file name at all, we need to<br>
+ // save this string, since the generator will refer to it later.<br>
+ Filename = strdup(FilenameTmp.c_str());<br>
SavedStrings.push_back(<u></u>Filename);<br>
}<br>
-<br>
+<br>
HeaderFileInfoTrait::key_type key = { File, Filename };<br>
Generator.insert(key, HFI, GeneratorTrait);<br>
++NumHeaderSearchEntries;<br>
@@ -1752,8 +1758,7 @@ void ASTWriter::WriteHeaderSearch(<u></u>const<br>
/// errors), we probably won't have to create file entries for any of<br>
/// the files in the AST.<br>
void ASTWriter::<u></u>WriteSourceManagerBlock(<u></u>SourceManager &SourceMgr,<br>
- const Preprocessor &PP,<br>
- StringRef isysroot) {<br>
+ const Preprocessor &PP) {<br>
RecordData Record;<br>
<br>
// Enter the source manager block.<br>
@@ -1902,17 +1907,10 @@ void ASTWriter::<u></u>WriteSourceManagerBlock(<br>
LineTableInfo &LineTable = SourceMgr.getLineTable();<br>
<br>
Record.clear();<br>
- // Emit the file names<br>
+ // Emit the file names.<br>
Record.push_back(LineTable.<u></u>getNumFilenames());<br>
- for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I) {<br>
- // Emit the file name<br>
- const char *Filename = LineTable.getFilename(I);<br>
- Filename = adjustFilenameForRelocatablePC<u></u>H(Filename, isysroot);<br>
- unsigned FilenameLen = Filename? strlen(Filename) : 0;<br>
- Record.push_back(FilenameLen);<br>
- if (FilenameLen)<br>
- Record.insert(Record.end(), Filename, Filename + FilenameLen);<br>
- }<br>
+ for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I)<br>
+ AddPath(LineTable.getFilename(<u></u>I), Record);<br>
<br>
// Emit the line entries<br>
for (LineTableInfo::iterator L = LineTable.begin(), LEnd = LineTable.end();<br>
@@ -2543,7 +2541,7 @@ void ASTWriter::WriteSubmodules(<u></u>Module *<br>
Record.clear();<br>
for (unsigned I = 0, N = Mod->Imports.size(); I != N; ++I) {<br>
unsigned ImportedID = getSubmoduleID(Mod->Imports[I]<u></u>);<br>
- assert(ImportedID && "Unknown submodule!");<br>
+ assert(ImportedID && "Unknown submodule!");<br>
Record.push_back(ImportedID);<br>
}<br>
Stream.EmitRecord(SUBMODULE_<u></u>IMPORTS, Record);<br>
@@ -4077,6 +4075,47 @@ void ASTWriter::AddString(StringRef Str,<br>
Record.insert(Record.end(), Str.begin(), Str.end());<br>
}<br>
<br>
+bool ASTWriter::<u></u>PreparePathForOutput(<u></u>SmallVectorImpl<char> &Path) {<br>
+ bool Changed = false;<br>
+<br>
+ if (!llvm::sys::path::is_<u></u>absolute(StringRef(Path.data()<u></u>, Path.size()))) {<br>
+ // Ask the file manager to fixup the relative path for us. This will<br>
+ // honor the working directory.<br>
+ if (Context)<br>
+ Context->getSourceManager().<u></u>getFileManager().<u></u>FixupRelativePath(Path);<br>
+<br>
+ // We want an absolute path even if we weren't given a spelling for the<br>
+ // current working directory.<br>
+ llvm::sys::fs::make_absolute(<u></u>Path);<br>
+<br>
+ Changed = true;<br>
+ }<br>
+<br>
+ // Remove a prefix to make the path relative, if relevant.<br>
+ const char *PathBegin = Path.data();<br>
+ const char *PathPtr =<br>
+ adjustFilenameForRelocatableAS<u></u>T(PathBegin, BaseDirectory);<br>
+ if (PathPtr != PathBegin) {<br>
+ Path.erase(Path.begin(), Path.begin() + (PathPtr - PathBegin));<br>
+ Changed = true;<br>
+ }<br>
+<br>
+ return Changed;<br>
+}<br>
+<br>
+void ASTWriter::AddPath(StringRef Path, RecordDataImpl &Record) {<br>
+ SmallString<128> FilePath(Path);<br>
+ PreparePathForOutput(FilePath)<u></u>;<br>
+ AddString(FilePath, Record);<br>
+}<br>
+<br>
+void ASTWriter::EmitRecordWithPath(<u></u>unsigned Abbrev, RecordDataImpl &Record,<br>
+ StringRef Path) {<br>
+ SmallString<128> FilePath(Path);<br>
+ PreparePathForOutput(FilePath)<u></u>;<br>
+ Stream.EmitRecordWithBlob(<u></u>Abbrev, Record, FilePath);<br>
+}<br>
+<br>
void ASTWriter::AddVersionTuple(<u></u>const VersionTuple &Version,<br>
RecordDataImpl &Record) {<br>
Record.push_back(Version.<u></u>getMajor());<br>
@@ -4161,6 +4200,7 @@ void ASTWriter::WriteAST(Sema &SemaRef,<br>
Context = nullptr;<br>
PP = nullptr;<br>
this->WritingModule = nullptr;<br>
+ this->BaseDirectory.clear();<br>
<br>
WritingAST = false;<br>
}<br>
@@ -4551,11 +4591,11 @@ void ASTWriter::WriteASTCore(Sema &SemaR<br>
Stream.EmitRecord(DECL_UPDATE_<u></u>OFFSETS, DeclUpdatesOffsetsRecord);<br>
WriteCXXBaseSpecifiersOffsets(<u></u>);<br>
WriteFileDeclIDsMap();<br>
- WriteSourceManagerBlock(<u></u>Context.getSourceManager(), PP, isysroot);<br>
+ WriteSourceManagerBlock(<u></u>Context.getSourceManager(), PP);<br>
<br>
WriteComments();<br>
WritePreprocessor(PP, isModule);<br>
- WriteHeaderSearch(PP.<u></u>getHeaderSearchInfo(), isysroot);<br>
+ WriteHeaderSearch(PP.<u></u>getHeaderSearchInfo());<br>
WriteSelectors(SemaRef);<br>
WriteReferencedSelectorsPool(<u></u>SemaRef);<br>
WriteIdentifierTable(PP, SemaRef.IdResolver, isModule);<br>
<br>
<br>
______________________________<u></u>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu" target="_blank">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/<u></u>mailman/listinfo/cfe-commits</a><br>
</blockquote></div>