Avoid producing implicit methods when we have a explicit template instantiation

declaration.

llvm-svn: 99311
This commit is contained in:
Rafael Espindola 2010-03-23 18:56:16 +00:00
parent 59f75bba24
commit 4d3745ade6
4 changed files with 57 additions and 12 deletions

View File

@ -3805,7 +3805,17 @@ void CodeGenVTables::EmitVTableRelatedData(GlobalDecl GD) {
return;
TemplateSpecializationKind kind = RD->getTemplateSpecializationKind();
if (kind == TSK_ImplicitInstantiation)
// The reason we have TSK_ExplicitInstantiationDeclaration in here (but not
// in Sema::MaybeMarkVirtualMembersReferenced) is for the case
// template<> void stdio_sync_filebuf<wchar_t>::xsgetn() {
// }
// extern template class stdio_sync_filebuf<wchar_t>;
// Since we are called after the extern declaration is seen.
if (kind == TSK_ImplicitInstantiation ||
kind == TSK_ExplicitInstantiationDeclaration)
CGM.DeferredVtables.push_back(RD);
else
GenerateClassData(CGM.getVtableLinkage(RD), RD);

View File

@ -310,8 +310,17 @@ GetLinkageForFunction(ASTContext &Context, const FunctionDecl *FD,
// instantiated when used so that the body can be considered for
// inlining, but that no out-of-line copy of the inline function would be
// generated in the translation unit. -- end note ]
if (FD->getTemplateSpecializationKind()
== TSK_ExplicitInstantiationDeclaration)
// We check the specialization kind of the class for implicit methods.
// They have a TSK_Undeclared specialization kind.
TemplateSpecializationKind TSK;
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
if (MD && MD->isImplicit())
TSK = MD->getParent()->getTemplateSpecializationKind();
else
TSK = FD->getTemplateSpecializationKind();
if (TSK == TSK_ExplicitInstantiationDeclaration)
return CodeGenModule::GVA_C99Inline;
return CodeGenModule::GVA_CXXInline;

View File

@ -4389,12 +4389,6 @@ Sema::ActOnExplicitInstantiation(Scope *S,
Def = cast_or_null<ClassTemplateSpecializationDecl>(
Specialization->getDefinition());
if (Def) {
TemplateSpecializationKind Old_TSK = Def->getTemplateSpecializationKind();
// Fix a TSK_ExplicitInstantiationDeclaration followed by a
// TSK_ExplicitInstantiationDefinition
if (Old_TSK == TSK_ExplicitInstantiationDeclaration &&
TSK == TSK_ExplicitInstantiationDefinition)
Def->setTemplateSpecializationKind(TSK);
InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);

View File

@ -3,6 +3,9 @@
// CHECK-NOT: @_ZTVN5test118stdio_sync_filebufIwEE = constant
// CHECK: @_ZTVN5test018stdio_sync_filebufIwEE = constant
// CHECK: define linkonce_odr void @_ZN5test21CIiE5fobarIdEEvT_
// CHECK: define available_externally void @_ZN5test21CIiE6zedbarEd
namespace test0 {
struct basic_streambuf {
virtual ~basic_streambuf();
@ -13,7 +16,12 @@ namespace test0 {
};
// This specialization should cause the vtable to be emitted, even with
// the following extern template declaration.
// the following extern template declaration (test at the top).
// The existance of the extern template declaration should prevent us from emitting
// destructors.
// CHECK: define available_externally void @_ZN5test018stdio_sync_filebufIwED0Ev
// CHECK: define available_externally void @_ZN5test018stdio_sync_filebufIwED2Ev
template<> void stdio_sync_filebuf<wchar_t>::xsgetn() {
}
extern template class stdio_sync_filebuf<wchar_t>;
@ -28,6 +36,30 @@ namespace test1 {
virtual void xsgetn();
};
// Just a declaration should not force the vtable to be emitted.
// Just a declaration should not force the vtable to be emitted
// (test at the top).
template<> void stdio_sync_filebuf<wchar_t>::xsgetn();
}
namespace test2 {
template<typename T1>
class C {
void zedbar(double) {
}
template<typename T2>
void fobar(T2 foo) {
}
};
extern template class C<int>;
void g() {
C<int> a;
// The extern template declaration should not prevent us from producing
/// foobar.
// (test at the top).
a.fobar(0.0);
// But it should prevent zebbar
// (test at the top).
a.zedbar(0.0);
}
}