diff --git a/clang/include/clang/Basic/Module.h b/clang/include/clang/Basic/Module.h index a53f87d7b77a..faaca22bd064 100644 --- a/clang/include/clang/Basic/Module.h +++ b/clang/include/clang/Basic/Module.h @@ -290,6 +290,10 @@ public: submodule_iterator submodule_end() { return SubModules.end(); } submodule_const_iterator submodule_end() const { return SubModules.end(); } + static StringRef getModuleInputBufferName() { + return ""; + } + /// \brief Print the module map for this module to the given stream. /// void print(llvm::raw_ostream &OS, unsigned Indent = 0) const; diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index f4ea5d3da08c..47063f78b5d9 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -131,6 +131,29 @@ ASTConsumer *GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI, Sysroot, OS); } +static SmallVectorImpl & +operator+=(SmallVectorImpl &Includes, StringRef RHS) { + Includes.append(RHS.begin(), RHS.end()); + return Includes; +} + +static void addHeaderInclude(StringRef HeaderName, + SmallVectorImpl &Includes, + const LangOptions &LangOpts) { + if (LangOpts.ObjC1) + Includes += "#import \""; + else + Includes += "#include \""; + Includes += HeaderName; + Includes += "\"\n"; +} + +static void addHeaderInclude(const FileEntry *Header, + SmallVectorImpl &Includes, + const LangOptions &LangOpts) { + addHeaderInclude(Header->getName(), Includes, LangOpts); +} + /// \brief Collect the set of header includes needed to construct the given /// module and update the TopHeaders file set of the module. /// @@ -142,7 +165,7 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr, ModuleMap &ModMap, clang::Module *Module, - SmallString<256> &Includes) { + SmallVectorImpl &Includes) { // Don't collect any headers for unavailable modules. if (!Module->isAvailable()) return; @@ -151,24 +174,14 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts, for (unsigned I = 0, N = Module->Headers.size(); I != N; ++I) { const FileEntry *Header = Module->Headers[I]; Module->TopHeaders.insert(Header); - if (LangOpts.ObjC1) - Includes += "#import \""; - else - Includes += "#include \""; - Includes += Header->getName(); - Includes += "\"\n"; + addHeaderInclude(Header, Includes, LangOpts); } if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader()) { Module->TopHeaders.insert(UmbrellaHeader); if (Module->Parent) { // Include the umbrella header for submodules. - if (LangOpts.ObjC1) - Includes += "#import \""; - else - Includes += "#include \""; - Includes += UmbrellaHeader->getName(); - Includes += "\"\n"; + addHeaderInclude(UmbrellaHeader, Includes, LangOpts); } } else if (const DirectoryEntry *UmbrellaDir = Module->getUmbrellaDir()) { // Add all of the headers we find in this subdirectory. @@ -194,12 +207,7 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts, } // Include this header umbrella header for submodules. - if (LangOpts.ObjC1) - Includes += "#import \""; - else - Includes += "#include \""; - Includes += Dir->path(); - Includes += "\"\n"; + addHeaderInclude(Dir->path(), Includes, LangOpts); } } @@ -255,77 +263,29 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI, return false; } - // Do we have an umbrella header for this module? - const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader(); - + FileManager &FileMgr = CI.getFileManager(); + // Collect the set of #includes we need to build the module. SmallString<256> HeaderContents; - collectModuleHeaderIncludes(CI.getLangOpts(), CI.getFileManager(), + if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader()) + addHeaderInclude(UmbrellaHeader, HeaderContents, CI.getLangOpts()); + collectModuleHeaderIncludes(CI.getLangOpts(), FileMgr, CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(), Module, HeaderContents); - if (UmbrellaHeader && HeaderContents.empty()) { - // Simple case: we have an umbrella header and there are no additional - // includes, we can just parse the umbrella header directly. - setCurrentInput(FrontendInputFile(UmbrellaHeader->getName(), - getCurrentFileKind(), - Module->IsSystem)); - return true; - } - - FileManager &FileMgr = CI.getFileManager(); - SmallString<128> HeaderName; - time_t ModTime; - if (UmbrellaHeader) { - // Read in the umbrella header. - // FIXME: Go through the source manager; the umbrella header may have - // been overridden. - std::string ErrorStr; - llvm::MemoryBuffer *UmbrellaContents - = FileMgr.getBufferForFile(UmbrellaHeader, &ErrorStr); - if (!UmbrellaContents) { - CI.getDiagnostics().Report(diag::err_missing_umbrella_header) - << UmbrellaHeader->getName() << ErrorStr; - return false; - } - - // Combine the contents of the umbrella header with the automatically- - // generated includes. - SmallString<256> OldContents = HeaderContents; - HeaderContents = UmbrellaContents->getBuffer(); - HeaderContents += "\n\n"; - HeaderContents += "/* Module includes */\n"; - HeaderContents += OldContents; - // Pretend that we're parsing the umbrella header. - HeaderName = UmbrellaHeader->getName(); - ModTime = UmbrellaHeader->getModificationTime(); - - delete UmbrellaContents; - } else { - // Pick an innocuous-sounding name for the umbrella header. - HeaderName = Module->Name + ".h"; - if (FileMgr.getFile(HeaderName, /*OpenFile=*/false, - /*CacheFailure=*/false)) { - // Try again! - HeaderName = Module->Name + "-module.h"; - if (FileMgr.getFile(HeaderName, /*OpenFile=*/false, - /*CacheFailure=*/false)) { - // Pick something ridiculous and go with it. - HeaderName = Module->Name + "-module.hmod"; - } - } - ModTime = time(0); - } - - // Remap the contents of the header name we're using to our synthesized - // buffer. - const FileEntry *HeaderFile = FileMgr.getVirtualFile(HeaderName, + StringRef InputName = Module::getModuleInputBufferName(); + + // We consistently construct a buffer as input to build the module. + // This means the main file for modules will always be a virtual one. + // FIXME: Maybe allow using a memory buffer as input directly instead of + // messing with virtual files. + const FileEntry *HeaderFile = FileMgr.getVirtualFile(InputName, HeaderContents.size(), - ModTime); + time(0)); llvm::MemoryBuffer *HeaderContentsBuf = llvm::MemoryBuffer::getMemBufferCopy(HeaderContents); CI.getSourceManager().overrideFileContents(HeaderFile, HeaderContentsBuf); - setCurrentInput(FrontendInputFile(HeaderName, getCurrentFileKind(), + setCurrentInput(FrontendInputFile(InputName, getCurrentFileKind(), Module->IsSystem)); return true; } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index cdb9646758cb..d060e795ded8 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -1111,7 +1111,7 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) { return Failure; } - if (!DisableValidation && + if (!DisableValidation && !OverriddenBuffer && ((off_t)Record[4] != File->getSize() #if !defined(LLVM_ON_WIN32) // In our regression testing, the Windows file system seems to