diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj index b6d2af5ad..cafcf2dad 100644 --- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj @@ -163,6 +163,7 @@ + diff --git a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs index ffedb0b0e..ce1793293 100644 --- a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs @@ -718,6 +718,12 @@ namespace ICSharpCode.Decompiler.Tests await RunForLibrary(cscOptions: cscOptions); } + [Test] + public async Task Issue3584([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions) + { + await RunForLibrary(cscOptions: cscOptions); + } + [Test] public async Task AssemblyCustomAttributes([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions) { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3584.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3584.cs new file mode 100644 index 000000000..3c583d827 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3584.cs @@ -0,0 +1,47 @@ +using System.Collections; +using System.Collections.Generic; + +namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty +{ + internal abstract class Issue4000 : IEnumerable, IEnumerable + { + public int Length; + + protected T[] results; + +#if !ROSLYN4 + public T this[int i] { + get { + if (i >= Length || i < 0) + { + return default(T); + } + if (results[i] != null && results[i].Equals(default(T))) + { + results[i] = CreateIthElement(i); + } + return results[i]; + } + } +#endif + + protected abstract T CreateIthElement(int i); + + public IEnumerator GetEnumerator() + { + for (int i = 0; i < Length; i++) + { + if (results[i] != null && results[i].Equals(default(T))) + { + results[i] = CreateIthElement(i); + } + yield return results[i]; + } + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } +} diff --git a/ICSharpCode.Decompiler/IL/ILTypeExtensions.cs b/ICSharpCode.Decompiler/IL/ILTypeExtensions.cs index fda8cb533..4977eba37 100644 --- a/ICSharpCode.Decompiler/IL/ILTypeExtensions.cs +++ b/ICSharpCode.Decompiler/IL/ILTypeExtensions.cs @@ -238,6 +238,8 @@ namespace ICSharpCode.Decompiler.IL default: return SpecialType.UnknownType; } + case DefaultValue defaultValue: + return defaultValue.Type; case ILFunction func when func.DelegateType != null: return func.DelegateType; default: diff --git a/ICSharpCode.Decompiler/IL/Instructions.cs b/ICSharpCode.Decompiler/IL/Instructions.cs index b3a73d336..96a6bd948 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.cs +++ b/ICSharpCode.Decompiler/IL/Instructions.cs @@ -318,6 +318,7 @@ namespace ICSharpCode.Decompiler.IL set { ValidateChild(value); SetChildInstruction(ref this.argument, value, 0); + InvalidateFlags(); } } protected sealed override int GetChildCount() @@ -4357,10 +4358,19 @@ namespace ICSharpCode.Decompiler.IL public override StackType ResultType { get { return StackType.O; } } protected override InstructionFlags ComputeFlags() { - return base.ComputeFlags() | InstructionFlags.SideEffect | InstructionFlags.MayThrow; + var baseFlags = base.ComputeFlags(); + if (baseFlags == InstructionFlags.None && Type.Equals(Argument.InferType(null))) + { + return InstructionFlags.None; + } + return baseFlags | InstructionFlags.SideEffect | InstructionFlags.MayThrow; } public override InstructionFlags DirectFlags { get { + if (Flags == InstructionFlags.None) + { + return InstructionFlags.None; + } return base.DirectFlags | InstructionFlags.SideEffect | InstructionFlags.MayThrow; } }