Skip to content

Conversation

AlexVlx
Copy link
Contributor

@AlexVlx AlexVlx commented Aug 4, 2025

Client apps can (and in the case of the MSVC STL do) set cdecl explicitly on new / delete implementations. On the other hand, Clang generates implicit decls with the target's default CC. This is problematic for SPIR-V, since the default there is spir_function, which is not compatible. Since we cannot change pre-existing headers / implementations, this patch sets the CC to C for the implicit host-side decls, when compiling for device, to prevent the conflict. This is fine because the host-side overloards do not get emitted on device.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Aug 4, 2025
@llvmbot
Copy link
Member

llvmbot commented Aug 4, 2025

@llvm/pr-subscribers-clang

Author: Alex Voicu (AlexVlx)

Changes

Client apps can (and in the case of the MSVC STL do) set cdecl explicitly on new / delete implementations. On the other hand, Clang generates implicit decls with the target's default CC. This is problematic for SPIR-V, since the default there is spir_function, which is not compatible. Since we cannot change pre-existing headers / implementations, this patch sets the CC to C for the implicit host-side decls, when compiling for device, to prevent the conflict. This is fine because the host-side overloards do not get emitted on device.


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

2 Files Affected:

  • (modified) clang/lib/Sema/SemaExprCXX.cpp (+7)
  • (added) clang/test/SemaHIP/amdgcnspirv-implicit-alloc-function-calling-conv.hip (+26)
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 0edfd6015cbd9..5b9cd65c52099 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -3497,6 +3497,13 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
   }
 
   auto CreateAllocationFunctionDecl = [&](Attr *ExtraAttr) {
+    // The MSVC STL has explicit cdecl on its (host-side) allocation function
+    // specializations for the allocation, so in order to prevent a CC clash
+    // we set cdecl on the host-side implicit decls, knowing these do not get
+    // emitted when compiling for device.
+    if (getLangOpts().CUDAIsDevice && ExtraAttr && isa<CUDAHostAttr>(ExtraAttr)
+        && Context.getTargetInfo().getTriple().isSPIRV())
+      EPI.ExtInfo = EPI.ExtInfo.withCallingConv(CallingConv::CC_C);
     QualType FnType = Context.getFunctionType(Return, Params, EPI);
     FunctionDecl *Alloc = FunctionDecl::Create(
         Context, GlobalCtx, SourceLocation(), SourceLocation(), Name, FnType,
diff --git a/clang/test/SemaHIP/amdgcnspirv-implicit-alloc-function-calling-conv.hip b/clang/test/SemaHIP/amdgcnspirv-implicit-alloc-function-calling-conv.hip
new file mode 100644
index 0000000000000..7e87a904054ce
--- /dev/null
+++ b/clang/test/SemaHIP/amdgcnspirv-implicit-alloc-function-calling-conv.hip
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv32 -verify
+// RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv64 -verify
+// RUN: %clang_cc1 %s -fcuda-is-device -std=c++17 -triple spirv64-amd-amdhsa -verify
+
+// expected-no-diagnostics
+
+namespace std
+{
+    enum class align_val_t : __SIZE_TYPE__ {};
+    struct nothrow_t { explicit nothrow_t() = default; };
+    extern nothrow_t const nothrow;
+}
+
+void* __attribute__((cdecl)) operator new(__SIZE_TYPE__);
+void* __attribute__((cdecl)) operator new[](__SIZE_TYPE__);
+void* __attribute__((cdecl)) operator new(__SIZE_TYPE__, ::std::align_val_t);
+void* __attribute__((cdecl)) operator new[](__SIZE_TYPE__, ::std::align_val_t);
+
+void __attribute__((cdecl)) operator delete(void*) noexcept;
+void __attribute__((cdecl)) operator delete[](void*) noexcept;
+void __attribute__((cdecl)) operator delete(void*, __SIZE_TYPE__) noexcept;
+void __attribute__((cdecl)) operator delete[](void*, __SIZE_TYPE__) noexcept;
+void __attribute__((cdecl)) operator delete(void*, ::std::align_val_t) noexcept;
+void __attribute__((cdecl)) operator delete[](void*, ::std::align_val_t) noexcept;
+void __attribute__((cdecl)) operator delete(void*, __SIZE_TYPE__, ::std::align_val_t) noexcept;
+void __attribute__((cdecl)) operator delete[](void*, __SIZE_TYPE__, ::std::align_val_t) noexcept;

@AlexVlx AlexVlx requested review from chinmaydd and yxsamliu August 4, 2025 20:20
Copy link

github-actions bot commented Aug 4, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Contributor

@chinmaydd chinmaydd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Specifically necessary to avoid CC clash on Windows for AMDGCNSPIRV. @yxsamliu any thoughts?

Copy link
Collaborator

@yxsamliu yxsamliu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM for now. If we encounter similar situation in future may consider a more generic approach.

@chinmaydd chinmaydd merged commit 327c64c into llvm:main Aug 8, 2025
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants