Browse Source

Fix #1323: NRE in DetectBestEnumValueDisplayMode; emit error message, if enum field definition has no constant value.

pull/1347/head
Siegfried Pammer 7 years ago
parent
commit
6c193ac50e
  1. 2
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  2. 6
      ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs
  3. 22
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

2
ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj

@ -71,12 +71,14 @@
<Compile Include="TestCases\Correctness\LocalFunctions.cs" /> <Compile Include="TestCases\Correctness\LocalFunctions.cs" />
<Compile Include="TestCases\Correctness\RefLocalsAndReturns.cs" /> <Compile Include="TestCases\Correctness\RefLocalsAndReturns.cs" />
<Compile Include="TestCases\ILPretty\Issue1256.cs" /> <Compile Include="TestCases\ILPretty\Issue1256.cs" />
<Compile Include="TestCases\ILPretty\Issue1323.cs" />
<Compile Include="TestCases\Pretty\OptionalArguments.cs" /> <Compile Include="TestCases\Pretty\OptionalArguments.cs" />
<Compile Include="TestCases\Pretty\CustomShortCircuitOperators.cs" /> <Compile Include="TestCases\Pretty\CustomShortCircuitOperators.cs" />
<Compile Include="TestCases\Pretty\ReduceNesting.cs" /> <Compile Include="TestCases\Pretty\ReduceNesting.cs" />
<Compile Include="TestCases\Pretty\TypeTests.cs" /> <Compile Include="TestCases\Pretty\TypeTests.cs" />
<Compile Include="TestCases\Pretty\YieldReturn.cs" /> <Compile Include="TestCases\Pretty\YieldReturn.cs" />
<None Include="TestCases\ILPretty\Issue1256.il" /> <None Include="TestCases\ILPretty\Issue1256.il" />
<None Include="TestCases\ILPretty\Issue1323.il" />
<None Include="TestCases\Ugly\NoDecimalConstants.Expected.cs" /> <None Include="TestCases\Ugly\NoDecimalConstants.Expected.cs" />
<Compile Include="TestCases\Ugly\NoDecimalConstants.cs" /> <Compile Include="TestCases\Ugly\NoDecimalConstants.cs" />
<None Include="TestCases\Disassembler\Pretty\SecurityDeclarations.il" /> <None Include="TestCases\Disassembler\Pretty\SecurityDeclarations.il" />

6
ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs

@ -124,6 +124,12 @@ namespace ICSharpCode.Decompiler.Tests
Run(); Run();
} }
[Test]
public void Issue1323()
{
Run();
}
[Test] [Test]
public void FSharpLoops_Debug() public void FSharpLoops_Debug()
{ {

22
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -984,6 +984,9 @@ namespace ICSharpCode.Decompiler.CSharp
case EnumValueDisplayMode.None: case EnumValueDisplayMode.None:
foreach (var enumMember in typeDecl.Members.OfType<EnumMemberDeclaration>()) { foreach (var enumMember in typeDecl.Members.OfType<EnumMemberDeclaration>()) {
enumMember.Initializer = null; enumMember.Initializer = null;
if (enumMember.GetSymbol() is IField f && f.ConstantValue == null) {
typeDecl.InsertChildBefore(enumMember, new Comment(" error: enumerator has no value"), Roles.Comment);
}
} }
break; break;
case EnumValueDisplayMode.All: case EnumValueDisplayMode.All:
@ -1010,7 +1013,7 @@ namespace ICSharpCode.Decompiler.CSharp
bool first = true; bool first = true;
long firstValue = 0, previousValue = 0; long firstValue = 0, previousValue = 0;
foreach (var field in typeDef.Fields) { foreach (var field in typeDef.Fields) {
if (MemberIsHidden(module, field.MetadataToken, settings)) continue; if (MemberIsHidden(module, field.MetadataToken, settings) || field.ConstantValue == null) continue;
long currentValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.ConstantValue, false); long currentValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.ConstantValue, false);
if (first) { if (first) {
firstValue = currentValue; firstValue = currentValue;
@ -1237,15 +1240,16 @@ namespace ICSharpCode.Decompiler.CSharp
{ {
Debug.Assert(decompilationContext.CurrentMember == field); Debug.Assert(decompilationContext.CurrentMember == field);
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext); var typeSystemAstBuilder = CreateAstBuilder(decompilationContext);
if (decompilationContext.CurrentTypeDefinition.Kind == TypeKind.Enum && field.ConstantValue != null) { if (decompilationContext.CurrentTypeDefinition.Kind == TypeKind.Enum) {
var enumDec = new EnumMemberDeclaration { Name = field.Name }; var enumDec = new EnumMemberDeclaration { Name = field.Name };
long initValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.ConstantValue, false); if (field.ConstantValue != null) {
enumDec.Initializer = typeSystemAstBuilder.ConvertConstantValue(decompilationContext.CurrentTypeDefinition.EnumUnderlyingType, field.ConstantValue); long initValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.ConstantValue, false);
if (enumDec.Initializer is PrimitiveExpression primitive enumDec.Initializer = typeSystemAstBuilder.ConvertConstantValue(decompilationContext.CurrentTypeDefinition.EnumUnderlyingType, field.ConstantValue);
&& initValue >= 0 && (decompilationContext.CurrentTypeDefinition.HasAttribute(KnownAttribute.Flags) if (enumDec.Initializer is PrimitiveExpression primitive
|| (initValue > 9 && (unchecked(initValue & (initValue - 1)) == 0 || unchecked(initValue & (initValue + 1)) == 0)))) && initValue >= 0 && (decompilationContext.CurrentTypeDefinition.HasAttribute(KnownAttribute.Flags)
{ || (initValue > 9 && (unchecked(initValue & (initValue - 1)) == 0 || unchecked(initValue & (initValue + 1)) == 0)))) {
primitive.SetValue(initValue, $"0x{initValue:X}"); primitive.SetValue(initValue, $"0x{initValue:X}");
}
} }
enumDec.Attributes.AddRange(field.GetAttributes().Select(a => new AttributeSection(typeSystemAstBuilder.ConvertAttribute(a)))); enumDec.Attributes.AddRange(field.GetAttributes().Select(a => new AttributeSection(typeSystemAstBuilder.ConvertAttribute(a))));
enumDec.AddAnnotation(new MemberResolveResult(null, field)); enumDec.AddAnnotation(new MemberResolveResult(null, field));

Loading…
Cancel
Save