Browse Source

Fix #1919: Use unmapped IL offsets at the start of a catch-block for the 'exception specifier' sequence point.

pull/1920/head
Siegfried Pammer 5 years ago
parent
commit
4db41f69db
  1. 21
      ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs
  2. 9
      ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs

21
ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs

@ -113,7 +113,13 @@ namespace ICSharpCode.Decompiler.CSharp
ILInstruction blockContainer = blockStatement.Annotations.OfType<ILInstruction>().FirstOrDefault(); ILInstruction blockContainer = blockStatement.Annotations.OfType<ILInstruction>().FirstOrDefault();
if (blockContainer != null) { if (blockContainer != null) {
StartSequencePoint(blockStatement.LBraceToken); StartSequencePoint(blockStatement.LBraceToken);
int intervalStart = blockContainer.ILRanges.First().Start; int intervalStart;
if (blockContainer.Parent is TryCatchHandler handler && !handler.ExceptionSpecifierILRange.IsEmpty) {
// if this block container is part of a TryCatchHandler, do not steal the exception-specifier IL range
intervalStart = handler.ExceptionSpecifierILRange.End;
} else {
intervalStart = blockContainer.ILRanges.First().Start;
}
// The end will be set to the first sequence point candidate location before the first statement of the function when the seqeunce point is adjusted // The end will be set to the first sequence point candidate location before the first statement of the function when the seqeunce point is adjusted
int intervalEnd = intervalStart + 1; int intervalEnd = intervalStart + 1;
@ -321,17 +327,20 @@ namespace ICSharpCode.Decompiler.CSharp
public override void VisitCatchClause(CatchClause catchClause) public override void VisitCatchClause(CatchClause catchClause)
{ {
StartSequencePoint(catchClause);
if (catchClause.Condition.IsNull) { if (catchClause.Condition.IsNull) {
StartSequencePoint(catchClause.CatchToken); var tryCatchHandler = catchClause.Annotation<TryCatchHandler>();
var function = catchClause.Ancestors.OfType<ILFunction>().FirstOrDefault(); if (!tryCatchHandler.ExceptionSpecifierILRange.IsEmpty) {
AddToSequencePointRaw(function, new[] { catchClause.Annotation<TryCatchHandler>().ExceptionSpecifierILRange }); StartSequencePoint(catchClause.CatchToken);
EndSequencePoint(catchClause.CatchToken.StartLocation, catchClause.RParToken.IsNull ? catchClause.CatchToken.EndLocation : catchClause.RParToken.EndLocation); var function = tryCatchHandler.Ancestors.OfType<ILFunction>().FirstOrDefault();
AddToSequencePointRaw(function, new[] { tryCatchHandler.ExceptionSpecifierILRange });
EndSequencePoint(catchClause.CatchToken.StartLocation, catchClause.RParToken.IsNull ? catchClause.CatchToken.EndLocation : catchClause.RParToken.EndLocation);
}
} else { } else {
StartSequencePoint(catchClause.WhenToken); StartSequencePoint(catchClause.WhenToken);
AddToSequencePoint(catchClause.Condition); AddToSequencePoint(catchClause.Condition);
EndSequencePoint(catchClause.WhenToken.StartLocation, catchClause.CondRParToken.EndLocation); EndSequencePoint(catchClause.WhenToken.StartLocation, catchClause.CondRParToken.EndLocation);
} }
StartSequencePoint(catchClause);
catchClause.Body.AcceptVisitor(this); catchClause.Body.AcceptVisitor(this);
EndSequencePoint(catchClause.StartLocation, catchClause.EndLocation); EndSequencePoint(catchClause.StartLocation, catchClause.EndLocation);
} }

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

@ -17,10 +17,12 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.IL.Transforms namespace ICSharpCode.Decompiler.IL.Transforms
{ {
@ -711,6 +713,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// </summary> /// </summary>
void TransformCatchVariable(TryCatchHandler handler, Block entryPoint, bool isCatchBlock) void TransformCatchVariable(TryCatchHandler handler, Block entryPoint, bool isCatchBlock)
{ {
List<Interval> ilOffsets = null;
if (!handler.Variable.IsSingleDefinition || handler.Variable.LoadCount != 1) if (!handler.Variable.IsSingleDefinition || handler.Variable.LoadCount != 1)
return; // handle.Variable already has non-trivial uses return; // handle.Variable already has non-trivial uses
if (!entryPoint.Instructions[0].MatchStLoc(out var exceptionVar, out var exceptionSlotLoad)) { if (!entryPoint.Instructions[0].MatchStLoc(out var exceptionVar, out var exceptionSlotLoad)) {
@ -720,6 +723,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (inlinedUnboxAny.Type.Equals(handler.Variable.Type)) { if (inlinedUnboxAny.Type.Equals(handler.Variable.Type)) {
context.Step("TransformCatchVariable - remove inlined UnboxAny", inlinedUnboxAny); context.Step("TransformCatchVariable - remove inlined UnboxAny", inlinedUnboxAny);
inlinedUnboxAny.ReplaceWith(inlinedUnboxAny.Argument); inlinedUnboxAny.ReplaceWith(inlinedUnboxAny.Argument);
(ilOffsets ?? (ilOffsets = new List<Interval>())).AddRange(inlinedUnboxAny.ILRanges);
} }
} }
return; return;
@ -746,6 +750,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
exceptionVar.Kind = VariableKind.ExceptionLocal; exceptionVar.Kind = VariableKind.ExceptionLocal;
exceptionVar.Type = handler.Variable.Type; exceptionVar.Type = handler.Variable.Type;
handler.Variable = exceptionVar; handler.Variable = exceptionVar;
if (isCatchBlock) {
(ilOffsets ?? (ilOffsets = new List<Interval>())).AddRange(entryPoint.Instructions[0].Descendants.SelectMany(o => o.ILRanges));
foreach (var offset in ilOffsets)
handler.AddExceptionSpecifierILRange(offset);
}
entryPoint.Instructions.RemoveAt(0); entryPoint.Instructions.RemoveAt(0);
} }

Loading…
Cancel
Save