Browse Source

Fix #2287: Prefer `ref target.field[0]` over `ref *target.field`

pull/2308/head
Daniel Grunwald 4 years ago
parent
commit
b4c5c0d212
  1. 7
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs
  2. 18
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

7
ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs

@ -530,6 +530,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -530,6 +530,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
num.ToString();
}
#if CS73
private unsafe static int Issue2287(ref StructWithFixedSizeMembers value)
{
return value.Integers[0] + value.Integers[1];
}
#endif
private unsafe static void* CastToVoidPtr(IntPtr intptr)
{
return (void*)intptr;

18
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -2818,8 +2818,22 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2818,8 +2818,22 @@ namespace ICSharpCode.Decompiler.CSharp
.WithILInstruction(inst);
if (inst.ResultType == StackType.Ref)
{
// convert pointer back to ref
return result.ConvertTo(new ByReferenceType(elementType), this);
// `target.field` has pointer-type.
if (inst.SlotInfo == PinnedRegion.InitSlot || inst.Parent is Conv { TargetType: IL.PrimitiveType.U })
{
// Convert pointer to ref if we're in a context where we're going to convert
// the ref back to a pointer.
return result.ConvertTo(new ByReferenceType(elementType), this);
}
else
{
// We can't use `ref *target.field` unless `target` is non-movable,
// but we can use `ref target.field[0]`.
var arrayAccess = new IndexerExpression(result, new PrimitiveExpression(0))
.WithRR(new ResolveResult(elementType));
return new DirectionExpression(FieldDirection.Ref, arrayAccess)
.WithoutILInstruction().WithRR(new ByReferenceResolveResult(arrayAccess.ResolveResult, ReferenceKind.Ref));
}
}
else
{

Loading…
Cancel
Save