diff options
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 9 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/apple-kext-linkage.C | 12 |
2 files changed, 17 insertions, 4 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 19c3b064d65..917f4b7545a 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -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); diff --git a/clang/test/CodeGenCXX/apple-kext-linkage.C b/clang/test/CodeGenCXX/apple-kext-linkage.C index 9df11511762..59d228e2300 100644 --- a/clang/test/CodeGenCXX/apple-kext-linkage.C +++ b/clang/test/CodeGenCXX/apple-kext-linkage.C @@ -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( |