Adjust r194296 to not apply the alias replacement for externally

available always-inline functions. This breaks libc++'s locale
implementation. Code generation for this case should be fixed, but this
is a stop gap fix for clang 3.4.

llvm-svn: 195501
This commit is contained in:
Joerg Sonnenberger 2013-11-22 21:34:35 +00:00
parent b39751bc9f
commit 374c2bb37e
2 changed files with 40 additions and 1 deletions

View File

@ -140,7 +140,14 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
// Instead of creating as alias to a linkonce_odr, replace all of the uses
// of the aliassee.
if (llvm::GlobalValue::isDiscardableIfUnused(Linkage)) {
if (llvm::GlobalValue::isDiscardableIfUnused(Linkage) &&
(TargetLinkage != llvm::GlobalValue::AvailableExternallyLinkage ||
!TargetDecl.getDecl()->hasAttr<AlwaysInlineAttr>())) {
// FIXME: An extern template instanciation 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.
Replacements[MangledName] = Aliasee;
return false;
}

View File

@ -1,6 +1,9 @@
// RUN: %clang_cc1 %s -triple x86_64-linux -emit-llvm -o - -mconstructor-aliases -O1 -disable-llvm-optzns | FileCheck %s
// RUN: %clang_cc1 %s -triple x86_64-linux -emit-llvm -o - -mconstructor-aliases | FileCheck --check-prefix=NOOPT %s
// RUN: %clang_cc1 -cc1 -triple x86_64--netbsd -emit-llvm \
// RUN: -mconstructor-aliases -O2 %s -o - | FileCheck --check-prefix=CHECK-RAUW %s
namespace test1 {
// 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
@ -129,3 +132,32 @@ namespace test8 {
struct zed : public bar {};
zed foo;
}
// CHECK-RAUW: @_ZTV1C = linkonce_odr unnamed_addr constant [4 x i8*] [{{[^@]*}}@_ZTI1C {{[^@]*}}@_ZN1CD2Ev {{[^@]*}}@_ZN1CD0Ev {{[^@]*}}]
// r194296 replaced C::~C with B::~B without emitting the later.
class A {
public:
A(int);
virtual ~A();
};
template <class>
class B : A {
public:
B()
: A(0) {
}
__attribute__((always_inline)) ~B() {
}
};
extern template class B<char>;
class C : B<char> {
};
void
fn1() {
new C;
}