diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index 3a964d636..b35e16220 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -138,7 +138,9 @@ namespace ICSharpCode.Decompiler.CSharp if (methodDefinition.HasBody) { var ilReader = new ILReader(); var function = ilReader.ReadIL(methodDefinition.Body, CancellationToken); + function.CheckInvariant(); function.Body = function.Body.AcceptVisitor(new TransformingVisitor()); + function.CheckInvariant(); var statementBuilder = new StatementBuilder(method, cecilMapper); var body = statementBuilder.ConvertAsBlock(function.Body); body.AcceptVisitor(new InsertParenthesesVisitor { diff --git a/ICSharpCode.Decompiler/IL/Instructions.cs b/ICSharpCode.Decompiler/IL/Instructions.cs index a720a1ee0..9e8e11b31 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.cs +++ b/ICSharpCode.Decompiler/IL/Instructions.cs @@ -1113,10 +1113,6 @@ namespace ICSharpCode.Decompiler.IL public sealed partial class Return : ILInstruction { public override StackType ResultType { get { return StackType.Void; } } - protected override InstructionFlags ComputeFlags() - { - return InstructionFlags.MayBranch | InstructionFlags.EndPointUnreachable; - } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitReturn(this); diff --git a/ICSharpCode.Decompiler/IL/Instructions.tt b/ICSharpCode.Decompiler/IL/Instructions.tt index 9bd92569d..08aff0c94 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.tt +++ b/ICSharpCode.Decompiler/IL/Instructions.tt @@ -126,7 +126,7 @@ new OpCode("localloc", "Allocates space in the stack frame", CustomClassName("LocAlloc"), Unary, ResultType("I"), MayThrow), new OpCode("ret", "Returns from the current method or lambda.", - CustomClassName("Return"), CustomConstructor, MayBranch, UnconditionalBranch), + CustomClassName("Return"), CustomConstructor, CustomComputeFlags, MayBranch, UnconditionalBranch), new OpCode("shl", "Shift left", BinaryNumeric), new OpCode("shr", "Shift right", BinaryNumeric), diff --git a/ICSharpCode.Decompiler/IL/Instructions/Branch.cs b/ICSharpCode.Decompiler/IL/Instructions/Branch.cs index 141a0de3f..b75462f76 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/Branch.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/Branch.cs @@ -75,6 +75,14 @@ namespace ICSharpCode.Decompiler.IL get { return targetBlock != null ? targetBlock.Label : CecilExtensions.OffsetToString(TargetILOffset); } } + internal override void CheckInvariant() + { + base.CheckInvariant(); + if (targetBlock != null) { + Debug.Assert(targetBlock.Parent is BlockContainer); + Debug.Assert(this.IsDescendantOf(targetBlock.Parent)); + } + } public override void WriteTo(ITextOutput output) { diff --git a/ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs index 9654f9021..45d9d48de 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs @@ -53,8 +53,28 @@ namespace ICSharpCode.Decompiler.IL } [Conditional("DEBUG")] - internal void CheckInvariant() + internal virtual void CheckInvariant() { + foreach (var child in Children) { + Debug.Assert(child.Parent == this); + // if child flags are invalid, parent flags must be too + Debug.Assert(child.flags != invalidFlags || this.flags == invalidFlags); + Debug.Assert(child.IsConnected == this.IsConnected); + child.CheckInvariant(); + } + } + + /// + /// Gets whether this node is a descendant of . + /// Also returns true if this==. + /// + public bool IsDescendantOf(ILInstruction possibleAncestor) + { + for (ILInstruction ancestor = this; ancestor != null; ancestor = ancestor.Parent) { + if (ancestor == possibleAncestor) + return true; + } + return false; } /// diff --git a/ICSharpCode.Decompiler/IL/Instructions/Return.cs b/ICSharpCode.Decompiler/IL/Instructions/Return.cs index c7886e3c2..1b8b9f912 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/Return.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/Return.cs @@ -47,6 +47,15 @@ namespace ICSharpCode.Decompiler.IL this.ReturnValue = argument; } + protected override InstructionFlags ComputeFlags() + { + InstructionFlags flags = InstructionFlags.MayBranch | InstructionFlags.EndPointUnreachable; + if (returnValue != null) { + flags |= returnValue.Flags; + } + return flags; + } + public override void WriteTo(ITextOutput output) { output.Write(OpCode); diff --git a/ILSpy/Languages/CSharpLanguage.cs b/ILSpy/Languages/CSharpLanguage.cs index 9a84d78c7..834f09d5f 100644 --- a/ILSpy/Languages/CSharpLanguage.cs +++ b/ILSpy/Languages/CSharpLanguage.cs @@ -212,7 +212,6 @@ namespace ICSharpCode.ILSpy { CSharpDecompiler decompiler = new CSharpDecompiler(type.Module); output.WriteLine(decompiler.Decompile(type).ToString()); - // AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: type); // codeDomBuilder.AddType(type); // RunTransformsAndGenerateCode(codeDomBuilder, output, options);