diff --git a/clang/include/clang/Basic/Module.h b/clang/include/clang/Basic/Module.h --- a/clang/include/clang/Basic/Module.h +++ b/clang/include/clang/Basic/Module.h @@ -141,6 +141,9 @@ /// The name of the umbrella entry, as written in the module map. std::string UmbrellaAsWritten; + // The path to the umbrella entry relative to the root module's \c Directory. + std::string UmbrellaRelativeToRootModuleDirectory; + /// The module through which entities defined in this module will /// eventually be exposed, for use in "private" modules. std::string ExportAsModule; @@ -188,6 +191,7 @@ /// file. struct Header { std::string NameAsWritten; + std::string PathRelativeToRootModuleDirectory; const FileEntry *Entry; explicit operator bool() { return Entry; } @@ -197,6 +201,7 @@ /// file. struct DirectoryName { std::string NameAsWritten; + std::string PathRelativeToRootModuleDirectory; const DirectoryEntry *Entry; explicit operator bool() { return Entry; } @@ -545,7 +550,8 @@ /// module. Header getUmbrellaHeader() const { if (auto *FE = Umbrella.dyn_cast()) - return Header{UmbrellaAsWritten, FE}; + return Header{UmbrellaAsWritten, UmbrellaRelativeToRootModuleDirectory, + FE}; return Header{}; } 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 @@ -649,12 +649,14 @@ /// Sets the umbrella header of the given module to the given /// header. void setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader, - Twine NameAsWritten); + const Twine &NameAsWritten, + const Twine &PathRelativeToRootModuleDirectory); /// Sets the umbrella directory of the given module to the given /// directory. void setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir, - Twine NameAsWritten); + const Twine &NameAsWritten, + const Twine &PathRelativeToRootModuleDirectory); /// Adds this header to the given module. /// \param Role The role of the header wrt the module. diff --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp --- a/clang/lib/Basic/Module.cpp +++ b/clang/lib/Basic/Module.cpp @@ -245,9 +245,10 @@ Module::DirectoryName Module::getUmbrellaDir() const { if (Header U = getUmbrellaHeader()) - return {"", U.Entry->getDir()}; + return {"", "", U.Entry->getDir()}; - return {UmbrellaAsWritten, Umbrella.dyn_cast()}; + return {UmbrellaAsWritten, UmbrellaRelativeToRootModuleDirectory, + Umbrella.dyn_cast()}; } void Module::addTopHeader(const FileEntry *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 @@ -342,7 +342,8 @@ // file relative to the module build directory (the directory containing // the module map file) so this will find the same file that we found // while parsing the module map. - addHeaderInclude(H.NameAsWritten, Includes, LangOpts, Module->IsExternC); + addHeaderInclude(H.PathRelativeToRootModuleDirectory, Includes, LangOpts, + Module->IsExternC); } } // Note that Module->PrivateHeaders will not be a TopHeader. @@ -351,8 +352,8 @@ Module->addTopHeader(UmbrellaHeader.Entry); if (Module->Parent) // Include the umbrella header for submodules. - addHeaderInclude(UmbrellaHeader.NameAsWritten, Includes, LangOpts, - Module->IsExternC); + addHeaderInclude(UmbrellaHeader.PathRelativeToRootModuleDirectory, + Includes, LangOpts, Module->IsExternC); } else if (Module::DirectoryName UmbrellaDir = Module->getUmbrellaDir()) { // Add all of the headers we find in this subdirectory. std::error_code EC; @@ -386,7 +387,8 @@ 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); + SmallString<128> RelativeHeader( + UmbrellaDir.PathRelativeToRootModuleDirectory); for (auto It = Components.rbegin(), End = Components.rend(); It != End; ++It) llvm::sys::path::append(RelativeHeader, *It); @@ -470,7 +472,7 @@ // Dig out the module definition. HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); Module *M = HS.lookupModule(CI.getLangOpts().CurrentModule, - /*AllowSearch=*/false); + /*AllowSearch=*/true); if (!M) { CI.getDiagnostics().Report(diag::err_missing_module) << CI.getLangOpts().CurrentModule << ModuleMapFilename; @@ -528,8 +530,8 @@ SmallString<256> HeaderContents; std::error_code Err = std::error_code(); if (Module::Header UmbrellaHeader = M->getUmbrellaHeader()) - addHeaderInclude(UmbrellaHeader.NameAsWritten, HeaderContents, - CI.getLangOpts(), M->IsExternC); + addHeaderInclude(UmbrellaHeader.PathRelativeToRootModuleDirectory, + HeaderContents, CI.getLangOpts(), M->IsExternC); Err = collectModuleHeaderIncludes( CI.getLangOpts(), FileMgr, CI.getDiagnostics(), CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(), M, diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -297,7 +297,8 @@ << Name; continue; } - Headers.push_back({std::string(Name), &FE->getFileEntry()}); + Headers.push_back( + {std::string(Name), std::string(Name), &FE->getFileEntry()}); } HS.getModuleMap().createHeaderModule(CI.getLangOpts().CurrentModule, Headers); 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 @@ -260,9 +260,10 @@ << UmbrellaMod->getFullModuleName(); else // Record this umbrella header. - setUmbrellaHeader(Mod, *File, RelativePathName.str()); + setUmbrellaHeader(Mod, *File, Header.FileName, RelativePathName.str()); } else { - Module::Header H = {std::string(RelativePathName.str()), *File}; + Module::Header H = {Header.FileName, std::string(RelativePathName.str()), + *File}; if (Header.Kind == Module::HK_Excluded) excludeHeader(Mod, H); else @@ -305,7 +306,7 @@ return false; auto Role = headerKindToRole(Header.Kind); - Module::Header H = {std::string(Path.str()), *File}; + Module::Header H = {Header.FileName, std::string(Path.str()), *File}; addHeader(Mod, H, Role); return true; } @@ -1038,11 +1039,13 @@ Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes; Result->Directory = FrameworkDir; + // Chop off the first framework bit, as that is implied. + StringRef RelativePath = UmbrellaName.str().substr( + Result->getTopLevelModule()->Directory->getName().size()); + RelativePath = llvm::sys::path::relative_path(RelativePath); + // umbrella header "umbrella-header-name" - // - // The "Headers/" component of the name is implied because this is - // a framework module. - setUmbrellaHeader(Result, *UmbrellaHeader, ModuleName + ".h"); + setUmbrellaHeader(Result, *UmbrellaHeader, ModuleName + ".h", RelativePath); // export * Result->Exports.push_back(Module::ExportDecl(nullptr, true)); @@ -1121,11 +1124,14 @@ return Result; } -void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader, - Twine NameAsWritten) { +void ModuleMap::setUmbrellaHeader( + Module *Mod, const FileEntry *UmbrellaHeader, const Twine &NameAsWritten, + const Twine &PathRelativeToRootModuleDirectory) { Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader)); Mod->Umbrella = UmbrellaHeader; Mod->UmbrellaAsWritten = NameAsWritten.str(); + Mod->UmbrellaRelativeToRootModuleDirectory = + PathRelativeToRootModuleDirectory.str(); UmbrellaDirs[UmbrellaHeader->getDir()] = Mod; // Notify callbacks that we just added a new header. @@ -1134,9 +1140,12 @@ } void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir, - Twine NameAsWritten) { + const Twine &NameAsWritten, + const Twine &PathRelativeToRootModuleDirectory) { Mod->Umbrella = UmbrellaDir; Mod->UmbrellaAsWritten = NameAsWritten.str(); + Mod->UmbrellaRelativeToRootModuleDirectory = + PathRelativeToRootModuleDirectory.str(); UmbrellaDirs[UmbrellaDir] = Mod; } @@ -2405,6 +2414,7 @@ } std::string DirName = std::string(Tok.getString()); + std::string DirNameAsWritten = DirName; SourceLocation DirNameLoc = consumeToken(); // Check whether we already have an umbrella. @@ -2446,7 +2456,7 @@ for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E; I != E && !EC; I.increment(EC)) { if (auto FE = SourceMgr.getFileManager().getFile(I->path())) { - Module::Header Header = {std::string(I->path()), *FE}; + Module::Header Header = {"", std::string(I->path()), *FE}; Headers.push_back(std::move(Header)); } } @@ -2467,7 +2477,7 @@ } // Record this umbrella directory. - Map.setUmbrellaDir(ActiveModule, Dir, DirName); + Map.setUmbrellaDir(ActiveModule, Dir, DirNameAsWritten, DirName); } /// Parse a module export declaration. diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -1921,10 +1921,9 @@ std::string Filename = std::string(key.Filename); if (key.Imported) Reader.ResolveImportedPath(M, Filename); - // FIXME: This is not always the right filename-as-written, but we're not - // going to use this information to rebuild the module, so it doesn't make - // a lot of difference. - Module::Header H = {std::string(key.Filename), *FileMgr.getFile(Filename)}; + // FIXME: NameAsWritten + Module::Header H = {std::string(key.Filename), "", + *FileMgr.getFile(Filename)}; ModMap.addHeader(Mod, H, HeaderRole, /*Imported*/true); HFI.isModuleHeader |= !(HeaderRole & ModuleMap::TextualHeader); } @@ -5618,7 +5617,8 @@ ResolveImportedPath(F, Filename); if (auto Umbrella = PP.getFileManager().getFile(Filename)) { if (!CurrentModule->getUmbrellaHeader()) - ModMap.setUmbrellaHeader(CurrentModule, *Umbrella, Blob); + // FIXME: NameAsWritten + ModMap.setUmbrellaHeader(CurrentModule, *Umbrella, Blob, ""); else if (CurrentModule->getUmbrellaHeader().Entry != *Umbrella) { if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) Error("mismatched umbrella headers in submodule"); @@ -5651,7 +5651,8 @@ ResolveImportedPath(F, Dirname); if (auto Umbrella = PP.getFileManager().getDirectory(Dirname)) { if (!CurrentModule->getUmbrellaDir()) - ModMap.setUmbrellaDir(CurrentModule, *Umbrella, Blob); + // FIXME: NameAsWritten + ModMap.setUmbrellaDir(CurrentModule, *Umbrella, Blob, ""); else if (CurrentModule->getUmbrellaDir().Entry != *Umbrella) { if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) Error("mismatched umbrella directories in submodule"); diff --git a/clang/test/Modules/Inputs/explicit-build-inferred/frameworks/Inferred.framework/Headers/Inferred.h b/clang/test/Modules/Inputs/explicit-build-inferred/frameworks/Inferred.framework/Headers/Inferred.h new file mode 100644 --- /dev/null +++ b/clang/test/Modules/Inputs/explicit-build-inferred/frameworks/Inferred.framework/Headers/Inferred.h @@ -0,0 +1 @@ +typedef int inferred; diff --git a/clang/test/Modules/Inputs/explicit-build-inferred/frameworks/module.modulemap b/clang/test/Modules/Inputs/explicit-build-inferred/frameworks/module.modulemap new file mode 100644 --- /dev/null +++ b/clang/test/Modules/Inputs/explicit-build-inferred/frameworks/module.modulemap @@ -0,0 +1 @@ +framework module * {} diff --git a/clang/test/Modules/explicit-build-inferred.cpp b/clang/test/Modules/explicit-build-inferred.cpp new file mode 100644 --- /dev/null +++ b/clang/test/Modules/explicit-build-inferred.cpp @@ -0,0 +1,13 @@ +// RUN: rm -rf %t && mkdir %t +// +// RUN: %clang_cc1 -fmodules -fno-implicit-modules -fimplicit-module-maps \ +// RUN: -emit-module -x c++ %S/Inputs/explicit-build-inferred/frameworks/module.modulemap \ +// RUN: -fmodule-name=Inferred -o %t/Inferred.pcm -F %S/Inputs/explicit-build-inferred/frameworks +// +// RUN: %clang_cc1 -fmodules -fno-implicit-modules -fsyntax-only %s \ +// RUN: -fmodule-map-file=%S/Inputs/explicit-build-inferred/frameworks/module.modulemap \ +// RUN: -fmodule-file=%t/Inferred.pcm -F %S/Inputs/explicit-build-inferred/frameworks + +#include + +inferred a = 0;