Skip to content

Commit

Permalink
Report diagnostic for BestFitMapping, ThrowOnUnmappableChar, and …
Browse files Browse the repository at this point in the history
…`LCIDConversion` (dotnet/runtimelab#291)

Commit migrated from dotnet/runtimelab@633f08d
  • Loading branch information
elinor-fung authored Nov 5, 2020
1 parent 01a1930 commit e756fa1
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 117 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ static class TypeNames

public const string MarshalUsingAttribute = "System.Runtime.InteropServices.MarshalUsingAttribute";

public const string LCIDConversionAttribute = "System.Runtime.InteropServices.LCIDConversionAttribute";

public const string System_Span_Metadata = "System.Span`1";
public const string System_Span = "System.Span";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ private TypePositionInfo()
{
this.ManagedIndex = UnsetIndex;
this.NativeIndex = UnsetIndex;
this.UnmanagedLCIDConversionArgIndex = UnsetIndex;
}
#pragma warning restore

Expand All @@ -49,7 +48,6 @@ private TypePositionInfo()

public int ManagedIndex { get; init; }
public int NativeIndex { get; init; }
public int UnmanagedLCIDConversionArgIndex { get; init; }

public MarshallingInfo MarshallingAttributeInfo { get; init; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ The default value of [`CharSet`](https://docs.microsoft.com/dotnet/api/system.ru

The built-in system treats `CharSet.None` as `CharSet.Ansi`. The P/Invoke source generator will treat `CharSet.None` as if the `CharSet` was not set.

### `char` marshaller
[`BestFitMapping`](https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.dllimportattribute.bestfitmapping) and [`ThrowOnUnmappableChar`](https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.dllimportattribute.throwonunmappablechar) will not be supported for `GeneratedDllImportAttribute`. These values only have meaning on Windows when marshalling string data (`char`, `string`, `StringBuilder`) as [ANSI](https://docs.microsoft.com/windows/win32/intl/code-pages). As the general recommendation - including from Windows - is to move away from ANSI, the P/Invoke source generator will not support these fields.

### `char` marshalling

Marshalling of `char` will not be supported when configured with any of the following:
- [`CharSet.Ansi`, `CharSet.Auto`, or `CharSet.None`](https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.charset) will not be supported.
Expand All @@ -23,7 +25,7 @@ For `CharSet.Ansi` and `CharSet.None`, the built-in system used the [system defa

For `CharSet.Auto`, the built-in system relied upon detection at runtime of the platform when determining the targeted encoding. Performing this check in generated code violates the "pay-for-play" principle. Given that there are no scenarios for this feature in `NetCoreApp` it will not be supported.

### `string` marshaller
### `string` marshalling

Marshalling of `string` will not be supported when configured with any of the following:
- [`CharSet.None`](https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.charset)
Expand All @@ -44,7 +46,7 @@ On Windows, marshalling using `CharSet.Auto` is treated as UTF-16. When marshall

Using a custom marshaller (i.e. [`ICustomMarshaler`](https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.icustommarshaler)) with the `UnmanagedType.CustomMarshaler` value on `MarshalAsAttribute` is not supported. This also implies `MarshalAsAttribute` fields: [`MarshalTypeRef`](https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.marshalasattribute.marshaltyperef), [`MarshalType`](https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.marshalasattribute.marshaltype), and [`MarshalCookie`](https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.marshalasattribute.marshalcookie) are unsupported.

### Array marshaller support
### Array marshalling

Marshalling of arrays will not be supported when using [`UnmangedType.SafeArray`](https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.unmanagedtype). This implies that the following `MarshalAsAttribute` fields are unsupported: [`SafeArraySubType`](https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.marshalasattribute.safearraysubtype) and [`SafeArrayUserDefinedSubType`](https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.marshalasattribute.safearrayuserdefinedsubtype)

Expand All @@ -54,6 +56,10 @@ Only single-dimensional arrays are supported for source generated marshalling.

In the source-generated marshalling, arrays will be allocated on the stack (instead of through [`AllocCoTaskMem`](https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.marshal.alloccotaskmem)) if they are passed by value or by read-only reference if they contain at most 256 bytes of data. The built-in system does not support this optimization for arrays.

### `LCIDConversion` support

[`LCIDConversionAttribute`](`https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.lcidconversionattribute`) will not be supported for methods marked with `GeneratedDllImportAttribute`.

## Verison 0

This version is the built-in IL Stub generation system that is triggered whenever a method marked with `DllImport` is invoked.
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,24 @@ partial class Test
ThrowOnUnmappableChar = true)]
public static partial void Method();
}
";

/// <summary>
/// Declaration with all supported DllImport named arguments.
/// </summary>
public static readonly string AllSupportedDllImportNamedArguments = @"
using System.Runtime.InteropServices;
partial class Test
{
[GeneratedDllImport(""DoesNotExist"",
CallingConvention = CallingConvention.Cdecl,
CharSet = CharSet.Unicode,
EntryPoint = ""UserDefinedEntryPoint"",
ExactSpelling = true,
PreserveSig = false,
SetLastError = true)]
public static partial void Method();
}
";

/// <summary>
Expand All @@ -180,17 +198,26 @@ partial class Test
private const bool IsTrue = true;
private const bool IsFalse = false;
private const string EntryPointName = nameof(Test) + nameof(IsFalse);
private const int One = 1;
private const int Two = 2;
[GeneratedDllImport(nameof(Test),
BestFitMapping = 0 != 1,
CallingConvention = (CallingConvention)1,
CharSet = (CharSet)2,
EntryPoint = EntryPointName,
ExactSpelling = IsTrue,
ExactSpelling = 0 != 1,
PreserveSig = IsFalse,
SetLastError = !IsFalse,
ThrowOnUnmappableChar = !IsTrue)]
public static partial void Method();
SetLastError = IsTrue)]
public static partial void Method1();
[GeneratedDllImport(nameof(Test),
CallingConvention = (CallingConvention)One,
CharSet = (CharSet)Two,
EntryPoint = EntryPointName,
ExactSpelling = One != Two,
PreserveSig = !IsFalse,
SetLastError = !IsTrue)]
public static partial void Method2();
}
";

