diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
index dc7dbb8b4..a46e34568 100644
--- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
+++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
@@ -1701,7 +1701,12 @@ namespace ICSharpCode.Decompiler.CSharp
{
return Translate(inst.Argument).ConvertTo(inst.Type, this);
}
-
+
+ protected internal override TranslatedExpression VisitExpressionTreeCast(ExpressionTreeCast inst, TranslationContext context)
+ {
+ return Translate(inst.Argument).ConvertTo(inst.Type, this, inst.IsChecked);
+ }
+
protected internal override TranslatedExpression VisitArglist(Arglist inst, TranslationContext context)
{
return new UndocumentedExpression { UndocumentedExpressionType = UndocumentedExpressionType.ArgListAccess }
diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
index 5d4782630..3283989fa 100644
--- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
+++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
@@ -283,6 +283,7 @@
+
diff --git a/ICSharpCode.Decompiler/IL/Instructions.cs b/ICSharpCode.Decompiler/IL/Instructions.cs
index 58941eba3..0ea2866d3 100644
--- a/ICSharpCode.Decompiler/IL/Instructions.cs
+++ b/ICSharpCode.Decompiler/IL/Instructions.cs
@@ -168,6 +168,8 @@ namespace ICSharpCode.Decompiler.IL
ArrayToPointer,
/// Maps a string value to an integer. This is used in switch(string).
StringToInt,
+ /// ILAst representation of Expression.Convert.
+ ExpressionTreeCast,
/// Push a typed reference of type class onto the stack.
MakeRefAny,
/// Push the type token stored in a typed reference.
@@ -4493,6 +4495,46 @@ namespace ICSharpCode.Decompiler.IL
}
}
namespace ICSharpCode.Decompiler.IL
+{
+ /// ILAst representation of Expression.Convert.
+ public sealed partial class ExpressionTreeCast : UnaryInstruction
+ {
+ IType type;
+ /// Returns the type operand.
+ public IType Type {
+ get { return type; }
+ set { type = value; InvalidateFlags(); }
+ }
+ public override StackType ResultType { get { return type.GetStackType(); } }
+ protected override InstructionFlags ComputeFlags()
+ {
+ return base.ComputeFlags() | InstructionFlags.MayThrow;
+ }
+ public override InstructionFlags DirectFlags {
+ get {
+ return base.DirectFlags | InstructionFlags.MayThrow;
+ }
+ }
+ public override void AcceptVisitor(ILVisitor visitor)
+ {
+ visitor.VisitExpressionTreeCast(this);
+ }
+ public override T AcceptVisitor(ILVisitor visitor)
+ {
+ return visitor.VisitExpressionTreeCast(this);
+ }
+ public override T AcceptVisitor(ILVisitor visitor, C context)
+ {
+ return visitor.VisitExpressionTreeCast(this, context);
+ }
+ protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
+ {
+ var o = other as ExpressionTreeCast;
+ return o != null && this.Argument.PerformMatch(o.Argument, ref match) && type.Equals(o.type) && this.IsChecked == o.IsChecked;
+ }
+ }
+}
+namespace ICSharpCode.Decompiler.IL
{
/// Push a typed reference of type class onto the stack.
public sealed partial class MakeRefAny : UnaryInstruction
@@ -5132,6 +5174,10 @@ namespace ICSharpCode.Decompiler.IL
{
Default(inst);
}
+ protected internal virtual void VisitExpressionTreeCast(ExpressionTreeCast inst)
+ {
+ Default(inst);
+ }
protected internal virtual void VisitMakeRefAny(MakeRefAny inst)
{
Default(inst);
@@ -5434,6 +5480,10 @@ namespace ICSharpCode.Decompiler.IL
{
return Default(inst);
}
+ protected internal virtual T VisitExpressionTreeCast(ExpressionTreeCast inst)
+ {
+ return Default(inst);
+ }
protected internal virtual T VisitMakeRefAny(MakeRefAny inst)
{
return Default(inst);
@@ -5736,6 +5786,10 @@ namespace ICSharpCode.Decompiler.IL
{
return Default(inst, context);
}
+ protected internal virtual T VisitExpressionTreeCast(ExpressionTreeCast inst, C context)
+ {
+ return Default(inst, context);
+ }
protected internal virtual T VisitMakeRefAny(MakeRefAny inst, C context)
{
return Default(inst, context);
@@ -5829,6 +5883,7 @@ namespace ICSharpCode.Decompiler.IL
"ldelema",
"array.to.pointer",
"string.to.int",
+ "expression.tree.cast",
"mkrefany",
"refanytype",
"refanyval",
diff --git a/ICSharpCode.Decompiler/IL/Instructions.tt b/ICSharpCode.Decompiler/IL/Instructions.tt
index bab9fd9ea..04a85831d 100644
--- a/ICSharpCode.Decompiler/IL/Instructions.tt
+++ b/ICSharpCode.Decompiler/IL/Instructions.tt
@@ -240,6 +240,10 @@
new OpCode("string.to.int", "Maps a string value to an integer. This is used in switch(string).",
CustomArguments("argument"), CustomConstructor, CustomWriteTo, ResultType("I4")),
+ new OpCode("expression.tree.cast", "ILAst representation of Expression.Convert.",
+ CustomClassName("ExpressionTreeCast"), Unary, HasTypeOperand, MayThrow, CustomConstructor, CustomWriteTo, ResultType("type.GetStackType()"),
+ MatchCondition("this.IsChecked == o.IsChecked")),
+
new OpCode("mkrefany", "Push a typed reference of type class onto the stack.",
CustomClassName("MakeRefAny"), Unary, HasTypeOperand, ResultType("O")),
new OpCode("refanytype", "Push the type token stored in a typed reference.",
diff --git a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTreeCast.cs b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTreeCast.cs
new file mode 100644
index 000000000..3fa452e24
--- /dev/null
+++ b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTreeCast.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ICSharpCode.Decompiler.TypeSystem;
+
+namespace ICSharpCode.Decompiler.IL
+{
+ partial class ExpressionTreeCast
+ {
+ public bool IsChecked { get; set; }
+
+ public ExpressionTreeCast(IType type, ILInstruction argument, bool isChecked)
+ : base(OpCode.ExpressionTreeCast, argument)
+ {
+ this.Type = type;
+ this.IsChecked = isChecked;
+ }
+
+ public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
+ {
+ ILRange.WriteTo(output, options);
+ output.Write(OpCode);
+ if (IsChecked) output.Write(".checked");
+ output.Write(' ');
+ type.WriteTo(output);
+ output.Write('(');
+ Argument.WriteTo(output, options);
+ output.Write(')');
+ }
+ }
+}