From: Erich Keane Date: Mon, 13 Aug 2018 18:33:20 +0000 (+0000) Subject: Enforce instantiation of template multiversion functions X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e0f3e3d9917bed4a6525ac066afba25fce0ccfa4;p=clang Enforce instantiation of template multiversion functions Multiversioned member functions inside of a template type were not properly being emitted. The solution to this is to simply ensure that their bodies are correctly evaluated/assigned during template instantiation. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@339597 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 2c51e39b34..ea07d5f80e 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -2743,7 +2743,7 @@ public: /// predicate. void forEachMultiversionedFunctionVersion( const FunctionDecl *FD, - llvm::function_ref Pred) const; + llvm::function_ref Pred) const; const CXXConstructorDecl * getCopyConstructorForExceptionObject(CXXRecordDecl *RD); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 7d9215802a..b96e24ae0f 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -9819,7 +9819,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { void ASTContext::forEachMultiversionedFunctionVersion( const FunctionDecl *FD, - llvm::function_ref Pred) const { + llvm::function_ref Pred) const { assert(FD->isMultiVersion() && "Only valid for multiversioned functions"); llvm::SmallDenseSet SeenDecls; FD = FD->getCanonicalDecl(); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 4c1d56b831..80980106c4 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -5175,10 +5175,20 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) { if (FunctionDecl *Function = dyn_cast(Inst.first)) { bool DefinitionRequired = Function->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition; - InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true, - DefinitionRequired, true); - if (Function->isDefined()) - Function->setInstantiationIsPending(false); + if (Function->isMultiVersion()) { + getASTContext().forEachMultiversionedFunctionVersion( + Function, [this, Inst, DefinitionRequired](FunctionDecl *CurFD) { + InstantiateFunctionDefinition(/*FIXME:*/ Inst.second, CurFD, true, + DefinitionRequired, true); + if (CurFD->isDefined()) + CurFD->setInstantiationIsPending(false); + }); + } else { + InstantiateFunctionDefinition(/*FIXME:*/ Inst.second, Function, true, + DefinitionRequired, true); + if (Function->isDefined()) + Function->setInstantiationIsPending(false); + } continue; } diff --git a/test/CodeGenCXX/attr-target-mv-member-funcs.cpp b/test/CodeGenCXX/attr-target-mv-member-funcs.cpp index 2e5db3b705..622b738ad2 100644 --- a/test/CodeGenCXX/attr-target-mv-member-funcs.cpp +++ b/test/CodeGenCXX/attr-target-mv-member-funcs.cpp @@ -111,13 +111,12 @@ int templ_use() { // CHECK: call i32 @_ZN5templIiE3fooEi.ifunc // CHECK: call i32 @_ZN5templIdE3fooEi.ifunc - // CHECK: define i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.resolver() comdat // CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.arch_sandybridge // CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.arch_ivybridge // CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.sse4.2 // CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi -// + // CHECK: define i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.resolver() comdat // CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.arch_sandybridge // CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.arch_ivybridge @@ -135,3 +134,12 @@ int templ_use() { // CHECK: define linkonce_odr i32 @_ZN1S3fooEi(%struct.S* %this, i32) // CHECK: ret i32 2 +// CHECK: define linkonce_odr i32 @_ZN5templIiE3fooEi.sse4.2 +// CHECK: declare i32 @_ZN5templIiE3fooEi.arch_sandybridge +// CHECK: define linkonce_odr i32 @_ZN5templIiE3fooEi.arch_ivybridge +// CHECK: define linkonce_odr i32 @_ZN5templIiE3fooEi + +// CHECK: define linkonce_odr i32 @_ZN5templIdE3fooEi.sse4.2 +// CHECK: declare i32 @_ZN5templIdE3fooEi.arch_sandybridge +// CHECK: define linkonce_odr i32 @_ZN5templIdE3fooEi.arch_ivybridge +// CHECK: define linkonce_odr i32 @_ZN5templIdE3fooEi