From: John McCall Date: Mon, 19 Sep 2011 18:05:26 +0000 (+0000) Subject: In apple-kext mode, use external linkage for explicit template instantiations X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5584d91c938384b57563edbca5c2d4f1c66ff02a;p=clang In apple-kext mode, use external linkage for explicit template instantiations instead of internal linkage. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@140030 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 19c3b064d6..917f4b7545 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/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/test/CodeGenCXX/apple-kext-linkage.C b/test/CodeGenCXX/apple-kext-linkage.C index 9df1151176..59d228e230 100644 --- a/test/CodeGenCXX/apple-kext-linkage.C +++ b/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 void bar() {} +template void bar(); +// CHECK: define internal i32 @_Z5identIiET_S0_( template 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(