Browse Source

Fix #3385: Allow address uses of structs in using transform, if the reference is passed to an in parameter.

pull/3405/head
Siegfried Pammer 3 months ago
parent
commit
5b90dbdabf
  1. 46
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Using.cs
  2. 2
      ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs
  3. 14
      ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs

46
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Using.cs

@ -39,6 +39,32 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -39,6 +39,32 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
}
private struct TypeA_Issue3385 : IDisposable
{
private int dummy;
public void Dispose()
{
}
#if !ROSLYN3
public static implicit operator TypeB_Issue3385(TypeA_Issue3385 a)
{
return default(TypeB_Issue3385);
}
#else
public static implicit operator TypeB_Issue3385(in TypeA_Issue3385 a)
{
return default(TypeB_Issue3385);
}
#endif
}
private struct TypeB_Issue3385
{
private int dummy;
}
#if CS80
[StructLayout(LayoutKind.Sequential, Size = 1)]
public ref struct UsingRefStruct
@ -161,5 +187,25 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -161,5 +187,25 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
}
#endif
public static void Issue3385()
{
#if ROSLYN3
using (TypeA_Issue3385 a = default(TypeA_Issue3385))
#else
using (TypeA_Issue3385 typeA_Issue = default(TypeA_Issue3385))
#endif
{
#if ROSLYN3
Empty(a);
#else
Empty(typeA_Issue);
#endif
}
}
private static void Empty(TypeB_Issue3385 b)
{
}
}
}

2
ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs

@ -448,7 +448,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -448,7 +448,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return inst != ldloca && inst.Parent is LdObj;
}
static bool IsPassedToInParameter(LdLoca ldloca)
internal static bool IsPassedToInParameter(LdLoca ldloca)
{
if (ldloca.Parent is not CallInstruction call)
{

14
ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs

@ -89,7 +89,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -89,7 +89,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
if (storeInst.Variable.LoadInstructions.Any(ld => !ld.IsDescendantOf(tryFinally)))
return false;
if (storeInst.Variable.AddressInstructions.Any(la => !la.IsDescendantOf(tryFinally) || (la.IsDescendantOf(tryFinally.TryBlock) && !ILInlining.IsUsedAsThisPointerInCall(la))))
if (!storeInst.Variable.AddressInstructions.All(ValidateAddressUse))
return false;
if (storeInst.Variable.StoreInstructions.Count > 1)
return false;
@ -104,6 +104,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -104,6 +104,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms
IsRefStruct = context.Settings.IntroduceRefModifiersOnStructs && storeInst.Variable.Type.Kind == TypeKind.Struct && storeInst.Variable.Type.IsByRefLike
}.WithILRange(storeInst);
return true;
bool ValidateAddressUse(LdLoca la)
{
if (!la.IsDescendantOf(tryFinally))
return false;
if (la.IsDescendantOf(tryFinally.TryBlock))
{
if (!(ILInlining.IsUsedAsThisPointerInCall(la) || ILInlining.IsPassedToInParameter(la)))
return false;
}
return true;
}
}
/// <summary>

Loading…
Cancel
Save