Browse Source

Translate the initializer of a `fixed` statement as managed reference and only apply the ref-to-pointer conversion at the end.

This way we create compilable code when the pinned variable type does not match the initializer type.
pull/2045/head
Daniel Grunwald 5 years ago
parent
commit
35c405b973
  1. 10
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs
  2. 30
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.il
  3. 14
      ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

10
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyFileVersion("4.0.0.0")]
[assembly: AssemblyInformationalVersion("4.0.0.0")]
@ -12,6 +13,15 @@ using System.Reflection; @@ -12,6 +13,15 @@ using System.Reflection;
[assembly: AssemblyProduct("Microsoft® .NET Framework")]
[assembly: CLSCompliant(false)]
internal sealed class ExtraUnsafeTests
{
public unsafe static void PinWithTypeMismatch(ref uint managedPtr)
{
fixed (ushort* ptr = &Unsafe.As<uint, ushort>(ref managedPtr)) {
}
}
}
namespace System.Runtime.CompilerServices
{
public static class Unsafe

30
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.il

@ -437,3 +437,33 @@ @@ -437,3 +437,33 @@
} // end of class System.Runtime.CompilerServices.IsReadOnlyAttribute
#endif
.class private auto ansi sealed beforefieldinit ExtraUnsafeTests
extends [CORE_ASSEMBLY]System.Object
{
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
.maxstack 1
ldarg.0
call instance void [CORE_ASSEMBLY]System.Object::.ctor()
ret
} // end of method ExtraUnsafeTests::.ctor
.method public hidebysig static void PinWithTypeMismatch(uint32& managedPtr)
{
.maxstack 8
.locals (
[0] uint16& pinned
)
// Pin:
ldarg.0
stloc.0
// Unpin:
ldc.i4 0
stloc.0
ret
}
}

14
ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

@ -832,7 +832,19 @@ namespace ICSharpCode.Decompiler.CSharp @@ -832,7 +832,19 @@ namespace ICSharpCode.Decompiler.CSharp
initExpr = exprBuilder.Translate(gpr.Argument);
}
} else {
initExpr = exprBuilder.Translate(inst.Init, typeHint: inst.Variable.Type).ConvertTo(inst.Variable.Type, exprBuilder);
IType refType = inst.Variable.Type;
if (refType is PointerType pointerType) {
refType = new ByReferenceType(pointerType.ElementType);
}
initExpr = exprBuilder.Translate(inst.Init, typeHint: refType).ConvertTo(refType, exprBuilder);
if (initExpr is DirectionExpression dirExpr) {
if (dirExpr.Expression is UnaryOperatorExpression uoe && uoe.Operator == UnaryOperatorType.Dereference) {
initExpr = uoe.Expression.Detach();
} else {
initExpr = new UnaryOperatorExpression(UnaryOperatorType.AddressOf, dirExpr.Expression.Detach())
.WithRR(new ResolveResult(inst.Variable.Type));
}
}
}
fixedStmt.Variables.Add(new VariableInitializer(inst.Variable.Name, initExpr).WithILVariable(inst.Variable));
fixedStmt.EmbeddedStatement = Convert(inst.Body);

Loading…
Cancel
Save