diff --git a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs index 49ff62cc2..7b38b2e90 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs @@ -537,6 +537,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms } } + /// + /// Gets whether the ILInstruction will turn into a C# expresion that is considered readonly by the C# compiler. + /// internal static bool IsReadonlyReference(ILInstruction addr) { switch (addr) diff --git a/ICSharpCode.Decompiler/IL/Transforms/IntroduceRefReadOnlyModifierOnLocals.cs b/ICSharpCode.Decompiler/IL/Transforms/IntroduceRefReadOnlyModifierOnLocals.cs index 946f15363..aba272b1f 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/IntroduceRefReadOnlyModifierOnLocals.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/IntroduceRefReadOnlyModifierOnLocals.cs @@ -52,8 +52,18 @@ namespace ICSharpCode.Decompiler.IL { foreach (var store in variable.StoreInstructions.OfType()) { + // Check if C# requires that the local is ref-readonly in order to allow the store: if (ILInlining.IsReadonlyReference(store.Value)) return true; + // Check whether the local needs to be ref-readonly to avoid changing the semantics of + // a readonly.ldelema: + ILInstruction val = store.Value; + while (val is LdFlda ldflda) + { + val = ldflda.Target; + } + if (val is LdElema { IsReadOnly: true }) + return true; } return false; }