diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-01-13 22:31:52 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-01-13 22:31:52 +0000 |
commit | 3a5999bc1cc661a0f71e0a186d12a8cbb3c9223c (patch) | |
tree | 66874550405b1917278b80b29582967fba1881da /clang/lib | |
parent | 071c69cd7c114409926c9bbc29233cc8ab19841f (diff) | |
download | bcm5719-llvm-3a5999bc1cc661a0f71e0a186d12a8cbb3c9223c.tar.gz bcm5719-llvm-3a5999bc1cc661a0f71e0a186d12a8cbb3c9223c.zip |
When inferring a module for a framework, first determine whether that
framework is actually a subframework within a top-level framework. If
so, only infer a module for the top-level framework and then dig out
the appropriate submodule.
This helps us cope with an amusing subframeworks anti-pattern, where
one uses -F <framework>/Frameworks to get direct include access to the
subframeworks of a framework (which otherwise would not be
permitted).
llvm-svn: 148148
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Lex/HeaderSearch.cpp | 47 |
1 files changed, 44 insertions, 3 deletions
diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index 070daa0cd12..6d2d72fc22d 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -860,7 +860,7 @@ Module *HeaderSearch::getModule(StringRef Name, bool AllowSearch) { } Module *HeaderSearch::getFrameworkModule(StringRef Name, - const DirectoryEntry *Dir) { + const DirectoryEntry *Dir) { if (Module *Module = ModMap.findModule(Name)) return Module; @@ -876,9 +876,50 @@ Module *HeaderSearch::getFrameworkModule(StringRef Name, case LMM_NewlyLoaded: return ModMap.findModule(Name); } + + // The top-level framework directory, from which we'll infer a framework + // module. + const DirectoryEntry *TopFrameworkDir = Dir; + + // The path from the module we're actually looking for back to the top-level + // framework name. + llvm::SmallVector<StringRef, 2> SubmodulePath; + SubmodulePath.push_back(Name); - // Try to infer a module map. - return ModMap.inferFrameworkModule(Name, Dir, /*Parent=*/0); + // Walk the directory structure to find any enclosing frameworks. + StringRef DirName = Dir->getName(); + do { + // Get the parent directory name. + DirName = llvm::sys::path::parent_path(DirName); + if (DirName.empty()) + break; + + // Determine whether this directory exists. + Dir = FileMgr.getDirectory(DirName); + if (!Dir) + break; + + // If this is a framework directory, then we're a subframework of this + // framework. + if (llvm::sys::path::extension(DirName) == ".framework") { + SubmodulePath.push_back(llvm::sys::path::stem(DirName)); + TopFrameworkDir = Dir; + } + } while (true); + + // Try to infer a module map from the top-level framework directory. + Module *Result = ModMap.inferFrameworkModule(SubmodulePath.back(), + TopFrameworkDir, + /*Parent=*/0); + + // Follow the submodule path to find the requested (sub)framework module + // within the top-level framework module. + SubmodulePath.pop_back(); + while (!SubmodulePath.empty() && Result) { + Result = ModMap.lookupModuleQualified(SubmodulePath.back(), Result); + SubmodulePath.pop_back(); + } + return Result; } |