https://github.com/eleviant updated 
https://github.com/llvm/llvm-project/pull/198538

>From cf3ff26bd18165f92a6dc00fdc985564d24126b3 Mon Sep 17 00:00:00 2001
From: Evgeny Leviant <[email protected]>
Date: Tue, 19 May 2026 16:26:53 +0200
Subject: [PATCH 1/5] Define signed int overflow with -fms-compatibility

It seems that unlike clang, MSVC doesn't treat signed integer overflow
as UB:

https://godbolt.org/z/GYWdjd3Ex

Patch defines SOW, when -fms-compatibility is used.
---
 clang/lib/Frontend/CompilerInvocation.cpp | 3 +--
 clang/test/CodeGen/ms-intrinsics.c        | 4 ++--
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Frontend/CompilerInvocation.cpp 
b/clang/lib/Frontend/CompilerInvocation.cpp
index 60749104252af..4881d94181111 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -4212,8 +4212,7 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, 
ArgList &Args,
     // Set the handler, if one is specified.
     Opts.OverflowHandler =
         std::string(Args.getLastArgValue(OPT_ftrapv_handler));
-  }
-  else if (Args.hasArg(OPT_fwrapv))
+  } else if (Args.hasArg(OPT_fwrapv) || Opts.MSVCCompat)
     Opts.setSignedOverflowBehavior(LangOptions::SOB_Defined);
   if (Args.hasArg(OPT_fwrapv_pointer))
     Opts.PointerOverflowDefined = true;
diff --git a/clang/test/CodeGen/ms-intrinsics.c 
b/clang/test/CodeGen/ms-intrinsics.c
index 271aced5e0b7c..8b719ef8cc1fd 100644
--- a/clang/test/CodeGen/ms-intrinsics.c
+++ b/clang/test/CodeGen/ms-intrinsics.c
@@ -504,8 +504,8 @@ unsigned char test_InterlockedCompareExchange128(
 }
 // CHECK-64: define{{.*}}i8 
