llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Keno Fischer (Keno)

<details>
<summary>Changes</summary>

This implements the mingw `-mcrtdll` option recently added to gcc.
This option is useful for having the compiler be in charge of crt
version selection while only shipping a single copy of mingw for a
multi-ABI toolchain. That said, there are various ABI dependent compiler
libraries (e.g. libstdc++), so a certain degree of ABI awareness is
nevertheless required in order to use this option correctly.

See also #<!-- -->149434 (which this branch includes, since it touches the same 
code).

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


10 Files Affected:

- (modified) clang/include/clang/Basic/DiagnosticFrontendKinds.td (+3) 
- (modified) clang/include/clang/Basic/LangOptions.def (+3) 
- (modified) clang/include/clang/Basic/LangOptions.h (+17) 
- (modified) clang/include/clang/Driver/Options.td (+6) 
- (modified) clang/lib/Basic/Targets/OSTargets.cpp (+47-1) 
- (modified) clang/lib/Driver/ToolChains/Clang.cpp (+1) 
- (modified) clang/lib/Driver/ToolChains/MinGW.cpp (+18-6) 
- (modified) clang/lib/Frontend/CompilerInvocation.cpp (+38) 
- (added) clang/test/Driver/mingw-mcrtdll.c (+30) 
- (modified) clang/test/Driver/mingw-msvcrt.c (+4-4) 


``````````diff
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td 
b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index 8a8db27490f06..3de97a0ec3955 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -393,6 +393,9 @@ def warn_hlsl_langstd_minimal :
           "recommend using %1 instead">,
   InGroup<HLSLDXCCompat>;
 
