diff --git a/clang/include/clang/Lex/ModuleMap.h b/clang/include/clang/Lex/ModuleMap.h --- a/clang/include/clang/Lex/ModuleMap.h +++ b/clang/include/clang/Lex/ModuleMap.h @@ -456,8 +456,11 @@ /// is effectively internal, but is exposed so HeaderSearch can call it. void resolveHeaderDirectives(const FileEntry *File) const; - /// Resolve all lazy header directives for the specified module. - void resolveHeaderDirectives(Module *Mod) const; + /// Resolve lazy header directives for the specified module. If File is + /// provided, only headers with same size and modtime are resolved. If File + /// is not set, all headers are resolved. + void resolveHeaderDirectives(Module *Mod, + llvm::Optional File) const; /// Reports errors if a module must not include a specific file. /// diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -331,7 +331,7 @@ return std::error_code(); // Resolve all lazy header directives to header files. - ModMap.resolveHeaderDirectives(Module); + ModMap.resolveHeaderDirectives(Module, /*File=*/llvm::None); // If any headers are missing, we can't build this module. In most cases, // diagnostics for this should have already been produced; we only get here diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -482,7 +482,7 @@ if (RequestingModule) { resolveUses(RequestingModule, /*Complain=*/false); - resolveHeaderDirectives(RequestingModule); + resolveHeaderDirectives(RequestingModule, /*File=*/llvm::None); } bool Excluded = false; @@ -1191,25 +1191,35 @@ auto BySize = LazyHeadersBySize.find(File->getSize()); if (BySize != LazyHeadersBySize.end()) { for (auto *M : BySize->second) - resolveHeaderDirectives(M); + resolveHeaderDirectives(M, File); LazyHeadersBySize.erase(BySize); } auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime()); if (ByModTime != LazyHeadersByModTime.end()) { for (auto *M : ByModTime->second) - resolveHeaderDirectives(M); + resolveHeaderDirectives(M, File); LazyHeadersByModTime.erase(ByModTime); } } -void ModuleMap::resolveHeaderDirectives(Module *Mod) const { +void ModuleMap::resolveHeaderDirectives( + Module *Mod, llvm::Optional File) const { bool NeedsFramework = false; - for (auto &Header : Mod->UnresolvedHeaders) - // This operation is logically const; we're just changing how we represent - // the header information for this file. - const_cast(this)->resolveHeader(Mod, Header, NeedsFramework); - Mod->UnresolvedHeaders.clear(); + SmallVector NewHeaders; + const auto Size = File ? File.getValue()->getSize() : 0; + const auto ModTime = File ? File.getValue()->getModificationTime() : 0; + + for (auto &Header : Mod->UnresolvedHeaders) { + if (File && ((Header.ModTime && Header.ModTime != ModTime) || + (Header.Size && Header.Size != Size))) + NewHeaders.push_back(Header); + else + // This operation is logically const; we're just changing how we represent + // the header information for this file. + const_cast(this)->resolveHeader(Mod, Header, NeedsFramework); + } + Mod->UnresolvedHeaders.swap(NewHeaders); } void ModuleMap::addHeader(Module *Mod, Module::Header Header, diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -1879,7 +1879,7 @@ // headers list when emitting resolved headers in the first loop below. // FIXME: It'd be preferable to avoid doing this if we were given // sufficient stat information in the module map. - HS.getModuleMap().resolveHeaderDirectives(M); + HS.getModuleMap().resolveHeaderDirectives(M, /*File=*/llvm::None); // If the file didn't exist, we can still create a module if we were given // enough information in the module map.