aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clang/lib/AST/ASTContext.cpp4
-rw-r--r--clang/test/CodeGenCXX/attr-cpuspecific.cpp1
-rw-r--r--clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp26
3 files changed, 18 insertions, 13 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index c085f52..648fa9f 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -9734,6 +9734,10 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
return true;
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+ // Multiversioned functions always have to be emitted, because they are used
+ // by the resolver.
+ if (FD->isMultiVersion())
+ return true;
// Forward declarations aren't required.
if (!FD->doesThisDeclarationHaveABody())
return FD->doesDeclarationForceExternallyVisibleDefinition();
diff --git a/clang/test/CodeGenCXX/attr-cpuspecific.cpp b/clang/test/CodeGenCXX/attr-cpuspecific.cpp
index ae5702f..d9b7b54 100644
--- a/clang/test/CodeGenCXX/attr-cpuspecific.cpp
+++ b/clang/test/CodeGenCXX/attr-cpuspecific.cpp
@@ -12,6 +12,7 @@ void foo() {
s.Func();
}
+// LINUX: define linkonce_odr void @_ZN1S4FuncEv.O
// LINUX: define void (%struct.S*)* @_ZN1S4FuncEv.resolver
// LINUX: ret void (%struct.S*)* @_ZN1S4FuncEv.S
// LINUX: ret void (%struct.S*)* @_ZN1S4FuncEv.O
diff --git a/clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp b/clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp
index 622b738..3d24c7a 100644
--- a/clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp
+++ b/clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp
@@ -72,6 +72,15 @@ int templ_use() {
// CHECK: @_ZN5templIiE3fooEi.ifunc = ifunc i32 (%struct.templ*, i32), i32 (%struct.templ*, i32)* ()* @_ZN5templIiE3fooEi.resolver
// CHECK: @_ZN5templIdE3fooEi.ifunc = ifunc i32 (%struct.templ.0*, i32), i32 (%struct.templ.0*, i32)* ()* @_ZN5templIdE3fooEi.resolver
+// CHECK: define linkonce_odr i32 @_ZN1S3fooEi.sse4.2(%struct.S* %this, i32)
+// CHECK: ret i32 0
+
+// CHECK: define linkonce_odr i32 @_ZN1S3fooEi.arch_ivybridge(%struct.S* %this, i32)
+// CHECK: ret i32 1
+
+// CHECK: define linkonce_odr i32 @_ZN1S3fooEi(%struct.S* %this, i32)
+// CHECK: ret i32 2
+
// CHECK: define i32 @_Z3barv()
// CHECK: %s = alloca %struct.S, align 1
// CHECK: %s2 = alloca %struct.S, align 1
@@ -123,23 +132,14 @@ int templ_use() {
// CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.sse4.2
// CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi
-// CHECK: define linkonce_odr i32 @_ZN1S3fooEi.sse4.2(%struct.S* %this, i32)
-// CHECK: ret i32 0
-
-// CHECK: declare i32 @_ZN1S3fooEi.arch_sandybridge(%struct.S*, i32)
-
-// CHECK: define linkonce_odr i32 @_ZN1S3fooEi.arch_ivybridge(%struct.S* %this, i32)
-// CHECK: ret i32 1
-
-// 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
+//
+// CHECK: declare i32 @_ZN1S3fooEi.arch_sandybridge(%struct.S*, i32)
+// CHECK: declare i32 @_ZN5templIiE3fooEi.arch_sandybridge
+// CHECK: declare i32 @_ZN5templIdE3fooEi.arch_sandybridge