diff options
author | Hans Wennborg <hans@hanshq.net> | 2018-08-14 09:20:55 +0000 |
---|---|---|
committer | Hans Wennborg <hans@hanshq.net> | 2018-08-14 09:20:55 +0000 |
commit | bdb1c367582dd7ce7cb80c234c9f4e7ea662b14b (patch) | |
tree | c51f6e1871983749af9919c66cab80fca8d88912 | |
parent | 2d49a13002de36ee8d3497acce01b711ed86c154 (diff) |
Merging r339597:
------------------------------------------------------------------------
r339597 | erichkeane | 2018-08-13 20:33:20 +0200 (Mon, 13 Aug 2018) | 7 lines
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/branches/release_70@339663 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/ASTContext.h | 2 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 18 | ||||
-rw-r--r-- | test/CodeGenCXX/attr-target-mv-member-funcs.cpp | 12 |
4 files changed, 26 insertions, 8 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index a9ab687a8d..6eb86183d9 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -2718,7 +2718,7 @@ public: /// predicate. void forEachMultiversionedFunctionVersion( const FunctionDecl *FD, - llvm::function_ref<void(const FunctionDecl *)> Pred) const; + llvm::function_ref<void(FunctionDecl *)> Pred) const; const CXXConstructorDecl * getCopyConstructorForExceptionObject(CXXRecordDecl *RD); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index d50f449378..f7546c7c0d 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -9811,7 +9811,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { void ASTContext::forEachMultiversionedFunctionVersion( const FunctionDecl *FD, - llvm::function_ref<void(const FunctionDecl *)> Pred) const { + llvm::function_ref<void(FunctionDecl *)> Pred) const { assert(FD->isMultiVersion() && "Only valid for multiversioned functions"); llvm::SmallDenseSet<const FunctionDecl*, 4> SeenDecls; FD = FD->getCanonicalDecl(); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 86492716f6..512b00b100 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -5192,10 +5192,20 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) { if (FunctionDecl *Function = dyn_cast<FunctionDecl>(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 |