diff options
Diffstat (limited to 'lib/Frontend/FrontendActions.cpp')
-rw-r--r-- | lib/Frontend/FrontendActions.cpp | 133 |
1 files changed, 49 insertions, 84 deletions
diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index 24960cf..47063f7 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -131,8 +131,31 @@ ASTConsumer *GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI, Sysroot, OS); } +static SmallVectorImpl<char> & +operator+=(SmallVectorImpl<char> &Includes, StringRef RHS) { + Includes.append(RHS.begin(), RHS.end()); + return Includes; +} + +static void addHeaderInclude(StringRef HeaderName, + SmallVectorImpl<char> &Includes, + const LangOptions &LangOpts) { + if (LangOpts.ObjC1) + Includes += "#import \""; + else + Includes += "#include \""; + Includes += HeaderName; + Includes += "\"\n"; +} + +static void addHeaderInclude(const FileEntry *Header, + SmallVectorImpl<char> &Includes, + const LangOptions &LangOpts) { + addHeaderInclude(Header->getName(), Includes, LangOpts); +} + /// \brief Collect the set of header includes needed to construct the given -/// module. +/// module and update the TopHeaders file set of the module. /// /// \param Module The module we're collecting includes from. /// @@ -142,30 +165,23 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr, ModuleMap &ModMap, clang::Module *Module, - SmallString<256> &Includes) { + SmallVectorImpl<char> &Includes) { // Don't collect any headers for unavailable modules. if (!Module->isAvailable()) return; // Add includes for each of these headers. for (unsigned I = 0, N = Module->Headers.size(); I != N; ++I) { - if (LangOpts.ObjC1) - Includes += "#import \""; - else - Includes += "#include \""; - Includes += Module->Headers[I]->getName(); - Includes += "\"\n"; + const FileEntry *Header = Module->Headers[I]; + Module->TopHeaders.insert(Header); + 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. @@ -184,17 +200,14 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts, // If this header is marked 'unavailable' in this module, don't include // it. - if (const FileEntry *Header = FileMgr.getFile(Dir->path())) + if (const FileEntry *Header = FileMgr.getFile(Dir->path())) { if (ModMap.isHeaderInUnavailableModule(Header)) continue; + Module->TopHeaders.insert(Header); + } // 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); } } @@ -250,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; } |