summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorErich Keane <erich.keane@intel.com>2018-08-13 18:33:20 +0000
committerErich Keane <erich.keane@intel.com>2018-08-13 18:33:20 +0000
commit0fb16483ac67f07af51b982e6f158078b5744154 (patch)
tree48ada68cd1ad0a16a20dbd4e504d609b9283ad47 /clang
parenta37bba47279164c7cd18a50279cdeb3185718095 (diff)
downloadbcm5719-llvm-0fb16483ac67f07af51b982e6f158078b5744154.tar.gz
bcm5719-llvm-0fb16483ac67f07af51b982e6f158078b5744154.zip
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. llvm-svn: 339597
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/AST/ASTContext.h2
-rw-r--r--clang/lib/AST/ASTContext.cpp2
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateDecl.cpp18
-rw-r--r--clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp12
4 files changed, 26 insertions, 8 deletions
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 2c51e39b34b..ea07d5f80ef 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -2743,7 +2743,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/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 7d9215802ac..b96e24ae0f3 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -9819,7 +9819,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/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 4c1d56b8311..80980106c4d 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -5175,10 +5175,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/clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp b/clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp
index 2e5db3b705e..622b738ad28 100644
--- a/clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp
+++ b/clang/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
OpenPOWER on IntegriCloud