From 318cb3dc5fd90c4b74fb4cd527dd12c4dee7dd66 Mon Sep 17 00:00:00 2001
From: jeremyd2019 <github@jdrake.com>
Date: Tue, 29 Jul 2025 10:01:43 -0700
Subject: [PATCH] [Clang][Cygwin] Enable few conditions that are shared with
 MinGW (#149637)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The Cygwin target is generally very similar to the MinGW target. The
default auto-import behavior, the default calling convention, the
`.dll.a` import library extension, the `__GXX_TYPEINFO_EQUALITY_INLINE`
pre-define by `g++`, and the long double configuration.

Co-authored-by: Mateusz Mikuła <oss@mateuszmikula.dev>
---
 clang/lib/AST/RecordLayoutBuilder.cpp      | 2 +-
 clang/lib/CIR/CodeGen/CIRGenModule.cpp     | 8 ++++----
 clang/lib/Driver/ToolChain.cpp             | 2 +-
 clang/lib/Driver/ToolChains/Clang.cpp      | 2 +-
 clang/lib/Frontend/InitPreprocessor.cpp    | 4 ++--
 clang/lib/Sema/SemaDecl.cpp                | 4 ++--
 clang/test/CodeGen/ms_struct-long-double.c | 1 +
 clang/test/Preprocessor/Inputs/llvm-windres.h | 14 ++++++++------
 clang/test/Preprocessor/init-x86.c         | 2 ++
 8 files changed, 14 insertions(+), 11 deletions(-)

diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp
index 6a74e98dd9..760b2fcdc0 100644
--- a/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -1953,7 +1953,7 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
           // silently there. For other targets that have ms_struct enabled
           // (most probably via a pragma or attribute), trigger a diagnostic
           // that defaults to an error.
-          if (!Context.getTargetInfo().getTriple().isWindowsGNUEnvironment())
+          if (!Context.getTargetInfo().getTriple().isOSCygMing())
             Diag(D->getLocation(), diag::warn_npot_ms_struct);
         }
         if (TypeSize > FieldAlign &&
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 3502705181..5bc29b81c2 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -1530,10 +1530,10 @@ static bool shouldAssumeDSOLocal(const CIRGenModule &cgm,
 
   const llvm::Triple &tt = cgm.getTriple();
   const CodeGenOptions &cgOpts = cgm.getCodeGenOpts();
-  if (tt.isWindowsGNUEnvironment()) {
-    // In MinGW, variables without DLLImport can still be automatically
-    // imported from a DLL by the linker; don't mark variables that
-    // potentially could come from another DLL as DSO local.
+  if (tt.isOSCygMing()) {
+    // In MinGW and Cygwin, variables without DLLImport can still be
+    // automatically imported from a DLL by the linker; don't mark variables
+    // that potentially could come from another DLL as DSO local.
 
     // With EmulatedTLS, TLS variables can be autoimported from other DLLs
     // (and this actually happens in the public interface of libstdc++), so
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 07a3ae925f..a47f0c3f3f 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -743,7 +743,7 @@ std::string ToolChain::buildCompilerRTBasename(const llvm::opt::ArgList &Args,
     break;
   case ToolChain::FT_Shared:
     if (TT.isOSWindows())
-      Suffix = TT.isWindowsGNUEnvironment() ? ".dll.a" : ".lib";
+      Suffix = TT.isOSCygMing() ? ".dll.a" : ".lib";
     else if (TT.isOSAIX())
       Suffix = ".a";
     else
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 6261332232..e171b2a752 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5963,7 +5963,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
     CmdArgs.push_back("-mms-bitfields");
   }
 
-  if (Triple.isWindowsGNUEnvironment()) {
+  if (Triple.isOSCygMing()) {
     Args.addOptOutFlag(CmdArgs, options::OPT_fauto_import,
                        options::OPT_fno_auto_import);
   }
diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp
index cce8392950..1e24c9428c 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -952,8 +952,8 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
   if (LangOpts.GNUCVersion && LangOpts.CPlusPlus11)
     Builder.defineMacro("__GXX_EXPERIMENTAL_CXX0X__");
 
-  if (TI.getTriple().isWindowsGNUEnvironment()) {
-    // Set ABI defining macros for libstdc++ for MinGW, where the
+  if (TI.getTriple().isOSCygMing()) {
+    // Set ABI defining macros for libstdc++ for MinGW and Cygwin, where the
     // default in libstdc++ differs from the defaults for this target.
     Builder.defineMacro("__GXX_TYPEINFO_EQUALITY_INLINE", "0");
   }
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index bb412ef678..4c07eedd2e 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -12586,9 +12586,9 @@ static bool isDefaultStdCall(FunctionDecl *FD, Sema &S) {
   if (FD->getName() == "main" || FD->getName() == "wmain")
     return false;
 
-  // Default calling convention for MinGW is __cdecl
+  // Default calling convention for MinGW and Cygwin is __cdecl
   const llvm::Triple &T = S.Context.getTargetInfo().getTriple();
-  if (T.isWindowsGNUEnvironment())
+  if (T.isOSCygMing())
     return false;
 
   // Default calling convention for WinMain, wWinMain and DllMain
diff --git a/clang/test/CodeGen/ms_struct-long-double.c b/clang/test/CodeGen/ms_struct-long-double.c
index 9b3ea7947a..eaab217f7c 100644
--- a/clang/test/CodeGen/ms_struct-long-double.c
+++ b/clang/test/CodeGen/ms_struct-long-double.c
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -emit-llvm-only -triple i686-windows-gnu -fdump-record-layouts %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm-only -triple i686-windows-cygnus -fdump-record-layouts %s | FileCheck %s
 // RUN: %clang_cc1 -emit-llvm-only -triple i686-linux -fdump-record-layouts -Wno-incompatible-ms-struct %s | FileCheck %s
 // RUN: not %clang_cc1 -emit-llvm-only -triple i686-linux -fdump-record-layouts %s 2>&1 | FileCheck %s -check-prefix=ERROR
 
diff --git a/clang/test/Preprocessor/Inputs/llvm-windres.h b/clang/test/Preprocessor/Inputs/llvm-windres.h
index 411ec48a8a..ef6bc47885 100644
--- a/clang/test/Preprocessor/Inputs/llvm-windres.h
+++ b/clang/test/Preprocessor/Inputs/llvm-windres.h
@@ -1,10 +1,12 @@
 #ifndef RC_INVOKED
-#error RC_INVOKED not defined
+#  error RC_INVOKED not defined
 #endif
-#ifndef _WIN32
-#error _WIN32 not defined
-#endif
-#ifndef __MINGW32__
-#error __MINGW32__ not defined
+#ifndef __CYGWIN__
+#  ifndef _WIN32
+#    error _WIN32 not defined
+#  endif
+#  ifndef __MINGW32__
+#    error __MINGW32__ not defined
+#  endif
 #endif
 #define MY_ID 42
diff --git a/clang/test/Preprocessor/init-x86.c b/clang/test/Preprocessor/init-x86.c
index 8ea4ce7915..f5fd976b3d 100644
--- a/clang/test/Preprocessor/init-x86.c
+++ b/clang/test/Preprocessor/init-x86.c
@@ -1535,6 +1535,7 @@
 // I386-CYGWIN:#define __GCC_ATOMIC_SHORT_LOCK_FREE 2
 // I386-CYGWIN:#define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
 // I386-CYGWIN:#define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
+// I386-CYGWIN:#define __GXX_TYPEINFO_EQUALITY_INLINE 0
 // I386-CYGWIN:#define __ILP32__ 1
 // I386-CYGWIN:#define __INT16_C(c) c
 // I386-CYGWIN:#define __INT16_C_SUFFIX__
@@ -1746,6 +1747,7 @@
 // X86_64-CYGWIN:#define __GCC_ATOMIC_SHORT_LOCK_FREE 2
 // X86_64-CYGWIN:#define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
 // X86_64-CYGWIN:#define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
+// X86_64-CYGWIN:#define __GXX_TYPEINFO_EQUALITY_INLINE 0
 // X86_64-CYGWIN:#define __INT16_C(c) c
 // X86_64-CYGWIN:#define __INT16_C_SUFFIX__
 // X86_64-CYGWIN:#define __INT16_FMTd__ "hd"
-- 
2.51.0.windows.1

