llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Akash Manna (akash-manna-sky)

<details>
<summary>Changes</summary>

Fixes #<!-- -->149372

A `target_clones` definition, a bare redeclaration and then one repeating the 
attribute asserted with `Default or Generic case must be last` in the `x86` 
resolver. Sema did not link the bare redeclaration to the definition, so 
CodeGen saw two functions named `f` and collected every version twice.

#<!-- -->169259 fixed the `Sema` side, so the attribute is inherited and each 
version is collected once. This adds the shape from the report.

Assisted-by : LLM tools.

---
Full diff: https://github.com/llvm/llvm-project/pull/237830.diff


4 Files Affected:

- (modified) clang/test/CodeGen/attr-target-clones.c (+25) 
- (added) clang/test/CodeGenCXX/attr-target-clones-redecl.cpp (+90) 
- (modified) clang/test/Sema/attr-target-clones.c (+18) 
- (modified) clang/test/SemaCXX/attr-target-clones.cpp (+31) 


``````````diff
diff --git a/clang/test/CodeGen/attr-target-clones.c 
b/clang/test/CodeGen/attr-target-clones.c
index ccf9b5615bde46..4c050870d9811f 100644
--- a/clang/test/CodeGen/attr-target-clones.c
+++ b/clang/test/CodeGen/attr-target-clones.c
@@ -155,6 +155,31 @@ int test_inherited(void) {
   // WINDOWS: call i32 @inherited()
 }
 
+// GH149372
+int __attribute__((target_clones("default,avx"))) redecl(int x) { return x; }
+int redecl(int);
+int __attribute__((target_clones("default,avx"))) redecl(int);
+// LINUX: define {{.*}}i32 @redecl.default.1(
+// LINUX: define {{.*}}i32 @redecl.avx.0(
+// LINUX: define weak_odr ptr @redecl.resolver() #[[ATTR_RESOLVER]] comdat
+// LINUX: ret ptr @redecl.avx.0
+// LINUX-NOT: ret ptr @redecl.avx.0
+// LINUX: ret ptr @redecl.default.1
+
+// DARWIN: define {{.*}}i32 @redecl.default.1(
+// DARWIN: define {{.*}}i32 @redecl.avx.0(
+// DARWIN: define weak_odr ptr @redecl.resolver() #[[ATTR_RESOLVER]] {
+// DARWIN: ret ptr @redecl.avx.0
+// DARWIN-NOT: ret ptr @redecl.avx.0
+// DARWIN: ret ptr @redecl.default.1
+
+// WINDOWS: define dso_local i32 @redecl.default.1(
+// WINDOWS: define dso_local i32 @redecl.avx.0(
+// WINDOWS: define weak_odr dso_local i32 @redecl(i32{{.*}}) 
#[[ATTR_RESOLVER]] comdat
+// WINDOWS: musttail call i32 @redecl.avx.0
+// WINDOWS-NOT: musttail call i32 @redecl.avx.0
+// WINDOWS: musttail call i32 @redecl.default.1
+
 inline int __attribute__((target_clones("arch=sandybridge,default,sse4.2")))
 foo_inline(void) { return 0; }
 inline int __attribute__((target_clones("arch=sandybridge,default,sse4.2")))
