r245390 - [modules] Fix HeaderFileInfo serialization to store all the known owning modules for a header, not just the current favourite.
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Tue Aug 18 16:42:23 PDT 2015
Author: rsmith
Date: Tue Aug 18 18:42:23 2015
New Revision: 245390
URL: http://llvm.org/viewvc/llvm-project?rev=245390&view=rev
Log:
[modules] Fix HeaderFileInfo serialization to store all the known owning modules for a header, not just the current favourite.
Modified:
cfe/trunk/include/clang/Lex/HeaderSearch.h
cfe/trunk/include/clang/Lex/ModuleMap.h
cfe/trunk/include/clang/Serialization/ASTWriter.h
cfe/trunk/lib/Lex/HeaderSearch.cpp
cfe/trunk/lib/Lex/ModuleMap.cpp
cfe/trunk/lib/Serialization/ASTReader.cpp
cfe/trunk/lib/Serialization/ASTWriter.cpp
Modified: cfe/trunk/include/clang/Lex/HeaderSearch.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/HeaderSearch.h?rev=245390&r1=245389&r2=245390&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/HeaderSearch.h (original)
+++ cfe/trunk/include/clang/Lex/HeaderSearch.h Tue Aug 18 18:42:23 2015
@@ -49,7 +49,8 @@ struct HeaderFileInfo {
/// SrcMgr::CharacteristicKind.
unsigned DirInfo : 2;
- /// \brief Whether this header file info was supplied by an external source.
+ /// \brief Whether this header file info was supplied by an external source,
+ /// and has not changed since.
unsigned External : 1;
/// \brief Whether this header is part of a module.
@@ -58,10 +59,6 @@ struct HeaderFileInfo {
/// \brief Whether this header is part of the module that we are building.
unsigned isCompilingModuleHeader : 1;
- /// \brief Whether this header is part of the module that we are building.
- /// This is an instance of ModuleMap::ModuleHeaderRole.
- unsigned HeaderRole : 2;
-
/// \brief Whether this structure is considered to already have been
/// "resolved", meaning that it was loaded from the external source.
unsigned Resolved : 1;
@@ -75,7 +72,7 @@ struct HeaderFileInfo {
/// those framework headers.
unsigned IndexHeaderMapHeader : 1;
- /// \brief Whether this file had been looked up as a header.
+ /// \brief Whether this file has been looked up as a header.
unsigned IsValid : 1;
/// \brief The number of times the file has been included already.
@@ -105,7 +102,6 @@ struct HeaderFileInfo {
HeaderFileInfo()
: isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User),
External(false), isModuleHeader(false), isCompilingModuleHeader(false),
- HeaderRole(ModuleMap::NormalHeader),
Resolved(false), IndexHeaderMapHeader(false), IsValid(0),
NumIncludes(0), ControllingMacroID(0), ControllingMacro(nullptr) {}
@@ -120,16 +116,6 @@ struct HeaderFileInfo {
return isImport || isPragmaOnce || NumIncludes || ControllingMacro ||
ControllingMacroID;
}
-
- /// \brief Get the HeaderRole properly typed.
- ModuleMap::ModuleHeaderRole getHeaderRole() const {
- return static_cast<ModuleMap::ModuleHeaderRole>(HeaderRole);
- }
-
- /// \brief Set the HeaderRole properly typed.
- void setHeaderRole(ModuleMap::ModuleHeaderRole Role) {
- HeaderRole = Role;
- }
};
/// \brief An external source of header file information, which may supply
@@ -189,7 +175,7 @@ class HeaderSearch {
/// \brief All of the preprocessor-specific data about files that are
/// included, indexed by the FileEntry's UID.
- std::vector<HeaderFileInfo> FileInfo;
+ mutable std::vector<HeaderFileInfo> FileInfo;
/// Keeps track of each lookup performed by LookupFile.
struct LookupFileCacheInfo {
@@ -575,20 +561,20 @@ private:
/// of the given search directory.
void loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir);
- /// \brief Return the HeaderFileInfo structure for the specified FileEntry.
- const HeaderFileInfo &getFileInfo(const FileEntry *FE) const {
- return const_cast<HeaderSearch*>(this)->getFileInfo(FE);
- }
-
public:
/// \brief Retrieve the module map.
ModuleMap &getModuleMap() { return ModMap; }
+ /// \brief Retrieve the module map.
+ const ModuleMap &getModuleMap() const { return ModMap; }
+
unsigned header_file_size() const { return FileInfo.size(); }
- /// \brief Get a \c HeaderFileInfo structure for the specified \c FileEntry,
- /// if one exists.
- bool tryGetFileInfo(const FileEntry *FE, HeaderFileInfo &Result) const;
+ /// \brief Return the HeaderFileInfo structure for the specified FileEntry.
+ HeaderFileInfo &getFileInfo(const FileEntry *FE);
+
+ /// \brief Return the HeaderFileInfo structure for the specified FileEntry.
+ const HeaderFileInfo *getExistingFileInfo(const FileEntry *FE) const;
// Used by external tools
typedef std::vector<DirectoryLookup>::const_iterator search_dir_iterator;
@@ -665,9 +651,6 @@ private:
/// named directory.
LoadModuleMapResult loadModuleMapFile(const DirectoryEntry *Dir,
bool IsSystem, bool IsFramework);
-
- /// \brief Return the HeaderFileInfo structure for the specified FileEntry.
- HeaderFileInfo &getFileInfo(const FileEntry *FE);
};
} // end namespace clang
Modified: cfe/trunk/include/clang/Lex/ModuleMap.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/ModuleMap.h?rev=245390&r1=245389&r2=245390&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/ModuleMap.h (original)
+++ cfe/trunk/include/clang/Lex/ModuleMap.h Tue Aug 18 18:42:23 2015
@@ -112,6 +112,13 @@ public:
KnownHeader() : Storage(nullptr, NormalHeader) { }
KnownHeader(Module *M, ModuleHeaderRole Role) : Storage(M, Role) { }
+ friend bool operator==(const KnownHeader &A, const KnownHeader &B) {
+ return A.Storage == B.Storage;
+ }
+ friend bool operator!=(const KnownHeader &A, const KnownHeader &B) {
+ return A.Storage != B.Storage;
+ }
+
/// \brief Retrieve the module the header is stored in.
Module *getModule() const { return Storage.getPointer(); }
@@ -242,6 +249,10 @@ private:
KnownHeader findHeaderInUmbrellaDirs(const FileEntry *File,
SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs);
+ /// \brief Given that \p File is not in the Headers map, look it up within
+ /// umbrella directories and find or create a module for it.
+ KnownHeader findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File);
+
/// \brief A convenience method to determine if \p File is (possibly nested)
/// in an umbrella directory.
bool isHeaderInUmbrellaDirs(const FileEntry *File) {
@@ -295,6 +306,14 @@ public:
/// that no module owns this header file.
KnownHeader findModuleForHeader(const FileEntry *File);
+ /// \brief Retrieve all the modules that contain the given header file. This
+ /// may not include umbrella modules, nor information from external sources,
+ /// if they have not yet been inferred / loaded.
+ ///
+ /// Typically, \ref findModuleForHeader should be used instead, as it picks
+ /// the preferred module for the header.
+ ArrayRef<KnownHeader> findAllModulesForHeader(const FileEntry *File) const;
+
/// \brief Reports errors if a module must not include a specific file.
///
/// \param RequestingModule The module including a file.
Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=245390&r1=245389&r2=245390&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTWriter.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTWriter.h Tue Aug 18 18:42:23 2015
@@ -493,7 +493,7 @@ private:
/// \brief Retrieve or create a submodule ID for this module.
unsigned getSubmoduleID(Module *Mod);
-
+
/// \brief Write the given subexpression to the bitstream.
void WriteSubStmt(Stmt *S,
llvm::DenseMap<Stmt *, uint64_t> &SubStmtEntries,
@@ -767,9 +767,10 @@ public:
/// source location.
serialization::SubmoduleID inferSubmoduleIDFromLocation(SourceLocation Loc);
- /// \brief Retrieve a submodule ID for this module.
- /// Returns 0 If no ID has been associated with the module.
- unsigned getExistingSubmoduleID(Module *Mod) const;
+ /// \brief Retrieve or create a submodule ID for this module, or return 0 if
+ /// the submodule is neither local (a submodle of the currently-written module)
+ /// nor from an imported module.
+ unsigned getLocalOrImportedSubmoduleID(Module *Mod);
/// \brief Note that the identifier II occurs at the given offset
/// within the identifier table.
Modified: cfe/trunk/lib/Lex/HeaderSearch.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/HeaderSearch.cpp?rev=245390&r1=245389&r2=245390&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/HeaderSearch.cpp (original)
+++ cfe/trunk/lib/Lex/HeaderSearch.cpp Tue Aug 18 18:42:23 2015
@@ -975,65 +975,72 @@ static void mergeHeaderFileInfo(HeaderFi
if (OtherHFI.External) {
HFI.DirInfo = OtherHFI.DirInfo;
- HFI.External = OtherHFI.External;
+ HFI.External = OtherHFI.External && (!HFI.IsValid || HFI.External);
HFI.IndexHeaderMapHeader = OtherHFI.IndexHeaderMapHeader;
}
if (HFI.Framework.empty())
HFI.Framework = OtherHFI.Framework;
-
- HFI.Resolved = true;
}
/// getFileInfo - Return the HeaderFileInfo structure for the specified
/// FileEntry.
HeaderFileInfo &HeaderSearch::getFileInfo(const FileEntry *FE) {
if (FE->getUID() >= FileInfo.size())
- FileInfo.resize(FE->getUID()+1);
-
+ FileInfo.resize(FE->getUID() + 1);
+
HeaderFileInfo &HFI = FileInfo[FE->getUID()];
- if (ExternalSource && !HFI.Resolved)
+ // FIXME: Use a generation count to check whether this is really up to date.
+ if (ExternalSource && !HFI.Resolved) {
+ HFI.Resolved = true;
mergeHeaderFileInfo(HFI, ExternalSource->GetHeaderFileInfo(FE));
- HFI.IsValid = 1;
+ }
+
+ HFI.IsValid = true;
+ // We have local information about this header file, so it's no longer
+ // strictly external.
+ HFI.External = false;
return HFI;
}
-bool HeaderSearch::tryGetFileInfo(const FileEntry *FE,
- HeaderFileInfo &Result) const {
- if (FE->getUID() >= FileInfo.size())
- return false;
- const HeaderFileInfo &HFI = FileInfo[FE->getUID()];
- if (HFI.IsValid) {
- Result = HFI;
- return true;
+const HeaderFileInfo *
+HeaderSearch::getExistingFileInfo(const FileEntry *FE) const {
+ // If we have an external source, ensure we have the latest information.
+ // FIXME: Use a generation count to check whether this is really up to date.
+ if (ExternalSource &&
+ (FE->getUID() >= FileInfo.size() || !FileInfo[FE->getUID()].Resolved)) {
+ auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);
+ if (ExternalHFI.External) {
+ if (FE->getUID() >= FileInfo.size())
+ FileInfo.resize(FE->getUID() + 1);
+ mergeHeaderFileInfo(FileInfo[FE->getUID()], ExternalHFI);
+ }
}
- return false;
+
+ if (FE->getUID() >= FileInfo.size())
+ return nullptr;
+
+ HeaderFileInfo &HFI = FileInfo[FE->getUID()];
+ if (!HFI.IsValid)
+ return nullptr;
+
+ return &HFI;
}
bool HeaderSearch::isFileMultipleIncludeGuarded(const FileEntry *File) {
// Check if we've ever seen this file as a header.
- if (File->getUID() >= FileInfo.size())
- return false;
-
- // Resolve header file info from the external source, if needed.
- HeaderFileInfo &HFI = FileInfo[File->getUID()];
- if (ExternalSource && !HFI.Resolved)
- mergeHeaderFileInfo(HFI, ExternalSource->GetHeaderFileInfo(File));
-
- return HFI.isPragmaOnce || HFI.isImport ||
- HFI.ControllingMacro || HFI.ControllingMacroID;
+ if (auto *HFI = getExistingFileInfo(File))
+ return HFI->isPragmaOnce || HFI->isImport || HFI->ControllingMacro ||
+ HFI->ControllingMacroID;
+ return false;
}
void HeaderSearch::MarkFileModuleHeader(const FileEntry *FE,
ModuleMap::ModuleHeaderRole Role,
bool isCompilingModuleHeader) {
- if (FE->getUID() >= FileInfo.size())
- FileInfo.resize(FE->getUID()+1);
-
- HeaderFileInfo &HFI = FileInfo[FE->getUID()];
- HFI.isModuleHeader = true;
+ auto &HFI = getFileInfo(FE);
+ HFI.isModuleHeader |= !(Role & ModuleMap::TextualHeader);
HFI.isCompilingModuleHeader |= isCompilingModuleHeader;
- HFI.setHeaderRole(Role);
}
bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP,
@@ -1143,7 +1150,7 @@ HeaderSearch::findModuleForHeader(const
if (ExternalSource) {
// Make sure the external source has handled header info about this file,
// which includes whether the file is part of a module.
- (void)getFileInfo(File);
+ (void)getExistingFileInfo(File);
}
return ModMap.findModuleForHeader(File);
}
Modified: cfe/trunk/lib/Lex/ModuleMap.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/ModuleMap.cpp?rev=245390&r1=245389&r2=245390&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/ModuleMap.cpp (original)
+++ cfe/trunk/lib/Lex/ModuleMap.cpp Tue Aug 18 18:42:23 2015
@@ -359,6 +359,13 @@ ModuleMap::KnownHeader ModuleMap::findMo
return MakeResult(Result);
}
+ return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
+}
+
+ModuleMap::KnownHeader
+ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) {
+ assert(!Headers.count(File) && "already have a module for this header");
+
SmallVector<const DirectoryEntry *, 2> SkippedDirs;
KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
if (H) {
@@ -419,19 +426,22 @@ ModuleMap::KnownHeader ModuleMap::findMo
UmbrellaDirs[SkippedDirs[I]] = Result;
}
- Headers[File].push_back(KnownHeader(Result, NormalHeader));
-
- // If a header corresponds to an unavailable module, don't report
- // that it maps to anything.
- if (!Result->isAvailable())
- return KnownHeader();
-
- return MakeResult(Headers[File].back());
+ KnownHeader Header(Result, NormalHeader);
+ Headers[File].push_back(Header);
+ return Header;
}
return KnownHeader();
}
+ArrayRef<ModuleMap::KnownHeader>
+ModuleMap::findAllModulesForHeader(const FileEntry *File) const {
+ auto It = Headers.find(File);
+ if (It == Headers.end())
+ return None;
+ return It->second;
+}
+
bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
return isHeaderUnavailableInModule(Header, nullptr);
}
@@ -787,14 +797,21 @@ static Module::HeaderKind headerRoleToKi
void ModuleMap::addHeader(Module *Mod, Module::Header Header,
ModuleHeaderRole Role) {
- if (!(Role & TextualHeader)) {
- bool isCompilingModuleHeader = Mod->getTopLevelModule() == CompilingModule;
- HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
- isCompilingModuleHeader);
- }
- Headers[Header.Entry].push_back(KnownHeader(Mod, Role));
+ KnownHeader KH(Mod, Role);
+ // Only add each header to the headers list once.
+ // FIXME: Should we diagnose if a header is listed twice in the
+ // same module definition?
+ auto &HeaderList = Headers[Header.Entry];
+ for (auto H : HeaderList)
+ if (H == KH)
+ return;
+
+ HeaderList.push_back(KH);
Mod->Headers[headerRoleToKind(Role)].push_back(std::move(Header));
+
+ bool isCompilingModuleHeader = Mod->getTopLevelModule() == CompilingModule;
+ HeaderInfo.MarkFileModuleHeader(Header.Entry, Role, isCompilingModuleHeader);
}
void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) {
Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=245390&r1=245389&r2=245390&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Tue Aug 18 18:42:23 2015
@@ -1556,14 +1556,15 @@ HeaderFileInfoTrait::ReadData(internal_k
using namespace llvm::support;
HeaderFileInfo HFI;
unsigned Flags = *d++;
- HFI.HeaderRole = static_cast<ModuleMap::ModuleHeaderRole>
- ((Flags >> 6) & 0x03);
- HFI.isImport = (Flags >> 5) & 0x01;
- HFI.isPragmaOnce = (Flags >> 4) & 0x01;
- HFI.DirInfo = (Flags >> 2) & 0x03;
- HFI.Resolved = (Flags >> 1) & 0x01;
+ // FIXME: Refactor with mergeHeaderFileInfo in HeaderSearch.cpp.
+ HFI.isImport |= (Flags >> 4) & 0x01;
+ HFI.isPragmaOnce |= (Flags >> 3) & 0x01;
+ HFI.DirInfo = (Flags >> 1) & 0x03;
HFI.IndexHeaderMapHeader = Flags & 0x01;
- HFI.NumIncludes = endian::readNext<uint16_t, little, unaligned>(d);
+ // FIXME: Find a better way to handle this. Maybe just store a
+ // "has been included" flag?
+ HFI.NumIncludes = std::max(endian::readNext<uint16_t, little, unaligned>(d),
+ HFI.NumIncludes);
HFI.ControllingMacroID = Reader.getGlobalIdentifierID(
M, endian::readNext<uint32_t, little, unaligned>(d));
if (unsigned FrameworkOffset =
@@ -1573,32 +1574,32 @@ HeaderFileInfoTrait::ReadData(internal_k
StringRef FrameworkName(FrameworkStrings + FrameworkOffset - 1);
HFI.Framework = HS->getUniqueFrameworkName(FrameworkName);
}
-
- if (d != End) {
+
+ assert((End - d) % 4 == 0 &&
+ "Wrong data length in HeaderFileInfo deserialization");
+ while (d != End) {
uint32_t LocalSMID = endian::readNext<uint32_t, little, unaligned>(d);
- if (LocalSMID) {
- // This header is part of a module. Associate it with the module to enable
- // implicit module import.
- SubmoduleID GlobalSMID = Reader.getGlobalSubmoduleID(M, LocalSMID);
- Module *Mod = Reader.getSubmodule(GlobalSMID);
- HFI.isModuleHeader = true;
- FileManager &FileMgr = Reader.getFileManager();
- ModuleMap &ModMap =
- Reader.getPreprocessor().getHeaderSearchInfo().getModuleMap();
- // FIXME: This information should be propagated through the
- // SUBMODULE_HEADER etc records rather than from here.
- // FIXME: We don't ever mark excluded headers.
- 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());
- }
+ auto HeaderRole = static_cast<ModuleMap::ModuleHeaderRole>(LocalSMID & 3);
+ LocalSMID >>= 2;
+
+ // This header is part of a module. Associate it with the module to enable
+ // implicit module import.
+ SubmoduleID GlobalSMID = Reader.getGlobalSubmoduleID(M, LocalSMID);
+ Module *Mod = Reader.getSubmodule(GlobalSMID);
+ FileManager &FileMgr = Reader.getFileManager();
+ ModuleMap &ModMap =
+ Reader.getPreprocessor().getHeaderSearchInfo().getModuleMap();
+
+ std::string Filename = key.Filename;
+ if (key.Imported)
+ Reader.ResolveImportedPath(M, Filename);
+ // FIXME: This is not always the right filename-as-written, but we're not
+ // going to use this information to rebuild the module, so it doesn't make
+ // a lot of difference.
+ Module::Header H = { key.Filename, FileMgr.getFile(Filename) };
+ ModMap.addHeader(Mod, H, HeaderRole);
}
- assert(End == d && "Wrong data length in HeaderFileInfo deserialization");
- (void)End;
-
// This HeaderFileInfo was externally loaded.
HFI.External = true;
return HFI;
Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=245390&r1=245389&r2=245390&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Tue Aug 18 18:42:23 2015
@@ -1637,13 +1637,14 @@ namespace {
std::pair<unsigned,unsigned>
EmitKeyDataLength(raw_ostream& Out, key_type_ref key, data_type_ref Data) {
using namespace llvm::support;
- endian::Writer<little> Writer(Out);
+ endian::Writer<little> LE(Out);
unsigned KeyLen = strlen(key.Filename) + 1 + 8 + 8;
- Writer.write<uint16_t>(KeyLen);
+ LE.write<uint16_t>(KeyLen);
unsigned DataLen = 1 + 2 + 4 + 4;
- if (Data.isModuleHeader)
- DataLen += 4;
- Writer.write<uint8_t>(DataLen);
+ for (auto ModInfo : HS.getModuleMap().findAllModulesForHeader(key.FE))
+ if (Writer.getLocalOrImportedSubmoduleID(ModInfo.getModule()))
+ DataLen += 4;
+ LE.write<uint8_t>(DataLen);
return std::make_pair(KeyLen, DataLen);
}
@@ -1663,11 +1664,9 @@ namespace {
endian::Writer<little> LE(Out);
uint64_t Start = Out.tell(); (void)Start;
- unsigned char Flags = (Data.HeaderRole << 6)
- | (Data.isImport << 5)
- | (Data.isPragmaOnce << 4)
- | (Data.DirInfo << 2)
- | (Data.Resolved << 1)
+ unsigned char Flags = (Data.isImport << 4)
+ | (Data.isPragmaOnce << 3)
+ | (Data.DirInfo << 1)
| Data.IndexHeaderMapHeader;
LE.write<uint8_t>(Flags);
LE.write<uint16_t>(Data.NumIncludes);
@@ -1694,9 +1693,15 @@ namespace {
}
LE.write<uint32_t>(Offset);
- if (Data.isModuleHeader) {
- Module *Mod = HS.findModuleForHeader(key.FE).getModule();
- LE.write<uint32_t>(Writer.getExistingSubmoduleID(Mod));
+ // FIXME: If the header is excluded, we should write out some
+ // record of that fact.
+ for (auto ModInfo : HS.getModuleMap().findAllModulesForHeader(key.FE)) {
+ if (uint32_t ModID =
+ Writer.getLocalOrImportedSubmoduleID(ModInfo.getModule())) {
+ uint32_t Value = (ModID << 2) | (unsigned)ModInfo.getRole();
+ assert((Value >> 2) == ModID && "overflow in header module info");
+ LE.write<uint32_t>(Value);
+ }
}
assert(Out.tell() - Start == DataLen && "Wrong data length");
@@ -1726,12 +1731,15 @@ void ASTWriter::WriteHeaderSearch(const
if (!File)
continue;
- // Use HeaderSearch's getFileInfo to make sure we get the HeaderFileInfo
- // from the external source if it was not provided already.
- HeaderFileInfo HFI;
- if (!HS.tryGetFileInfo(File, HFI) ||
- (HFI.External && Chain) ||
- (HFI.isModuleHeader && !HFI.isCompilingModuleHeader))
+ // Get the file info. This will load info from the external source if
+ // necessary. Skip emitting this file if we have no information on it
+ // as a header file (in which case HFI will be null) or if it hasn't
+ // changed since it was loaded. Also skip it if it's for a modular header
+ // from a different module; in that case, we rely on the module(s)
+ // containing the header to provide this information.
+ const HeaderFileInfo *HFI = HS.getExistingFileInfo(File);
+ if (!HFI || (HFI->External && Chain) ||
+ (HFI->isModuleHeader && !HFI->isCompilingModuleHeader))
continue;
// Massage the file path into an appropriate form.
@@ -1745,7 +1753,7 @@ void ASTWriter::WriteHeaderSearch(const
}
HeaderFileInfoTrait::key_type key = { File, Filename };
- Generator.insert(key, HFI, GeneratorTrait);
+ Generator.insert(key, *HFI, GeneratorTrait);
++NumHeaderSearchEntries;
}
@@ -2283,27 +2291,28 @@ void ASTWriter::WritePreprocessorDetail(
}
}
-unsigned ASTWriter::getSubmoduleID(Module *Mod) {
+unsigned ASTWriter::getLocalOrImportedSubmoduleID(Module *Mod) {
if (!Mod)
return 0;
llvm::DenseMap<Module *, unsigned>::iterator Known = SubmoduleIDs.find(Mod);
if (Known != SubmoduleIDs.end())
return Known->second;
-
- return SubmoduleIDs[Mod] = NextSubmoduleID++;
-}
-unsigned ASTWriter::getExistingSubmoduleID(Module *Mod) const {
- if (!Mod)
+ if (Mod->getTopLevelModule() != WritingModule)
return 0;
- llvm::DenseMap<Module *, unsigned>::const_iterator
- Known = SubmoduleIDs.find(Mod);
- if (Known != SubmoduleIDs.end())
- return Known->second;
+ return SubmoduleIDs[Mod] = NextSubmoduleID++;
+}
- return 0;
+unsigned ASTWriter::getSubmoduleID(Module *Mod) {
+ // FIXME: This can easily happen, if we have a reference to a submodule that
+ // did not result in us loading a module file for that submodule. For
+ // instance, a cross-top-level-module 'conflict' declaration will hit this.
+ unsigned ID = getLocalOrImportedSubmoduleID(Mod);
+ assert((ID || !Mod) &&
+ "asked for module ID for non-local, non-imported module");
+ return ID;
}
/// \brief Compute the number of modules within the given tree (including the
@@ -2542,9 +2551,6 @@ void ASTWriter::WriteSubmodules(Module *
Stream.ExitBlock();
- // FIXME: This can easily happen, if we have a reference to a submodule that
- // did not result in us loading a module file for that submodule. For
- // instance, a cross-top-level-module 'conflict' declaration will hit this.
assert((NextSubmoduleID - FirstSubmoduleID ==
getNumberOfModules(WritingModule)) &&
"Wrong # of submodules; found a reference to a non-local, "
More information about the cfe-commits
mailing list