Browse Source

Fix #3512: Local function name collides with local variable name

pull/3529/head
Siegfried Pammer 5 months ago
parent
commit
f97e59760b
  1. 23
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/QualifierTests.cs
  2. 89
      ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs

23
ICSharpCode.Decompiler.Tests/TestCases/Pretty/QualifierTests.cs

@ -312,7 +312,30 @@ namespace ICSharpCode.Decompiler.Tests.Pretty
QualifierTests.i.Test(); QualifierTests.i.Test();
} }
} }
#if CS70
private void LocalConflictsWithLocalFunction()
{
int num = 0;
LocalFunction();
void LocalFunction()
{
QualifierTests qualifierTests2 = qualifierTests();
i.Test();
Z(qualifierTests2);
}
QualifierTests qualifierTests()
{
num.ToString();
return new QualifierTests(new string[0]);
}
}
private void Z(QualifierTests qualifierTests)
{
}
#endif
public QualifierTests(string[] Array) public QualifierTests(string[] Array)
{ {
System.Array.Sort(Array); System.Array.Sort(Array);

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

@ -452,53 +452,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{ {
var (currentFunction, parentContext) = this.workList.Dequeue(); var (currentFunction, parentContext) = this.workList.Dequeue();
if (currentFunction.Kind == ILFunctionKind.LocalFunction)
{
// assign names to local functions
if (!LocalFunctionDecompiler.ParseLocalFunctionName(currentFunction.Name, out _, out var newName) || !IsValidName(newName))
newName = null;
string nameWithoutNumber;
int number;
if (!string.IsNullOrEmpty(newName))
{
nameWithoutNumber = SplitName(newName, out number);
}
else
{
nameWithoutNumber = "f";
number = 1;
}
int count;
if (!parentContext.IsReservedVariableName(nameWithoutNumber, out int currentIndex))
{
count = 1;
}
else
{
if (currentIndex < number)
count = number;
else
count = Math.Max(number, currentIndex) + 1;
}
parentContext.ReserveVariableName(nameWithoutNumber, count);
if (count > 1)
{
newName = nameWithoutNumber + count.ToString();
}
else
{
newName = nameWithoutNumber;
}
currentFunction.Name = newName;
currentFunction.ReducedMethod.Name = newName;
parentContext.Add((MethodDefinitionHandle)currentFunction.ReducedMethod.MetadataToken, newName);
}
var nestedContext = new VariableScope(currentFunction, this.context, parentContext); var nestedContext = new VariableScope(currentFunction, this.context, parentContext);
currentFunction.Body.AcceptVisitor(this, nestedContext);
foreach (var localFunction in currentFunction.LocalFunctions) foreach (var localFunction in currentFunction.LocalFunctions)
{
AssignNameToLocalFunction(localFunction, nestedContext);
workList.Enqueue((localFunction, nestedContext)); workList.Enqueue((localFunction, nestedContext));
}
currentFunction.Body.AcceptVisitor(this, nestedContext);
if (currentFunction.Kind != ILFunctionKind.TopLevelFunction) if (currentFunction.Kind != ILFunctionKind.TopLevelFunction)
{ {
@ -510,6 +472,47 @@ namespace ICSharpCode.Decompiler.IL.Transforms
} }
} }
private static void AssignNameToLocalFunction(ILFunction function, VariableScope parentContext)
{
if (!LocalFunctionDecompiler.ParseLocalFunctionName(function.Name, out _, out var newName) || !IsValidName(newName))
newName = null;
string nameWithoutNumber;
int number;
if (!string.IsNullOrEmpty(newName))
{
nameWithoutNumber = SplitName(newName, out number);
}
else
{
nameWithoutNumber = "f";
number = 1;
}
int count;
if (!parentContext.IsReservedVariableName(nameWithoutNumber, out int currentIndex))
{
count = 1;
}
else
{
if (currentIndex < number)
count = number;
else
count = Math.Max(number, currentIndex) + 1;
}
parentContext.ReserveVariableName(nameWithoutNumber, count);
if (count > 1)
{
newName = nameWithoutNumber + count.ToString();
}
else
{
newName = nameWithoutNumber;
}
function.Name = newName;
function.ReducedMethod.Name = newName;
parentContext.Add((MethodDefinitionHandle)function.ReducedMethod.MetadataToken, newName);
}
Unit VisitChildren(ILInstruction inst, VariableScope context) Unit VisitChildren(ILInstruction inst, VariableScope context)
{ {
foreach (var child in inst.Children) foreach (var child in inst.Children)

Loading…
Cancel
Save