Browse Source

Do not transforms pattern further as if they were real instructions.

pull/4091/head
Daniel Grunwald 3 days ago
parent
commit
42d70f74e2
  1. 11
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  2. 18
      ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs
  3. 2
      ILSpy-tests

11
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -29,6 +29,7 @@ using ICSharpCode.Decompiler.CSharp.Resolver;
using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.CSharp.Transforms; using ICSharpCode.Decompiler.CSharp.Transforms;
using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.IL.Patterns;
using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.IL.Transforms;
using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
@ -5387,6 +5388,16 @@ namespace ICSharpCode.Decompiler.CSharp
.WithILInstruction(matchInstruction); .WithILInstruction(matchInstruction);
} }
case Comp comp: case Comp comp:
if (comp.MatchLogicNot(out var operand) && MatchInstruction.IsPatternMatch(operand, out _, settings))
{
// logic.not as a pattern
Expression sub = TranslatePattern(operand, leftHandType).Expression;
if (sub is UnaryOperatorExpression { Operator: UnaryOperatorType.PatternNot } uoe)
{
return uoe.Expression.Detach().WithILInstruction(comp);
}
return new UnaryOperatorExpression(UnaryOperatorType.PatternNot, sub).WithILInstruction(comp);
}
TranslatedExpression constantValue; TranslatedExpression constantValue;
if (comp.Right is DefaultValue dv) if (comp.Right is DefaultValue dv)
{ {

18
ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs

@ -599,18 +599,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{ {
context.Step("conditional operator", inst); context.Step("conditional operator", inst);
IType type = v.Type; IType type = v.Type;
// Try to tighten the type; this matters esp. for logic.and/logic.or: // Try to tighten the type to `bool`; this matters esp. for logic.and/logic.or:
IType type1 = value1.InferType(context.TypeSystem); IType type1 = value1.InferType(context.TypeSystem);
IType type2 = value2.InferType(context.TypeSystem); IType type2 = value2.InferType(context.TypeSystem);
if (type1.IsKnownType(KnownTypeCode.Boolean) && ( if (type1.IsKnownType(KnownTypeCode.Boolean)
type2.IsKnownType(KnownTypeCode.Boolean) && (type2.IsKnownType(KnownTypeCode.Boolean) || value2 is LdcI4 { Value: 0 or 1 }))
|| value2 is LdcI4 { Value: 0 or 1 }
))
{ {
type = type1; type = type1;
} }
else if (type2.IsKnownType(KnownTypeCode.Boolean) else if (type2.IsKnownType(KnownTypeCode.Boolean) && value1 is LdcI4 { Value: 0 or 1 })
&& value1 is LdcI4 { Value: 0 or 1 })
{ {
type = type2; type = type2;
} }
@ -1024,5 +1021,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
context.EndStep(condition); context.EndStep(condition);
} }
} }
protected internal override void VisitMatchInstruction(MatchInstruction inst)
{
inst.TestedOperand.AcceptVisitor(this);
// Do not recurse into the sub-patterns: patterns are restricted to use only certain ILInstructions,
// and arbitrary transforms might not stay within that allowed set of instructions.
}
} }
} }

2
ILSpy-tests

@ -1 +1 @@
Subproject commit 4ccc3f0108007242c95025590edd4cc6ef1fb731 Subproject commit 9668d49b9f71b40045e5417b55d20e330be95921
Loading…
Cancel
Save