diff --git a/clang/test/CodeGenCXX/attr-target-clones-redecl.cpp 
b/clang/test/CodeGenCXX/attr-target-clones-redecl.cpp
new file mode 100644
index 00000000000000..c72beb1e11ccb9
--- /dev/null
+++ b/clang/test/CodeGenCXX/attr-target-clones-redecl.cpp
@@ -0,0 +1,90 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -O2 -emit-llvm-only %s
+
+// GH149372: redeclarations must not duplicate the versions in the resolver.
+
+// CHECK: @_Z1ci.ifunc = weak_odr alias i32 (i32), ptr @_Z1ci
+// CHECK: @_Z1fi.ifunc = weak_odr alias i32 (i32), ptr @_Z1fi
+// CHECK: @_ZN2ns1gEi.ifunc = weak_odr alias i32 (i32), ptr @_ZN2ns1gEi
+// CHECK: @h.ifunc = weak_odr alias i32 (i32), ptr @h
+// CHECK: @_ZL1si.ifunc = internal alias i32 (i32), ptr @_ZL1si
+// CHECK: @_Z1di.ifunc = weak_odr alias i32 (i32), ptr @_Z1di
+// CHECK: @_Z1ci = weak_odr ifunc i32 (i32), ptr @_Z1ci.resolver
+// CHECK: @_Z1fi = weak_odr ifunc i32 (i32), ptr @_Z1fi.resolver
+// CHECK: @_ZN2ns1gEi = weak_odr ifunc i32 (i32), ptr @_ZN2ns1gEi.resolver
+// CHECK: @h = weak_odr ifunc i32 (i32), ptr @h.resolver
+// CHECK: @_ZL1si = internal ifunc i32 (i32), ptr @_ZL1si.resolver
+// CHECK: @_Z1di = weak_odr ifunc i32 (i32), ptr @_Z1di.resolver
+
+int __attribute__((target_clones("default,avx"))) c(int x) { return x; }
+// CHECK: define {{.*}}i32 @_Z1ci.default.1(
+// CHECK: define {{.*}}i32 @_Z1ci.avx.0(
+// CHECK: define weak_odr ptr @_Z1ci.resolver() #[[ATTR_RESOLVER:[0-9]+]] 
comdat
+// CHECK: ret ptr @_Z1ci.avx.0
+// CHECK: ret ptr @_Z1ci.default.1
+
+enum { VALUE = 3 };
+
+extern int glob_x;
+
+int __attribute__((target_clones("default,avx"))) f(int x) { return x + glob_x 
+ VALUE; }
+
+int f(int);
+int __attribute__((target_clones("default,avx"))) f(int);
+// CHECK: define {{.*}}i32 @_Z1fi.default.1(
+// CHECK: define {{.*}}i32 @_Z1fi.avx.0(
+// CHECK: define weak_odr ptr @_Z1fi.resolver() #[[ATTR_RESOLVER]] comdat
+// CHECK: ret ptr @_Z1fi.avx.0
+// CHECK-NOT: ret ptr @_Z1fi.avx.0
+// CHECK: ret ptr @_Z1fi.default.1
+
+namespace ns {
+int __attribute__((target_clones("default,avx"))) g(int x) { return x; }
+int g(int);
+int __attribute__((target_clones("default,avx"))) g(int);
+}
+// CHECK: define {{.*}}i32 @_ZN2ns1gEi.default.1(
+// CHECK: define {{.*}}i32 @_ZN2ns1gEi.avx.0(
+// CHECK: define weak_odr ptr @_ZN2ns1gEi.resolver() #[[ATTR_RESOLVER]] comdat
+// CHECK: ret ptr @_ZN2ns1gEi.avx.0
+// CHECK-NOT: ret ptr @_ZN2ns1gEi.avx.0
+// CHECK: ret ptr @_ZN2ns1gEi.default.1
+
+extern "C" int __attribute__((target_clones("default,avx"))) h(int x) { return 
x; }
+extern "C" int h(int);
+extern "C" int __attribute__((target_clones("default,avx"))) h(int);
+// CHECK: define {{.*}}i32 @h.default.1(
+// CHECK: define {{.*}}i32 @h.avx.0(
+// CHECK: define weak_odr ptr @h.resolver() #[[ATTR_RESOLVER]] comdat
+// CHECK: ret ptr @h.avx.0
+// CHECK-NOT: ret ptr @h.avx.0
+// CHECK: ret ptr @h.default.1
+
+static int __attribute__((target_clones("default,avx"))) s(int x) { return x; }
+static int s(int);
+static int __attribute__((target_clones("default,avx"))) s(int);
+int use_s(int x) { return s(x); }
+// CHECK: define {{.*}}i32 @_Z5use_si(
+// CHECK: call noundef i32 @_ZL1si(
+// CHECK: define internal ptr @_ZL1si.resolver() #[[ATTR_RESOLVER]] {
+// CHECK: ret ptr @_ZL1si.avx.0
+// CHECK-NOT: ret ptr @_ZL1si.avx.0
+// CHECK: ret ptr @_ZL1si.default.1
+
+int __attribute__((target_clones("default,avx"))) d(int);
+int d(int);
+int __attribute__((target_clones("default,avx"))) d(int);
+int d(int x) { return x; }
+int d(int);
+// CHECK: define {{.*}}i32 @_Z1di.default.1(
+// CHECK: define {{.*}}i32 @_Z1di.avx.0(
+// CHECK: define weak_odr ptr @_Z1di.resolver() #[[ATTR_RESOLVER]] comdat
+// CHECK: ret ptr @_Z1di.avx.0
+// CHECK-NOT: ret ptr @_Z1di.avx.0
+// CHECK: ret ptr @_Z1di.default.1
+
+// The internal function's versions are emitted at the end of the module.
+// CHECK: define internal {{.*}}i32 @_ZL1si.default.1(
+// CHECK: define internal {{.*}}i32 @_ZL1si.avx.0(
+
+// CHECK: attributes #[[ATTR_RESOLVER]] = { disable_sanitizer_instrumentation }
diff --git a/clang/test/Sema/attr-target-clones.c 
b/clang/test/Sema/attr-target-clones.c
index 7ff8a02bf53321..918f1dc1340ad4 100644
--- a/clang/test/Sema/attr-target-clones.c
+++ b/clang/test/Sema/attr-target-clones.c
@@ -39,6 +39,24 @@ int __attribute__((target_clones("sse4.2", "default"))) 
redecl7(void);
 // expected-note@-2 {{previous declaration is here}}
 int __attribute__((target("sse4.2"))) redecl7(void) { return 1; }
 
