diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.Predicates.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.Predicates.cs index 784738ac..03340794 100644 --- a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.Predicates.cs +++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.Predicates.cs @@ -946,6 +946,19 @@ private bool IsUnchecked(string targetTypeName, Stmt stmt) targetTypeName = transparentStruct.Name; } } + else + { + // The platform-dependent narrowing that could overflow on a 32-bit target only happens + // when the generator emits the explicit `(nint)`/`(nuint)` cast, which it only does for + // `VarDecl` initializers (see `UncheckStmt`). Outside of that context an expression keeps + // its natural C# type and never needs an `unchecked` scope, so evaluate native-sized + // integer targets against their widest equivalent. + targetTypeName = targetTypeName switch { + "nint" or "IntPtr" => "long", + "nuint" or "UIntPtr" => "ulong", + _ => targetTypeName, + }; + } switch (stmt.StmtClass) { diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/C/CLongDefinesRegressionTestUnix.CSharp.Latest.Unix.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/C/CLongDefinesRegressionTestUnix.CSharp.Latest.Unix.cs index e1295a25..ef10a49a 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/C/CLongDefinesRegressionTestUnix.CSharp.Latest.Unix.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/C/CLongDefinesRegressionTestUnix.CSharp.Latest.Unix.cs @@ -5,7 +5,7 @@ public static unsafe partial class Methods [return: NativeTypeName("_Bool")] public static bool SDL_size_add_check_overflow([NativeTypeName("size_t")] nuint a, [NativeTypeName("size_t")] nuint b, [NativeTypeName("size_t *")] nuint* ret) { - if (b > unchecked(18446744073709551615U) - a) + if (b > (18446744073709551615U) - a) { return (0) != 0; } diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CTest.cs index 4b9bb199..f43e780a 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/CTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CTest.cs @@ -382,7 +382,7 @@ public Task CLongDefinesTestUnix() public Task CLongDefinesRegressionTestUnix() { // This test is to catch a potential regression when changing how native integers are handled - // Specifically, (18446744073709551615U) became unchecked(18446744073709551615U) + // Specifically, (18446744073709551615U) must not be wrapped in an unnecessary unchecked scope // Macro values are taken from the Linux headers when using Clang // Some values are substituted for simplicity @@ -406,9 +406,8 @@ bool SDL_size_add_check_overflow(size_t a, size_t b, size_t *ret) } "; - // The expected below currently does not represent the ideal behavior. - // Ideally, the unchecked keywork is removed as it is unnecessary. - // This issue is tracked here: https://github.com/dotnet/ClangSharp/issues/709 + // The unnecessary unchecked scope around the `ulong` literal is now elided; see + // https://github.com/dotnet/ClangSharp/issues/709 return ValidateGeneratedCSharpLatestUnixBaselineAsync(inputContents, commandLineArgs: DefaultCClangCommandLineArgs, language: "c", languageStandard: DefaultCStandard); }