aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2013-01-14 17:57:51 +0000
committerDouglas Gregor <dgregor@apple.com>2013-01-14 17:57:51 +0000
commit8767dc29ec23f96e71658f760333bdf5d87283d5 (patch)
tree73cd52be999f6251088eff14f7c70dd913089146
parent19f8e85d2e0ba2b97ad848b5f879ec96ebc1660e (diff)
Infer "link" lines for top-level frameworks. Essentially, a framework
will have a shared library with the same name as its framework (and no suffix!) within its .framework directory. Detect this both when inferring the whole top-level framework and when parsing a module map. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172439 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/Module.h8
-rw-r--r--lib/Lex/ModuleMap.cpp30
-rw-r--r--test/Modules/Inputs/Module.framework/Module0
-rw-r--r--test/Modules/Inputs/NoUmbrella.framework/NoUmbrella0
-rw-r--r--test/Modules/autolink.m14
5 files changed, 50 insertions, 2 deletions
diff --git a/include/clang/Basic/Module.h b/include/clang/Basic/Module.h
index 2bda801d18..6264c2db7b 100644
--- a/include/clang/Basic/Module.h
+++ b/include/clang/Basic/Module.h
@@ -237,7 +237,13 @@ public:
return false;
}
-
+
+ /// \brief Determine whether this module is a subframework of another
+ /// framework.
+ bool isSubFramework() const {
+ return IsFramework && Parent && Parent->isPartOfFramework();
+ }
+
/// \brief Retrieve the full name of this module, including the path from
/// its top-level module.
std::string getFullModuleName() const;
diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp
index 6b0eb79a10..72e79511ee 100644
--- a/lib/Lex/ModuleMap.cpp
+++ b/lib/Lex/ModuleMap.cpp
@@ -383,6 +383,23 @@ bool ModuleMap::canInferFrameworkModule(const DirectoryEntry *ParentDir,
return canInfer;
}
+/// \brief For a framework module, infer the framework against which we
+/// should link.
+static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
+ FileManager &FileMgr) {
+ assert(Mod->IsFramework && "Can only infer linking for framework modules");
+ assert(!Mod->isSubFramework() &&
+ "Can only infer linking for top-level frameworks");
+
+ SmallString<128> LibName;
+ LibName += FrameworkDir->getName();
+ llvm::sys::path::append(LibName, Mod->Name);
+ if (FileMgr.getFile(LibName)) {
+ Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
+ /*IsFramework=*/true));
+ }
+}
+
Module *
ModuleMap::inferFrameworkModule(StringRef ModuleName,
const DirectoryEntry *FrameworkDir,
@@ -537,6 +554,12 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName,
}
}
+ // If the module is a top-level framework, automatically link against the
+ // framework.
+ if (!Result->isSubFramework()) {
+ inferFrameworkLink(Result, FrameworkDir, FileMgr);
+ }
+
return Result;
}
@@ -1147,6 +1170,13 @@ void ModuleMapParser::parseModuleDecl() {
HadError = true;
}
+ // If the active module is a top-level framework, and there are no link
+ // libraries, automatically link against the framework.
+ if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
+ ActiveModule->LinkLibraries.empty()) {
+ inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
+ }
+
// We're done parsing this module. Pop back to the previous module.
ActiveModule = PreviousActiveModule;
}
diff --git a/test/Modules/Inputs/Module.framework/Module b/test/Modules/Inputs/Module.framework/Module
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/Modules/Inputs/Module.framework/Module
diff --git a/test/Modules/Inputs/NoUmbrella.framework/NoUmbrella b/test/Modules/Inputs/NoUmbrella.framework/NoUmbrella
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/Modules/Inputs/NoUmbrella.framework/NoUmbrella
diff --git a/test/Modules/autolink.m b/test/Modules/autolink.m
index e4db6991fc..3c6998f7bf 100644
--- a/test/Modules/autolink.m
+++ b/test/Modules/autolink.m
@@ -13,6 +13,18 @@ int g() {
return autolink;
}
-// CHECK: !llvm.link.libraries = !{![[AUTOLINK:[0-9]+]], ![[AUTOLINK_FRAMEWORK:[0-9]+]]}
+@import Module.SubFramework;
+const char *get_module_subframework() {
+ return module_subframework;
+}
+
+@import NoUmbrella;
+int use_no_umbrella() {
+ return no_umbrella_A;
+}
+
+// CHECK: !llvm.link.libraries = !{![[AUTOLINK:[0-9]+]], ![[AUTOLINK_FRAMEWORK:[0-9]+]], ![[MODULE:[0-9]+]], ![[NOUMBRELLA:[0-9]+]]}
// CHECK: ![[AUTOLINK]] = metadata !{metadata !"autolink", i1 false}
// CHECK: ![[AUTOLINK_FRAMEWORK]] = metadata !{metadata !"autolink_framework", i1 true}
+// CHECK: ![[MODULE]] = metadata !{metadata !"Module", i1 true}
+// CHECK: ![[NOUMBRELLA]] = metadata !{metadata !"NoUmbrella", i1 true}