-
Notifications
You must be signed in to change notification settings - Fork 116
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unbounded string fields should be declared with []
instead of [0...0]
bounds
#912
Comments
Unfortunately, metadata only storing rank and size of array. I think, such declaration should be done in projections. |
@kennykerr @AArnott @sotteson1 for their thoughts. |
I agree with @timsneath that we should be able to distinguish between unbounded and fixed size array fields. |
This is what ClangSharp emits.
Is that enough information to identify this case? |
CsWin32 plans to interpret 0 and 1 length arrays as variable length. It would be great if the metadata were consistent on the length (0 vs 1), but CsWin32 can certainly be made to detect either one. |
Not strictly, no. The one true discriminator is the As a workaround to preserving the additional semantics of Though, honestly, given the reach and impact of this repo's artifacts, I'd much like to see it move closer to tooling that better persists vital information from the SDK header files. |
Zero length arrays are not legal in ISO C but they are allowed in MSVC C (and gcc) at the end of a struct. Still, I'd be surprised if they appear in the SDK headers. |
That was my thought, too. And then I went looking... There are, in d3dkmthk.h, mstcpip.h, nvme.h, and others. So that's that then. |
Zero length arrays are legal in C99+ as a flexible array member (pg. 103, ¶16) at the end of a structure, such as: typedef struct _D3DKMT_DISPLAYMODELIST
{
D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId;
UINT ModeCount;
D3DKMT_DISPLAYMODE pModeList[0];
} D3DKMT_DISPLAYMODELIST; |
@riverar I'm pretty sure the syntax for flexible array members is |
I can get these to output C#
IL
If I try to change the C# to C#
IL
A simplified repro branch is at https://github.com/microsoft/win32metadata/tree/mikebattista/flexiblearrays. Below is where we can rewrite the C# if we detect fields with win32metadata/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs Lines 336 to 347 in c83afaf
We also have an opportunity to rewrite the array field signature when writing to the winmd. We can do that here. The knobs are provided by https://learn.microsoft.com/dotnet/api/system.reflection.metadata.ecma335.arrayshapeencoder.shape. Everything I've tried so far that compiles emits |
While I agree that we should ideally be able to identify these in metadata, I don't think actually changing the definition is appropriate. Add an attribute if needed to indicate these may be unbounded, but if the original struct has a field with a |
We could add an attribute to all fields that have a I'm not sure how to reliably automate |
I implemented a fix that seems to be pretty reliable. We now apply
|
This is great. |
That seems to ignore the concern raised here:
typedef struct _SP_DEVICE_INTERFACE_DETAIL_DATA_W {
DWORD cbSize;
WCHAR DevicePath[ANYSIZE_ARRAY];
} SP_DEVICE_INTERFACE_DETAIL_DATA_W, *PSP_DEVICE_INTERFACE_DETAIL_DATA_W; but apparently drops the size information in the generated metadata: [StructSizeField("cbSize")]
[SupportedArchitecture(Architecture.X64 | Architecture.Arm64)]
public struct SP_DEVICE_INTERFACE_DETAIL_DATA_W
{
public uint cbSize;
[FlexibleArray]
public char[] DevicePath;
} Is this an oversight? |
No we haven't changed the size. |
I'm confused. I just looked at the metadata 50.0.71-preview published 3 days ago, and it describes public struct SP_DEVICE_INTERFACE_DETAIL_DATA_W
{
public uint cbSize;
[FlexibleArray]
public char[] DevicePath;
} There's no mention of the This must not happen, as explained here. Am I just blind in not seeing where the size information is persisted, or is this a bug? |
@tim-weis You're not blind. You just have your C# glasses on. :) If you decompile the winmd to IL instead, you see the length of the array is still there:
See, in C# one cannot express an array type with a fixed length for an inline array except in very restrictive conditions. But IL can express it. So a C# decompiler just drops the detail. But it's there in the metadata for your projection. |
@AArnott That makes sense, thank you. The specific pair of C# glasses I was wearing go by the name ILSpy. Ildasm.exe did in fact produce output similar to the IL snippet you posted. So Executing
produces the following IL:
The |
@tim-weis I use ILSpy too. It has a dropdown in the toolbar to switch from decompiling to C# or IL. |
Looks like this was already addressed, 59.x is showing: .field /* 04039E80 */ public valuetype [Windows.Win32.winmd]Windows.Win32.Networking.WinSock.SOCKET_SECURITY_PROTOCOL SecurityProtocol
.field /* 04039E81 */ public uint32 SecurityFlags
.field /* 04039E82 */ public uint32 IpsecFlags
.field /* 04039E83 */ public valuetype [netstandard]System.Guid AuthipMMPolicyKey
.field /* 04039E84 */ public valuetype [netstandard]System.Guid AuthipQMPolicyKey
.field /* 04039E85 */ public valuetype [netstandard]System.Guid Reserved
.field /* 04039E86 */ public uint64 Reserved2
.field /* 04039E87 */ public uint32 UserNameStringLen
.field /* 04039E88 */ public uint32 DomainNameStringLen
.field /* 04039E89 */ public uint32 PasswordStringLen
+.field /* 04039E8A */ public char[0...0] AllStrings
.custom instance void [Windows.Win32.winmd]Windows.Win32.Foundation.Metadata.FlexibleArrayAttribute::.ctor() = (
01 00 00 00
)
|
A number of structs in SetupAPI.h contain string fields of arbitrary size, for example:
While this is projected "correctly", since
ANYSIZE_ARRAY
is defined to 1, as the documentation notes, this is merely a limitation of the ability for C to accurately declare an indeterminately-sized array. See https://docs.microsoft.com/en-us/windows/win32/api/setupapi/ns-setupapi-sp_device_interface_detail_data_w.There are a few other structs with a similar formulation, at least in
SetupAPI.h
:SP_INF_INFORMATION
andSP_DRVINFO_DETAIL_DATA_W
are two examples.Per §I.8.9.1 "Array types" of ECMA-335, these can simply be declared as unbounded. That is, instead of:
we should declare this field as:
The distinction is important, since otherwise a language projection cannot distinguish between an unbounded array and a single-item array.
The text was updated successfully, but these errors were encountered: