aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-11-17 01:41:17 +0000
committerDouglas Gregor <dgregor@apple.com>2011-11-17 01:41:17 +0000
commit2821c7f8870629b56b9c41e1c50c7a091edd544d (patch)
treebb4276ce86ceb2228834e36daa67c0d07fa07443
parenteeea7c44a6986752fedee1ef1bcef855db373872 (diff)
When we're loading a framework header, first try to turn the framework
into a module. This module can either be loaded from a module map in the framework directory (which isn't quite working yet) or inferred from an umbrella header (which does work, and replaces the existing hack). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@144877 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Lex/HeaderSearch.h14
-rw-r--r--include/clang/Lex/ModuleMap.h5
-rw-r--r--lib/Lex/HeaderSearch.cpp48
-rw-r--r--lib/Lex/ModuleMap.cpp28
-rw-r--r--test/Modules/auto-module-import.c2
5 files changed, 90 insertions, 7 deletions
diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h
index 07cdc55180..21654c16cc 100644
--- a/include/clang/Lex/HeaderSearch.h
+++ b/include/clang/Lex/HeaderSearch.h
@@ -389,6 +389,20 @@ public:
///
/// \returns The module, if found; otherwise, null.
ModuleMap::Module *getModule(StringRef Name, bool AllowSearch = true);
+
+ /// \brief Retrieve a module with the given name, which may be part of the
+ /// given framework.
+ ///
+ /// \param Name The name of the module to retrieve.
+ ///
+ /// \param Dir The framework directory (e.g., ModuleName.framework).
+ ///
+ /// \returns The module, if found; otherwise, null.
+ ModuleMap::Module *getFrameworkModule(StringRef Name,
+ const DirectoryEntry *Dir);
+
+ /// \brief Retrieve the module map.
+ ModuleMap &getModuleMap() { return ModMap; }
unsigned header_file_size() const { return FileInfo.size(); }
diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h
index 74cca6b881..e9bf1b35c1 100644
--- a/include/clang/Lex/ModuleMap.h
+++ b/include/clang/Lex/ModuleMap.h
@@ -137,6 +137,11 @@ public:
/// \returns The named module, if known; otherwise, returns null.
Module *findModule(StringRef Name);
+ /// \brief Infer the contents of a framework module map from the given
+ /// framework directory.
+ Module *inferFrameworkModule(StringRef ModuleName,
+ const DirectoryEntry *FrameworkDir);
+
/// \brief Parse the given module map file, and record any modules we
/// encounter.
///
diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp
index 161c4b6d14..cc9c8c16f7 100644
--- a/lib/Lex/HeaderSearch.cpp
+++ b/lib/Lex/HeaderSearch.cpp
@@ -311,7 +311,8 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
FrameworkName.push_back('/');
// FrameworkName = "/System/Library/Frameworks/Cocoa"
- FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos);
+ StringRef ModuleName(Filename.begin(), SlashPos);
+ FrameworkName += ModuleName;
// FrameworkName = "/System/Library/Frameworks/Cocoa.framework/"
FrameworkName += ".framework/";
@@ -337,6 +338,18 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
}
+ // If we're allowed to look for modules, try to load or create the module
+ // corresponding to this framework.
+ ModuleMap::Module *Module = 0;
+ if (SuggestedModule) {
+ if (const DirectoryEntry *FrameworkDir
+ = FileMgr.getDirectory(FrameworkName)) {
+ if ((Module = HS.getFrameworkModule(ModuleName, FrameworkDir)) &&
+ Module->Name == BuildingModule)
+ Module = 0;
+ }
+ }
+
// Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h"
unsigned OrigSize = FrameworkName.size();
@@ -348,16 +361,16 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1);
}
- /// Determine whether this is the module we're building or not.
- bool AutomaticImport = SuggestedModule &&
- (BuildingModule != StringRef(Filename.begin(), SlashPos)) &&
+ // Determine whether this is the module we're building or not.
+ // FIXME: Do we still need the ".." hack?
+ bool AutomaticImport = Module &&
!Filename.substr(SlashPos + 1).startswith("..");
FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end());
if (const FileEntry *FE = FileMgr.getFile(FrameworkName.str(),
/*openFile=*/!AutomaticImport)) {
if (AutomaticImport)
- *SuggestedModule = StringRef(Filename.begin(), SlashPos);
+ *SuggestedModule = Module->Name;
return FE;
}
@@ -372,7 +385,7 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
const FileEntry *FE = FileMgr.getFile(FrameworkName.str(),
/*openFile=*/!AutomaticImport);
if (FE && AutomaticImport)
- *SuggestedModule = StringRef(Filename.begin(), SlashPos);
+ *SuggestedModule = Module->Name;
return FE;
}
@@ -839,6 +852,29 @@ ModuleMap::Module *HeaderSearch::getModule(StringRef Name, bool AllowSearch) {
return 0;
}
+
+ModuleMap::Module *HeaderSearch::getFrameworkModule(StringRef Name,
+ const DirectoryEntry *Dir) {
+ if (ModuleMap::Module *Module = ModMap.findModule(Name))
+ return Module;
+
+ // Try to load a module map file.
+ switch (loadModuleMapFile(Dir)) {
+ case LMM_InvalidModuleMap:
+ break;
+
+ case LMM_AlreadyLoaded:
+ case LMM_NoDirectory:
+ return 0;
+
+ case LMM_NewlyLoaded:
+ return ModMap.findModule(Name);
+ }
+
+ // Try to infer a module map.
+ return ModMap.inferFrameworkModule(Name, Dir);
+}
+
HeaderSearch::LoadModuleMapResult
HeaderSearch::loadModuleMapFile(StringRef DirName) {
diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp
index f6751b78f1..0c51659cab 100644
--- a/lib/Lex/ModuleMap.cpp
+++ b/lib/Lex/ModuleMap.cpp
@@ -127,6 +127,34 @@ ModuleMap::Module *ModuleMap::findModule(StringRef Name) {
return 0;
}
+ModuleMap::Module *
+ModuleMap::inferFrameworkModule(StringRef ModuleName,
+ const DirectoryEntry *FrameworkDir) {
+ // Check whether we've already found this module.
+ if (Module *Module = findModule(ModuleName))
+ return Module;
+
+ // 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);
+
+ // 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
+ // idea.
+ if (!UmbrellaHeader)
+ return 0;
+
+ Module *Result = new Module(ModuleName, SourceLocation());
+ Result->UmbrellaHeader = UmbrellaHeader;
+ Headers[UmbrellaHeader] = Result;
+ UmbrellaDirs[FrameworkDir] = Result;
+ Modules[ModuleName] = Result;
+ return Result;
+}
+
static void indent(llvm::raw_ostream &OS, unsigned Spaces) {
OS << std::string(' ', Spaces);
}
diff --git a/test/Modules/auto-module-import.c b/test/Modules/auto-module-import.c
index 0187174238..1dda642593 100644
--- a/test/Modules/auto-module-import.c
+++ b/test/Modules/auto-module-import.c
@@ -1,6 +1,6 @@
// RUN: rm -rf %t
-// RUN: %clang_cc1 -x objective-c -fmodule-cache-path %t -fauto-module-import -F %S/Inputs -verify %s
+// RUN: %clang_cc1 -x objective-c -fmodule-cache-path %t -fauto-module-import -F %S/Inputs %s -verify
#include <DependsOnModule/DependsOnModule.h>