diff --git a/ICSharpCode.Decompiler/IL/ILReader.cs b/ICSharpCode.Decompiler/IL/ILReader.cs
index 66ebbd3ff..d1ae0d7f1 100644
--- a/ICSharpCode.Decompiler/IL/ILReader.cs
+++ b/ICSharpCode.Decompiler/IL/ILReader.cs
@@ -953,7 +953,7 @@ namespace ICSharpCode.Decompiler.IL
private ILInstruction LdElem(IType type)
{
- return Push(new LdObj(new LdElema(indices: Pop(), array: Pop(), type: type), type));
+ return Push(new LdObj(new LdElema(indices: Pop(), array: Pop(), type: type) { DelayExceptions = true }, type));
}
private ILInstruction StElem(IType type)
@@ -961,7 +961,7 @@ namespace ICSharpCode.Decompiler.IL
var value = Pop(type.GetStackType());
var index = Pop();
var array = Pop();
- return new StObj(new LdElema(type, array, index), value, type);
+ return new StObj(new LdElema(type, array, index) { DelayExceptions = true }, value, type);
}
ILInstruction InitObj(ILInstruction target, IType type)
diff --git a/ICSharpCode.Decompiler/IL/Instructions.cs b/ICSharpCode.Decompiler/IL/Instructions.cs
index d5bedce57..c7e8cb131 100644
--- a/ICSharpCode.Decompiler/IL/Instructions.cs
+++ b/ICSharpCode.Decompiler/IL/Instructions.cs
@@ -2177,17 +2177,18 @@ namespace ICSharpCode.Decompiler.IL
clone.Target = this.target.Clone();
return clone;
}
+ public bool DelayExceptions;
readonly IField field;
/// Returns the field operand.
public IField Field { get { return field; } }
public override StackType ResultType { get { return StackType.Ref; } }
protected override InstructionFlags ComputeFlags()
{
- return target.Flags | InstructionFlags.MayThrow;
+ return target.Flags | (DelayExceptions ? InstructionFlags.None : InstructionFlags.MayThrow);
}
public override InstructionFlags DirectFlags {
get {
- return InstructionFlags.MayThrow;
+ return (DelayExceptions ? InstructionFlags.None : InstructionFlags.MayThrow);
}
}
public override void WriteTo(ITextOutput output)
@@ -3223,16 +3224,17 @@ namespace ICSharpCode.Decompiler.IL
clone.Indices.AddRange(this.Indices.Select(arg => arg.Clone()));
return clone;
}
+ public bool DelayExceptions;
public override StackType ResultType { get { return StackType.Ref; } }
/// Gets whether the 'readonly' prefix was applied to this instruction.
public bool IsReadOnly { get; set; }
protected override InstructionFlags ComputeFlags()
{
- return array.Flags | Indices.Aggregate(InstructionFlags.None, (f, arg) => f | arg.Flags) | InstructionFlags.MayThrow;
+ return array.Flags | Indices.Aggregate(InstructionFlags.None, (f, arg) => f | arg.Flags) | (DelayExceptions ? InstructionFlags.None : InstructionFlags.MayThrow);
}
public override InstructionFlags DirectFlags {
get {
- return InstructionFlags.MayThrow;
+ return (DelayExceptions ? InstructionFlags.None : InstructionFlags.MayThrow);
}
}
public override void WriteTo(ITextOutput output)
diff --git a/ICSharpCode.Decompiler/IL/Instructions.tt b/ICSharpCode.Decompiler/IL/Instructions.tt
index dfd067207..15e50b638 100644
--- a/ICSharpCode.Decompiler/IL/Instructions.tt
+++ b/ICSharpCode.Decompiler/IL/Instructions.tt
@@ -150,7 +150,7 @@
CustomClassName("LdFld"), CustomArguments("target"), MemoryAccess, SupportsVolatilePrefix, SupportsUnalignedPrefix, MayThrow,
HasFieldOperand, ResultType("field.Type.GetStackType()")),
new OpCode("ldflda", "Load address of instance field",
- CustomClassName("LdFlda"), CustomArguments("target"), MayThrow, HasFieldOperand, ResultType("Ref")),
+ CustomClassName("LdFlda"), CustomArguments("target"), MayThrowIfNotDelayed, HasFieldOperand, ResultType("Ref")),
new OpCode("stfld", "Store value to instance field",
CustomClassName("StFld"), CustomArguments("target", "value"),
MemoryAccess, SupportsVolatilePrefix, SupportsUnalignedPrefix, MayThrow, HasFieldOperand,
@@ -199,7 +199,7 @@
CustomClassName("LdLen"), CustomArguments("array"), CustomConstructor, CustomWriteTo, MayThrow),
new OpCode("ldelema", "Load address of array element.",
CustomClassName("LdElema"), HasTypeOperand, CustomChildren(new [] { new ArgumentInfo("array"), new ArgumentInfo("indices") { IsCollection = true } }, true),
- MayThrow, ResultType("Ref"), SupportsReadonlyPrefix),
+ MayThrowIfNotDelayed, ResultType("Ref"), SupportsReadonlyPrefix),
new OpCode("array.to.pointer", "Converts an array pointer (O) to a reference to the first element, or to a null reference if the array is null or empty." + Environment.NewLine
+ "Also used to convert a string to a reference to the first character.",
CustomArguments("array"), ResultType("Ref")),
@@ -534,6 +534,10 @@ namespace ICSharpCode.Decompiler.IL
// Instructions without this trait must evaluate all arguments left-to-right before having any effect of their own.
static Action ControlFlow = HasFlag("InstructionFlags.ControlFlow");
+ static Action MayThrowIfNotDelayed = HasFlag("(DelayExceptions ? InstructionFlags.None : InstructionFlags.MayThrow)") + (opCode => {
+ opCode.Members.Add("public bool DelayExceptions;");
+ });
+
static Action BaseClass(string name)
{
return opCode => {