From 201cbad62dca645abcee1fd01df3e29bf5fe0deb Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Thu, 13 Mar 2014 16:46:36 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@203813 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Lex/HeaderSearch.h | 17 ++++++++++++----- lib/Lex/HeaderSearch.cpp | 12 ++++++++++++ lib/Serialization/ASTWriter.cpp | 8 ++++---- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index d3b3193572..e326db763c 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -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(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(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::const_iterator search_dir_iterator; diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index 97bff4f277..46d4d41b9a 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -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()) diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index fc1806fca6..95a470d922 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -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. -- 2.40.0