Skip to content

Commit

Permalink
Merge pull request #353 from tannergooding/main
Browse files Browse the repository at this point in the history
Ensure that bool as a struct field is correctly handled
  • Loading branch information
tannergooding committed Jun 17, 2022
2 parents 127f2a3 + 3a153d0 commit 946fd3f
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 4 deletions.
32 changes: 28 additions & 4 deletions sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down
Expand Up @@ -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]
Expand Down Expand Up @@ -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*")]
Expand All @@ -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")]
Expand All @@ -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")]
Expand All @@ -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]
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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")]
Expand All @@ -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]
Expand Down
Expand Up @@ -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]
Expand Down Expand Up @@ -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*")]
Expand All @@ -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")]
Expand All @@ -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")]
Expand All @@ -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]
Expand All @@ -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]
Expand Down Expand Up @@ -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")]
Expand All @@ -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);
Expand Down

0 comments on commit 946fd3f

Please sign in to comment.