forked from OSchip/llvm-project
Reinstate patch to turn explicit template instantiations into weak symbols
llvm-svn: 98424
This commit is contained in:
parent
d071c6019a
commit
89cae0f224
|
@ -285,8 +285,7 @@ GetLinkageForFunction(ASTContext &Context, const FunctionDecl *FD,
|
|||
break;
|
||||
|
||||
case TSK_ExplicitInstantiationDefinition:
|
||||
// FIXME: explicit instantiation definitions should use weak linkage
|
||||
return CodeGenModule::GVA_StrongExternal;
|
||||
return CodeGenModule::GVA_ExplicitTemplateInstantiation;
|
||||
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
case TSK_ImplicitInstantiation:
|
||||
|
@ -335,7 +334,8 @@ CodeGenModule::getFunctionLinkage(const FunctionDecl *D) {
|
|||
// In C99 mode, 'inline' functions are guaranteed to have a strong
|
||||
// definition somewhere else, so we can use available_externally linkage.
|
||||
return llvm::Function::AvailableExternallyLinkage;
|
||||
} else if (Linkage == GVA_CXXInline || Linkage == GVA_TemplateInstantiation) {
|
||||
} else if (Linkage == GVA_CXXInline || Linkage == GVA_TemplateInstantiation ||
|
||||
Linkage == GVA_ExplicitTemplateInstantiation) {
|
||||
// In C++, the compiler has to emit a definition in every translation unit
|
||||
// that references the function. We should use linkonce_odr because
|
||||
// a) if all references in this translation unit are optimized away, we
|
||||
|
@ -589,6 +589,7 @@ bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) {
|
|||
|
||||
// static, static inline, always_inline, and extern inline functions can
|
||||
// always be deferred. Normal inline functions can be deferred in C99/C++.
|
||||
// Implicit template instantiations can also be deferred in C++.
|
||||
if (Linkage == GVA_Internal || Linkage == GVA_C99Inline ||
|
||||
Linkage == GVA_CXXInline || Linkage == GVA_TemplateInstantiation)
|
||||
return true;
|
||||
|
@ -1043,15 +1044,15 @@ GetLinkageForVariable(ASTContext &Context, const VarDecl *VD) {
|
|||
switch (TSK) {
|
||||
case TSK_Undeclared:
|
||||
case TSK_ExplicitSpecialization:
|
||||
|
||||
// FIXME: ExplicitInstantiationDefinition should be weak!
|
||||
case TSK_ExplicitInstantiationDefinition:
|
||||
return CodeGenModule::GVA_StrongExternal;
|
||||
|
||||
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
llvm_unreachable("Variable should not be instantiated");
|
||||
// Fall through to treat this like any other instantiation.
|
||||
|
||||
case TSK_ExplicitInstantiationDefinition:
|
||||
return CodeGenModule::GVA_ExplicitTemplateInstantiation;
|
||||
|
||||
case TSK_ImplicitInstantiation:
|
||||
return CodeGenModule::GVA_TemplateInstantiation;
|
||||
}
|
||||
|
@ -1171,7 +1172,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
|
|||
GV->setLinkage(llvm::GlobalVariable::WeakODRLinkage);
|
||||
else
|
||||
GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage);
|
||||
} else if (Linkage == GVA_TemplateInstantiation)
|
||||
} else if (Linkage == GVA_TemplateInstantiation ||
|
||||
Linkage == GVA_ExplicitTemplateInstantiation)
|
||||
GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage);
|
||||
else if (!getLangOptions().CPlusPlus && !CodeGenOpts.NoCommon &&
|
||||
!D->hasExternalStorage() && !D->getInit() &&
|
||||
|
|
|
@ -437,7 +437,8 @@ public:
|
|||
GVA_C99Inline,
|
||||
GVA_CXXInline,
|
||||
GVA_StrongExternal,
|
||||
GVA_TemplateInstantiation
|
||||
GVA_TemplateInstantiation,
|
||||
GVA_ExplicitTemplateInstantiation
|
||||
};
|
||||
|
||||
llvm::GlobalVariable::LinkageTypes
|
||||
|
|
|
@ -12,10 +12,10 @@ T X<T>::member1;
|
|||
template<typename T>
|
||||
T X<T>::member2 = 17;
|
||||
|
||||
// CHECK: @_ZN1XIiE7member1E = global i32 0
|
||||
// CHECK: @_ZN1XIiE7member1E = weak global i32 0
|
||||
template int X<int>::member1;
|
||||
|
||||
// CHECK: @_ZN1XIiE7member2E = global i32 17
|
||||
// CHECK: @_ZN1XIiE7member2E = weak global i32 17
|
||||
template int X<int>::member2;
|
||||
|
||||
// For implicit instantiation of
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -o %t %s
|
||||
// RUN: grep "define i32 @_ZNK4plusIillEclERKiRKl" %t | count 1
|
||||
// RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -o - %s | FileCheck %s
|
||||
|
||||
template<typename T, typename U, typename Result>
|
||||
struct plus {
|
||||
|
@ -11,4 +10,5 @@ Result plus<T, U, Result>::operator()(const T& t, const U& u) const {
|
|||
return t + u;
|
||||
}
|
||||
|
||||
// CHECK: define linkonce_odr i32 @_ZNK4plusIillEclERKiRKl
|
||||
template struct plus<int, long, long>;
|
||||
|
|
|
@ -30,15 +30,15 @@ namespace Casts {
|
|||
|
||||
template <int N> T<N> f() { return T<N>(); }
|
||||
|
||||
// CHECK: define void @_ZN5Casts8implicitILj4EEEvPN9enable_ifIXleT_Li4EEvE4typeE
|
||||
// CHECK: define linkonce_odr void @_ZN5Casts8implicitILj4EEEvPN9enable_ifIXleT_Li4EEvE4typeE
|
||||
template void implicit<4>(void*);
|
||||
// CHECK: define void @_ZN5Casts6cstyleILj4EEEvPN9enable_ifIXleT_cvjLi4EEvE4typeE
|
||||
// CHECK: define linkonce_odr void @_ZN5Casts6cstyleILj4EEEvPN9enable_ifIXleT_cvjLi4EEvE4typeE
|
||||
template void cstyle<4>(void*);
|
||||
// CHECK: define void @_ZN5Casts10functionalILj4EEEvPN9enable_ifIXleT_cvjLi4EEvE4typeE
|
||||
// CHECK: define linkonce_odr void @_ZN5Casts10functionalILj4EEEvPN9enable_ifIXleT_cvjLi4EEvE4typeE
|
||||
template void functional<4>(void*);
|
||||
// CHECK: define void @_ZN5Casts7static_ILj4EEEvPN9enable_ifIXleT_cvjLi4EEvE4typeE
|
||||
// CHECK: define linkonce_odr void @_ZN5Casts7static_ILj4EEEvPN9enable_ifIXleT_cvjLi4EEvE4typeE
|
||||
template void static_<4>(void*);
|
||||
|
||||
// CHECK: define i64 @_ZN5Casts1fILi6EEENS_1TIXT_EEEv
|
||||
// CHECK: define linkonce_odr i64 @_ZN5Casts1fILi6EEENS_1TIXT_EEEv
|
||||
template T<6> f<6>();
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ namespace test7 {
|
|||
X(U*, typename int_c<(meta<T>::value + meta<U>::value)>::type *) { }
|
||||
};
|
||||
|
||||
// CHECK: define void @_ZN5test71XIiEC1IdEEPT_PNS_5int_cIXplL_ZNS_4metaIiE5valueEEsrNS6_IS3_EE5valueEE4typeE
|
||||
// CHECK: define linkonce_odr void @_ZN5test71XIiEC1IdEEPT_PNS_5int_cIXplL_ZNS_4metaIiE5valueEEsrNS6_IS3_EE5valueEE4typeE
|
||||
template X<int>::X(double*, float*);
|
||||
}
|
||||
|
||||
|
@ -101,6 +101,6 @@ namespace test8 {
|
|||
template<typename T>
|
||||
void f(int_c<meta<T>::type::value>) { }
|
||||
|
||||
// CHECK: define void @_ZN5test81fIiEEvNS_5int_cIXsrNS_4metaIT_E4typeE5valueEEE
|
||||
// CHECK: define linkonce_odr void @_ZN5test81fIiEEvNS_5int_cIXsrNS_4metaIT_E4typeE5valueEEE
|
||||
template void f<int>(int_c<sizeof(int)>);
|
||||
}
|
||||
|
|
|
@ -250,26 +250,26 @@ void f() { __fill_a<int>(); }
|
|||
namespace Expressions {
|
||||
// Unary operators.
|
||||
|
||||
// CHECK: define void @_ZN11Expressions2f1ILi1EEEvPAplngT_Li2E_i
|
||||
// CHECK: define linkonce_odr void @_ZN11Expressions2f1ILi1EEEvPAplngT_Li2E_i
|
||||
template <int i> void f1(int (*)[(-i) + 2]) { };
|
||||
template void f1<1>(int (*)[1]);
|
||||
|
||||
// CHECK: define void @_ZN11Expressions2f2ILi1EEEvPApsT__i
|
||||
// CHECK: define linkonce_odr void @_ZN11Expressions2f2ILi1EEEvPApsT__i
|
||||
template <int i> void f2(int (*)[+i]) { };
|
||||
template void f2<1>(int (*)[1]);
|
||||
|
||||
// Binary operators.
|
||||
|
||||
// CHECK: define void @_ZN11Expressions2f3ILi1EEEvPAplT_T__i
|
||||
// CHECK: define linkonce_odr void @_ZN11Expressions2f3ILi1EEEvPAplT_T__i
|
||||
template <int i> void f3(int (*)[i+i]) { };
|
||||
template void f3<1>(int (*)[2]);
|
||||
|
||||
// CHECK: define void @_ZN11Expressions2f4ILi1EEEvPAplplLi2ET_T__i
|
||||
// CHECK: define linkonce_odr void @_ZN11Expressions2f4ILi1EEEvPAplplLi2ET_T__i
|
||||
template <int i> void f4(int (*)[2 + i+i]) { };
|
||||
template void f4<1>(int (*)[4]);
|
||||
|
||||
// The ternary operator.
|
||||
// CHECK: define void @_ZN11Expressions2f4ILb1EEEvPAquT_Li1ELi2E_i
|
||||
// CHECK: define linkonce_odr void @_ZN11Expressions2f4ILb1EEEvPAquT_Li1ELi2E_i
|
||||
template <bool b> void f4(int (*)[b ? 1 : 2]) { };
|
||||
template void f4<true>(int (*)[1]);
|
||||
}
|
||||
|
@ -305,7 +305,7 @@ template<typename T, typename = Policy<P, true> > class Alloc
|
|||
T *allocate(int, const void*) { return 0; }
|
||||
};
|
||||
|
||||
// CHECK: define i8* @_ZN6PR58615AllocIcNS_6PolicyINS_1PELb1EEEE8allocateEiPKv
|
||||
// CHECK: define linkonce_odr i8* @_ZN6PR58615AllocIcNS_6PolicyINS_1PELb1EEEE8allocateEiPKv
|
||||
template class Alloc<char>;
|
||||
}
|
||||
|
||||
|
@ -369,7 +369,7 @@ namespace test0 {
|
|||
namespace test1 {
|
||||
template<typename T> struct X { };
|
||||
template<template<class> class Y, typename T> void f(Y<T>) { }
|
||||
// CHECK: define void @_ZN5test11fINS_1XEiEEvT_IT0_E
|
||||
// CHECK: define linkonce_odr void @_ZN5test11fINS_1XEiEEvT_IT0_E
|
||||
template void f(X<int>);
|
||||
}
|
||||
|
||||
|
@ -447,7 +447,7 @@ namespace test7 {
|
|||
void g(zed<&foo::bar>*)
|
||||
{}
|
||||
}
|
||||
// CHECK: define void @_ZN5test81AILZNS_1B5valueEEE3incEv
|
||||
// CHECK: define linkonce_odr void @_ZN5test81AILZNS_1B5valueEEE3incEv
|
||||
namespace test8 {
|
||||
template <int &counter> class A { void inc() { counter++; } };
|
||||
class B { static int value; };
|
||||
|
|
|
@ -15,8 +15,8 @@ struct B {
|
|||
|
||||
template<typename T> B::B(T) {}
|
||||
|
||||
// CHECK: define void @_ZN1BC1IiEET_(%struct.B* %this, i32)
|
||||
// CHECK: define void @_ZN1BC2IiEET_(%struct.B* %this, i32)
|
||||
// CHECK: define linkonce_odr void @_ZN1BC1IiEET_(%struct.B* %this, i32)
|
||||
// CHECK: define linkonce_odr void @_ZN1BC2IiEET_(%struct.B* %this, i32)
|
||||
template B::B(int);
|
||||
|
||||
template<typename T>
|
||||
|
|
|
@ -6,19 +6,19 @@ template<typename T> struct A {
|
|||
|
||||
// Explicit instantiations have external linkage.
|
||||
|
||||
// CHECK: define void @_ZN1AIiE1gEv(
|
||||
// CHECK: define linkonce_odr void @_ZN1AIiE1gEv(
|
||||
template void A<int>::g();
|
||||
|
||||
// CHECK: define void @_ZN1AIfE1fEf(
|
||||
// CHECK: define void @_ZN1AIfE1gEv(
|
||||
// CHECK: define linkonce_odr void @_ZN1AIfE1fEf(
|
||||
// CHECK: define linkonce_odr void @_ZN1AIfE1gEv(
|
||||
// FIXME: This should also emit the vtable.
|
||||
template struct A<float>;
|
||||
|
||||
// CHECK: define void @_Z1fIiEvT_
|
||||
// CHECK: define linkonce_odr void @_Z1fIiEvT_
|
||||
template <typename T> void f(T) { }
|
||||
template void f<int>(int);
|
||||
|
||||
// CHECK: define void @_Z1gIiEvT_
|
||||
// CHECK: define linkonce_odr void @_Z1gIiEvT_
|
||||
template <typename T> inline void g(T) { }
|
||||
template void g<int>(int);
|
||||
|
||||
|
|
|
@ -256,7 +256,7 @@ namespace PR6199 {
|
|||
|
||||
struct B { operator A(); };
|
||||
|
||||
// CHECK: define void @_ZN6PR61992f2IiEENS_1AET_
|
||||
// CHECK: define linkonce_odr void @_ZN6PR61992f2IiEENS_1AET_
|
||||
template<typename T> A f2(T) {
|
||||
B b;
|
||||
// CHECK: call void @_ZN6PR61991BcvNS_1AEEv
|
||||
|
|
Loading…
Reference in New Issue