@test_InterlockedCompareExchange128(ptr{{.*}}%Destination, i64{{[a-z_ 
]*}}%ExchangeHigh, i64{{[a-z_ ]*}}%ExchangeLow, 
ptr{{.*}}%ComparandResult){{.*}}{
 // CHECK-64: %incdec.ptr = getelementptr inbounds nuw i8, ptr %Destination, 
i64 8
-// CHECK-64: %inc = add nsw i64 %ExchangeHigh, 1
-// CHECK-64: %inc1 = add nsw i64 %ExchangeLow, 1
+// CHECK-64: %inc = add i64 %ExchangeHigh, 1
+// CHECK-64: %inc1 = add i64 %ExchangeLow, 1
 // CHECK-64: %incdec.ptr2 = getelementptr inbounds nuw i8, ptr 
%ComparandResult, i64 8
 // CHECK-64: [[EH:%[0-9]+]] = zext i64 %inc to i128
 // CHECK-64: [[EL:%[0-9]+]] = zext i64 %inc1 to i128

>From 3bf20b61eac00cba34859d7940531af68319f994 Mon Sep 17 00:00:00 2001
From: Evgeny Leviant <[email protected]>
Date: Tue, 19 May 2026 20:39:19 +0200
Subject: [PATCH 2/5] Allow -fno-wrapv to force UB on signed int overflow

---
 clang/include/clang/Options/Options.td    |  2 +-
 clang/lib/Frontend/CompilerInvocation.cpp |  8 ++++++--
 clang/test/CodeGen/wrapv.c                | 12 ++++++++++++
 3 files changed, 19 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/CodeGen/wrapv.c

diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 753e3ac1b74a5..6cea62106a06b 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -4808,7 +4808,7 @@ def fwrapv : Flag<["-"], "fwrapv">, Group<f_Group>,
   Visibility<[ClangOption, CLOption, CC1Option, FlangOption, FC1Option]>,
   HelpText<"Treat signed integer overflow as two's complement">;
 def fno_wrapv : Flag<["-"], "fno-wrapv">, Group<f_Group>,
-  Visibility<[ClangOption, CLOption, FlangOption]>;
+  Visibility<[ClangOption, CC1Option, CLOption, FlangOption]>;
 def fwrapv_pointer : Flag<["-"], "fwrapv-pointer">, Group<f_Group>,
   Visibility<[ClangOption, CLOption, CC1Option, FlangOption, FC1Option]>,
   HelpText<"Treat pointer overflow as two's complement">;
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp 
b/clang/lib/Frontend/CompilerInvocation.cpp
index 4881d94181111..9fc695a74a3c7 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -3797,7 +3797,10 @@ void CompilerInvocationBase::GenerateLangArgs(const 
LangOptions &Opts,
     GenerateArg(Consumer, OPT_ftrapv);
     GenerateArg(Consumer, OPT_ftrapv_handler, Opts.OverflowHandler);
   } else if (Opts.SignedOverflowBehavior == LangOptions::SOB_Defined) {
-    GenerateArg(Consumer, OPT_fwrapv);
+    if (!Opts.MSVCCompat)
+      GenerateArg(Consumer, OPT_fwrapv);
+  } else if (Opts.MSVCCompat) {
+    GenerateArg(Consumer, OPT_fno_wrapv);
   }
   if (Opts.PointerOverflowDefined)
     GenerateArg(Consumer, OPT_fwrapv_pointer);
@@ -4212,8 +4215,9 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, 
ArgList &Args,
     // Set the handler, if one is specified.
     Opts.OverflowHandler =
         std::string(Args.getLastArgValue(OPT_ftrapv_handler));
-  } else if (Args.hasArg(OPT_fwrapv) || Opts.MSVCCompat)
+  } else if (Args.hasFlag(OPT_fwrapv, OPT_fno_wrapv, Opts.MSVCCompat)) {
     Opts.setSignedOverflowBehavior(LangOptions::SOB_Defined);
+  }
   if (Args.hasArg(OPT_fwrapv_pointer))
     Opts.PointerOverflowDefined = true;
 
diff --git a/clang/test/CodeGen/wrapv.c b/clang/test/CodeGen/wrapv.c
new file mode 100644
index 0000000000000..312695c3d25c6
--- /dev/null
+++ b/clang/test/CodeGen/wrapv.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s --check-prefix=NOWRAP
+// RUN: %clang_cc1 -fno-wrapv -emit-llvm %s -o - | FileCheck %s 
--check-prefix=NOWRAP
+// RUN: %clang_cc1 -fno-wrapv -fms-compatibility -emit-llvm %s -o - | 
FileCheck %s --check-prefix=NOWRAP
+// RUN: %clang_cc1 -fwrapv -emit-llvm %s -o - | FileCheck %s 
--check-prefix=WRAP
+// RUN: %clang_cc1 -fms-compatibility -emit-llvm %s -o - | FileCheck %s 
--check-prefix=WRAP
+
+// NOWRAP: %add = add nsw i32 %0, 1
+// WRAP: %add = add i32 %0, 1
+
+int add1(int x) {
+  return x + 1;
+}

>From cba5e8232b37fffe9dcfb1ef92e0b1b2ab6faf79 Mon Sep 17 00:00:00 2001
From: Evgeny Leviant <[email protected]>
Date: Tue, 19 May 2026 21:28:49 +0200
Subject: [PATCH 3/5] Attempt to fix Windows builder

