Alias must point to a definition

Reapplying the patch after modifying the test case.

Inlining the destructor caused the compiler to generate bad IR which failed the Verifier in the backend.
https://llvm.org/bugs/show_bug.cgi?id=30341

This patch disables alias to available_externally definitions.

Reviewers: eugenis, rsmith

Differential Revision: https://reviews.llvm.org/D24682

llvm-svn: 283063
This commit is contained in:
Aditya Kumar 2016-10-02 03:06:36 +00:00
parent f230b0aa43
commit e84372b039
2 changed files with 26 additions and 8 deletions

View File

@ -134,6 +134,11 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
llvm::GlobalValue::LinkageTypes TargetLinkage =
getFunctionLinkage(TargetDecl);
// available_externally definitions aren't real definitions, so we cannot
// create an alias to one.
if (TargetLinkage == llvm::GlobalValue::AvailableExternallyLinkage)
return true;
// Check if we have it already.
StringRef MangledName = getMangledName(AliasDecl);
llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
@ -156,14 +161,7 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
// 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.
if (llvm::GlobalValue::isDiscardableIfUnused(Linkage)) {
addReplacement(MangledName, Aliasee);
return false;
}

View File

@ -0,0 +1,20 @@
// 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.
// The destructors have different return type for different targets.
// CHECK: define linkonce_odr {{.*}} @_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;