summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2018-08-14 09:20:55 +0000
committerHans Wennborg <hans@hanshq.net>2018-08-14 09:20:55 +0000
commitbdb1c367582dd7ce7cb80c234c9f4e7ea662b14b (patch)
treec51f6e1871983749af9919c66cab80fca8d88912
parent2d49a13002de36ee8d3497acce01b711ed86c154 (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.h2
-rw-r--r--lib/AST/ASTContext.cpp2
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp18
-rw-r--r--test/CodeGenCXX/attr-target-mv-member-funcs.cpp12
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