diff --git a/ICSharpCode.Decompiler/ILAst/ILInlining.cs b/ICSharpCode.Decompiler/ILAst/ILInlining.cs
index c1c904951..ea88c3206 100644
--- a/ICSharpCode.Decompiler/ILAst/ILInlining.cs
+++ b/ICSharpCode.Decompiler/ILAst/ILInlining.cs
@@ -169,7 +169,10 @@ namespace ICSharpCode.Decompiler.ILAst
bool InlineIfPossible(ILVariable v, ILExpression inlinedExpression, ILNode next, bool aggressive)
{
// ensure the variable is accessed only a single time
- if (!(numStloc.GetOrDefault(v) == 1 && numLdloc.GetOrDefault(v) == 1 && numLdloca.GetOrDefault(v) == 0))
+ if (numStloc.GetOrDefault(v) != 1)
+ return false;
+ int ldloc = numLdloc.GetOrDefault(v);
+ if (ldloc > 1 || ldloc + numLdloca.GetOrDefault(v) != 1)
return false;
if (next is ILCondition)
@@ -180,7 +183,12 @@ namespace ICSharpCode.Decompiler.ILAst
ILExpression parent;
int pos;
if (FindLoadInNext(next as ILExpression, v, inlinedExpression, out parent, out pos) == true) {
- if (!aggressive && !v.IsGenerated && !NonAggressiveInlineInto((ILExpression)next, parent, inlinedExpression))
+ if (ldloc == 0)
+ {
+ if (!IsGeneratedValueTypeTemporary((ILExpression)next, parent, pos, v))
+ return false;
+ }
+ else if (!aggressive && !v.IsGenerated && !NonAggressiveInlineInto((ILExpression)next, parent, inlinedExpression))
return false;
// Assign the ranges of the ldloc instruction:
@@ -192,6 +200,15 @@ namespace ICSharpCode.Decompiler.ILAst
}
return false;
}
+
+ ///
+ /// Is this a temporary variable generated by the C# compiler for instance method calls on immutable value type values
+ ///
+ bool IsGeneratedValueTypeTemporary(ILExpression next, ILExpression parent, int pos, ILVariable v)
+ {
+ return pos == 0 && v.Type != null && v.Type.IsValueType && next.Code == ILCode.Stloc
+ && (parent.Code == ILCode.Call || parent.Code == ILCode.Callvirt) && ((MethodReference)parent.Operand).HasThis;
+ }
bool NonAggressiveInlineInto(ILExpression next, ILExpression parent, ILExpression inlinedExpression)
{
@@ -214,7 +231,7 @@ namespace ICSharpCode.Decompiler.ILAst
return false;
}
}
-
+
///
/// Gets whether 'expressionBeingMoved' can be inlined into 'expr'.
///
@@ -243,7 +260,7 @@ namespace ICSharpCode.Decompiler.ILAst
ILExpression arg = expr.Arguments[i];
- if (arg.Code == ILCode.Ldloc && arg.Operand == v) {
+ if ((arg.Code == ILCode.Ldloc || arg.Code == ILCode.Ldloca) && arg.Operand == v) {
parent = expr;
pos = i;
return true;