hiraditya updated this revision to Diff 71827.
hiraditya added a comment.

Added a test case (contributed by Eric).


https://reviews.llvm.org/D24682

Files:
  clang/lib/CodeGen/CGCXX.cpp
  clang/test/CodeGenCXX/alias-available-externally.cpp

Index: clang/test/CodeGenCXX/alias-available-externally.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/alias-available-externally.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -O1 -std=c++11 -emit-llvm -disable-llvm-passes -o - %s | 
FileCheck %s
+// Clang should not generate alias to available_externally definitions.
+// Check that the destructor of Foo is defined.
+// CHECK: define linkonce_odr void @_ZN3FooD2Ev
+template <class CharT>
+struct String {
+  String() {}
+  ~String();
+};
+
+template <class CharT>
+inline __attribute__((visibility("hidden"), always_inline))
+String<CharT>::~String() {}
+
+extern template struct String<char>;
+
+struct Foo : public String<char> { Foo() { String<char> s; } };
+
+Foo f;
Index: clang/lib/CodeGen/CGCXX.cpp
===================================================================
--- clang/lib/CodeGen/CGCXX.cpp
+++ clang/lib/CodeGen/CGCXX.cpp
@@ -134,6 +134,16 @@
   llvm::GlobalValue::LinkageTypes TargetLinkage =
       getFunctionLinkage(TargetDecl);
 
+  // Disallow aliases to available_externally because available_externally
+  // will not be there in the end to allow the creation of the alias (PR30341).
+  // FIXME: An extern template instantiation will create functions with
+  // linkage "AvailableExternally". In libc++, some classes also define
+  // members with attribute "AlwaysInline" and expect no reference to
+  // be generated. It is desirable to reenable this optimisation after
+  // corresponding LLVM changes.
+  if (TargetLinkage == llvm::GlobalValue::AvailableExternallyLinkage)
+    return true;
+
   // Check if we have it already.
   StringRef MangledName = getMangledName(AliasDecl);
   llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
@@ -157,13 +167,7 @@
   // Instead of creating as alias to a linkonce_odr, replace all of the uses
   // of the aliasee.
   if (llvm::GlobalValue::isDiscardableIfUnused(Linkage) &&
-     (TargetLinkage != llvm::GlobalValue::AvailableExternallyLinkage ||
-      !TargetDecl.getDecl()->hasAttr<AlwaysInlineAttr>())) {
-    // FIXME: An extern template instantiation will create functions with
-    // linkage "AvailableExternally". In libc++, some classes also define
-    // members with attribute "AlwaysInline" and expect no reference to
-    // be generated. It is desirable to reenable this optimisation after
-    // corresponding LLVM changes.
+      !TargetDecl.getDecl()->hasAttr<AlwaysInlineAttr>()) {
     addReplacement(MangledName, Aliasee);
     return false;
   }


Index: clang/test/CodeGenCXX/alias-available-externally.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/alias-available-externally.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -O1 -std=c++11 -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
+// Clang should not generate alias to available_externally definitions.
+// Check that the destructor of Foo is defined.
+// CHECK: define linkonce_odr void @_ZN3FooD2Ev
+template <class CharT>
+struct String {
+  String() {}
+  ~String();
+};
+
+template <class CharT>
+inline __attribute__((visibility("hidden"), always_inline))
+String<CharT>::~String() {}
+
+extern template struct String<char>;
+
+struct Foo : public String<char> { Foo() { String<char> s; } };
+
+Foo f;
Index: clang/lib/CodeGen/CGCXX.cpp
===================================================================
--- clang/lib/CodeGen/CGCXX.cpp
+++ clang/lib/CodeGen/CGCXX.cpp
@@ -134,6 +134,16 @@
   llvm::GlobalValue::LinkageTypes TargetLinkage =
       getFunctionLinkage(TargetDecl);
 
+  // Disallow aliases to available_externally because available_externally
+  // will not be there in the end to allow the creation of the alias (PR30341).
+  // FIXME: An extern template instantiation will create functions with
+  // linkage "AvailableExternally". In libc++, some classes also define
+  // members with attribute "AlwaysInline" and expect no reference to
+  // be generated. It is desirable to reenable this optimisation after
+  // corresponding LLVM changes.
+  if (TargetLinkage == llvm::GlobalValue::AvailableExternallyLinkage)
+    return true;
+
   // Check if we have it already.
   StringRef MangledName = getMangledName(AliasDecl);
   llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
@@ -157,13 +167,7 @@
   // Instead of creating as alias to a linkonce_odr, replace all of the uses
   // of the aliasee.
   if (llvm::GlobalValue::isDiscardableIfUnused(Linkage) &&
-     (TargetLinkage != llvm::GlobalValue::AvailableExternallyLinkage ||
-      !TargetDecl.getDecl()->hasAttr<AlwaysInlineAttr>())) {
-    // FIXME: An extern template instantiation will create functions with
-    // linkage "AvailableExternally". In libc++, some classes also define
-    // members with attribute "AlwaysInline" and expect no reference to
-    // be generated. It is desirable to reenable this optimisation after
-    // corresponding LLVM changes.
+      !TargetDecl.getDecl()->hasAttr<AlwaysInlineAttr>()) {
     addReplacement(MangledName, Aliasee);
     return false;
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to