Expand All @@ -204,6 +231,19 @@ partial class Test
[GeneratedDllImport(""DoesNotExist"")]
public static partial void Method(int t = 0);
}
";

/// <summary>
/// Declaration with LCIDConversionAttribute.
/// </summary>
public static readonly string LCIDConversionAttribute = @"
using System.Runtime.InteropServices;
partial class Test
{
[LCIDConversion(0)]
[GeneratedDllImport(""DoesNotExist"")]
public static partial void Method();
}
";

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ public static IEnumerable<object[]> CodeSnippetsToCompile()
// Unsupported MarshalAsAttribute usage
// * UnmanagedType.CustomMarshaler, MarshalTypeRef, MarshalType, MarshalCookie
yield return new object[] { CodeSnippets.MarshalAsCustomMarshalerOnTypes, 16, 0 };

// Unsupported named arguments
// * BestFitMapping, ThrowOnUnmappableChar
yield return new object[] { CodeSnippets.AllDllImportNamedArguments, 2, 0 };

// LCIDConversion
yield return new object[] { CodeSnippets.LCIDConversionAttribute, 1, 0 };
}

[Theory]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static IEnumerable<object[]> CodeSnippetsToCompile_NoDiagnostics()
yield return new[] { CodeSnippets.NestedNamespace };
yield return new[] { CodeSnippets.NestedTypes };
yield return new[] { CodeSnippets.UserDefinedEntryPoint };
yield return new[] { CodeSnippets.AllDllImportNamedArguments };
yield return new[] { CodeSnippets.AllSupportedDllImportNamedArguments };
yield return new[] { CodeSnippets.DefaultParameters };
yield return new[] { CodeSnippets.UseCSharpFeaturesForConstants };
yield return new[] { CodeSnippets.BasicParametersAndModifiers<byte>() };
Expand Down

0 comments on commit e756fa1

Please sign in to comment.