Prevent outputting HeaderFileInfos for files not used as headers

When building an AST file, we don't want to output HeaderFileInfo
structures for files that are not actually used as headers in the
current context.  This can lead to assuming that unrelated files have
include counts of 0, defeating multiple-include prevention.

This is accomplished by adding an IsValid bit to the HFI.

llvm-svn: 203813
This commit is contained in:
Ben Langmuir 2014-03-13 16:46:36 +00:00
parent 2b124d1a5d
commit d285c50390
3 changed files with 28 additions and 9 deletions

View File

@ -73,6 +73,9 @@ struct HeaderFileInfo {
/// provided via a header map. This bit indicates when this is one of
/// those framework headers.
unsigned IndexHeaderMapHeader : 1;
/// \brief Whether this file had been looked up as a header.
unsigned IsValid : 1;
/// \brief The number of times the file has been included already.
unsigned short NumIncludes;
@ -102,7 +105,7 @@ struct HeaderFileInfo {
: isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User),
External(false), isModuleHeader(false), isCompilingModuleHeader(false),
HeaderRole(ModuleMap::NormalHeader),
Resolved(false), IndexHeaderMapHeader(false),
Resolved(false), IndexHeaderMapHeader(false), IsValid(0),
NumIncludes(0), ControllingMacroID(0), ControllingMacro(0) {}
/// \brief Retrieve the controlling macro for this header file, if
@ -557,16 +560,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; }
unsigned header_file_size() const { return FileInfo.size(); }
/// \brief Return the HeaderFileInfo structure for the specified FileEntry.
const HeaderFileInfo &getFileInfo(const FileEntry *FE) const {
return const_cast<HeaderSearch*>(this)->getFileInfo(FE);
}
/// \brief Get a \c HeaderFileInfo structure for the specified \c FileEntry,
/// if one exists.
bool tryGetFileInfo(const FileEntry *FE, HeaderFileInfo &Result) const;
// Used by external tools
typedef std::vector<DirectoryLookup>::const_iterator search_dir_iterator;

View File

@ -988,9 +988,21 @@ HeaderFileInfo &HeaderSearch::getFileInfo(const FileEntry *FE) {
HeaderFileInfo &HFI = FileInfo[FE->getUID()];
if (ExternalSource && !HFI.Resolved)
mergeHeaderFileInfo(HFI, ExternalSource->GetHeaderFileInfo(FE));
HFI.IsValid = 1;
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;
}
return false;
}
bool HeaderSearch::isFileMultipleIncludeGuarded(const FileEntry *File) {
// Check if we've ever seen this file as a header.
if (File->getUID() >= FileInfo.size())

View File

@ -1547,10 +1547,10 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS, StringRef isysroot) {
// Use HeaderSearch's getFileInfo to make sure we get the HeaderFileInfo
// from the external source if it was not provided already.
const HeaderFileInfo &HFI = HS.getFileInfo(File);
if (HFI.External && Chain)
continue;
if (HFI.isModuleHeader && !HFI.isCompilingModuleHeader)
HeaderFileInfo HFI;
if (!HS.tryGetFileInfo(File, HFI) ||
(HFI.External && Chain) ||
(HFI.isModuleHeader && !HFI.isCompilingModuleHeader))
continue;
// Turn the file name into an absolute path, if it isn't already.