Use aliases for more constructors and destructors.

With this patch we produce alias for cases like

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

We just have to be careful to produce the same aliases in every TU because
of comdats.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@194000 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index 7dd850b..25f3e6f 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -95,12 +95,16 @@
     return true;
 
   return TryEmitDefinitionAsAlias(GlobalDecl(D, Dtor_Base),
-                                  GlobalDecl(BaseD, Dtor_Base));
+                                  GlobalDecl(BaseD, Dtor_Base),
+                                  false);
 }
 
 /// Try to emit a definition as a global alias for another definition.
+/// If \p InEveryTU is true, we know that an equivalent alias can be produced
+/// in every translation unit.
 bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
-                                             GlobalDecl TargetDecl) {
+                                             GlobalDecl TargetDecl,
+                                             bool InEveryTU) {
   if (!getCodeGenOpts().CXXCtorDtorAliases)
     return true;
 
@@ -108,34 +112,34 @@
   // 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:
-    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 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)) {
+    if (!InEveryTU)
+      return true;
+
+    // In addition to making sure we produce it in every TU, we have to make
+    // sure llvm keeps it.
+    // FIXME: Instead of outputting an alias we could just replace every use of
+    // AliasDecl with TargetDecl.
+    assert(Linkage == TargetLinkage);
+    Linkage = llvm::GlobalValue::WeakODRLinkage;
+  }
+
+  // We can't use an alias if the linkage is not valid for one.
+  if (!llvm::GlobalAlias::isValidLinkage(Linkage))
     return true;
 
+  // Check if we have it already.
+  StringRef MangledName = getMangledName(AliasDecl);
+  llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
+  if (Entry && !Entry->isDeclaration())
+    return false;
+
   // Derive the type for the alias.
   llvm::PointerType *AliasType
     = getTypes().GetFunctionType(AliasDecl)->getPointerTo();
@@ -153,10 +157,7 @@
     new llvm::GlobalAlias(AliasType, Linkage, "", Aliasee, &getModule());
 
   // Switch any previous uses to the alias.
-  StringRef MangledName = getMangledName(AliasDecl);
-  llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
   if (Entry) {
-    assert(Entry->isDeclaration() && "definition already exists for alias");
     assert(Entry->getType() == AliasType &&
            "declaration exists with different type");
     Alias->takeName(Entry);
@@ -177,11 +178,14 @@
   // The complete constructor is equivalent to the base constructor
   // for classes with no virtual bases.  Try to emit it as an alias.
   if (getTarget().getCXXABI().hasConstructorVariants() &&
-      ctorType == Ctor_Complete &&
       !ctor->getParent()->getNumVBases() &&
-      !TryEmitDefinitionAsAlias(GlobalDecl(ctor, Ctor_Complete),
-                                GlobalDecl(ctor, Ctor_Base)))
-    return;
+      (ctorType == Ctor_Complete || ctorType == Ctor_Base)) {
+    bool ProducedAlias =
+        !TryEmitDefinitionAsAlias(GlobalDecl(ctor, Ctor_Complete),
+                                  GlobalDecl(ctor, Ctor_Base), true);
+    if (ctorType == Ctor_Complete && ProducedAlias)
+      return;
+  }
 
   const CGFunctionInfo &fnInfo =
     getTypes().arrangeCXXConstructorDeclaration(ctor, ctorType);
@@ -218,11 +222,18 @@
                                       CXXDtorType dtorType) {
   // The complete destructor is equivalent to the base destructor for
   // classes with no virtual bases, so try to emit it as an alias.
-  if (dtorType == Dtor_Complete &&
-      !dtor->getParent()->getNumVBases() &&
-      !TryEmitDefinitionAsAlias(GlobalDecl(dtor, Dtor_Complete),
-                                GlobalDecl(dtor, Dtor_Base)))
-    return;
+  if (!dtor->getParent()->getNumVBases() &&
+      (dtorType == Dtor_Complete || dtorType == Dtor_Base)) {
+    bool ProducedAlias =
+        !TryEmitDefinitionAsAlias(GlobalDecl(dtor, Dtor_Complete),
+                                  GlobalDecl(dtor, Dtor_Base), true);
+    if (ProducedAlias) {
+      if (dtorType == Dtor_Complete)
+        return;
+      if (dtor->isVirtual())
+        getVTables().EmitThunks(GlobalDecl(dtor, Dtor_Complete));
+    }
+  }
 
   // The base destructor is equivalent to the base destructor of its
   // base class if there is exactly one non-virtual base class with a
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp
index 0956fee..996bd90 100644
--- a/lib/CodeGen/CGVTables.cpp
+++ b/lib/CodeGen/CGVTables.cpp
@@ -387,10 +387,6 @@
       return;
     }
 
-    // If a function has a body, it should have available_externally linkage.
-    assert(ThunkFn->hasAvailableExternallyLinkage() &&
-           "Function should have available_externally linkage!");
-
     // Change the linkage.
     CGM.setFunctionLinkage(GD, ThunkFn);
     return;
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 25aaae6..249ad33 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -1034,7 +1034,8 @@
   
   // C++ related functions.
 
-  bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target);
+  bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target,
+                                bool InEveryTU);
   bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D);
 
   void EmitNamespace(const NamespaceDecl *D);