diff options
-rw-r--r-- | lib/CodeGen/CGVtable.cpp | 12 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 13 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 8 | ||||
-rw-r--r-- | test/CodeGenCXX/PR6677.cpp | 36 |
4 files changed, 57 insertions, 12 deletions
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 9204e4e565..cedefba1e4 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -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); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 1606710bc5..69ce49cbb1 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -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; diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index abe9363352..d7b613e02b 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -4389,13 +4389,7 @@ 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); + Def->setTemplateSpecializationKind(TSK); InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK); } diff --git a/test/CodeGenCXX/PR6677.cpp b/test/CodeGenCXX/PR6677.cpp index 8d168f1106..29c737c8e9 100644 --- a/test/CodeGenCXX/PR6677.cpp +++ b/test/CodeGenCXX/PR6677.cpp @@ -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); + } +} |