---
 compiler-rt/test/ubsan/TestCases/Integer/shift.cpp | 8 ++++----
 compiler-rt/test/ubsan/TestCases/Misc/abs.cpp      | 4 ++--
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/compiler-rt/test/ubsan/TestCases/Integer/shift.cpp 
b/compiler-rt/test/ubsan/TestCases/Integer/shift.cpp
index 50db16dac18ec..3c4f9692b7a33 100644
--- a/compiler-rt/test/ubsan/TestCases/Integer/shift.cpp
+++ b/compiler-rt/test/ubsan/TestCases/Integer/shift.cpp
@@ -1,5 +1,5 @@
-// RUN: %clangxx -DLSH_OVERFLOW -DOP='<<' -fsanitize=shift-base 
-fno-sanitize-recover=shift %s -o %t1 && not %run %t1 2>&1 | FileCheck %s 
--check-prefix=CHECK-LSH_OVERFLOW
-// RUN: %clangxx -DLSH_OVERFLOW -DOP='<<=' -fsanitize=shift 
-fno-sanitize-recover=shift %s -o %t2 && not %run %t2 2>&1 | FileCheck %s 
--check-prefix=CHECK-LSH_OVERFLOW
+// RUN: %clangxx -DLSH_OVERFLOW -fno-wrapv -DOP='<<' -fsanitize=shift-base 
-fno-sanitize-recover=shift %s -o %t1 && not %run %t1 2>&1 | FileCheck %s 
--check-prefix=CHECK-LSH_OVERFLOW
+// RUN: %clangxx -DLSH_OVERFLOW -fno-wrapv -DOP='<<=' -fsanitize=shift 
-fno-sanitize-recover=shift %s -o %t2 && not %run %t2 2>&1 | FileCheck %s 
--check-prefix=CHECK-LSH_OVERFLOW
 // RUN: %clangxx -DTOO_LOW -DOP='<<' -fsanitize=shift-exponent 
-fno-sanitize-recover=shift %s -o %t3 && not %run %t3 2>&1 | FileCheck %s 
--check-prefix=CHECK-TOO_LOW
 // RUN: %clangxx -DTOO_LOW -DOP='>>' -fsanitize=shift 
-fno-sanitize-recover=shift %s -o %t4 && not %run %t4 2>&1 | FileCheck %s 
--check-prefix=CHECK-TOO_LOW
 // RUN: %clangxx -DTOO_LOW -DOP='<<=' -fsanitize=shift 
-fno-sanitize-recover=shift %s -o %t5 && not %run %t5 2>&1 | FileCheck %s 
--check-prefix=CHECK-TOO_LOW
@@ -9,8 +9,8 @@
 // RUN: %clangxx -DTOO_HIGH -DOP='<<=' -fsanitize=shift 
-fno-sanitize-recover=shift %s -o %t9 && not %run %t9 2>&1 | FileCheck %s 
--check-prefix=CHECK-TOO_HIGH
 // RUN: %clangxx -DTOO_HIGH -DOP='>>=' -fsanitize=shift 
-fno-sanitize-recover=shift %s -o %t10 && not %run %t10 2>&1 | FileCheck %s 
--check-prefix=CHECK-TOO_HIGH
 
-// RUN: %clangxx -DLSH_OVERFLOW -DOP='<<' -fsanitize=shift-exponent 
-fno-sanitize-recover=shift %s -o %t12 && %run %t12
-// RUN: %clangxx -DLSH_OVERFLOW -DOP='>>' -fsanitize=shift-exponent 
-fno-sanitize-recover=shift %s -o %t13 && %run %t13
+// RUN: %clangxx -DLSH_OVERFLOW -fno-wrapv -DOP='<<' -fsanitize=shift-exponent 
-fno-sanitize-recover=shift %s -o %t12 && %run %t12
+// RUN: %clangxx -DLSH_OVERFLOW -fno-wrapv -DOP='>>' -fsanitize=shift-exponent 
-fno-sanitize-recover=shift %s -o %t13 && %run %t13
 // RUN: %clangxx -DTOO_LOW -DOP='<<' -fsanitize=shift-base 
-fno-sanitize-recover=shift %s -o %t14 && %run %t14
 // RUN: %clangxx -DTOO_LOW -DOP='>>' -fsanitize=shift-base 
-fno-sanitize-recover=shift %s -o %t15 && %run %t15
 // RUN: %clangxx -DTOO_HIGH -DOP='<<' -fsanitize=shift-base 
