diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 8f769d9..2318cf0 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -454,10 +454,32 @@ CodeGenModule::getFunctionLinkage(const FunctionDecl *D) {
   // don't need to codegen it.  b) if the function persists, it needs to be
   // merged with other definitions. c) C++ has the ODR, so we know the
   // definition is dependable.
-  if (Linkage == GVA_CXXInline || Linkage == GVA_TemplateInstantiation)
+  if (Linkage == GVA_CXXInline || Linkage == GVA_TemplateInstantiation) {
+    if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+      if (MD->isVirtual()) {
+        const CXXRecordDecl *RD = MD->getParent();
+        // If the vtable is going to be in another TU, so can this method.
+        if (!getVTables().ShouldEmitVTableInThisTU(RD))
+          return llvm::GlobalVariable::AvailableExternallyLinkage;
+
+        llvm::GlobalVariable::LinkageTypes VTL =
+          getVTableLinkage(MD->getParent());
+        if (VTL == llvm::GlobalVariable::ExternalLinkage)
+          // We used to produce a linkonce_odr linkage in this case. That
+          // maps to a weak symbol and it seems that the darwin linker cannot
+          // handle weak symbols in one TU being strong on another in some
+          // circunstances. Given that, for interoperability with old .o files,
+          // we cannot produce a strong symbol. We at least produce a weak_odr
+          // which prevents the symbol from being dropped.
+          return llvm::Function::WeakODRLinkage;
+        if (VTL == llvm::GlobalVariable::AvailableExternallyLinkage)
+          return llvm::GlobalVariable::AvailableExternallyLinkage;
+      }
+    }
     return !Context.getLangOpts().AppleKext 
              ? llvm::Function::LinkOnceODRLinkage 
              : llvm::Function::InternalLinkage;
+  }
   
   // An explicit instantiation of a template has weak linkage, since
   // explicit instantiations can occur in multiple translation units
diff --git a/test/CodeGenCXX/key-function-weak.cpp b/test/CodeGenCXX/key-function-weak.cpp
new file mode 100644
index 0000000..5d94100
--- /dev/null
+++ b/test/CodeGenCXX/key-function-weak.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+
+struct foo {
+  virtual ~foo();
+};
+struct bar : public foo {
+  virtual void zed();
+};
+void bar::zed() {
+}
+
+// CHECK: define weak_odr void @_ZN3barD0Ev
diff --git a/test/CodeGenCXX/template-linkage.cpp b/test/CodeGenCXX/template-linkage.cpp
index 20508c1..300186c 100644
--- a/test/CodeGenCXX/template-linkage.cpp
+++ b/test/CodeGenCXX/template-linkage.cpp
@@ -37,7 +37,7 @@ template<typename T> void X1<T>::blarg() { }
 extern template struct X0<char>;
 extern template struct X1<char>;
 
-// CHECK: define linkonce_odr void @_ZN2X1IcED1Ev(%struct.X1* %this) unnamed_addr
+// CHECK: declare void @_ZN2X1IcED1Ev(%struct.X1*)
 void test_X1() {
   X1<char> i1c;
 }
diff --git a/test/CodeGenCXX/virtual-implicit-copy-assignment.cpp b/test/CodeGenCXX/virtual-implicit-copy-assignment.cpp
index 70bc6fc..6e4c361 100644
--- a/test/CodeGenCXX/virtual-implicit-copy-assignment.cpp
+++ b/test/CodeGenCXX/virtual-implicit-copy-assignment.cpp
@@ -8,4 +8,4 @@ struct D : B { D(); virtual void a(); };
 void D::a() {}
 
 // CHECK: @_ZTV1D = {{.*}} @_ZN1DaSERKS_ 
-// CHECK: define linkonce_odr {{.*}} @_ZN1DaSERKS_
+// CHECK: define {{.*}} @_ZN1DaSERKS_
diff --git a/test/CodeGenCXX/virtual-implicit-move-assignment.cpp b/test/CodeGenCXX/virtual-implicit-move-assignment.cpp
index d8ac1ed..59c5516 100644
--- a/test/CodeGenCXX/virtual-implicit-move-assignment.cpp
+++ b/test/CodeGenCXX/virtual-implicit-move-assignment.cpp
@@ -9,4 +9,4 @@ void D::a() {}
 D d;
 
 // CHECK: @_ZTV1D = {{.*}} @_ZN1DaSEOS_ 
-// CHECK: define linkonce_odr {{.*}} @_ZN1DaSEOS_
+// CHECK: define {{.*}} @_ZN1DaSEOS_