+// GH149372
+int __attribute__((target_clones("sse4.2", "default"))) redecl8(void) { return 
1; }
+int redecl8(void);
+int __attribute__((target_clones("sse4.2", "default"))) redecl8(void);
+
+int __attribute__((target_clones("sse4.2", "default"))) redecl9(void);
+int redecl9(void);
+int __attribute__((target_clones("sse4.2", "default"))) redecl9(void);
+int redecl9(void);
+int __attribute__((target_clones("sse4.2", "default"))) redecl9(void) { return 
1; }
+int redecl9(void);
+
+int __attribute__((target_clones("sse4.2", "default"))) redecl10(void) { 
return 1; }
+int redecl10(void);
+// expected-error@+2 {{'target_clones' attribute does not match previous 
declaration}}
+// expected-note@-2 {{previous declaration is here}}
+int __attribute__((target_clones("arch=atom", "default"))) redecl10(void);
+
 int __attribute__((target("sse4.2"))) redef2(void) { return 1; }
 // expected-error@+2 {{multiversioning attributes cannot be combined}}
 // expected-note@-2 {{previous declaration is here}}
diff --git a/clang/test/SemaCXX/attr-target-clones.cpp 
b/clang/test/SemaCXX/attr-target-clones.cpp
index 68c9a4ff48ed9e..8952beeb47127a 100644
--- a/clang/test/SemaCXX/attr-target-clones.cpp
+++ b/clang/test/SemaCXX/attr-target-clones.cpp
@@ -9,3 +9,34 @@ void uses_lambda() {
   auto x = []()__attribute__((target_clones("sse4.2", "arch=ivybridge", 
"default"))) {};
   x();
 }
+
+// GH149372
+int __attribute__((target_clones("default,avx"))) redecl(int x) { return x; }
+int redecl(int);
+int __attribute__((target_clones("default,avx"))) redecl(int);
+
+int __attribute__((target_clones("default,avx"))) redecl2(int x) { return x; }
+int redecl2(int);
+// expected-error@+2 {{'target_clones' attribute does not match previous 
declaration}}
+// expected-note@-2 {{previous declaration is here}}
+int __attribute__((target_clones("default,sse4.2"))) redecl2(int);
+
+namespace ns {
+int __attribute__((target_clones("default,avx"))) redecl3(int x) { return x; }
+int redecl3(int);
+int __attribute__((target_clones("default,avx"))) redecl3(int);
+}
+
+extern "C" int __attribute__((target_clones("default,avx"))) redecl4(int x) { 
return x; }
+extern "C" int redecl4(int);
+extern "C" int __attribute__((target_clones("default,avx"))) redecl4(int);
+
+static int __attribute__((target_clones("default,avx"))) redecl5(int x) { 
return x; }
+static int redecl5(int);
+static int __attribute__((target_clones("default,avx"))) redecl5(int);
+
+int __attribute__((target_clones("default,avx"))) redecl6(int x) { return x; }
+int redecl6(int);
+int __attribute__((target_clones("default,avx"))) redecl6(int);
+int __attribute__((target_clones("default,avx"))) redecl6(long x) { return x; }
+int redecl6(long);

``````````

</details>


https://github.com/llvm/llvm-project/pull/237830
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to