Browse Source

Pattern Matching: Ensure that we always return a non-null instruction after successfully matching a pattern.

pull/3049/head
Siegfried Pammer 2 years ago
parent
commit
800067e488
  1. 72
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/PatternMatching.cs
  2. 21
      ICSharpCode.Decompiler/IL/Transforms/PatternMatchingTransform.cs

72
ICSharpCode.Decompiler.Tests/TestCases/Pretty/PatternMatching.cs

@ -503,6 +503,66 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -503,6 +503,66 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
}
public void RecursivePattern_NullableIntField_Var(object obj)
{
if (obj is X { NullableIntField: var nullableIntField })
{
Console.WriteLine("Test " + nullableIntField.Value);
}
else
{
Console.WriteLine("not Test");
}
}
public void RecursivePattern_NullableIntProp_Const(object obj)
{
if (obj is X { NullableIntProp: 42 } x)
{
Console.WriteLine("Test " + x);
}
else
{
Console.WriteLine("not Test");
}
}
public void RecursivePattern_NullableIntProp_Var(object obj)
{
if (obj is X { NullableIntProp: var nullableIntProp })
{
Console.WriteLine("Test " + nullableIntProp.Value);
}
else
{
Console.WriteLine("not Test");
}
}
public void RecursivePattern_NullableCustomStructField_Const(object obj)
{
if (obj is X { NullableCustomStructField: { I: 42, Obj: not null } nullableCustomStructField })
{
Console.WriteLine("Test " + nullableCustomStructField.I);
}
else
{
Console.WriteLine("not Test");
}
}
public void RecursivePattern_NullableCustomStructField_Var(object obj)
{
if (obj is X { NullableCustomStructField: var nullableCustomStructField, Obj: null })
{
Console.WriteLine("Test " + nullableCustomStructField.Value);
}
else
{
Console.WriteLine("not Test");
}
}
public void RecursivePattern_NullableCustomStructProp_Const(object obj)
{
if (obj is X { NullableCustomStructProp: { I: 42, Obj: not null } nullableCustomStructProp })
@ -514,6 +574,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -514,6 +574,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine("not Test");
}
}
public void RecursivePattern_NullableCustomStructProp_Var(object obj)
{
if (obj is X { NullableCustomStructProp: var nullableCustomStructProp, Obj: null })
{
Console.WriteLine("Test " + nullableCustomStructProp.Value);
}
else
{
Console.WriteLine("not Test");
}
}
#endif
private bool F()
{

21
ICSharpCode.Decompiler/IL/Transforms/PatternMatchingTransform.cs

@ -186,11 +186,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -186,11 +186,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true;
}
private static ILInstruction? DetectPropertySubPatterns(MatchInstruction parentPattern, ILInstruction? trueInst,
private static ILInstruction DetectPropertySubPatterns(MatchInstruction parentPattern, ILInstruction trueInst,
ILInstruction parentFalseInst, BlockContainer container, ILTransformContext context, ref ControlFlowGraph? cfg)
{
ILInstruction? prevTrueInst = trueInst;
while (trueInst != null)
while (true)
{
Block? trueBlock = trueInst as Block;
if (!(trueBlock != null || trueInst.MatchBranch(out trueBlock)))
@ -201,13 +200,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -201,13 +200,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
break;
}
trueInst = DetectPropertySubPattern(parentPattern, trueBlock, parentFalseInst, context, ref cfg);
if (trueInst != null)
var nextTrueInst = DetectPropertySubPattern(parentPattern, trueBlock, parentFalseInst, context, ref cfg);
if (nextTrueInst != null)
{
prevTrueInst = trueInst;
trueInst = nextTrueInst;
}
else
{
break;
}
}
return prevTrueInst;
return trueInst;
}
private static ILInstruction? DetectPropertySubPattern(MatchInstruction parentPattern, Block block,
@ -288,7 +291,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -288,7 +291,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (targetVariable.Type.IsKnownType(KnownTypeCode.NullableOfT))
{
return MatchNullableHasValueCheckPattern(block, varPattern, parentFalseInst, context, ref cfg);
return MatchNullableHasValueCheckPattern(block, varPattern, parentFalseInst, context, ref cfg)
?? block;
}
var instructionAfterNullCheck = MatchNullCheckPattern(block, varPattern, parentFalseInst, context);
@ -339,6 +343,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -339,6 +343,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
block.Instructions.Add(trueInst);
return trueInst;
}
private static ILInstruction? MatchNullableHasValueCheckPattern(Block block, MatchInstruction varPattern,
ILInstruction parentFalseInst, ILTransformContext context, ref ControlFlowGraph? cfg)
{

Loading…
Cancel
Save