Browse Source

Don't unnecessarily default-initialize variables prior to a call with out-parameter.

pull/1087/head
Daniel Grunwald 7 years ago
parent
commit
96d9e63f4c
  1. 12
      ICSharpCode.Decompiler/FlowAnalysis/DefiniteAssignmentVisitor.cs
  2. 13
      ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs
  3. 2
      ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs

12
ICSharpCode.Decompiler/FlowAnalysis/DefiniteAssignmentVisitor.cs

@ -183,7 +183,17 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -183,7 +183,17 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
protected internal override void VisitLdLoca(LdLoca inst)
{
EnsureInitialized(inst.Variable);
// A variable needs to be initialized before we can take it by reference.
// The exception is if the variable is passed to an out parameter.
if (!IsOutArgument(inst)) {
EnsureInitialized(inst.Variable);
}
}
static bool IsOutArgument(ILInstruction inst)
{
return inst.Parent is CallInstruction call
&& call.GetParameter(inst.ChildIndex)?.IsOut == true;
}
}
}

13
ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs

@ -64,6 +64,19 @@ namespace ICSharpCode.Decompiler.IL @@ -64,6 +64,19 @@ namespace ICSharpCode.Decompiler.IL
this.Method = method;
this.Arguments = new InstructionCollection<ILInstruction>(this, 0);
}
/// <summary>
/// Gets the parameter for the argument with the specified index.
/// Returns null for the <c>this</c> parameter.
/// </summary>
public IParameter GetParameter(int argumentIndex)
{
int firstParamIndex = (Method.IsStatic || OpCode == OpCode.NewObj) ? 0 : 1;
if (argumentIndex < firstParamIndex) {
return null; // asking for 'this' parameter
}
return Method.Parameters[argumentIndex - firstParamIndex];
}
public override StackType ResultType {
get {

2
ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs

@ -338,7 +338,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -338,7 +338,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return CleanUpVariableName(m.Name.Substring(3));
}
}
var p = m.Parameters.ElementAtOrDefault((!(call is NewObj) && !m.IsStatic) ? i - 1 : i);
var p = call.GetParameter(i);
if (p != null && !string.IsNullOrEmpty(p.Name))
return CleanUpVariableName(p.Name);
break;

Loading…
Cancel
Save