diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index 466b63f8e..d502ff0f3 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -1068,8 +1068,8 @@ namespace ICSharpCode.Decompiler.CSharp if (!parameter.Type.ContainsAnonymousType()) arguments[i] = arguments[i].ConvertTo(parameter.Type, this); - if (parameter.IsOut && arguments[i].Expression is DirectionExpression) { - ((DirectionExpression)arguments[i].Expression).FieldDirection = FieldDirection.Out; + if (parameter.IsOut && arguments[i].Expression is DirectionExpression dirExpr) { + dirExpr.FieldDirection = FieldDirection.Out; } } diff --git a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs index d89f73b38..72b35b3d7 100644 --- a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs @@ -25,6 +25,7 @@ using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.IL.Patterns; +using System; namespace ICSharpCode.Decompiler.CSharp { @@ -60,7 +61,11 @@ namespace ICSharpCode.Decompiler.CSharp protected internal override Statement VisitNop(Nop inst) { - return new EmptyStatement(); + var stmt = new EmptyStatement(); + if (inst.Comment != null) { + stmt.AddChild(new Comment(inst.Comment), Roles.Comment); + } + return stmt; } protected internal override Statement VisitIfInstruction(IfInstruction inst) diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs b/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs index 9c6997ac3..b73ab839b 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs @@ -108,6 +108,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms { try { this.context = context; + EnsureExpressionStatementsAreValid(rootNode); FindInsertionPoints(rootNode, 0); ResolveCollisions(); InsertVariableDeclarations(); @@ -117,6 +118,45 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms } } + #region EnsureExpressionStatementsAreValid + void EnsureExpressionStatementsAreValid(AstNode rootNode) + { + foreach (var stmt in rootNode.DescendantsAndSelf.OfType()) { + if (!IsValidInStatementExpression(stmt.Expression)) { + // assign result to dummy variable + var v = new ILVariable(VariableKind.StackSlot, stmt.Expression.GetResolveResult().Type, 0); + v.Name = "_"; + stmt.Expression = new AssignmentExpression( + new IdentifierExpression(v.Name).WithRR(new ILVariableResolveResult(v, v.Type)), + stmt.Expression.Detach()); + } + } + } + + private static bool IsValidInStatementExpression(Expression expr) + { + switch (expr) { + case InvocationExpression ie: + case ObjectCreateExpression oce: + case AssignmentExpression ae: + return true; + case UnaryOperatorExpression uoe: + switch (uoe.Operator) { + case UnaryOperatorType.PostIncrement: + case UnaryOperatorType.PostDecrement: + case UnaryOperatorType.Increment: + case UnaryOperatorType.Decrement: + case UnaryOperatorType.Await: + return true; + default: + return false; + } + default: + return false; + } + } + #endregion + #region FindInsertionPoints List<(InsertionPoint InsertionPoint, BlockContainer Loop)> loopTracking = new List<(InsertionPoint, BlockContainer)>(); diff --git a/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs b/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs index cb9be9174..5822105b6 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs @@ -47,7 +47,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms ILVariable v; ILInstruction copiedExpr; if (block.Instructions[i].MatchStLoc(out v, out copiedExpr)) { - if (v.IsSingleDefinition && CanPerformCopyPropagation(v, copiedExpr)) { + if (v.IsSingleDefinition && v.LoadCount == 0 && v.Kind == VariableKind.StackSlot) { + // dead store to stack + if (copiedExpr.Flags == InstructionFlags.None) { + // no-op -> delete + block.Instructions.RemoveAt(i--); + } else { + // evaluate the value for its side-effects + block.Instructions[i] = copiedExpr; + } + } else if (v.IsSingleDefinition && CanPerformCopyPropagation(v, copiedExpr)) { DoPropagate(v, copiedExpr, block, ref i, context); } } diff --git a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs index 05dbc278e..5c2fc5121 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs @@ -336,7 +336,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms static bool IsSafeForInlineOver(ILInstruction expr, ILInstruction expressionBeingMoved) { return SemanticHelper.MayReorder(expressionBeingMoved, expr); - } } }