From a0b06b965a7fd4473700ae3b60ef63dfcc7b5afa Mon Sep 17 00:00:00 2001
From: Tomohiro Kashiwada <kikairoya@gmail.com>
Date: Mon, 15 Sep 2025 02:09:46 +0900
Subject: [PATCH] [Clang][Cygwin] Cygwin x86_64 should accept __stdcall
 (#158385)

Cygwin should support calling convention attributes `__cdecl`,
`__stdcall`, `__thiscall`, and `__fastcall`, even though they have no
effect in x86_64, as done in MinGW.

Originally reported in
https://cygwin.com/pipermail/cygwin/2025-September/258782.html

---------

Co-authored-by: Jeremy Drake <github@jdrake.com>
(cherry picked from commit b01cddee0e69bd283a0f1830f24fae326371f1de)
---
 clang/lib/Basic/Targets/X86.h                 | 23 ++++++++++++
 clang/test/CodeGen/X86/cygwin-varargs.c       | 35 -------------------
 clang/test/CodeGen/calling-conv-ignored.c     |  2 ++
 clang/test/CodeGen/debug-info-cc.c            |  6 ++--
 clang/test/CodeGen/ms_abi.c                   |  2 ++
 clang/test/CodeGen/sysv_abi.c                 |  4 +++
 .../x64-windows-calling-convention-handling.c |  4 ++-
 clang/test/Sema/MicrosoftCompatibility-x64.c  |  4 ++-
 8 files changed, 41 insertions(+), 39 deletions(-)
 delete mode 100644 clang/test/CodeGen/X86/cygwin-varargs.c

diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h
index a7be080695..da1644f57e 100644
--- a/clang/lib/Basic/Targets/X86.h
+++ b/clang/lib/Basic/Targets/X86.h
@@ -1002,6 +1002,29 @@ public:
       Builder.defineMacro("_GNU_SOURCE");
   }
 
+  CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+    switch (CC) {
+    case CC_X86StdCall:
+    case CC_X86ThisCall:
+    case CC_X86FastCall:
+      return CCCR_Ignore;
+    case CC_C:
+    case CC_X86VectorCall:
+    case CC_IntelOclBicc:
+    case CC_PreserveMost:
+    case CC_PreserveAll:
+    case CC_PreserveNone:
+    case CC_X86_64SysV:
+    case CC_Swift:
+    case CC_SwiftAsync:
+    case CC_X86RegCall:
+    case CC_DeviceKernel:
+      return CCCR_OK;
+    default:
+      return CCCR_Warning;
+    }
+  }
+
   BuiltinVaListKind getBuiltinVaListKind() const override {
     return TargetInfo::CharPtrBuiltinVaList;
   }
diff --git a/clang/test/CodeGen/X86/cygwin-varargs.c b/clang/test/CodeGen/X86/cygwin-varargs.c
deleted file mode 100644
index 4eea7d64bc..0000000000
--- a/clang/test/CodeGen/X86/cygwin-varargs.c
+++ /dev/null
@@ -1,35 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-windows-gnu -emit-llvm < %s | FileCheck %s
-// RUN: %clang_cc1 -triple x86_64-pc-cygwin -emit-llvm < %s | FileCheck %s
-
-struct foo {
-  int x;
-  float y;
-  char z;
-};
-// CHECK: %[[STRUCT_FOO:.*]] = type { i32, float, i8 }
-
-void f(int a, ...) {
-  // CHECK-LABEL: define dso_local void @f
-  __builtin_va_list ap;
-  __builtin_va_start(ap, a);
-  // CHECK: %[[AP:.*]] = alloca ptr
-  // CHECK: call void @llvm.va_start
-  int b = __builtin_va_arg(ap, int);
-  // CHECK: %[[AP_CUR:.*]] = load ptr, ptr %[[AP]]
-  // CHECK-NEXT: %[[AP_NEXT:.*]] = getelementptr inbounds i8, ptr %[[AP_CUR]], i64 8
-  // CHECK-NEXT: store ptr %[[AP_NEXT]], ptr %[[AP]]
-  double _Complex c = __builtin_va_arg(ap, double _Complex);
-  // CHECK: %[[AP_CUR2:.*]] = load ptr, ptr %[[AP]]
-  // CHECK-NEXT: %[[AP_NEXT2:.*]] = getelementptr inbounds i8, ptr %[[AP_CUR2]], i64 8
-  // CHECK-NEXT: store ptr %[[AP_NEXT2]], ptr %[[AP]]
-  // CHECK-NEXT: load ptr, ptr %[[AP_CUR2]]
-  struct foo d = __builtin_va_arg(ap, struct foo);
-  // CHECK: %[[AP_CUR3:.*]] = load ptr, ptr %[[AP]]
-  // CHECK-NEXT: %[[AP_NEXT3:.*]] = getelementptr inbounds i8, ptr %[[AP_CUR3]], i64 8
-  // CHECK-NEXT: store ptr %[[AP_NEXT3]], ptr %[[AP]]
-  __builtin_va_list ap2;
-  __builtin_va_copy(ap2, ap);
-  // CHECK: call void @llvm.va_copy
-  __builtin_va_end(ap);
-  // CHECK: call void @llvm.va_end
-}
diff --git a/clang/test/CodeGen/calling-conv-ignored.c b/clang/test/CodeGen/calling-conv-ignored.c
index 9c47f641ea..5dbc7e4084 100644
--- a/clang/test/CodeGen/calling-conv-ignored.c
+++ b/clang/test/CodeGen/calling-conv-ignored.c
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -triple i686-windows-msvc   -emit-llvm -o - %s | FileCheck %s --check-prefix=X86
 // RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -o - %s | FileCheck %s --check-prefix=X64
