diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index f2aa95a3b..6f3f1cbac 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -532,6 +532,9 @@ namespace ICSharpCode.Decompiler.CSharp internal ExpressionWithResolveResult LogicNot(TranslatedExpression expr) { + // "!expr" implicitly converts to bool so we can remove the cast; + // but only if doing so wouldn't cause us to call a user-defined "operator !" + expr = expr.UnwrapImplicitBoolConversion(type => !type.GetMethods(m => m.IsOperator && m.Name == "op_LogicalNot").Any()); return new UnaryOperatorExpression(UnaryOperatorType.Not, expr.Expression) .WithRR(new OperatorResolveResult(compilation.FindType(KnownTypeCode.Boolean), ExpressionType.Not, expr.ResolveResult)); } @@ -2476,6 +2479,7 @@ namespace ICSharpCode.Decompiler.CSharp .WithRR(new ResolveResult(compilation.FindType(KnownTypeCode.Boolean))); } + condition = condition.UnwrapImplicitBoolConversion(); trueBranch = AdjustConstantExpressionToType(trueBranch, falseBranch.Type); falseBranch = AdjustConstantExpressionToType(falseBranch, trueBranch.Type); @@ -2522,7 +2526,7 @@ namespace ICSharpCode.Decompiler.CSharp .WithRR(rr); } } - + protected internal override TranslatedExpression VisitAddressOf(AddressOf inst, TranslationContext context) { IType targetTypeHint = null; diff --git a/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs b/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs index e2f14d4a6..5455f5934 100644 --- a/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs @@ -431,7 +431,27 @@ namespace ICSharpCode.Decompiler.CSharp .WithoutILInstruction() .WithRR(new ConstantResolveResult(compilation.FindType(KnownTypeCode.Int32), val)); } - + + /// + /// In conditional contexts, remove the bool-cast emitted when converting + /// an "implicit operator bool" invocation. + /// + public TranslatedExpression UnwrapImplicitBoolConversion(Func typeFilter = null) + { + if (!this.Type.IsKnownType(KnownTypeCode.Boolean)) + return this; + if (!(this.ResolveResult is ConversionResolveResult rr)) + return this; + if (!(rr.Conversion.IsUserDefined && rr.Conversion.IsImplicit)) + return this; + if (typeFilter != null && !typeFilter(rr.Input.Type)) + return this; + if (this.Expression is CastExpression cast) { + return this.UnwrapChild(cast.Expression); + } + return this; + } + /// /// Converts this expression to a boolean expression. ///