Use aliases for more constructors and destructors.
authorRafael Espindola <rafael.espindola@gmail.com>
Wed, 9 Oct 2013 16:13:15 +0000 (16:13 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Wed, 9 Oct 2013 16:13:15 +0000 (16:13 +0000)
With this patch we produce alias for cases like

template<typename T>
struct foobar {
  foobar() {
  }
};
template struct foobar<void>;

It is safe to use aliases to weak symbols, as long and the alias itself is also
weak.

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

lib/CodeGen/CGCXX.cpp
test/CodeGenCXX/destructors.cpp

index 7dd850be0bdd8a0bc297c583c5e5b271fc5b66ae..d181f8d37b249d5d28cde84b5d6c7c2e0a7cb1e0 100644 (file)
@@ -108,32 +108,17 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
   // support aliases with that linkage, fail.
   llvm::GlobalValue::LinkageTypes Linkage = getFunctionLinkage(AliasDecl);
 
-  switch (Linkage) {
-  // We can definitely emit aliases to definitions with external linkage.
-  case llvm::GlobalValue::ExternalLinkage:
-  case llvm::GlobalValue::ExternalWeakLinkage:
-    break;
-
-  // Same with local linkage.
-  case llvm::GlobalValue::InternalLinkage:
-  case llvm::GlobalValue::PrivateLinkage:
-  case llvm::GlobalValue::LinkerPrivateLinkage:
-    break;
-
-  // We should try to support linkonce linkages.
-  case llvm::GlobalValue::LinkOnceAnyLinkage:
-  case llvm::GlobalValue::LinkOnceODRLinkage:
+  // We can't use an alias if the linkage is not valid for one.
+  if (!llvm::GlobalAlias::isValidLinkage(Linkage))
     return true;
 
-  // Other linkages will probably never be supported.
-  default:
-    return true;
-  }
-
   llvm::GlobalValue::LinkageTypes TargetLinkage
     = getFunctionLinkage(TargetDecl);
 
-  if (llvm::GlobalValue::isWeakForLinker(TargetLinkage))
+  // Don't create an strong alias to a linker weak symbol. If the linker
+  // decides to drop the symbol, the alias would become undefined.
+  if (llvm::GlobalValue::isWeakForLinker(TargetLinkage) &&
+      !llvm::GlobalValue::isWeakForLinker(Linkage))
     return true;
 
   // Derive the type for the alias.
index f2c6f212ad63fb7082b76af729e9d69a27d070b7..0be188b29c7b2275c0bac13223110190921773ea 100644 (file)
@@ -6,10 +6,16 @@
 // CHECK: @_ZN5test11OD2Ev = alias {{.*}} @_ZN5test11AD2Ev
 // CHECK: @_ZN5test11SD2Ev = alias bitcast {{.*}} @_ZN5test11AD2Ev
 
+// CHECK: @_ZN6test106foobarIvEC1Ev = alias weak_odr void (%"struct.test10::foobar"*)* @_ZN6test106foobarIvEC2Ev
+
+// CHECK: @_ZN6test116foobarIvEC1Ev = alias linkonce_odr void (%"struct.test11::foobar"*)* @_ZN6test116foobarIvEC2Ev
+
 // CHECK: @_ZN5test312_GLOBAL__N_11DD1Ev = alias internal {{.*}} @_ZN5test312_GLOBAL__N_11DD2Ev
 // CHECK: @_ZN5test312_GLOBAL__N_11DD2Ev = alias internal bitcast {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev
 // CHECK: @_ZN5test312_GLOBAL__N_11CD1Ev = alias internal {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev
 
+// CHECK: @_ZN6PR752617allocator_derivedD1Ev = alias linkonce_odr void (%"struct.PR7526::allocator_derived"*)* @_ZN6PR752617allocator_derivedD2Ev
+
 struct A {
   int a;
   
@@ -44,9 +50,6 @@ namespace PR7526 {
   // CHECK: call void @__cxa_call_unexpected
   allocator::~allocator() throw() { foo(); }
 
-  // CHECK-LABEL: define linkonce_odr void @_ZN6PR752617allocator_derivedD1Ev(%"struct.PR7526::allocator_derived"* %this) unnamed_addr
-  // CHECK-NOT: call void @__cxa_call_unexpected
-  // CHECK:     }
   void foo() {
     allocator_derived ad;
   }
@@ -419,3 +422,25 @@ namespace test9 {
   // CHECK: ret void
 
   // CHECK: attributes [[NUW]] = {{[{].*}} nounwind {{.*[}]}}
+
+
+namespace test10 {
+  template<typename T>
+  struct foobar {
+    foobar() {
+    }
+  };
+
+  template struct foobar<void>;
+}
+
+namespace test11 {
+  void g();
+  template<typename T>
+  struct foobar {
+    foobar() {
+      g();
+    }
+  };
+  foobar<void> x;
+}