@@ -227,30 +227,76 @@ private static bool DoesMethodMatchUnsafeAccessorDeclaration(ref GenerationConte
227227 // If we are, do it first.
228228 if ( ! ignoreCustomModifiers )
229229 {
230- // Compare custom modifiers on the signatures.
231- var declCustomMod = declSig . GetEmbeddedSignatureData ( EmbeddedSignatureDataKind . RequiredCustomModifier , EmbeddedSignatureDataKind . OptionalCustomModifier ) ?? Array . Empty < EmbeddedSignatureData > ( ) ;
232- var maybeCustomMod = maybeSig . GetEmbeddedSignatureData ( EmbeddedSignatureDataKind . RequiredCustomModifier , EmbeddedSignatureDataKind . OptionalCustomModifier ) ?? Array . Empty < EmbeddedSignatureData > ( ) ;
233- if ( ! CompareEmbeddedData ( context . Kind , declCustomMod , maybeCustomMod ) )
230+ // Compare any unmanaged callconv and custom modifiers on the signatures.
231+ // We treat unmanaged calling conventions at the same level of precedance
232+ // as custom modifiers, eventhough they are normally bits in a signature.
233+ ReadOnlySpan < EmbeddedSignatureDataKind > kinds = new EmbeddedSignatureDataKind [ ]
234+ {
235+ EmbeddedSignatureDataKind . UnmanagedCallConv ,
236+ EmbeddedSignatureDataKind . RequiredCustomModifier ,
237+ EmbeddedSignatureDataKind . OptionalCustomModifier
238+ } ;
239+
240+ var declData = declSig . GetEmbeddedSignatureData ( kinds ) ?? Array . Empty < EmbeddedSignatureData > ( ) ;
241+ var maybeData = maybeSig . GetEmbeddedSignatureData ( kinds ) ?? Array . Empty < EmbeddedSignatureData > ( ) ;
242+ if ( declData . Length != maybeData . Length )
234243 {
235244 return false ;
236245 }
246+
247+ // Validate the custom modifiers match precisely.
248+ for ( int i = 0 ; i < declData . Length ; ++ i )
249+ {
250+ EmbeddedSignatureData dd = declData [ i ] ;
251+ EmbeddedSignatureData md = maybeData [ i ] ;
252+ if ( dd . kind != md . kind || dd . type != md . type )
253+ {
254+ return false ;
255+ }
256+
257+ // The indices on non-constructor declarations require
258+ // some slight modification since there is always an extra
259+ // argument in the declaration compared to the target.
260+ string declIndex = dd . index ;
261+ if ( context . Kind != UnsafeAccessorKind . Constructor )
262+ {
263+ string unmanagedCallConvMaybe = string . Empty ;
264+
265+ // Check for and drop the unmanaged calling convention
266+ // value suffix to add it back after updating below.
267+ if ( declIndex . Contains ( '|' ) )
268+ {
269+ Debug . Assert ( dd . kind == EmbeddedSignatureDataKind . UnmanagedCallConv ) ;
270+ var tmp = declIndex . Split ( '|' ) ;
271+ Debug . Assert ( tmp . Length == 2 ) ;
272+ declIndex = tmp [ 0 ] ;
273+ unmanagedCallConvMaybe = "|" + tmp [ 1 ] ;
274+ }
275+
276+ // Decrement the second to last index by one to
277+ // account for the difference in declarations.
278+ string [ ] lvls = declIndex . Split ( '.' ) ;
279+ int toUpdate = lvls . Length < 2 ? 0 : lvls . Length - 2 ;
280+ int idx = int . Parse ( lvls [ toUpdate ] , CultureInfo . InvariantCulture ) ;
281+ idx -- ;
282+ lvls [ toUpdate ] = idx . ToString ( ) ;
283+ declIndex = string . Join ( "." , lvls ) + unmanagedCallConvMaybe ;
284+ }
285+
286+ if ( declIndex != md . index )
287+ {
288+ return false ;
289+ }
290+ }
237291 }
238292
239- // Validate calling convention.
293+ // Validate calling convention of declaration .
240294 if ( ( declSig . Flags & MethodSignatureFlags . UnmanagedCallingConventionMask )
241295 != ( maybeSig . Flags & MethodSignatureFlags . UnmanagedCallingConventionMask ) )
242296 {
243297 return false ;
244298 }
245299
246- // Compare unmanaged callconv on the signatures.
247- var declUnmanaged = declSig . GetEmbeddedSignatureData ( EmbeddedSignatureDataKind . UnmanagedCallConv ) ?? Array . Empty < EmbeddedSignatureData > ( ) ;
248- var maybeUnmanaged = maybeSig . GetEmbeddedSignatureData ( EmbeddedSignatureDataKind . UnmanagedCallConv ) ?? Array . Empty < EmbeddedSignatureData > ( ) ;
249- if ( ! CompareEmbeddedData ( context . Kind , declUnmanaged , maybeUnmanaged ) )
250- {
251- return false ;
252- }
253-
254300 // Validate argument count and return type
255301 if ( context . Kind == UnsafeAccessorKind . Constructor )
256302 {
@@ -300,64 +346,6 @@ private static bool DoesMethodMatchUnsafeAccessorDeclaration(ref GenerationConte
300346 }
301347
302348 return true ;
303-
304- static bool CompareEmbeddedData (
305- UnsafeAccessorKind kind ,
306- EmbeddedSignatureData [ ] declData ,
307- EmbeddedSignatureData [ ] maybeData )
308- {
309- if ( declData . Length != maybeData . Length )
310- {
311- return false ;
312- }
313-
314- // Validate the custom modifiers match precisely.
315- for ( int i = 0 ; i < declData . Length ; ++ i )
316- {
317- EmbeddedSignatureData dd = declData [ i ] ;
318- EmbeddedSignatureData md = maybeData [ i ] ;
319- if ( dd . kind != md . kind || dd . type != md . type )
320- {
321- return false ;
322- }
323-
324- // The indices on non-constructor declarations require
325- // some slight modification since there is always an extra
326- // argument in the declaration compared to the target.
327- string declIndex = dd . index ;
328- if ( kind != UnsafeAccessorKind . Constructor )
329- {
330- string unmanagedCallConvMaybe = string . Empty ;
331-
332- // Check for and drop the unmanaged calling convention
333- // value suffix to add it back after updating below.
334- if ( declIndex . Contains ( '|' ) )
335- {
336- Debug . Assert ( dd . kind == EmbeddedSignatureDataKind . UnmanagedCallConv ) ;
337- var tmp = declIndex . Split ( '|' ) ;
338- Debug . Assert ( tmp . Length == 2 ) ;
339- declIndex = tmp [ 0 ] ;
340- unmanagedCallConvMaybe = "|" + tmp [ 1 ] ;
341- }
342-
343- // Decrement the second to last index by one to
344- // account for the difference in declarations.
345- string [ ] lvls = declIndex . Split ( '.' ) ;
346- int toUpdate = lvls . Length < 2 ? 0 : lvls . Length - 2 ;
347- int idx = int . Parse ( lvls [ toUpdate ] , CultureInfo . InvariantCulture ) ;
348- idx -- ;
349- lvls [ toUpdate ] = idx . ToString ( ) ;
350- declIndex = string . Join ( "." , lvls ) + unmanagedCallConvMaybe ;
351- }
352-
353- if ( declIndex != md . index )
354- {
355- return false ;
356- }
357- }
358-
359- return true ;
360- }
361349 }
362350
363351 private static bool TrySetTargetMethod ( ref GenerationContext context , string name , out bool isAmbiguous , bool ignoreCustomModifiers = true )
0 commit comments