From b6139e2127cea5f8815895aab5034d2b76ce570d Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Fri, 17 Jun 2022 07:15:00 -0700 Subject: [PATCH 1/2] Adding tests covering bool as a struct/union field --- .../Base/StructDeclarationTest.cs | 8 ++++++++ .../Base/UnionDeclarationTest.cs | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/Base/StructDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/Base/StructDeclarationTest.cs index ad53f2f7..a9c1ff52 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/Base/StructDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/Base/StructDeclarationTest.cs @@ -25,6 +25,7 @@ public abstract class StructDeclarationTest : PInvokeGeneratorTest [TestCase("unsigned short", "ushort")] [TestCase("unsigned int", "uint")] [TestCase("unsigned long long", "ulong")] + [TestCase("bool", "byte")] public Task BasicWithNativeTypeNameTest(string nativeType, string expectedManagedType) => BasicWithNativeTypeNameTestImpl(nativeType, expectedManagedType); [Test] @@ -57,6 +58,7 @@ public abstract class StructDeclarationTest : PInvokeGeneratorTest [TestCase("unsigned short", "ushort")] [TestCase("unsigned int", "uint")] [TestCase("unsigned long long", "ulong")] + [TestCase("bool", "byte")] public Task FixedSizedBufferNonPrimitiveWithNativeTypeNameTest(string nativeType, string expectedManagedType) => FixedSizedBufferNonPrimitiveWithNativeTypeNameTestImpl(nativeType, expectedManagedType); [TestCase("double *", "double*")] @@ -75,6 +77,7 @@ public abstract class StructDeclarationTest : PInvokeGeneratorTest [TestCase("unsigned short", "ushort")] [TestCase("unsigned int", "uint")] [TestCase("unsigned long long", "ulong")] + [TestCase("bool", "byte")] public Task FixedSizedBufferPrimitiveTest(string nativeType, string expectedManagedType) => FixedSizedBufferPrimitiveTestImpl(nativeType, expectedManagedType); [TestCase("unsigned char", "byte")] @@ -87,6 +90,7 @@ public abstract class StructDeclarationTest : PInvokeGeneratorTest [TestCase("unsigned short", "ushort")] [TestCase("unsigned int", "uint")] [TestCase("unsigned long long", "ulong")] + [TestCase("bool", "byte")] public Task FixedSizedBufferPrimitiveMultidimensionalTest(string nativeType, string expectedManagedType) => FixedSizedBufferPrimitiveMultidimensionalTestImpl(nativeType, expectedManagedType); [TestCase("unsigned char", "byte")] @@ -99,6 +103,7 @@ public abstract class StructDeclarationTest : PInvokeGeneratorTest [TestCase("unsigned short", "ushort")] [TestCase("unsigned int", "uint")] [TestCase("unsigned long long", "ulong")] + [TestCase("bool", "byte")] public Task FixedSizedBufferPrimitiveTypedefTest(string nativeType, string expectedManagedType) => FixedSizedBufferPrimitiveTypedefTestImpl(nativeType, expectedManagedType); [Test] @@ -131,6 +136,7 @@ public abstract class StructDeclarationTest : PInvokeGeneratorTest [TestCase("unsigned short", "ushort")] [TestCase("unsigned int", "uint")] [TestCase("unsigned long long", "ulong")] + [TestCase("bool", "byte")] public Task NestedWithNativeTypeNameTest(string nativeType, string expectedManagedType) => NestedWithNativeTypeNameTestImpl(nativeType, expectedManagedType); [Test] @@ -169,6 +175,7 @@ public abstract class StructDeclarationTest : PInvokeGeneratorTest [TestCase("unsigned short", "ushort")] [TestCase("unsigned int", "uint")] [TestCase("unsigned long long", "ulong")] + [TestCase("bool", "byte")] public Task SkipNonDefinitionWithNativeTypeNameTest(string nativeType, string expectedManagedType) => SkipNonDefinitionWithNativeTypeNameTestImpl(nativeType, expectedManagedType); [TestCase("unsigned char", "byte")] @@ -181,6 +188,7 @@ public abstract class StructDeclarationTest : PInvokeGeneratorTest [TestCase("unsigned short", "ushort")] [TestCase("unsigned int", "uint")] [TestCase("unsigned long long", "ulong")] + [TestCase("bool", "byte")] public Task TypedefTest(string nativeType, string expectedManagedType) => TypedefTestImpl(nativeType, expectedManagedType); [Test] diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/Base/UnionDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/Base/UnionDeclarationTest.cs index 2b3fca0f..f81d0029 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/Base/UnionDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/Base/UnionDeclarationTest.cs @@ -25,6 +25,7 @@ public abstract class UnionDeclarationTest : PInvokeGeneratorTest [TestCase("unsigned short", "ushort")] [TestCase("unsigned int", "uint")] [TestCase("unsigned long long", "ulong")] + [TestCase("bool", "byte")] public Task BasicWithNativeTypeNameTest(string nativeType, string expectedManagedType) => BasicWithNativeTypeNameTestImpl(nativeType, expectedManagedType); [Test] @@ -57,6 +58,7 @@ public abstract class UnionDeclarationTest : PInvokeGeneratorTest [TestCase("unsigned short", "ushort")] [TestCase("unsigned int", "uint")] [TestCase("unsigned long long", "ulong")] + [TestCase("bool", "byte")] public Task FixedSizedBufferNonPrimitiveWithNativeTypeNameTest(string nativeType, string expectedManagedType) => FixedSizedBufferNonPrimitiveWithNativeTypeNameTestImpl(nativeType, expectedManagedType); [TestCase("double *", "double*")] @@ -75,6 +77,7 @@ public abstract class UnionDeclarationTest : PInvokeGeneratorTest [TestCase("unsigned short", "ushort")] [TestCase("unsigned int", "uint")] [TestCase("unsigned long long", "ulong")] + [TestCase("bool", "byte")] public Task FixedSizedBufferPrimitiveTest(string nativeType, string expectedManagedType) => FixedSizedBufferPrimitiveTestImpl(nativeType, expectedManagedType); [TestCase("unsigned char", "byte")] @@ -87,6 +90,7 @@ public abstract class UnionDeclarationTest : PInvokeGeneratorTest [TestCase("unsigned short", "ushort")] [TestCase("unsigned int", "uint")] [TestCase("unsigned long long", "ulong")] + [TestCase("bool", "byte")] public Task FixedSizedBufferPrimitiveMultidimensionalTest(string nativeType, string expectedManagedType) => FixedSizedBufferPrimitiveMultidimensionalTestImpl(nativeType, expectedManagedType); [TestCase("unsigned char", "byte")] @@ -99,6 +103,7 @@ public abstract class UnionDeclarationTest : PInvokeGeneratorTest [TestCase("unsigned short", "ushort")] [TestCase("unsigned int", "uint")] [TestCase("unsigned long long", "ulong")] + [TestCase("bool", "byte")] public Task FixedSizedBufferPrimitiveTypedefTest(string nativeType, string expectedManagedType) => FixedSizedBufferPrimitiveTypedefTestImpl(nativeType, expectedManagedType); [Test] @@ -125,6 +130,7 @@ public abstract class UnionDeclarationTest : PInvokeGeneratorTest [TestCase("unsigned short", "ushort")] [TestCase("unsigned int", "uint")] [TestCase("unsigned long long", "ulong")] + [TestCase("bool", "byte")] public Task NestedWithNativeTypeNameTest(string nativeType, string expectedManagedType) => NestedWithNativeTypeNameTestImpl(nativeType, expectedManagedType); [Test] @@ -160,6 +166,7 @@ public abstract class UnionDeclarationTest : PInvokeGeneratorTest [TestCase("unsigned short", "ushort")] [TestCase("unsigned int", "uint")] [TestCase("unsigned long long", "ulong")] + [TestCase("bool", "byte")] public Task SkipNonDefinitionWithNativeTypeNameTest(string nativeType, string expectedManagedType) => SkipNonDefinitionWithNativeTypeNameTestImpl(nativeType, expectedManagedType); [TestCase("unsigned char", "byte")] @@ -172,6 +179,7 @@ public abstract class UnionDeclarationTest : PInvokeGeneratorTest [TestCase("unsigned short", "ushort")] [TestCase("unsigned int", "uint")] [TestCase("unsigned long long", "ulong")] + [TestCase("bool", "byte")] public Task TypedefTest(string nativeType, string expectedManagedType) => TypedefTestImpl(nativeType, expectedManagedType); protected abstract Task BasicTestImpl(string nativeType, string expectedManagedType); From 3a153d055098ade9d46f7b6aa61e596f4072d54f Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Fri, 17 Jun 2022 07:30:14 -0700 Subject: [PATCH 2/2] Ensure that bool as a struct field is correctly handled --- .../PInvokeGenerator.VisitDecl.cs | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs index d9cd6a84..5841e88d 100644 --- a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs +++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs @@ -404,6 +404,20 @@ private void VisitFieldDecl(FieldDecl fieldDecl) var type = fieldDecl.Type; var typeName = GetRemappedTypeName(fieldDecl, context: null, type, out var nativeTypeName); + if (typeName == "bool") + { + // bool is not blittable, so we shouldn't use it for structs that may be in P/Invoke signatures + typeName = "byte"; + nativeTypeName = string.IsNullOrWhiteSpace(nativeTypeName) ? "bool" : nativeTypeName; + } + + if (_config.GenerateCompatibleCode && typeName.StartsWith("bool*")) + { + // bool* is not blittable in compat mode, so we shouldn't use it for structs that may be in P/Invoke signatures + typeName = typeName.Replace("bool*", "byte*"); + nativeTypeName = string.IsNullOrWhiteSpace(nativeTypeName) ? typeName.Replace("byte*", "bool *") : nativeTypeName; + } + int? offset = null; if (fieldDecl.Parent.IsUnion) { @@ -509,11 +523,21 @@ private void VisitFunctionDecl(FunctionDecl functionDecl) AddDiagnostic(DiagnosticLevel.Warning, $"Found manual import for {name} with no class remapping. First Parameter Type: {firstParameterTypeName}; Return Type: {returnTypeName}", functionDecl); } - if ((isVirtual || !hasBody) && (returnTypeName == "bool")) + if (isVirtual || !hasBody) { - // bool is not blittable, so we shouldn't use it for P/Invoke signatures - returnTypeName = "byte"; - nativeTypeName = string.IsNullOrWhiteSpace(nativeTypeName) ? "bool" : nativeTypeName; + if (returnTypeName == "bool") + { + // bool is not blittable, so we shouldn't use it for P/Invoke signatures + returnTypeName = "byte"; + nativeTypeName = string.IsNullOrWhiteSpace(nativeTypeName) ? "bool" : nativeTypeName; + } + + if (_config.GenerateCompatibleCode && returnTypeName.StartsWith("bool*")) + { + // bool* is not blittable in compat mode, so we shouldn't use it for P/Invoke signatures + returnTypeName = returnTypeName.Replace("bool*", "byte*"); + nativeTypeName = string.IsNullOrWhiteSpace(nativeTypeName) ? returnTypeName.Replace("byte*", "bool *") : nativeTypeName; + } } var type = functionDecl.Type;