diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 22baa654084978b49c651d6f5b3aba8e80b37a3d..cfb2d6291b8aa80c0c8ed986cf121565d721fae6 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -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; } diff --git a/test/CodeGenCXX/ctor-dtor-alias.cpp b/test/CodeGenCXX/ctor-dtor-alias.cpp index 6efd0bf9f870b155922358a2d89d9764ea1721c0..235d1650dec92df4067fdf2f9d20291fc29276c0 100644 --- a/test/CodeGenCXX/ctor-dtor-alias.cpp +++ b/test/CodeGenCXX/ctor-dtor-alias.cpp @@ -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; +}