]> granicus.if.org Git - clang/commitdiff
Avoid producing mismatched comdats.
authorRafael Espindola <rafael.espindola@gmail.com>
Tue, 12 Nov 2013 22:06:46 +0000 (22:06 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Tue, 12 Nov 2013 22:06:46 +0000 (22:06 +0000)
The problem was that given

template<typename T>
struct foo {
  ~foo() {}
};
template class foo<int>;

We would produce a alias, creating a comdat with D0 and D1, since the symbols
have to be weak. Another TU is not required to have a explicit template
instantiation definition or an explict template instantiation declaration and
for

template<typename T>
struct foo {
  ~foo() {}
};
foo<int> a;

we would produce a comdat with only one symbol in it.

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

lib/CodeGen/CGCXX.cpp
test/CodeGenCXX/ctor-dtor-alias.cpp

index 0f55616ea6b14788ca3bd6bec390e036773faa32..b16c59d5f65032e3e975d02c13e90e53d902a83a 100644 (file)
@@ -146,14 +146,15 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
     /// how aliases work.
     if (Ref->isDeclaration())
       return true;
-
-    // Don't create an alias to a linker weak symbol unless we know we can do
-    // that in every TU. This avoids producing different COMDATs in different
-    // TUs.
-    if (llvm::GlobalValue::isWeakForLinker(TargetLinkage))
-      return true;
   }
 
+  // Don't create an alias to a linker weak symbol. This avoids producing
+  // different COMDATs in different TUs. Another option would be to
+  // output the alias both for weak_odr and linkonce_odr, but that
+  // requires explicit comdat support in the IL.
+  if (llvm::GlobalValue::isWeakForLinker(TargetLinkage))
+    return true;
+
   // Create the alias with no name.
   llvm::GlobalAlias *Alias = 
     new llvm::GlobalAlias(AliasType, Linkage, "", Aliasee, &getModule());
index ef56564d3dd82234fe28d25697eac2f0f8155306..266eecc8093de0614e1dc78c1913a887a84cd735 100644 (file)
@@ -1,10 +1,14 @@
 // RUN: %clang_cc1 %s -triple x86_64-linux -emit-llvm -o - -mconstructor-aliases | FileCheck %s
 
 namespace test1 {
-// test that we produce an alias when the destructor is weak_odr
+// test that we don't produce an alias when the destructor is weak_odr. The
+// reason to avoid it that another TU might have no explicit template
+// instantiation definition or declaration, causing it to to output only
+// one of the destructors as linkonce_odr, producing a different comdat.
+
+// CHECK-DAG: define weak_odr void @_ZN5test16foobarIvEC2Ev
+// CHECK-DAG: define weak_odr void @_ZN5test16foobarIvEC1Ev
 
-// CHECK-DAG: @_ZN5test16foobarIvEC1Ev = alias weak_odr void (%"struct.test1::foobar"*)* @_ZN5test16foobarIvEC2Ev
-// CHECK-DAG: define weak_odr void @_ZN5test16foobarIvEC2Ev(
 template <typename T> struct foobar {
   foobar() {}
 };