From: Richard Smith Date: Sat, 16 May 2015 02:28:53 +0000 (+0000) Subject: [modules] Retain the name as written for umbrella headers and directories, rather... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4c293dd558b4086f7d7d26cec547a02a0ce2685f;p=clang [modules] Retain the name as written for umbrella headers and directories, rather than converting to an absolute path. No observable change expected, but this allows us to correctly compute the module for an umbrella header, which later changes will require. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@237508 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/Module.h b/include/clang/Basic/Module.h index 524986f29d..7470610740 100644 --- a/include/clang/Basic/Module.h +++ b/include/clang/Basic/Module.h @@ -65,6 +65,9 @@ public: /// \brief The umbrella header or directory. llvm::PointerUnion Umbrella; + + /// \brief The name of the umbrella entry, as written in the module map. + std::string UmbrellaAsWritten; private: /// \brief The submodules of this module, indexed by name. @@ -105,6 +108,17 @@ public: struct Header { std::string NameAsWritten; const FileEntry *Entry; + + explicit operator bool() { return Entry; } + }; + + /// \brief Information about a directory name as found in the module map + /// file. + struct DirectoryName { + std::string NameAsWritten; + const DirectoryEntry *Entry; + + explicit operator bool() { return Entry; } }; /// \brief The headers that are part of this module. @@ -370,12 +384,14 @@ public: /// \brief Retrieve the directory for which this module serves as the /// umbrella. - const DirectoryEntry *getUmbrellaDir() const; + DirectoryName getUmbrellaDir() const; /// \brief Retrieve the header that serves as the umbrella header for this /// module. - const FileEntry *getUmbrellaHeader() const { - return Umbrella.dyn_cast(); + Header getUmbrellaHeader() const { + if (auto *E = Umbrella.dyn_cast()) + return Header{UmbrellaAsWritten, E}; + return Header{}; } /// \brief Determine whether this module has an umbrella directory that is diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h index a15ac9e826..83a410dfc9 100644 --- a/include/clang/Lex/ModuleMap.h +++ b/include/clang/Lex/ModuleMap.h @@ -437,11 +437,13 @@ public: /// \brief Sets the umbrella header of the given module to the given /// header. - void setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader); + void setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader, + Twine NameAsWritten); /// \brief Sets the umbrella directory of the given module to the given /// directory. - void setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir); + void setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir, + Twine NameAsWritten); /// \brief Adds this header to the given module. /// \param Role The role of the header wrt the module. diff --git a/lib/Basic/Module.cpp b/lib/Basic/Module.cpp index 97f0a035b0..7308665bd2 100644 --- a/lib/Basic/Module.cpp +++ b/lib/Basic/Module.cpp @@ -138,11 +138,11 @@ std::string Module::getFullModuleName() const { return Result; } -const DirectoryEntry *Module::getUmbrellaDir() const { - if (const FileEntry *Header = getUmbrellaHeader()) - return Header->getDir(); +Module::DirectoryName Module::getUmbrellaDir() const { + if (Header U = getUmbrellaHeader()) + return {"", U.Entry->getDir()}; - return Umbrella.dyn_cast(); + return {UmbrellaAsWritten, Umbrella.dyn_cast()}; } ArrayRef Module::getTopHeaders(FileManager &FileMgr) { @@ -334,15 +334,15 @@ void Module::print(raw_ostream &OS, unsigned Indent) const { OS << "\n"; } - if (const FileEntry *UmbrellaHeader = getUmbrellaHeader()) { + if (Header H = getUmbrellaHeader()) { OS.indent(Indent + 2); OS << "umbrella header \""; - OS.write_escaped(UmbrellaHeader->getName()); + OS.write_escaped(H.NameAsWritten); OS << "\"\n"; - } else if (const DirectoryEntry *UmbrellaDir = getUmbrellaDir()) { + } else if (DirectoryName D = getUmbrellaDir()) { OS.indent(Indent + 2); OS << "umbrella \""; - OS.write_escaped(UmbrellaDir->getName()); + OS.write_escaped(D.NameAsWritten); OS << "\"\n"; } diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index b64424a9ae..2d8bb71ee1 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -949,16 +949,18 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance, FrontendOpts.Inputs.push_back( FrontendInputFile(ModuleMapFile->getName(), IK)); } else { + SmallString<128> FakeModuleMapFile(Module->Directory->getName()); + llvm::sys::path::append(FakeModuleMapFile, "__inferred_module.map"); + FrontendOpts.Inputs.push_back(FrontendInputFile(FakeModuleMapFile, IK)); + llvm::raw_string_ostream OS(InferredModuleMapContent); Module->print(OS); OS.flush(); - FrontendOpts.Inputs.push_back( - FrontendInputFile("__inferred_module.map", IK)); std::unique_ptr ModuleMapBuffer = llvm::MemoryBuffer::getMemBuffer(InferredModuleMapContent); ModuleMapFile = Instance.getFileManager().getVirtualFile( - "__inferred_module.map", InferredModuleMapContent.size(), 0); + FakeModuleMapFile, InferredModuleMapContent.size(), 0); SourceMgr.overrideFileContents(ModuleMapFile, std::move(ModuleMapBuffer)); } diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index 0defe5c0c3..46cdeebfdb 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -152,22 +152,6 @@ static std::error_code addHeaderInclude(StringRef HeaderName, return std::error_code(); } -static std::error_code addHeaderInclude(const FileEntry *Header, - SmallVectorImpl &Includes, - const LangOptions &LangOpts, - bool IsExternC) { - // Use an absolute path if we don't have a filename as written in the module - // map file; this ensures that we will identify the right file independent of - // header search paths. - if (llvm::sys::path::is_absolute(Header->getName())) - return addHeaderInclude(Header->getName(), Includes, LangOpts, IsExternC); - - SmallString<256> AbsName(Header->getName()); - if (std::error_code Err = llvm::sys::fs::make_absolute(AbsName)) - return Err; - return addHeaderInclude(AbsName, Includes, LangOpts, IsExternC); -} - /// \brief Collect the set of header includes needed to construct the given /// module and update the TopHeaders file set of the module. /// @@ -196,20 +180,20 @@ collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr, } // Note that Module->PrivateHeaders will not be a TopHeader. - if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader()) { - // FIXME: Track the name as written here. - Module->addTopHeader(UmbrellaHeader); + if (Module::Header UmbrellaHeader = Module->getUmbrellaHeader()) { + Module->addTopHeader(UmbrellaHeader.Entry); if (Module->Parent) { // Include the umbrella header for submodules. - if (std::error_code Err = addHeaderInclude(UmbrellaHeader, Includes, - LangOpts, Module->IsExternC)) + if (std::error_code Err = addHeaderInclude(UmbrellaHeader.NameAsWritten, + Includes, LangOpts, + Module->IsExternC)) return Err; } - } else if (const DirectoryEntry *UmbrellaDir = Module->getUmbrellaDir()) { + } else if (Module::DirectoryName UmbrellaDir = Module->getUmbrellaDir()) { // Add all of the headers we find in this subdirectory. std::error_code EC; SmallString<128> DirNative; - llvm::sys::path::native(UmbrellaDir->getName(), DirNative); + llvm::sys::path::native(UmbrellaDir.Entry->getName(), DirNative); for (llvm::sys::fs::recursive_directory_iterator Dir(DirNative, EC), DirEnd; Dir != DirEnd && !EC; Dir.increment(EC)) { @@ -231,11 +215,20 @@ collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr, if (ModMap.isHeaderUnavailableInModule(Header, Module)) continue; + // Compute the relative path from the directory to this file. + SmallVector Components; + auto PathIt = llvm::sys::path::rbegin(Dir->path()); + for (int I = 0; I != Dir.level() + 1; ++I, ++PathIt) + Components.push_back(*PathIt); + SmallString<128> RelativeHeader(UmbrellaDir.NameAsWritten); + for (auto It = Components.rbegin(), End = Components.rend(); It != End; + ++It) + llvm::sys::path::append(RelativeHeader, *It); + // Include this header as part of the umbrella directory. - // FIXME: Track the name as written through to here. Module->addTopHeader(Header); - if (std::error_code Err = - addHeaderInclude(Header, Includes, LangOpts, Module->IsExternC)) + if (std::error_code Err = addHeaderInclude(RelativeHeader, Includes, + LangOpts, Module->IsExternC)) return Err; } @@ -327,10 +320,9 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI, // Collect the set of #includes we need to build the module. SmallString<256> HeaderContents; std::error_code Err = std::error_code(); - if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader()) - // FIXME: Track the file name as written. - Err = addHeaderInclude(UmbrellaHeader, HeaderContents, CI.getLangOpts(), - Module->IsExternC); + if (Module::Header UmbrellaHeader = Module->getUmbrellaHeader()) + Err = addHeaderInclude(UmbrellaHeader.NameAsWritten, HeaderContents, + CI.getLangOpts(), Module->IsExternC); if (!Err) Err = collectModuleHeaderIncludes( CI.getLangOpts(), FileMgr, diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index 287ee146c6..412918362d 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -705,14 +705,16 @@ Module *ModuleMap::inferFrameworkModule(StringRef ModuleName, Result->IsSystem |= Attrs.IsSystem; Result->IsExternC |= Attrs.IsExternC; Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive; + Result->Directory = FrameworkDir; if (!Parent) Modules[ModuleName] = Result; // umbrella header "umbrella-header-name" - Result->Umbrella = UmbrellaHeader; - Headers[UmbrellaHeader].push_back(KnownHeader(Result, NormalHeader)); - UmbrellaDirs[UmbrellaHeader->getDir()] = Result; + // + // The "Headers/" component of the name is implied because this is + // a framework module. + setUmbrellaHeader(Result, UmbrellaHeader, ModuleName + ".h"); // export * Result->Exports.push_back(Module::ExportDecl(nullptr, true)); @@ -773,14 +775,18 @@ Module *ModuleMap::inferFrameworkModule(StringRef ModuleName, return Result; } -void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){ +void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader, + Twine NameAsWritten) { Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader)); Mod->Umbrella = UmbrellaHeader; + Mod->UmbrellaAsWritten = NameAsWritten.str(); UmbrellaDirs[UmbrellaHeader->getDir()] = Mod; } -void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) { +void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir, + Twine NameAsWritten) { Mod->Umbrella = UmbrellaDir; + Mod->UmbrellaAsWritten = NameAsWritten.str(); UmbrellaDirs[UmbrellaDir] = Mod; } @@ -1779,7 +1785,7 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, HadError = true; } else { // Record this umbrella header. - Map.setUmbrellaHeader(ActiveModule, File); + Map.setUmbrellaHeader(ActiveModule, File, RelativePathName.str()); } } else if (LeadingToken == MMToken::ExcludeKeyword) { Module::Header H = {RelativePathName.str(), File}; @@ -1861,7 +1867,7 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { } // Record this umbrella directory. - Map.setUmbrellaDir(ActiveModule, Dir); + Map.setUmbrellaDir(ActiveModule, Dir, DirName); } /// \brief Parse a module export declaration. diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp index ddc3fa646b..f1d0593c8e 100644 --- a/lib/Lex/PPLexerChange.cpp +++ b/lib/Lex/PPLexerChange.cpp @@ -474,7 +474,7 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { if (!getDiagnostics().isIgnored(diag::warn_uncovered_module_header, StartLoc)) { ModuleMap &ModMap = getHeaderSearchInfo().getModuleMap(); - const DirectoryEntry *Dir = Mod->getUmbrellaDir(); + const DirectoryEntry *Dir = Mod->getUmbrellaDir().Entry; vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem(); std::error_code EC; for (vfs::recursive_directory_iterator Entry(FS, Dir->getName(), EC), End; diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 08fd923f47..3273ef9744 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -4270,10 +4270,12 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { } case SUBMODULE_UMBRELLA_HEADER: { - if (const FileEntry *Umbrella = PP.getFileManager().getFile(Blob)) { + std::string Filename = Blob; + ResolveImportedPath(F, Filename); + if (auto *Umbrella = PP.getFileManager().getFile(Filename)) { if (!CurrentModule->getUmbrellaHeader()) - ModMap.setUmbrellaHeader(CurrentModule, Umbrella); - else if (CurrentModule->getUmbrellaHeader() != Umbrella) { + ModMap.setUmbrellaHeader(CurrentModule, Umbrella, Blob); + else if (CurrentModule->getUmbrellaHeader().Entry != Umbrella) { // This can be a spurious difference caused by changing the VFS to // point to a different copy of the file, and it is too late to // to rebuild safely. @@ -4306,11 +4308,12 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { } case SUBMODULE_UMBRELLA_DIR: { - if (const DirectoryEntry *Umbrella - = PP.getFileManager().getDirectory(Blob)) { + std::string Dirname = Blob; + ResolveImportedPath(F, Dirname); + if (auto *Umbrella = PP.getFileManager().getDirectory(Dirname)) { if (!CurrentModule->getUmbrellaDir()) - ModMap.setUmbrellaDir(CurrentModule, Umbrella); - else if (CurrentModule->getUmbrellaDir() != Umbrella) { + ModMap.setUmbrellaDir(CurrentModule, Umbrella, Blob); + else if (CurrentModule->getUmbrellaDir().Entry != Umbrella) { if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) Error("mismatched umbrella directories in submodule"); return OutOfDate; diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 2963b32857..b206342678 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -2439,16 +2439,16 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { } // Emit the umbrella header, if there is one. - if (const FileEntry *UmbrellaHeader = Mod->getUmbrellaHeader()) { + if (auto UmbrellaHeader = Mod->getUmbrellaHeader()) { Record.clear(); Record.push_back(SUBMODULE_UMBRELLA_HEADER); - Stream.EmitRecordWithBlob(UmbrellaAbbrev, Record, - UmbrellaHeader->getName()); - } else if (const DirectoryEntry *UmbrellaDir = Mod->getUmbrellaDir()) { + Stream.EmitRecordWithBlob(UmbrellaAbbrev, Record, + UmbrellaHeader.NameAsWritten); + } else if (auto UmbrellaDir = Mod->getUmbrellaDir()) { Record.clear(); Record.push_back(SUBMODULE_UMBRELLA_DIR); Stream.EmitRecordWithBlob(UmbrellaDirAbbrev, Record, - UmbrellaDir->getName()); + UmbrellaDir.NameAsWritten); } // Emit the headers.