Browse Source

Fix #2283: string.to.int instruction entails a conversion to string of the input value

pull/2301/head
Siegfried Pammer 4 years ago
parent
commit
63ca748b9a
  1. 92
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs
  2. 5
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  3. 9
      ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

92
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs

@ -37,6 +37,36 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -37,6 +37,36 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
}
public class ImplicitString
{
private readonly string s;
public ImplicitString(string s)
{
this.s = s;
}
public static implicit operator string(ImplicitString v)
{
return v.s;
}
}
public class ExplicitString
{
private readonly string s;
public ExplicitString(string s)
{
this.s = s;
}
public static explicit operator string(ExplicitString v)
{
return v.s;
}
}
public enum State
{
False,
@ -379,6 +409,68 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -379,6 +409,68 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
}
public static string SwitchOverImplicitString(ImplicitString s)
{
switch (s)
{
case "First case":
return "Text1";
case "Second case":
return "Text2";
case "Third case":
return "Text3";
case "Fourth case":
return "Text4";
case "Fifth case":
return "Text5";
case "Sixth case":
return "Text6";
case "Seventh case":
return "Text7";
case "Eighth case":
return "Text8";
case "Ninth case":
return "Text9";
case "Tenth case":
return "Text10";
case "Eleventh case":
return "Text11";
default:
return "Default";
}
}
public static string SwitchOverExplicitString(ExplicitString s)
{
switch ((string)s)
{
case "First case":
return "Text1";
case "Second case":
return "Text2";
case "Third case":
return "Text3";
case "Fourth case":
return "Text4";
case "Fifth case":
return "Text5";
case "Sixth case":
return "Text6";
case "Seventh case":
return "Text7";
case "Eighth case":
return "Text8";
case "Ninth case":
return "Text9";
case "Tenth case":
return "Text10";
case "Eleventh case":
return "Text11";
default:
return "Default";
}
}
#if !ROSLYN
public static string SwitchOverBool(bool b)
{

5
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -3642,6 +3642,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -3642,6 +3642,7 @@ namespace ICSharpCode.Decompiler.CSharp
protected internal override TranslatedExpression VisitSwitchInstruction(SwitchInstruction inst, TranslationContext context)
{
TranslatedExpression value;
IType type;
if (inst.Value is StringToInt strToInt)
{
value = Translate(strToInt.Argument)
@ -3650,11 +3651,13 @@ namespace ICSharpCode.Decompiler.CSharp @@ -3650,11 +3651,13 @@ namespace ICSharpCode.Decompiler.CSharp
this,
allowImplicitConversion: false // switch-expression does not support implicit conversions
);
type = compilation.FindType(KnownTypeCode.String);
}
else
{
strToInt = null;
value = Translate(inst.Value);
type = value.Type;
}
IL.SwitchSection defaultSection = inst.GetDefaultSection();
@ -3683,7 +3686,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -3683,7 +3686,7 @@ namespace ICSharpCode.Decompiler.CSharp
else
{
long val = section.Labels.Values.Single();
var rr = statementBuilder.CreateTypedCaseLabel(val, value.Type, strToInt?.Map).Single();
var rr = statementBuilder.CreateTypedCaseLabel(val, type, strToInt?.Map).Single();
ses.Pattern = astBuilder.ConvertConstantValue(rr);
}
ses.Body = TranslateSectionBody(section);

9
ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

@ -144,12 +144,14 @@ namespace ICSharpCode.Decompiler.CSharp @@ -144,12 +144,14 @@ namespace ICSharpCode.Decompiler.CSharp
// unpack nullable type, if necessary:
// we need to do this in all cases, because there are nullable bools and enum types as well.
type = NullableType.GetUnderlyingType(type);
if (type.IsKnownType(KnownTypeCode.Boolean))
{
value = i != 0;
}
else if (type.IsKnownType(KnownTypeCode.String) && map != null)
else if (map != null)
{
Debug.Assert(type.IsKnownType(KnownTypeCode.String));
var keys = map.Where(entry => entry.Value == i).Select(entry => entry.Key);
foreach (var key in keys)
yield return new ConstantResolveResult(type, key);
@ -196,6 +198,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -196,6 +198,7 @@ namespace ICSharpCode.Decompiler.CSharp
caseLabelMapping = new Dictionary<Block, ConstantResolveResult>();
TranslatedExpression value;
IType type;
if (inst.Value is StringToInt strToInt)
{
value = exprBuilder.Translate(strToInt.Argument)
@ -204,11 +207,13 @@ namespace ICSharpCode.Decompiler.CSharp @@ -204,11 +207,13 @@ namespace ICSharpCode.Decompiler.CSharp
exprBuilder,
allowImplicitConversion: true
);
type = exprBuilder.compilation.FindType(KnownTypeCode.String);
}
else
{
strToInt = null;
value = exprBuilder.Translate(inst.Value);
type = value.Type;
}
IL.SwitchSection defaultSection = inst.GetDefaultSection();
@ -229,7 +234,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -229,7 +234,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
else
{
var values = section.Labels.Values.SelectMany(i => CreateTypedCaseLabel(i, value.Type, strToInt?.Map)).ToArray();
var values = section.Labels.Values.SelectMany(i => CreateTypedCaseLabel(i, type, strToInt?.Map)).ToArray();
if (section.HasNullLabel)
{
astSection.CaseLabels.Add(new CaseLabel(new NullReferenceExpression()));

Loading…
Cancel
Save