+// RUN: %clang_cc1 -triple x86_64-windows-gnu  -emit-llvm -o - %s | FileCheck %s --check-prefix=X64
+// RUN: %clang_cc1 -triple x86_64-cygwin       -emit-llvm -o - %s | FileCheck %s --check-prefix=X64
 // RUN: %clang_cc1 -triple i686-windows-msvc   -emit-llvm -o - %s -fdefault-calling-conv=vectorcall | FileCheck %s --check-prefix=X86-VEC
 // RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -o - %s -fdefault-calling-conv=vectorcall | FileCheck %s --check-prefix=X64-VEC
 
diff --git a/clang/test/CodeGen/debug-info-cc.c b/clang/test/CodeGen/debug-info-cc.c
index 2bfb1c28e9..e430e4c8ed 100644
--- a/clang/test/CodeGen/debug-info-cc.c
+++ b/clang/test/CodeGen/debug-info-cc.c
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -o - -emit-llvm -debug-info-kind=limited %s | FileCheck %s --check-prefix=LINUX
-// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -o - -emit-llvm -debug-info-kind=limited %s | FileCheck %s --check-prefix=WINDOWS
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc   -o - -emit-llvm -debug-info-kind=limited %s | FileCheck %s --check-prefix=WINDOWS
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-gnu    -o - -emit-llvm -debug-info-kind=limited %s | FileCheck %s --check-prefix=WINDOWS
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-cygnus -o - -emit-llvm -debug-info-kind=limited %s | FileCheck %s --check-prefix=WINDOWS
 // RUN: %clang_cc1 -triple i386-pc-linux-gnu -o - -emit-llvm -debug-info-kind=limited %s | FileCheck %s --check-prefix=LINUX32
 // RUN: %clang_cc1 -triple armv7--linux-gnueabihf -o - -emit-llvm -debug-info-kind=limited %s | FileCheck %s --check-prefix=ARM
 
@@ -77,7 +79,7 @@ __attribute__((intel_ocl_bicc)) int add_inteloclbicc(int a, int b) {
 }
 #endif
 
