]> granicus.if.org Git - clang/commitdiff
Enforce instantiation of template multiversion functions
authorErich Keane <erich.keane@intel.com>
Mon, 13 Aug 2018 18:33:20 +0000 (18:33 +0000)
committerErich Keane <erich.keane@intel.com>
Mon, 13 Aug 2018 18:33:20 +0000 (18:33 +0000)
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

include/clang/AST/ASTContext.h
lib/AST/ASTContext.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/CodeGenCXX/attr-target-mv-member-funcs.cpp

index 2c51e39b34bc948413a1d161bf0d9ae502c440b7..ea07d5f80efd9b4194120fa76340cbba89bd19aa 100644 (file)
@@ -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);
index 7d9215802ace75d760c16ade0adfb36bee040a75..b96e24ae0f30f99d3f481cde4c1c888d5b2ec8ae 100644 (file)
@@ -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();
index 4c1d56b8311652559829a9e9c34192b9da590768..80980106c4d76880a79277315513f23704878619 100644 (file)
@@ -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;
     }
 
index 2e5db3b705e46b6b74a73a842d7462dbecc871f2..622b738ad284a7d84bbc29b85c696e7e47495140 100644 (file)
@@ -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