]> granicus.if.org Git - clang/commitdiff
In apple-kext mode, use external linkage for explicit template instantiations
authorJohn McCall <rjmccall@apple.com>
Mon, 19 Sep 2011 18:05:26 +0000 (18:05 +0000)
committerJohn McCall <rjmccall@apple.com>
Mon, 19 Sep 2011 18:05:26 +0000 (18:05 +0000)
instead of internal linkage.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@140030 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CodeGenModule.cpp
test/CodeGenCXX/apple-kext-linkage.C

index 19c3b064d65d8188658637bb51328a83b8fad21e..917f4b7545aa72efcbeb3a25e939fa9bb0cbd90b 100644 (file)
@@ -400,7 +400,12 @@ CodeGenModule::getFunctionLinkage(const FunctionDecl *D) {
   // definition somewhere else, so we can use available_externally linkage.
   if (Linkage == GVA_C99Inline)
     return llvm::Function::AvailableExternallyLinkage;
-  
+
+  // Note that Apple's kernel linker doesn't support symbol
+  // coalescing, so we need to avoid linkonce and weak linkages there.
+  // Normally, this means we just map to internal, but for explicit
+  // instantiations we'll map to external.
+
   // In C++, the compiler has to emit a definition in every translation unit
   // that references the function.  We should use linkonce_odr because
   // a) if all references in this translation unit are optimized away, we
@@ -419,7 +424,7 @@ CodeGenModule::getFunctionLinkage(const FunctionDecl *D) {
   if (Linkage == GVA_ExplicitTemplateInstantiation)
     return !Context.getLangOptions().AppleKext
              ? llvm::Function::WeakODRLinkage
-             : llvm::Function::InternalLinkage;
+             : llvm::Function::ExternalLinkage;
   
   // Otherwise, we have strong external linkage.
   assert(Linkage == GVA_StrongExternal);
index 9df11511762c9b2bd6acd198d16261dfe11908e6..59d228e2300c38543657e627562c8408bc10a663 100644 (file)
@@ -13,13 +13,21 @@ void foo() {
   Derived d1;                  // ok
 }
 
+// CHECK: define internal i32 @_Z1fj(
 inline unsigned f(unsigned n) { return n == 0 ? 0 : n + f(n-1); }
 
 unsigned g(unsigned n) { return f(n); }
 
+// rdar://problem/10133200: give explicit instantiations external linkage in kernel mode
+// CHECK: define void @_Z3barIiEvv()
+template <typename T> void bar() {}
+template void bar<int>();
 
+// CHECK: define internal i32 @_Z5identIiET_S0_(
 template <typename X> X ident(X x) { return x; }
+
 int foo(int n) { return ident(n); }
 
-// CHECK-NOT: define linkonce_odr
-// CHECK 5 : define internal
+// CHECK: define internal void @_ZN7DerivedD1Ev(
+// CHECK: define internal void @_ZN7DerivedD0Ev(
+// CHECK: define internal void @_ZN7DeriveddlEPv(