diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Using.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Using.cs index 9674b8cf7..04e819c70 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Using.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Using.cs @@ -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 } } #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) + { + } } } diff --git a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs index 7b38b2e90..3e2c743c8 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs @@ -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) { diff --git a/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs index 96fe3d13d..020166ac0 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs @@ -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 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; + } } ///