diff --git a/clang/lib/CodeGen/CGVtable.cpp b/clang/lib/CodeGen/CGVtable.cpp index cedefba1e4e8..9204e4e565cc 100644 --- a/clang/lib/CodeGen/CGVtable.cpp +++ b/clang/lib/CodeGen/CGVtable.cpp @@ -3805,17 +3805,7 @@ void CodeGenVTables::EmitVTableRelatedData(GlobalDecl GD) { return; TemplateSpecializationKind kind = RD->getTemplateSpecializationKind(); - - - // The reason we have TSK_ExplicitInstantiationDeclaration in here (but not - // in Sema::MaybeMarkVirtualMembersReferenced) is for the case - // template<> void stdio_sync_filebuf::xsgetn() { - // } - // extern template class stdio_sync_filebuf; - // Since we are called after the extern declaration is seen. - - if (kind == TSK_ImplicitInstantiation || - kind == TSK_ExplicitInstantiationDeclaration) + if (kind == TSK_ImplicitInstantiation) CGM.DeferredVtables.push_back(RD); else GenerateClassData(CGM.getVtableLinkage(RD), RD); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 69ce49cbb182..1606710bc5cd 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -310,17 +310,8 @@ 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 ] - - // 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(FD); - if (MD && MD->isImplicit()) - TSK = MD->getParent()->getTemplateSpecializationKind(); - else - TSK = FD->getTemplateSpecializationKind(); - - if (TSK == TSK_ExplicitInstantiationDeclaration) + if (FD->getTemplateSpecializationKind() + == TSK_ExplicitInstantiationDeclaration) return CodeGenModule::GVA_C99Inline; return CodeGenModule::GVA_CXXInline; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index d7b613e02b21..abe9363352ea 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4389,7 +4389,13 @@ Sema::ActOnExplicitInstantiation(Scope *S, Def = cast_or_null( Specialization->getDefinition()); if (Def) { - Def->setTemplateSpecializationKind(TSK); + 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); } diff --git a/clang/test/CodeGenCXX/PR6677.cpp b/clang/test/CodeGenCXX/PR6677.cpp index 29c737c8e9ba..8d168f110608 100644 --- a/clang/test/CodeGenCXX/PR6677.cpp +++ b/clang/test/CodeGenCXX/PR6677.cpp @@ -3,9 +3,6 @@ // 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(); @@ -16,12 +13,7 @@ namespace test0 { }; // This specialization should cause the vtable to be emitted, even with - // 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 + // the following extern template declaration. template<> void stdio_sync_filebuf::xsgetn() { } extern template class stdio_sync_filebuf; @@ -36,30 +28,6 @@ namespace test1 { virtual void xsgetn(); }; - // Just a declaration should not force the vtable to be emitted - // (test at the top). + // Just a declaration should not force the vtable to be emitted. template<> void stdio_sync_filebuf::xsgetn(); } - -namespace test2 { - template - class C { - void zedbar(double) { - } - template - void fobar(T2 foo) { - } - }; - extern template class C; - void g() { - C 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); - } -}