diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs index da5547d19..118e2a144 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs @@ -23,6 +23,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { public class TypeAnalysisTests { + private class @_ + { + } + private byte[] byteArray; public byte SubtractFrom256(byte b) @@ -123,6 +127,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { Console.WriteLine(o is Random); Console.WriteLine(!(o is Random)); + // If we didn't escape the '_' identifier here, this would look like a discard pattern + Console.WriteLine(o is @_); } public byte[] CreateArrayWithInt(int length) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.il index c782d8855..a6c1cab18 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.il @@ -32,6 +32,21 @@ .class public auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.TypeAnalysisTests extends [mscorlib]System.Object { + .class auto ansi nested private beforefieldinit _ + extends [mscorlib]System.Object + { + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ret + } // end of method _::.ctor + + } // end of class _ + .field private uint8[] byteArray .method public hidebysig instance uint8 SubtractFrom256(uint8 b) cil managed @@ -392,7 +407,7 @@ .method public hidebysig instance void OperatorIs(object o) cil managed { - // Code size 35 (0x23) + // Code size 50 (0x32) .maxstack 8 IL_0000: nop IL_0001: ldarg.1 @@ -409,7 +424,13 @@ IL_001a: ceq IL_001c: call void [mscorlib]System.Console::WriteLine(bool) IL_0021: nop - IL_0022: ret + IL_0022: ldarg.1 + IL_0023: isinst ICSharpCode.Decompiler.Tests.TestCases.Pretty.TypeAnalysisTests/_ + IL_0028: ldnull + IL_0029: cgt.un + IL_002b: call void [mscorlib]System.Console::WriteLine(bool) + IL_0030: nop + IL_0031: ret } // end of method TypeAnalysisTests::OperatorIs .method public hidebysig instance uint8[] diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.opt.il index dd4e9ea13..c6d2a75a3 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.opt.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.opt.il @@ -32,6 +32,21 @@ .class public auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.TypeAnalysisTests extends [mscorlib]System.Object { + .class auto ansi nested private beforefieldinit _ + extends [mscorlib]System.Object + { + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ret + } // end of method _::.ctor + + } // end of class _ + .field private uint8[] byteArray .method public hidebysig instance uint8 SubtractFrom256(uint8 b) cil managed @@ -278,7 +293,7 @@ .method public hidebysig instance void OperatorIs(object o) cil managed { - // Code size 32 (0x20) + // Code size 46 (0x2e) .maxstack 8 IL_0000: ldarg.1 IL_0001: isinst [mscorlib]System.Random @@ -292,7 +307,12 @@ IL_0017: ldc.i4.0 IL_0018: ceq IL_001a: call void [mscorlib]System.Console::WriteLine(bool) - IL_001f: ret + IL_001f: ldarg.1 + IL_0020: isinst ICSharpCode.Decompiler.Tests.TestCases.Pretty.TypeAnalysisTests/_ + IL_0025: ldnull + IL_0026: cgt.un + IL_0028: call void [mscorlib]System.Console::WriteLine(bool) + IL_002d: ret } // end of method TypeAnalysisTests::OperatorIs .method public hidebysig instance uint8[] diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.opt.roslyn.il index 7d78eaa65..91e86af1a 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.opt.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.opt.roslyn.il @@ -36,6 +36,21 @@ .class public auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.TypeAnalysisTests extends [mscorlib]System.Object { + .class auto ansi nested private beforefieldinit _ + extends [mscorlib]System.Object + { + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ret + } // end of method _::.ctor + + } // end of class _ + .field private uint8[] byteArray .method public hidebysig instance uint8 SubtractFrom256(uint8 b) cil managed @@ -282,7 +297,7 @@ .method public hidebysig instance void OperatorIs(object o) cil managed { - // Code size 32 (0x20) + // Code size 46 (0x2e) .maxstack 8 IL_0000: ldarg.1 IL_0001: isinst [mscorlib]System.Random @@ -296,7 +311,12 @@ IL_0017: ldc.i4.0 IL_0018: ceq IL_001a: call void [mscorlib]System.Console::WriteLine(bool) - IL_001f: ret + IL_001f: ldarg.1 + IL_0020: isinst ICSharpCode.Decompiler.Tests.TestCases.Pretty.TypeAnalysisTests/_ + IL_0025: ldnull + IL_0026: cgt.un + IL_0028: call void [mscorlib]System.Console::WriteLine(bool) + IL_002d: ret } // end of method TypeAnalysisTests::OperatorIs .method public hidebysig instance uint8[] diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.roslyn.il index ab3f048fd..b5f24f5ce 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.roslyn.il @@ -36,6 +36,22 @@ .class public auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.TypeAnalysisTests extends [mscorlib]System.Object { + .class auto ansi nested private beforefieldinit _ + extends [mscorlib]System.Object + { + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method _::.ctor + + } // end of class _ + .field private uint8[] byteArray .method public hidebysig instance uint8 SubtractFrom256(uint8 b) cil managed @@ -393,7 +409,7 @@ .method public hidebysig instance void OperatorIs(object o) cil managed { - // Code size 35 (0x23) + // Code size 50 (0x32) .maxstack 8 IL_0000: nop IL_0001: ldarg.1 @@ -410,7 +426,13 @@ IL_001a: ceq IL_001c: call void [mscorlib]System.Console::WriteLine(bool) IL_0021: nop - IL_0022: ret + IL_0022: ldarg.1 + IL_0023: isinst ICSharpCode.Decompiler.Tests.TestCases.Pretty.TypeAnalysisTests/_ + IL_0028: ldnull + IL_0029: cgt.un + IL_002b: call void [mscorlib]System.Console::WriteLine(bool) + IL_0030: nop + IL_0031: ret } // end of method TypeAnalysisTests::OperatorIs .method public hidebysig instance uint8[] diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs index 9992fa33e..21acadc9a 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs @@ -395,9 +395,13 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor public static bool IsKeyword(string identifier, AstNode context) { // only 2-10 char lower-case identifiers can be keywords - if (identifier.Length > maxKeywordLength || identifier.Length < 2 || identifier[0] < 'a') { + if (identifier.Length > maxKeywordLength || identifier.Length == 0) { return false; } + if (identifier[0] < 'a') { + // we escape _ as identifier to avoid ambiguities with discard patterns + return identifier == "_"; + } if (unconditionalKeywords.Contains(identifier)) { return true; }