MODULE_MAP_FILE = 14,
/// \brief Record code for the signature that identifiers this AST file.
- SIGNATURE = 15
+ SIGNATURE = 15,
+
+ /// \brief Record code for the module build directory.
+ MODULE_DIRECTORY = 16,
};
/// \brief Record types that occur within the input-files block
serialization::InputFile getInputFile(ModuleFile &F, unsigned ID,
bool Complain = true);
- /// \brief Get a FileEntry out of stored-in-PCH filename, making sure we take
- /// into account all the necessary relocations.
- const FileEntry *getFileEntry(StringRef filename);
-
- void MaybeAddSystemRootToFilename(ModuleFile &M, std::string &Filename);
+public:
+ void ResolveImportedPath(ModuleFile &M, std::string &Filename);
+ static void ResolveImportedPath(std::string &Filename, StringRef Prefix);
+private:
struct ImportedModule {
ModuleFile *Mod;
ModuleFile *ImportedBy;
const ModuleFile *ImportedBy,
unsigned ClientLoadCapabilities);
ASTReadResult ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities);
- bool ParseLineTable(ModuleFile &F, SmallVectorImpl<uint64_t> &Record);
+ bool ParseLineTable(ModuleFile &F, const RecordData &Record);
bool ReadSourceManagerBlock(ModuleFile &F);
llvm::BitstreamCursor &SLocCursorForID(int ID);
SourceLocation getImportLocation(ModuleFile *F);
// \brief Read a string
static std::string ReadString(const RecordData &Record, unsigned &Idx);
+ // \brief Read a path
+ std::string ReadPath(ModuleFile &F, const RecordData &Record, unsigned &Idx);
+
/// \brief Read a version tuple.
static VersionTuple ReadVersionTuple(const RecordData &Record, unsigned &Idx);
/// \brief The module we're currently writing, if any.
Module *WritingModule;
-
+
+ /// \brief The base directory for any relative paths we emit.
+ std::string BaseDirectory;
+
/// \brief Indicates when the AST writing is actively performing
/// serialization, rather than just queueing updates.
bool WritingAST;
StringRef isysroot, const std::string &OutputFile);
void WriteInputFiles(SourceManager &SourceMgr,
HeaderSearchOptions &HSOpts,
- StringRef isysroot,
bool Modules);
void WriteSourceManagerBlock(SourceManager &SourceMgr,
- const Preprocessor &PP,
- StringRef isysroot);
+ const Preprocessor &PP);
void WritePreprocessor(const Preprocessor &PP, bool IsModule);
- void WriteHeaderSearch(const HeaderSearch &HS, StringRef isysroot);
+ void WriteHeaderSearch(const HeaderSearch &HS);
void WritePreprocessorDetail(PreprocessingRecord &PPRec);
void WriteSubmodules(Module *WritingModule);
/// writing a precompiled header.
///
/// \param isysroot if non-empty, write a relocatable file whose headers
- /// are relative to the given system root.
+ /// are relative to the given system root. If we're writing a module, its
+ /// build directory will be used in preference to this if both are available.
void WriteAST(Sema &SemaRef,
const std::string &OutputFile,
Module *WritingModule, StringRef isysroot,
/// \brief Add a string to the given record.
void AddString(StringRef Str, RecordDataImpl &Record);
+ /// \brief Convert a path from this build process into one that is appropriate
+ /// for emission in the module file.
+ bool PreparePathForOutput(SmallVectorImpl<char> &Path);
+
+ /// \brief Add a path to the given record.
+ void AddPath(StringRef Path, RecordDataImpl &Record);
+
+ /// \brief Emit the current record with the given path as a blob.
+ void EmitRecordWithPath(unsigned Abbrev, RecordDataImpl &Record,
+ StringRef Path);
+
/// \brief Add a version tuple to the given record
void AddVersionTuple(const VersionTuple &Version, RecordDataImpl &Record);
/// \brief The name of the module.
std::string ModuleName;
+ /// \brief The base directory of the module.
+ std::string BaseDirectory;
+
std::string getTimestampFilename() const {
return FileName + ".timestamp";
}
/// \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();
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);
}
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;
}
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>
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;
}
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());
}
}
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;
}
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] != '/')
- Filename.insert(Filename.begin(), '/');
-
- Filename.insert(Filename.begin(), isysroot.begin(), isysroot.end());
+ SmallString<128> Buffer;
+ llvm::sys::path::append(Buffer, Prefix, Filename);
+ Filename.assign(Buffer.begin(), Buffer.end());
}
ASTReader::ASTReadResult
}
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;
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,
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:
Listener->ReadModuleName(F.ModuleName);
break;
+ case MODULE_DIRECTORY:
+ F.BaseDirectory = Blob;
+ break;
+
case MODULE_MAP_FILE:
if (ASTReadResult Result =
ReadModuleMapFileBlock(Record, F, ImportedBy, ClientLoadCapabilities))
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
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) {
// 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)
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:
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)
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;
}
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++];
///
/// The on-disk hash table contains a mapping from each header path to
/// information about that header (how many times it has been included, its
-/// controlling macro, etc.). Note that we actually hash based on the
-/// filename, and support "deep" comparisons of file names based on current
+/// controlling macro, etc.). Note that we actually hash based on the size
+/// and mtime, and support "deep" comparisons of file names based on current
/// inode numbers, so that the search can cope with non-normalized path names
/// and symlinks.
class HeaderFileInfoTrait {
off_t Size;
time_t ModTime;
const char *Filename;
+ bool Imported;
};
typedef const internal_key_type &internal_key_ref;
///
/// \param Filename the file name to adjust.
///
-/// \param isysroot When non-NULL, the PCH file is a relocatable PCH file and
-/// the returned filename will be adjusted by this system root.
+/// \param BaseDir When non-NULL, the PCH file is a relocatable AST file and
+/// the returned filename will be adjusted by this root directory.
///
/// \returns either the original filename (if it needs no adjustment) or the
/// adjusted filename (which points into the @p Filename parameter).
static const char *
-adjustFilenameForRelocatablePCH(const char *Filename, StringRef isysroot) {
+adjustFilenameForRelocatableAST(const char *Filename, StringRef BaseDir) {
assert(Filename && "No file name to adjust?");
- if (isysroot.empty())
+ if (BaseDir.empty())
return Filename;
// Verify that the filename and the system root have the same prefix.
unsigned Pos = 0;
- for (; Filename[Pos] && Pos < isysroot.size(); ++Pos)
- if (Filename[Pos] != isysroot[Pos])
+ for (; Filename[Pos] && Pos < BaseDir.size(); ++Pos)
+ if (Filename[Pos] != BaseDir[Pos])
return Filename; // Prefixes don't match.
// We hit the end of the filename before we hit the end of the system root.
if (!Filename[Pos])
return Filename;
- // If the file name has a '/' at the current position, skip over the '/'.
- // We distinguish sysroot-based includes from absolute includes by the
- // absence of '/' at the beginning of sysroot-based includes.
- if (Filename[Pos] == '/')
+ // If there's not a path separator at the end of the base directory nor
+ // immediately after it, then this isn't within the base directory.
+ if (!llvm::sys::path::is_separator(Filename[Pos])) {
+ if (!llvm::sys::path::is_separator(BaseDir.back()))
+ return Filename;
+ } else {
+ // If the file name has a '/' at the current position, skip over the '/'.
+ // We distinguish relative paths from absolute paths by the
+ // absence of '/' at the beginning of relative paths.
+ //
+ // FIXME: This is wrong. We distinguish them by asking if the path is
+ // absolute, which isn't the same thing. And there might be multiple '/'s
+ // in a row. Use a better mechanism to indicate whether we have emitted an
+ // absolute or relative path.
++Pos;
+ }
return Filename + Pos;
}
Record.push_back(VERSION_MINOR);
Record.push_back(CLANG_VERSION_MAJOR);
Record.push_back(CLANG_VERSION_MINOR);
+ assert((!WritingModule || isysroot.empty()) &&
+ "writing module as a relocatable PCH?");
Record.push_back(!isysroot.empty());
Record.push_back(ASTHasCompilerErrors);
Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record,
Record.push_back(getSignature());
Stream.EmitRecord(SIGNATURE, Record);
- // Module name
if (WritingModule) {
+ // Module name
BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(MODULE_NAME));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
Stream.EmitRecordWithBlob(AbbrevCode, Record, WritingModule->Name);
}
+ if (WritingModule && WritingModule->Directory) {
+ // Module directory.
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(MODULE_DIRECTORY));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Directory
+ unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev);
+ RecordData Record;
+ Record.push_back(MODULE_DIRECTORY);
+
+ SmallString<128> BaseDir(WritingModule->Directory->getName());
+ Context.getSourceManager().getFileManager().FixupRelativePath(BaseDir);
+ llvm::sys::fs::make_absolute(BaseDir);
+ Stream.EmitRecordWithBlob(AbbrevCode, Record, BaseDir);
+
+ // Write out all other paths relative to the base directory if possible.
+ BaseDirectory.assign(BaseDir.begin(), BaseDir.end());
+ } else if (!isysroot.empty()) {
+ // Write out paths relative to the sysroot if possible.
+ BaseDirectory = isysroot;
+ }
+
// Module map file
if (WritingModule) {
Record.clear();
- auto addModMap = [&](const FileEntry *F) {
- SmallString<128> ModuleMap(F->getName());
- llvm::sys::fs::make_absolute(ModuleMap);
- AddString(ModuleMap.str(), Record);
- };
auto &Map = PP.getHeaderSearchInfo().getModuleMap();
// Primary module map file.
- addModMap(Map.getModuleMapFileForUniquing(WritingModule));
+ AddPath(Map.getModuleMapFileForUniquing(WritingModule)->getName(), Record);
// Additional module map files.
- if (auto *AdditionalModMaps = Map.getAdditionalModuleMapFiles(WritingModule)) {
+ if (auto *AdditionalModMaps =
+ Map.getAdditionalModuleMapFiles(WritingModule)) {
Record.push_back(AdditionalModMaps->size());
for (const FileEntry *F : *AdditionalModMaps)
- addModMap(F);
+ AddPath(F->getName(), Record);
} else {
Record.push_back(0);
}
Record.push_back((*M)->File->getSize());
Record.push_back((*M)->File->getModificationTime());
Record.push_back((*M)->Signature);
- const std::string &FileName = (*M)->FileName;
- Record.push_back(FileName.size());
- Record.append(FileName.begin(), FileName.end());
+ AddPath((*M)->FileName, Record);
}
Stream.EmitRecord(IMPORTS, Record);
}
FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
unsigned FileAbbrevCode = Stream.EmitAbbrev(FileAbbrev);
- SmallString<128> MainFilePath(MainFile->getName());
-
- llvm::sys::fs::make_absolute(MainFilePath);
-
- const char *MainFileNameStr = MainFilePath.c_str();
- MainFileNameStr = adjustFilenameForRelocatablePCH(MainFileNameStr,
- isysroot);
Record.clear();
Record.push_back(ORIGINAL_FILE);
Record.push_back(SM.getMainFileID().getOpaqueValue());
- Stream.EmitRecordWithBlob(FileAbbrevCode, Record, MainFileNameStr);
+ EmitRecordWithPath(FileAbbrevCode, Record, MainFile->getName());
}
Record.clear();
WriteInputFiles(Context.SourceMgr,
PP.getHeaderSearchInfo().getHeaderSearchOpts(),
- isysroot,
PP.getLangOpts().Modules);
Stream.ExitBlock();
}
void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
HeaderSearchOptions &HSOpts,
- StringRef isysroot,
bool Modules) {
using namespace llvm;
Stream.EnterSubblock(INPUT_FILES_BLOCK_ID, 4);
// Whether this file was overridden.
Record.push_back(Entry.BufferOverridden);
- // Turn the file name into an absolute path, if it isn't already.
- const char *Filename = Entry.File->getName();
- SmallString<128> FilePath(Filename);
-
- // Ask the file manager to fixup the relative path for us. This will
- // honor the working directory.
- SourceMgr.getFileManager().FixupRelativePath(FilePath);
-
- // FIXME: This call to make_absolute shouldn't be necessary, the
- // call to FixupRelativePath should always return an absolute path.
- llvm::sys::fs::make_absolute(FilePath);
- Filename = FilePath.c_str();
-
- Filename = adjustFilenameForRelocatablePCH(Filename, isysroot);
-
- Stream.EmitRecordWithBlob(IFAbbrevCode, Record, Filename);
- }
+ EmitRecordWithPath(IFAbbrevCode, Record, Entry.File->getName());
+ }
Stream.ExitBlock();
// The hash is based only on size/time of the file, so that the reader can
// match even when symlinking or excess path elements ("foo/../", "../")
// change the form of the name. However, complete path is still the key.
+ //
+ // FIXME: Using the mtime here will cause problems for explicit module
+ // imports.
return llvm::hash_combine(key.FE->getSize(),
key.FE->getModificationTime());
}
/// \brief Write the header search block for the list of files that
///
/// \param HS The header search structure to save.
-void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS, StringRef isysroot) {
+void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {
SmallVector<const FileEntry *, 16> FilesByUID;
HS.getFileMgr().GetUniqueIDMapping(FilesByUID);
(HFI.isModuleHeader && !HFI.isCompilingModuleHeader))
continue;
- // Turn the file name into an absolute path, if it isn't already.
+ // Massage the file path into an appropriate form.
const char *Filename = File->getName();
- Filename = adjustFilenameForRelocatablePCH(Filename, isysroot);
-
- // If we performed any translation on the file name at all, we need to
- // save this string, since the generator will refer to it later.
- if (Filename != File->getName()) {
- Filename = strdup(Filename);
+ SmallString<128> FilenameTmp(Filename);
+ if (PreparePathForOutput(FilenameTmp)) {
+ // If we performed any translation on the file name at all, we need to
+ // save this string, since the generator will refer to it later.
+ Filename = strdup(FilenameTmp.c_str());
SavedStrings.push_back(Filename);
}
-
+
HeaderFileInfoTrait::key_type key = { File, Filename };
Generator.insert(key, HFI, GeneratorTrait);
++NumHeaderSearchEntries;
/// errors), we probably won't have to create file entries for any of
/// the files in the AST.
void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
- const Preprocessor &PP,
- StringRef isysroot) {
+ const Preprocessor &PP) {
RecordData Record;
// Enter the source manager block.
LineTableInfo &LineTable = SourceMgr.getLineTable();
Record.clear();
- // Emit the file names
+ // Emit the file names.
Record.push_back(LineTable.getNumFilenames());
- for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I) {
- // Emit the file name
- const char *Filename = LineTable.getFilename(I);
- Filename = adjustFilenameForRelocatablePCH(Filename, isysroot);
- unsigned FilenameLen = Filename? strlen(Filename) : 0;
- Record.push_back(FilenameLen);
- if (FilenameLen)
- Record.insert(Record.end(), Filename, Filename + FilenameLen);
- }
+ for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I)
+ AddPath(LineTable.getFilename(I), Record);
// Emit the line entries
for (LineTableInfo::iterator L = LineTable.begin(), LEnd = LineTable.end();
Record.clear();
for (unsigned I = 0, N = Mod->Imports.size(); I != N; ++I) {
unsigned ImportedID = getSubmoduleID(Mod->Imports[I]);
- assert(ImportedID && "Unknown submodule!");
+ assert(ImportedID && "Unknown submodule!");
Record.push_back(ImportedID);
}
Stream.EmitRecord(SUBMODULE_IMPORTS, Record);
Record.insert(Record.end(), Str.begin(), Str.end());
}
+bool ASTWriter::PreparePathForOutput(SmallVectorImpl<char> &Path) {
+ bool Changed = false;
+
+ if (!llvm::sys::path::is_absolute(StringRef(Path.data(), Path.size()))) {
+ // Ask the file manager to fixup the relative path for us. This will
+ // honor the working directory.
+ if (Context)
+ Context->getSourceManager().getFileManager().FixupRelativePath(Path);
+
+ // We want an absolute path even if we weren't given a spelling for the
+ // current working directory.
+ llvm::sys::fs::make_absolute(Path);
+
+ Changed = true;
+ }
+
+ // Remove a prefix to make the path relative, if relevant.
+ const char *PathBegin = Path.data();
+ const char *PathPtr =
+ adjustFilenameForRelocatableAST(PathBegin, BaseDirectory);
+ if (PathPtr != PathBegin) {
+ Path.erase(Path.begin(), Path.begin() + (PathPtr - PathBegin));
+ Changed = true;
+ }
+
+ return Changed;
+}
+
+void ASTWriter::AddPath(StringRef Path, RecordDataImpl &Record) {
+ SmallString<128> FilePath(Path);
+ PreparePathForOutput(FilePath);
+ AddString(FilePath, Record);
+}
+
+void ASTWriter::EmitRecordWithPath(unsigned Abbrev, RecordDataImpl &Record,
+ StringRef Path) {
+ SmallString<128> FilePath(Path);
+ PreparePathForOutput(FilePath);
+ Stream.EmitRecordWithBlob(Abbrev, Record, FilePath);
+}
+
void ASTWriter::AddVersionTuple(const VersionTuple &Version,
RecordDataImpl &Record) {
Record.push_back(Version.getMajor());
Context = nullptr;
PP = nullptr;
this->WritingModule = nullptr;
+ this->BaseDirectory.clear();
WritingAST = false;
}
Stream.EmitRecord(DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord);
WriteCXXBaseSpecifiersOffsets();
WriteFileDeclIDsMap();
- WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot);
+ WriteSourceManagerBlock(Context.getSourceManager(), PP);
WriteComments();
WritePreprocessor(PP, isModule);
- WriteHeaderSearch(PP.getHeaderSearchInfo(), isysroot);
+ WriteHeaderSearch(PP.getHeaderSearchInfo());
WriteSelectors(SemaRef);
WriteReferencedSelectorsPool(SemaRef);
WriteIdentifierTable(PP, SemaRef.IdResolver, isModule);