-fno-sanitize-recover=shift %s -o %t16 && %run %t16
diff --git a/compiler-rt/test/ubsan/TestCases/Misc/abs.cpp 
b/compiler-rt/test/ubsan/TestCases/Misc/abs.cpp
index 5f4beec1e6294..30c9891f224f6 100644
--- a/compiler-rt/test/ubsan/TestCases/Misc/abs.cpp
+++ b/compiler-rt/test/ubsan/TestCases/Misc/abs.cpp
@@ -1,7 +1,7 @@
-// RUN: %clangxx -fsanitize=signed-integer-overflow -w %s -O3 -o %t
+// RUN: %clangxx -fno-wrapv -fsanitize=signed-integer-overflow -w %s -O3 -o %t
 // RUN: %run %t 2>&1 | FileCheck %s --check-prefix=RECOVER
 
-// RUN: %clangxx -fsanitize=signed-integer-overflow 
-fno-sanitize-recover=signed-integer-overflow -w %s -O3 -o %t.abort
+// RUN: %clangxx -fno-wrapv -fsanitize=signed-integer-overflow 
-fno-sanitize-recover=signed-integer-overflow -w %s -O3 -o %t.abort
 // RUN: not %run %t.abort 2>&1 | FileCheck %s --check-prefix=ABORT
 
 #include <limits.h>

>From e6dab43e8412be9cd54666c8fa173eecdd9bc1cd Mon Sep 17 00:00:00 2001
From: Evgeny Leviant <[email protected]>
Date: Wed, 20 May 2026 14:56:40 +0200
Subject: [PATCH 4/5] Fix rendering of integer overflow options

---
 clang/include/clang/Driver/CommonArgs.h    | 3 ++-
 clang/lib/Driver/ToolChains/Clang.cpp      | 8 ++++----
 clang/lib/Driver/ToolChains/CommonArgs.cpp | 7 +++++--
 clang/lib/Driver/ToolChains/Flang.cpp      | 2 +-
 clang/test/Driver/clang_wrapv_opts.c       | 6 ++++++
 5 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/clang/include/clang/Driver/CommonArgs.h 
b/clang/include/clang/Driver/CommonArgs.h
index 0af1b89425227..34b3d302fe189 100644
--- a/clang/include/clang/Driver/CommonArgs.h
+++ b/clang/include/clang/Driver/CommonArgs.h
@@ -283,7 +283,8 @@ void renderGlobalISelOptions(const Driver &D, const 
llvm::opt::ArgList &Args,
                              const llvm::Triple &Triple);
 
 void renderCommonIntegerOverflowOptions(const llvm::opt::ArgList &Args,
-                                        llvm::opt::ArgStringList &CmdArgs);
+                                        llvm::opt::ArgStringList &CmdArgs,
+                                        bool IsMSVCCompat);
 
 bool shouldEnableVectorizerAtOLevel(const llvm::opt::ArgList &Args,
                                     bool isSlpVec);
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 8d8e00bbaf7d0..8e9f8ed3bc14b 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7121,10 +7121,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
 
   Args.AddLastArg(CmdArgs, options::OPT_ftrap_function_EQ);
 
-  // Handle -f[no-]wrapv and -f[no-]strict-overflow, which are used by both
-  // clang and flang.
-  renderCommonIntegerOverflowOptions(Args, CmdArgs);
-
   Args.AddLastArg(CmdArgs, options::OPT_ffinite_loops,
                   options::OPT_fno_finite_loops);
 
@@ -7396,6 +7392,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
       CmdArgs.push_back("-fms-define-stdc");
   }
 
+  // Handle -f[no-]wrapv and -f[no-]strict-overflow, which are used by both
+  // clang and flang.
+  renderCommonIntegerOverflowOptions(Args, CmdArgs, IsMSVCCompat);
+
   // -fms-anonymous-structs is disabled by default.
   // Determine whether to enable Microsoft named anonymous struct/union 
