Skip to content

Commit 5b90dbd

Browse files
Fix #3385: Allow address uses of structs in using transform, if the reference is passed to an in parameter.
1 parent 807ac32 commit 5b90dbd

File tree

3 files changed

+60
-2
lines changed

3 files changed

+60
-2
lines changed

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

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,32 @@ void IDisposable.Dispose()
3939
}
4040
}
4141

42+
private struct TypeA_Issue3385 : IDisposable
43+
{
44+
private int dummy;
45+
46+
public void Dispose()
47+
{
48+
}
49+
50+
#if !ROSLYN3
51+
public static implicit operator TypeB_Issue3385(TypeA_Issue3385 a)
52+
{
53+
return default(TypeB_Issue3385);
54+
}
55+
#else
56+
public static implicit operator TypeB_Issue3385(in TypeA_Issue3385 a)
57+
{
58+
return default(TypeB_Issue3385);
59+
}
60+
#endif
61+
}
62+
63+
private struct TypeB_Issue3385
64+
{
65+
private int dummy;
66+
}
67+
4268
#if CS80
4369
[StructLayout(LayoutKind.Sequential, Size = 1)]
4470
public ref struct UsingRefStruct
@@ -161,5 +187,25 @@ public void UsingRefStruct1(UsingRefStruct s)
161187
}
162188
}
163189
#endif
190+
191+
public static void Issue3385()
192+
{
193+
#if ROSLYN3
194+
using (TypeA_Issue3385 a = default(TypeA_Issue3385))
195+
#else
196+
using (TypeA_Issue3385 typeA_Issue = default(TypeA_Issue3385))
197+
#endif
198+
{
199+
#if ROSLYN3
200+
Empty(a);
201+
#else
202+
Empty(typeA_Issue);
203+
#endif
204+
}
205+
}
206+
207+
private static void Empty(TypeB_Issue3385 b)
208+
{
209+
}
164210
}
165211
}

ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ static bool IsUsedAsThisPointerInFieldRead(LdLoca ldloca)
448448
return inst != ldloca && inst.Parent is LdObj;
449449
}
450450

451-
static bool IsPassedToInParameter(LdLoca ldloca)
451+
internal static bool IsPassedToInParameter(LdLoca ldloca)
452452
{
453453
if (ldloca.Parent is not CallInstruction call)
454454
{

ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ bool TransformUsing(Block block, int i)
8989
return false;
9090
if (storeInst.Variable.LoadInstructions.Any(ld => !ld.IsDescendantOf(tryFinally)))
9191
return false;
92-
if (storeInst.Variable.AddressInstructions.Any(la => !la.IsDescendantOf(tryFinally) || (la.IsDescendantOf(tryFinally.TryBlock) && !ILInlining.IsUsedAsThisPointerInCall(la))))
92+
if (!storeInst.Variable.AddressInstructions.All(ValidateAddressUse))
9393
return false;
9494
if (storeInst.Variable.StoreInstructions.Count > 1)
9595
return false;
@@ -104,6 +104,18 @@ bool TransformUsing(Block block, int i)
104104
IsRefStruct = context.Settings.IntroduceRefModifiersOnStructs && storeInst.Variable.Type.Kind == TypeKind.Struct && storeInst.Variable.Type.IsByRefLike
105105
}.WithILRange(storeInst);
106106
return true;
107+
108+
bool ValidateAddressUse(LdLoca la)
109+
{
110+
if (!la.IsDescendantOf(tryFinally))
111+
return false;
112+
if (la.IsDescendantOf(tryFinally.TryBlock))
113+
{
114+
if (!(ILInlining.IsUsedAsThisPointerInCall(la) || ILInlining.IsPassedToInParameter(la)))
115+
return false;
116+
}
117+
return true;
118+
}
107119
}
108120

109121
/// <summary>

0 commit comments

Comments
 (0)