+def err_unknown_crtdll : Error<"unknown Windows/MinGW C runtime library '%0'">,
+                         DefaultFatal;
+
 // ClangIR frontend errors
 def err_cir_to_cir_transform_failed : Error<
     "CIR-to-CIR transformation failed">, DefaultFatal;
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index e43238ba683f2..46f03982a041b 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -493,6 +493,9 @@ LANGOPT(BoundsSafety, 1, 0, NotCompatible, "Bounds safety 
extension for C")
 
 LANGOPT(PreserveVec3Type, 1, 0, NotCompatible, "Preserve 3-component vector 
type")
 
+ENUM_LANGOPT(MinGWCRTDll, WindowsCRTDLLVersion, 4, 
WindowsCRTDLLVersion::CRTDLL_Default, NotCompatible,
+             "MinGW specific. Controls the __MSVCRT_VERSION and related 
preprocessor defines.")
+
 #undef LANGOPT
 #undef ENUM_LANGOPT
 #undef VALUE_LANGOPT
diff --git a/clang/include/clang/Basic/LangOptions.h 
b/clang/include/clang/Basic/LangOptions.h
index 4c642c9e10c91..a0160017b6813 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -164,6 +164,23 @@ class LangOptionsBase {
     MSVC2022_9 = 1939,
   };
 
+  enum WindowsCRTDLLVersion {
+    CRTDLL_Default,
+    CRTDLL,
+    MSVCRT10,
+    MSVCRT20,
+    MSVCRT40,
+    MSVCRTD,
+    MSVCR70,
+    MSVCR71,
+    MSVCR80,
+    MSVCR90,
+    MSVCR100,
+    MSVCR110,
+    MSVCR120,
+    UCRT
+  };
+
   enum SYCLMajorVersion {
     SYCL_None,
     SYCL_2017,
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index d0b54a446309b..6ad978c525812 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1625,6 +1625,12 @@ defm auto_import : BoolFOption<"auto-import",
   PosFlag<SetTrue, [], [], "MinGW specific. Enable code generation support for 
"
           "automatic dllimport, and enable support for it in the linker. "
           "Enabled by default.">>;
+def mcrtdll_EQ : Joined<["-"], "mcrtdll=">,
+                 Group<m_Group>,
+                 Visibility<[ClangOption, CC1Option]>,
+                 HelpText<"MinGW specific. Changes preprocessor flags and "
+                          "linker options to use the"
+                          "specified C runtime library.">;
 } // let Flags = [TargetSpecific]
 
 // In the future this option will be supported by other offloading
diff --git a/clang/lib/Basic/Targets/OSTargets.cpp 
b/clang/lib/Basic/Targets/OSTargets.cpp
index e744e84a5b079..8e48228d1220f 100644
--- a/clang/lib/Basic/Targets/OSTargets.cpp
+++ b/clang/lib/Basic/Targets/OSTargets.cpp
@@ -141,8 +141,54 @@ static void addMinGWDefines(const llvm::Triple &Triple, 
const LangOptions &Opts,
     DefineStd(Builder, "WIN64", Opts);
     Builder.defineMacro("__MINGW64__");
   }
-  Builder.defineMacro("__MSVCRT__");
   Builder.defineMacro("__MINGW32__");
+  if (Opts.getMinGWCRTDll() == LangOptions::WindowsCRTDLLVersion::CRTDLL) {
+    Builder.defineMacro("__CRTDLL__");
+  } else {
+    Builder.defineMacro("__MSVCRT__");
+    switch (Opts.getMinGWCRTDll()) {
+    case LangOptions::WindowsCRTDLLVersion::CRTDLL_Default:
+      break;
+    case LangOptions::WindowsCRTDLLVersion::MSVCRT10:
+      Builder.defineMacro("__MSVCRT_VERSION__", "0x100");
+      break;
+    case LangOptions::WindowsCRTDLLVersion::MSVCRT20:
+      Builder.defineMacro("__MSVCRT_VERSION__", "0x200");
+      break;
+    case LangOptions::WindowsCRTDLLVersion::MSVCRT40:
+      Builder.defineMacro("__MSVCRT_VERSION__", "0x400");
+      break;
+    case LangOptions::WindowsCRTDLLVersion::MSVCRTD:
+      Builder.defineMacro("__MSVCRT_VERSION__", "0x600");
+      break;
+    case LangOptions::WindowsCRTDLLVersion::MSVCR70:
+      Builder.defineMacro("__MSVCRT_VERSION__", "0x700");
+      break;
+    case LangOptions::WindowsCRTDLLVersion::MSVCR71:
+      Builder.defineMacro("__MSVCRT_VERSION__", "0x701");
+      break;
+    case LangOptions::WindowsCRTDLLVersion::MSVCR80:
+      Builder.defineMacro("__MSVCRT_VERSION__", "0x800");
+      break;
+    case LangOptions::WindowsCRTDLLVersion::MSVCR90:
+      Builder.defineMacro("__MSVCRT_VERSION__", "0x900");
+      break;
+    case LangOptions::WindowsCRTDLLVersion::MSVCR100:
+      Builder.defineMacro("__MSVCRT_VERSION__", "0xA00");
+      break;
+    case LangOptions::WindowsCRTDLLVersion::MSVCR110:
+      Builder.defineMacro("__MSVCRT_VERSION__", "0xB00");
+      break;
+    case LangOptions::WindowsCRTDLLVersion::MSVCR120:
+      Builder.defineMacro("__MSVCRT_VERSION__", "0xC00");
+      break;
+    case LangOptions::WindowsCRTDLLVersion::UCRT:
+      Builder.defineMacro("_UCRT");
+      break;
+    default:
+      llvm_unreachable("Unknown MinGW CRT version");
+    }
+  }
   addCygMingDefines(Opts, Builder);
 }
 
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index fe1865888bdd0..79344f4e760d9 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5970,6 +5970,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
   if (Triple.isWindowsGNUEnvironment()) {
     Args.addOptOutFlag(CmdArgs, options::OPT_fauto_import,
                        options::OPT_fno_auto_import);
+    Args.addLastArg(CmdArgs, options::OPT_mcrtdll_EQ);
   }
 
   if (Args.hasFlag(options::OPT_fms_volatile, options::OPT_fno_ms_volatile,
diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp 
b/clang/lib/Driver/ToolChains/MinGW.cpp
index 7d093d20b3dd9..7223cda83fa70 100644
--- a/clang/lib/Driver/ToolChains/MinGW.cpp
+++ b/clang/lib/Driver/ToolChains/MinGW.cpp
@@ -85,12 +85,24 @@ void tools::MinGW::Linker::AddLibGCC(const ArgList &Args,
 
   CmdArgs.push_back("-lmoldname");
   CmdArgs.push_back("-lmingwex");
-  for (auto Lib : Args.getAllArgValues(options::OPT_l))
-    if (StringRef(Lib).starts_with("msvcr") ||
-        StringRef(Lib).starts_with("ucrt") ||
-        StringRef(Lib).starts_with("crtdll"))
-      return;
-  CmdArgs.push_back("-lmsvcrt");
+
+  if (Arg *A = Args.getLastArg(options::OPT_mcrtdll_EQ)) {
+    std::string mcrtdll = (Twine("-l") + A->getValue()).str();
+    CmdArgs.push_back(Args.MakeArgStringRef(mcrtdll));
+  } else {
+    for (auto Lib : Args.getAllArgValues(options::OPT_l))
+      if (StringRef(Lib).starts_with("msvcr") ||
+          StringRef(Lib).starts_with("ucrt") ||
+          StringRef(Lib).starts_with("crtdll")) {
+        Lib = (llvm::Twine("-l") + Lib).str();
+        // Respect the user's chosen crt variant, but still provide it
+        // again as the last linker argument, because some of the libraries
+        // we added above may depend on it.
+        CmdArgs.push_back(Args.MakeArgStringRef(Lib));
+        return;
+      }
+    CmdArgs.push_back("-lmsvcrt");
+  }
 }
 
 void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp 
b/clang/lib/Frontend/CompilerInvocation.cpp
index b9f75796ecc16..26d05bc419ccb 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -4705,6 +4705,44 @@ bool CompilerInvocation::ParseLangArgs(LangOptions 
&Opts, ArgList &Args,
     }
   }
 
+  // Process MinGW -mcrtdll option
+  if (Arg *A = Args.getLastArg(OPT_mcrtdll_EQ)) {
+    Opts.MinGWCRTDll =
+        llvm::StringSwitch<enum LangOptions::WindowsCRTDLLVersion>(
+            A->getValue())
+            .StartsWithLower("crtdll",
+                             LangOptions::WindowsCRTDLLVersion::CRTDLL)
+            .StartsWithLower("msvcrt10",
+                             LangOptions::WindowsCRTDLLVersion::MSVCRT10)
+            .StartsWithLower("msvcrt20",
+                             LangOptions::WindowsCRTDLLVersion::MSVCRT20)
+            .StartsWithLower("msvcrt40",
+                             LangOptions::WindowsCRTDLLVersion::MSVCRT40)
+            .StartsWithLower("msvcr40",
+                             LangOptions::WindowsCRTDLLVersion::MSVCRT40)
+            .StartsWithLower("msvcrtd",
+                             LangOptions::WindowsCRTDLLVersion::MSVCRTD)
+            .StartsWithLower("msvcr70",
+                             LangOptions::WindowsCRTDLLVersion::MSVCR70)
+            .StartsWithLower("msvcr71",
+                             LangOptions::WindowsCRTDLLVersion::MSVCR71)
+            .StartsWithLower("msvcr80",
+                             LangOptions::WindowsCRTDLLVersion::MSVCR80)
+            .StartsWithLower("msvcr90",
+                             LangOptions::WindowsCRTDLLVersion::MSVCR90)
+            .StartsWithLower("msvcr100",
+                             LangOptions::WindowsCRTDLLVersion::MSVCR100)
+            .StartsWithLower("msvcr110",
+                             LangOptions::WindowsCRTDLLVersion::MSVCR110)
+            .StartsWithLower("msvcr120",
+                             LangOptions::WindowsCRTDLLVersion::MSVCR120)
+            .StartsWithLower("ucrt", LangOptions::WindowsCRTDLLVersion::UCRT)
+            .Default(LangOptions::WindowsCRTDLLVersion::CRTDLL_Default);
+    if (Opts.MinGWCRTDll == LangOptions::WindowsCRTDLLVersion::CRTDLL_Default) 
{
+      Diags.Report(diag::err_unknown_crtdll) << A->getValue();
+    }
+  }
+
   return Diags.getNumErrors() == NumErrorsBefore;
 }
 
diff --git a/clang/test/Driver/mingw-mcrtdll.c 
b/clang/test/Driver/mingw-mcrtdll.c
new file mode 100644
index 0000000000000..4558628766169
--- /dev/null
+++ b/clang/test/Driver/mingw-mcrtdll.c
@@ -0,0 +1,30 @@
+// RUN: %clang -v --target=x86_64-w64-mingw32 -### %s 2>&1 | FileCheck 
-check-prefix=DEFAULT %s
+// RUN: %clang -v --target=x86_64-w64-mingw32 -mcrtdll=msvcr90 -### %s 2>&1 | 
FileCheck -check-prefix=MSVCR90 %s
+// RUN: %clang -v --target=x86_64-w64-mingw32 -mcrtdll=msvcr90_suffix -### %s 
2>&1 | FileCheck -check-prefix=MSVCR90_SUFFIX %s
+// RUN: %clang -v --target=x86_64-w64-mingw32 -mcrtdll=ucrt -### %s 2>&1 | 
FileCheck -check-prefix=UCRT %s
+// RUN: %clang -v --target=x86_64-w64-mingw32 -mcrtdll=ucrtbase -### %s 2>&1 | 
FileCheck -check-prefix=UCRTBASE %s
+
+// RUN: %clang -dM -E --target=x86_64-w64-mingw32 %s 2>&1  | FileCheck 
-check-prefix=DEFINE_DEFAULT %s
+// RUN: %clang -dM -E --target=x86_64-w64-mingw32 -mcrtdll=msvcr90 %s 2>&1  | 
FileCheck -check-prefix=DEFINE_MSVCR90 %s
+// RUN: %clang -dM -E --target=x86_64-w64-mingw32 -mcrtdll=msvcr90_suffix %s 
2>&1  | FileCheck -check-prefix=DEFINE_MSVCR90 %s
+// RUN: %clang -dM -E --target=x86_64-w64-mingw32 -mcrtdll=ucrt %s 2>&1  | 
FileCheck -check-prefix=DEFINE_UCRT %s
+// RUN: %clang -dM -E --target=x86_64-w64-mingw32 -mcrtdll=ucrtbase %s 2>&1  | 
FileCheck -check-prefix=DEFINE_UCRT %s
+// RUN: not %clang -dM -E --target=x86_64-w64-mingw32 -mcrtdll=bad %s 2>&1  | 
FileCheck -check-prefix=BAD %s
+
+// DEFAULT: "-lmingwex" "-lmsvcrt"
+// DEFINE_DEFAULT: #define __MSVCRT__
+// MSVCR90: "-lmingwex" "-lmsvcr90"
+// DEFINE_MSVCR90: #define __MSVCRT_VERSION__ 0x900
+// DEFINE_MSVCR90: #define __MSVCRT__
+// MSVCR90-NOT: "-lmsvcrt"
+// MSVCR90_SUFFIX: "-lmingwex" "-lmsvcr90_suffix"
+// MSVCR90_SUFFIX-NOT: "-lmsvcrt"
+// UCRT: "-lmingwex" "-lucrt"
+// DEFINE_UCRT: #define _UCRT
+// DEFINE_UCRT-NOT: #define __MSVCRT_VERSION__
+// UCRT-NOT: "-lmsvcrt"
+// UCRTBASE: "-lmingwex" "-lucrtbase"
+// UCRTBASE-NOT: "-lmsvcrt"
+// DEFINE_CRTDLL: #define __CRTDLL__
+// DEFINE_CRTDLL-NOT: #define __MSVCRT__
+// BAD: error: unknown Windows/MinGW C runtime library 'bad'
diff --git a/clang/test/Driver/mingw-msvcrt.c b/clang/test/Driver/mingw-msvcrt.c
index 340ce1f57b0f8..e1648630476a0 100644
--- a/clang/test/Driver/mingw-msvcrt.c
+++ b/clang/test/Driver/mingw-msvcrt.c
@@ -7,10 +7,10 @@
 // CHECK_DEFAULT: "-lmingwex" "-lmsvcrt" "-ladvapi32"
 // CHECK_DEFAULT-SAME: "-lmsvcrt" "-lkernel32" "{{.*}}crtend.o"
 // CHECK_MSVCR120: "-lmsvcr120"
-// CHECK_MSVCR120-SAME: "-lmingwex" "-ladvapi32"
+// CHECK_MSVCR120-SAME: "-lmingwex" "-lmsvcr120" "-ladvapi32"
 // CHECK_UCRTBASE: "-lucrtbase"
-// CHECK_UCRTBASE-SAME: "-lmingwex" "-ladvapi32"
+// CHECK_UCRTBASE-SAME: "-lmingwex" "-lucrtbase" "-ladvapi32"
 // CHECK_UCRT: "-lucrt"
-// CHECK_UCRT-SAME: "-lmingwex" "-ladvapi32"
+// CHECK_UCRT-SAME: "-lmingwex" "-lucrt" "-ladvapi32"
 // CHECK_CRTDLL: "-lcrtdll"
-// CHECK_CRTDLL-SAME: "-lmingwex" "-ladvapi32"
+// CHECK_CRTDLL-SAME: "-lmingwex" "-lcrtdll" "-ladvapi32"

``````````

</details>


https://github.com/llvm/llvm-project/pull/149469
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to