Browse Source

Improve NullPropagation (?.) when fields of value-type are involved.

pull/1600/head
Daniel Grunwald 6 years ago
parent
commit
0e0179edff
  1. 14
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/NullPropagation.cs
  2. 6
      ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs

14
ICSharpCode.Decompiler.Tests/TestCases/Pretty/NullPropagation.cs

@ -25,6 +25,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
private class MyClass private class MyClass
{ {
public int IntVal; public int IntVal;
public readonly int ReadonlyIntVal;
public MyStruct StructField;
public readonly MyStruct ReadonlyStructField;
public string Text; public string Text;
public MyClass Field; public MyClass Field;
public MyClass Property { public MyClass Property {
@ -45,6 +48,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
private struct MyStruct private struct MyStruct
{ {
public int IntVal; public int IntVal;
public readonly int ReadonlyIntVal;
public MyClass Field; public MyClass Field;
public MyStruct? Property1 => null; public MyStruct? Property1 => null;
public MyStruct Property2 => default(MyStruct); public MyStruct Property2 => default(MyStruct);
@ -179,6 +183,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Use(GetMyClass()?.Text ?? "Hello"); Use(GetMyClass()?.Text ?? "Hello");
} }
public void CallOnValueTypeField()
{
Use(GetMyClass()?.IntVal.ToString());
Use(GetMyStruct()?.IntVal.ToString());
Use(GetMyClass()?.ReadonlyIntVal.ToString());
Use(GetMyStruct()?.ReadonlyIntVal.ToString());
GetMyClass()?.StructField.Done();
GetMyClass()?.ReadonlyStructField.Done();
}
public void InvokeDelegate(EventHandler eh) public void InvokeDelegate(EventHandler eh)
{ {
eh?.Invoke(null, EventArgs.Empty); eh?.Invoke(null, EventArgs.Empty);

6
ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs

@ -186,6 +186,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return chainLength >= 1; return chainLength >= 1;
} else if (inst.MatchLdFld(out var target, out _)) { } else if (inst.MatchLdFld(out var target, out _)) {
inst = target; inst = target;
} else if (inst.MatchLdFlda(out target, out var f)) {
if (target is AddressOf addressOf && f.DeclaringType.Kind == TypeKind.Struct) {
inst = addressOf.Value;
} else {
inst = target;
}
} else if (inst is CallInstruction call && call.OpCode != OpCode.NewObj) { } else if (inst is CallInstruction call && call.OpCode != OpCode.NewObj) {
if (call.Arguments.Count == 0) { if (call.Arguments.Count == 0) {
return false; return false;

Loading…
Cancel
Save