support.
   // This implements "last flag wins" semantics for -fms-anonymous-structs,
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp 
b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 6a0dcfca62c60..c724e6ff595c5 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -3390,8 +3390,9 @@ void tools::renderGlobalISelOptions(const Driver &D, 
const ArgList &Args,
 }
 
 void tools::renderCommonIntegerOverflowOptions(const ArgList &Args,
-                                               ArgStringList &CmdArgs) {
-  bool use_fwrapv = false;
+                                               ArgStringList &CmdArgs,
+                                               bool IsMSVCCompat) {
+  bool use_fwrapv = IsMSVCCompat;
   bool use_fwrapv_pointer = false;
   for (const Arg *A : Args.filtered(
            options::OPT_fstrict_overflow, options::OPT_fno_strict_overflow,
@@ -3424,6 +3425,8 @@ void tools::renderCommonIntegerOverflowOptions(const 
ArgList &Args,
 
   if (use_fwrapv)
     CmdArgs.push_back("-fwrapv");
+  if (!use_fwrapv && IsMSVCCompat)
+    CmdArgs.push_back("-fno-wrapv");
   if (use_fwrapv_pointer)
     CmdArgs.push_back("-fwrapv-pointer");
 }
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp 
b/clang/lib/Driver/ToolChains/Flang.cpp
index 4c722a2e021eb..892a455167205 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -1269,7 +1269,7 @@ void Flang::ConstructJob(Compilation &C, const JobAction 
&JA,
   }
 
   renderGlobalISelOptions(D, Args, CmdArgs, Triple);
-  renderCommonIntegerOverflowOptions(Args, CmdArgs);
+  renderCommonIntegerOverflowOptions(Args, CmdArgs, false);
 
   assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
   if (Output.isFilename()) {
diff --git a/clang/test/Driver/clang_wrapv_opts.c 
b/clang/test/Driver/clang_wrapv_opts.c
index 295d8deb0d99d..012d8f5131d5f 100644
--- a/clang/test/Driver/clang_wrapv_opts.c
+++ b/clang/test/Driver/clang_wrapv_opts.c
@@ -18,3 +18,9 @@
 
 // RUN: %clang -### -S -fno-wrapv-pointer -fno-strict-overflow -fno-wrapv 
-Werror %s 2>&1 | FileCheck -check-prefix=CHECK4-POINTER %s 
--implicit-check-not="-fwrapv"
 // CHECK4-POINTER: "-fwrapv-pointer"
+
+// RUN: %clang -### -S --target=x86_64-windows-msvc -Werror %s 2>&1 | 
FileCheck -check-prefix=CHECK5 %s
+// CHECK5: "-fwrapv"
+
+// RUN: %clang -### -S -fno-wrapv --target=x86_64-windows-msvc -Werror %s 2>&1 
| FileCheck -check-prefix=CHECK6 %s
+// CHECK6: "-fno-wrapv"

>From 393e5d66fad248d3c441992fcbe577abc9fb4b1e Mon Sep 17 00:00:00 2001
From: Evgeny Leviant <[email protected]>
Date: Wed, 27 May 2026 12:32:33 +0200
Subject: [PATCH 5/5] Document implicitly enabled frontend options

---
 clang/docs/UsersManual.rst | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst
index 4c4c4c4aa9706..3392a210f0bb0 100644
--- a/clang/docs/UsersManual.rst
+++ b/clang/docs/UsersManual.rst
@@ -4189,6 +4189,11 @@ Changing the MSVC compatibility version makes clang 
behave more like that
 version of MSVC. For example, ``-fms-compatibility-version=19`` will enable
 C++14 features and define ``char16_t`` and ``char32_t`` as builtin types.
 
+For compatibility with existing MSVC behavior, ``-fms-compatibility`` also
+implicitly enables several other options, including ``-fno-strict-aliasing``,
+``-fwrapv`` and ``-fdelayed-template-parsing``. When MSVC compatibility is
+set to a version earlier than 19, it also enables ``-fno-threadsafe-statics``.
+
 .. _cxx:
 
 C++ Language Features

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

Reply via email to