-#ifdef _WIN64
+#if defined(_WIN64) || defined(__CYGWIN__)
 // WINDOWS: !DISubprogram({{.*}}"add_sysvabi", {{.*}}type: ![[FTY:[0-9]+]]
 // WINDOWS: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_X86_64SysV,
 __attribute__((sysv_abi)) int add_sysvabi(int a, int b) {
diff --git a/clang/test/CodeGen/ms_abi.c b/clang/test/CodeGen/ms_abi.c
index 528e546f31..f5b859b5a4 100644
--- a/clang/test/CodeGen/ms_abi.c
+++ b/clang/test/CodeGen/ms_abi.c
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-unknown-freebsd10.0 -emit-llvm < %s | FileCheck -check-prefix=FREEBSD %s
 // RUN: %clang_cc1 -triple x86_64-pc-win32 -emit-llvm < %s | FileCheck -check-prefix=WIN64 %s
+// RUN: %clang_cc1 -triple x86_64-mingw    -emit-llvm < %s | FileCheck -check-prefix=WIN64 %s
+// RUN: %clang_cc1 -triple x86_64-cygwin   -emit-llvm < %s | FileCheck -check-prefix=WIN64 %s
 // RUN: %clang_cc1 -triple x86_64-uefi -emit-llvm < %s | FileCheck -check-prefix=WIN64 %s
 
 struct foo {
diff --git a/clang/test/CodeGen/sysv_abi.c b/clang/test/CodeGen/sysv_abi.c
index 29ea819c2a..a66ecc6e26 100644
--- a/clang/test/CodeGen/sysv_abi.c
+++ b/clang/test/CodeGen/sysv_abi.c
@@ -1,7 +1,11 @@
 // RUN: %clang_cc1 -triple x86_64-pc-win32 -emit-llvm  -target-cpu skylake-avx512 < %s | FileCheck %s --check-prefixes=CHECK,AVX
+// RUN: %clang_cc1 -triple x86_64-mingw    -emit-llvm  -target-cpu skylake-avx512 < %s | FileCheck %s --check-prefixes=CHECK,AVX
+// RUN: %clang_cc1 -triple x86_64-cygwin   -emit-llvm  -target-cpu skylake-avx512 < %s | FileCheck %s --check-prefixes=CHECK,AVX
 // RUN: %clang_cc1 -triple x86_64-linux -emit-llvm  -target-cpu skylake-avx512 < %s | FileCheck %s --check-prefixes=CHECK,AVX
 // RUN: %clang_cc1 -triple x86_64-uefi -emit-llvm  -target-cpu skylake-avx512 < %s | FileCheck %s --check-prefixes=CHECK,AVX
 // RUN: %clang_cc1 -triple x86_64-pc-win32 -emit-llvm < %s | FileCheck %s --check-prefixes=CHECK,NOAVX
+// RUN: %clang_cc1 -triple x86_64-mingw    -emit-llvm < %s | FileCheck %s --check-prefixes=CHECK,NOAVX
+// RUN: %clang_cc1 -triple x86_64-cygwin   -emit-llvm < %s | FileCheck %s --check-prefixes=CHECK,NOAVX
 // RUN: %clang_cc1 -triple x86_64-linux -emit-llvm < %s | FileCheck %s --check-prefixes=CHECK,NOAVX
 // RUN: %clang_cc1 -triple x86_64-uefi -emit-llvm < %s | FileCheck %s --check-prefixes=CHECK,NOAVX
 
diff --git a/clang/test/Parser/x64-windows-calling-convention-handling.c b/clang/test/Parser/x64-windows-calling-convention-handling.c
index c027663414..224931c4eb 100644
--- a/clang/test/Parser/x64-windows-calling-convention-handling.c
+++ b/clang/test/Parser/x64-windows-calling-convention-handling.c
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -triple x86_64-windows -fms-compatibility -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple x86_64-windows -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple x86_64-mingw   -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple x86_64-cygwin  -fsyntax-only -verify %s
 
 int __cdecl cdecl(int a, int b, int c, int d) { // expected-no-diagnostics
   return a + b + c + d;
diff --git a/clang/test/Sema/MicrosoftCompatibility-x64.c b/clang/test/Sema/MicrosoftCompatibility-x64.c
index 7d1f64996e..a422b549dc 100644
--- a/clang/test/Sema/MicrosoftCompatibility-x64.c
+++ b/clang/test/Sema/MicrosoftCompatibility-x64.c
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 %s -Wmicrosoft -verify -fms-compatibility -triple x86_64-pc-win32
+// RUN: %clang_cc1 %s -Wmicrosoft -verify -triple x86_64-pc-win32
+// RUN: %clang_cc1 %s -Wmicrosoft -verify -triple x86_64-w64-mingw32
+// RUN: %clang_cc1 %s -Wmicrosoft -verify -triple x86_64-pc-cygwin
 
 // None of these should warn. stdcall is treated as equivalent to cdecl on
 // x64.
-- 
2.51.0.windows.1

