From: Douglas Gregor Date: Tue, 6 Dec 2011 19:39:29 +0000 (+0000) Subject: When inferring a module map for a framework, infer subframework X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ac252a3b0f8101a7274309e4a5cf2d5f0fdba675;p=clang When inferring a module map for a framework, infer subframework modules for each of its subframeworks. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@145957 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h index 1ef4f674e2..262e50db23 100644 --- a/include/clang/Lex/ModuleMap.h +++ b/include/clang/Lex/ModuleMap.h @@ -146,7 +146,8 @@ public: /// \brief Infer the contents of a framework module map from the given /// framework directory. Module *inferFrameworkModule(StringRef ModuleName, - const DirectoryEntry *FrameworkDir); + const DirectoryEntry *FrameworkDir, + Module *Parent); /// \brief Retrieve the module map file containing the definition of the given /// module. diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index f090e03174..1b969b93be 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -849,7 +849,7 @@ Module *HeaderSearch::getFrameworkModule(StringRef Name, } // Try to infer a module map. - return ModMap.inferFrameworkModule(Name, Dir); + return ModMap.inferFrameworkModule(Name, Dir, /*Parent=*/0); } diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index 581a5d5631..ac5ae1e311 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -20,6 +20,7 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetOptions.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" #include "llvm/Support/PathV2.h" #include "llvm/Support/raw_ostream.h" @@ -219,17 +220,19 @@ ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework, Module * ModuleMap::inferFrameworkModule(StringRef ModuleName, - const DirectoryEntry *FrameworkDir) { + const DirectoryEntry *FrameworkDir, + Module *Parent) { // Check whether we've already found this module. - if (Module *Module = findModule(ModuleName)) - return Module; + if (Module *Mod = lookupModuleQualified(ModuleName, Parent)) + return Mod; + + FileManager &FileMgr = SourceMgr->getFileManager(); // Look for an umbrella header. llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName()); llvm::sys::path::append(UmbrellaName, "Headers"); llvm::sys::path::append(UmbrellaName, ModuleName + ".h"); - const FileEntry *UmbrellaHeader - = SourceMgr->getFileManager().getFile(UmbrellaName); + const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName); // FIXME: If there's no umbrella header, we could probably scan the // framework to load *everything*. But, it's not clear that this is a good @@ -237,8 +240,14 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName, if (!UmbrellaHeader) return 0; - Module *Result = new Module(ModuleName, SourceLocation(), - /*IsFramework=*/true); + Module *Result = new Module(ModuleName, SourceLocation(), Parent, + /*IsFramework=*/true, /*IsExplicit=*/false); + + if (Parent) + Parent->SubModules[ModuleName] = Result; + else + Modules[ModuleName] = Result; + // umbrella "umbrella-header-name" Result->UmbrellaHeader = UmbrellaHeader; Headers[UmbrellaHeader] = Result; @@ -251,9 +260,24 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName, Result->InferSubmodules = true; Result->InferExportWildcard = true; - // FIXME: Look for subframeworks. + // Look for subframeworks. + llvm::error_code EC; + llvm::SmallString<128> SubframeworksDirName = StringRef(FrameworkDir->getName()); + llvm::sys::path::append(SubframeworksDirName, "Frameworks"); + for (llvm::sys::fs::directory_iterator Dir(SubframeworksDirName.str(), EC), + DirEnd; + Dir != DirEnd && !EC; Dir.increment(EC)) { + if (!StringRef(Dir->path()).endswith(".framework")) + continue; + + if (const DirectoryEntry *SubframeworkDir + = FileMgr.getDirectory(Dir->path())) { + // FIXME: Do we want to warn about subframeworks without umbrella headers? + inferFrameworkModule(llvm::sys::path::stem(Dir->path()), SubframeworkDir, + Result); + } + } - Modules[ModuleName] = Result; return Result; } diff --git a/test/Modules/Inputs/Module.framework/Frameworks/SubFramework.framework/Headers/SubFramework.h b/test/Modules/Inputs/Module.framework/Frameworks/SubFramework.framework/Headers/SubFramework.h new file mode 100644 index 0000000000..438fc9c516 --- /dev/null +++ b/test/Modules/Inputs/Module.framework/Frameworks/SubFramework.framework/Headers/SubFramework.h @@ -0,0 +1,4 @@ +#ifndef MODULE_SUBFRAMEWORK_H +#define MODULE_SUBFRAMEWORK_H +char *module_subframework; +#endif diff --git a/test/Modules/auto-module-import.c b/test/Modules/auto-module-import.c index 4c71f06a84..373c0411bd 100644 --- a/test/Modules/auto-module-import.c +++ b/test/Modules/auto-module-import.c @@ -29,3 +29,13 @@ void testSubframeworkOther() { void testSubframeworkOtherAgain() { double *sfo1 = sub_framework_other; } + +void testModuleSubFramework() { + char *msf = module_subframework; +} + +#include // expected-warning{{treating #include as an import of module 'Module.SubFramework'}} + +void testModuleSubFrameworkAgain() { + char *msf = module_subframework; +} diff --git a/test/Modules/on-demand-build.m b/test/Modules/on-demand-build.m index 2c6a759b43..7843014453 100644 --- a/test/Modules/on-demand-build.m +++ b/test/Modules/on-demand-build.m @@ -16,7 +16,7 @@ void test_getModuleVersion() { OtherClass *other = [Module alloc]; // expected-error{{init}} } -#ifdef MODULE_H -# error MODULE_H should not be hidden +#ifdef MODULE_SUBFRAMEWORK_H +# error MODULE_SUBFRAMEWORK_H should be hidden #endif