llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Arseniy Obolenskiy (aobolensk)

<details>
<summary>Changes</summary>

On amdgcnspirv, __cdecl has no device-side equivalent, so it needs to be 
normalized to the device default CC to match plain function type

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


2 Files Affected:

- (modified) clang/lib/Sema/SemaType.cpp (+13) 
- (added) clang/test/SemaHIP/amdgcnspirv-host-cconv-in-abstract-type.hip (+35) 


``````````diff
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index f7789b7475e8e..b994080a58bb4 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -8349,6 +8349,19 @@ static bool handleFunctionTypeAttr(TypeProcessingState 
&state, ParsedAttr &attr,
     return true;
 
   const FunctionType *fn = unwrapped.get();
+
+  // On amdgcnspirv, __cdecl on an abstract function type has no device-side
+  // equivalent, so normalize it to the device default CC to match an
+  // unadorned function type. Skip named decls and variadic types.
+  if (CC == CC_C && S.getLangOpts().CUDAIsDevice &&
+      S.Context.getTargetInfo().getTriple().isSPIRV() &&
+      state.getDeclarator().mayOmitIdentifier()) {
+    const auto *FnP = dyn_cast<FunctionProtoType>(fn);
+    if (!FnP || !FnP->isVariadic())
+      CC = S.Context.getDefaultCallingConvention(/*IsVariadic=*/false,
+                                                 /*IsCXXMethod=*/false);
+  }
+
   CallingConv CCOld = fn->getCallConv();
   Attr *CCAttr = getCCTypeAttr(S.Context, attr);
 
diff --git a/clang/test/SemaHIP/amdgcnspirv-host-cconv-in-abstract-type.hip 
b/clang/test/SemaHIP/amdgcnspirv-host-cconv-in-abstract-type.hip
new file mode 100644
index 0000000000000..a624edc1bf564
--- /dev/null
+++ b/clang/test/SemaHIP/amdgcnspirv-host-cconv-in-abstract-type.hip
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv32 -aux-triple 
x86_64-pc-windows-msvc -fms-extensions -verify
+// RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv64 -aux-triple 
x86_64-pc-windows-msvc -fms-extensions -verify
+// RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv64-amd-amdhsa 
-aux-triple x86_64-pc-windows-msvc -fms-extensions -verify
+
+// __cdecl on an abstract function type must normalize to the device default
+// so std::function<void()> matches the library specialization keyed on
+// __cdecl on amdgcnspirv Windows.
+
+// expected-no-diagnostics
+
+template <class T> struct classify_fn {
+  static constexpr int value = 0;
+};
+template <class R, class... A> struct classify_fn<R __cdecl(A...)> {
+  static constexpr int value = 1;
+};
+template <class R, class... A> struct classify_fn<R __vectorcall(A...)> {
+  static constexpr int value = 2;
+};
+template <class R> struct classify_fn<R __cdecl(int, ...)> {
+  static constexpr int value = 3;
+};
+
+// Unadorned function types resolve to the __cdecl specialization.
+static_assert(classify_fn<void()>::value == 1, "void() must match __cdecl");
+static_assert(classify_fn<int(double, char)>::value == 1,
+              "int(double,char) must match __cdecl");
+
+// Variadic __cdecl keeps its own specialization, not the device default.
+static_assert(classify_fn<int __cdecl(int, ...)>::value == 3,
+              "variadic __cdecl must match its own specialization");
+
+// __vectorcall must not be folded into the device default alongside __cdecl.
+static_assert(classify_fn<void __vectorcall()>::value == 2,
+              "__vectorcall must match its own specialization, not __cdecl");

``````````

</details>


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

Reply via email to