diff --git a/DecompilerNuGetDemos.workbook b/DecompilerNuGetDemos.workbook
index 49df888ea..a381ee75b 100644
--- a/DecompilerNuGetDemos.workbook
+++ b/DecompilerNuGetDemos.workbook
@@ -6,7 +6,7 @@ platforms:
- DotNetCore
packages:
- id: ICSharpCode.Decompiler
- version: 3.0.0.3246-beta1
+ version: 3.0.0.3287-beta2
---
Setup: load the references required to work with the decompiler
diff --git a/ICSharpCode.Decompiler.Console/ICSharpCode.Decompiler.Console.csproj b/ICSharpCode.Decompiler.Console/ICSharpCode.Decompiler.Console.csproj
index eb6e687e9..29b6d2dbc 100644
--- a/ICSharpCode.Decompiler.Console/ICSharpCode.Decompiler.Console.csproj
+++ b/ICSharpCode.Decompiler.Console/ICSharpCode.Decompiler.Console.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/ICSharpCode.Decompiler.PowerShell/Demo.ps1 b/ICSharpCode.Decompiler.PowerShell/Demo.ps1
index cd7482c52..36674d23c 100644
--- a/ICSharpCode.Decompiler.PowerShell/Demo.ps1
+++ b/ICSharpCode.Decompiler.PowerShell/Demo.ps1
@@ -1,5 +1,13 @@
-Import-Module .\bin\Debug\netstandard2.0\ICSharpCode.Decompiler.PSCore.dll
-$decompiler = Get-Decompiler .\bin\Debug\netstandard2.0\ICSharpCode.Decompiler.PSCore.dll
+$basePath = $PSScriptRoot
+if ([string]::IsNullOrEmpty($basePath))
+{
+ $basePath = Split-Path -parent $psISE.CurrentFile.Fullpath
+}
+
+$modulePath = $basePath + '\bin\Debug\netstandard2.0\ICSharpCode.Decompiler.Powershell.dll'
+
+Import-Module $modulePath
+$decompiler = Get-Decompiler $modulePath
$classes = Get-DecompiledTypes $decompiler -Types class
$classes.Count
@@ -10,6 +18,6 @@ foreach ($c in $classes)
}
-Get-DecompiledSource $decompiler -TypeName ICSharpCode.Decompiler.PSCore.GetDecompilerCmdlet
+Get-DecompiledSource $decompiler -TypeName ICSharpCode.Decompiler.PowerShell.GetDecompilerCmdlet
Get-DecompiledProject $decompiler -OutputPath .\decomptest
\ No newline at end of file
diff --git a/ICSharpCode.Decompiler.PowerShell/ICSharpCode.Decompiler.PowerShell.csproj b/ICSharpCode.Decompiler.PowerShell/ICSharpCode.Decompiler.PowerShell.csproj
index 673d1ecc4..4e3dce1bf 100644
--- a/ICSharpCode.Decompiler.PowerShell/ICSharpCode.Decompiler.PowerShell.csproj
+++ b/ICSharpCode.Decompiler.PowerShell/ICSharpCode.Decompiler.PowerShell.csproj
@@ -8,7 +8,7 @@
-
+
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Loops.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Loops.cs
index adc0c6660..96a3ab4e2 100644
--- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Loops.cs
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Loops.cs
@@ -82,6 +82,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Console.WriteLine(FirstOrDefault(new List { 1, 2, 3, 4, 5 }));
Console.WriteLine(NoForeachDueToMultipleCurrentAccess(new List { 1, 2, 3, 4, 5 }));
Console.WriteLine(NoForeachCallWithSideEffect(new CustomClassEnumeratorWithIDisposable()));
+ LoopWithGotoRepeat();
}
public static void ForWithMultipleVariables()
@@ -222,5 +223,32 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
return CallWithSideEffect();
}
}
+
+ static bool GetBool(string text)
+ {
+ return false;
+ }
+
+ // https://github.com/icsharpcode/ILSpy/issues/915
+ static void LoopWithGotoRepeat()
+ {
+ Console.WriteLine("LoopWithGotoRepeat:");
+ try {
+ REPEAT:
+ Console.WriteLine("after repeat label");
+ while (GetBool("Loop condition")) {
+ if (GetBool("if1")) {
+ if (GetBool("if3")) {
+ goto REPEAT;
+ }
+ break;
+ }
+ }
+ Console.WriteLine("after loop");
+ } finally {
+ Console.WriteLine("finally");
+ }
+ Console.WriteLine("after finally");
+ }
}
}
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/StackTypes.il b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/StackTypes.il
index 338a9cbce..2c8e3383c 100644
--- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/StackTypes.il
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/StackTypes.il
@@ -21,7 +21,7 @@ extends [mscorlib]System.Object
.entrypoint
call void Program::InlineAssignByte()
- //call void Program::Int32OrNativeTests()
+ call void Program::Int32OrNativeTests()
ret
} // end of method Main
@@ -48,7 +48,6 @@ pointless:
ret
}
- /*
.method public static void Int32OrNativeTests()
{
ldstr "Int32OrNative(0x7fffffff, false) = {0}"
@@ -79,6 +78,7 @@ pointless:
box native int
call void [mscorlib]System.Console::WriteLine(string, object)
+ /*
ldstr "Int32OrNativeLoopStyle(0x7fffffff):"
call void [mscorlib]System.Console::WriteLine(string)
ldc.i4 0x7fffffff
@@ -100,6 +100,7 @@ pointless:
call native int Program::Int32OrNativeDeadCode(int32)
box native int
call void [mscorlib]System.Console::WriteLine(string, object)
+ */
ldc.i4 0x7fffffff
call void Program::RunInt32OrNativeMultiUse(int32)
@@ -115,6 +116,26 @@ pointless:
use_i4:
ldarg.0
br after_if
+ use_native_int:
+ ldarg.0
+ conv.u
+ br after_if
+ after_if:
+ ldc.i4.1
+ add
+ ret
+ }
+
+ /*
+ .method public static native int Int32OrNativeReordered(int32 val, bool use_native)
+ {
+ // The spec is ambiguous whether the addition will be in 32-bits or native size.
+ // The microsoft runtime picks native size.
+ ldarg.1
+ brtrue use_native_int
+ use_i4:
+ ldarg.0
+ br after_if
after_if:
ldc.i4.1
add
@@ -124,9 +145,11 @@ pointless:
conv.u
br after_if
}
-
+
.method public static void Int32OrNativeLoopStyle(int32 val)
{
+ // The spec is ambiguous whether the addition will be in 32-bits or native size.
+ // The microsoft runtime picks native size.
.locals init (
int32 i
)
@@ -149,6 +172,8 @@ pointless:
.method public static native int Int32OrNativeDeadCode(int32 val)
{
+ // The spec is ambiguous whether the addition will be in 32-bits or native size.
+ // The microsoft runtime picks 32-bits.
use_i4:
ldarg.0
br after_if
@@ -161,6 +186,7 @@ pointless:
conv.u
br after_if
}
+ */
.method public static void RunInt32OrNativeMultiUse(int32 val)
{
@@ -229,8 +255,7 @@ pointless:
add
ret
}
- */
-
+
.method public static void Print(native int val)
{
ldarg.0
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs
index 480228762..9e4eef012 100644
--- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs
@@ -327,6 +327,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
SimpleStruct* ptr = stackalloc SimpleStruct[checked(count * 2)];
SimpleStruct* ptr2 = stackalloc SimpleStruct[10];
+ ptr->X = count;
+ ptr[1].X = ptr->X;
+ for (int i = 2; i < 10; i++) {
+ ptr[i].X = count;
+ }
return this.UsePointer(&ptr->Y);
}
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.il
index e4d7a0692..65de1dfd2 100644
--- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.il
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.il
@@ -10,7 +10,7 @@
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
-.assembly veti52ie
+.assembly '5mgf1rnb'
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
@@ -20,15 +20,15 @@
.hash algorithm 0x00008004
.ver 0:0:0:0
}
-.module veti52ie.dll
-// MVID: {F873CF77-738D-4A61-B0C6-96B9F5621119}
+.module '5mgf1rnb.dll'
+// MVID: {C39B0AE8-69C3-4207-B912-FCEE701C71E8}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
-// Image base: 0x028F0000
+// Image base: 0x00C60000
// =============== CLASS MEMBERS DECLARATION ===================
@@ -1238,11 +1238,13 @@
.method public hidebysig instance string
StackAllocStruct(int32 count) cil managed
{
- // Code size 46 (0x2e)
- .maxstack 2
+ // Code size 110 (0x6e)
+ .maxstack 3
.locals init (valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct* V_0,
valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct* V_1,
- string V_2)
+ int32 V_2,
+ string V_3,
+ bool V_4)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldc.i4.2
@@ -1258,16 +1260,50 @@
IL_0018: mul.ovf.un
IL_0019: localloc
IL_001b: stloc.1
- IL_001c: ldarg.0
- IL_001d: ldloc.0
- IL_001e: ldflda float64 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::Y
- IL_0023: conv.u
- IL_0024: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UsePointer(float64*)
- IL_0029: stloc.2
- IL_002a: br.s IL_002c
-
- IL_002c: ldloc.2
- IL_002d: ret
+ IL_001c: ldloc.0
+ IL_001d: ldarg.1
+ IL_001e: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::X
+ IL_0023: ldloc.0
+ IL_0024: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
+ IL_002a: add
+ IL_002b: ldloc.0
+ IL_002c: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::X
+ IL_0031: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::X
+ IL_0036: ldc.i4.2
+ IL_0037: stloc.2
+ IL_0038: br.s IL_0051
+
+ IL_003a: nop
+ IL_003b: ldloc.0
+ IL_003c: ldloc.2
+ IL_003d: conv.i
+ IL_003e: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
+ IL_0044: mul
+ IL_0045: add
+ IL_0046: ldarg.1
+ IL_0047: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::X
+ IL_004c: nop
+ IL_004d: ldloc.2
+ IL_004e: ldc.i4.1
+ IL_004f: add
+ IL_0050: stloc.2
+ IL_0051: ldloc.2
+ IL_0052: ldc.i4.s 10
+ IL_0054: clt
+ IL_0056: stloc.s V_4
+ IL_0058: ldloc.s V_4
+ IL_005a: brtrue.s IL_003a
+
+ IL_005c: ldarg.0
+ IL_005d: ldloc.0
+ IL_005e: ldflda float64 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::Y
+ IL_0063: conv.u
+ IL_0064: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UsePointer(float64*)
+ IL_0069: stloc.3
+ IL_006a: br.s IL_006c
+
+ IL_006c: ldloc.3
+ IL_006d: ret
} // end of method UnsafeCode::StackAllocStruct
.method family hidebysig virtual instance void
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.opt.il
index 96247420b..1a0b0ea04 100644
--- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.opt.il
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.opt.il
@@ -10,7 +10,7 @@
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
-.assembly '24yl5hoc'
+.assembly av3nix0s
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
@@ -20,15 +20,15 @@
.hash algorithm 0x00008004
.ver 0:0:0:0
}
-.module '24yl5hoc.dll'
-// MVID: {73FF4D49-1CDC-4675-A00D-0D382845C323}
+.module av3nix0s.dll
+// MVID: {3E5B8427-2816-45EA-9E7A-139AA9452535}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
-// Image base: 0x013A0000
+// Image base: 0x025C0000
// =============== CLASS MEMBERS DECLARATION ===================
@@ -986,9 +986,10 @@
.method public hidebysig instance string
StackAllocStruct(int32 count) cil managed
{
- // Code size 41 (0x29)
- .maxstack 2
- .locals init (valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct* V_0)
+ // Code size 97 (0x61)
+ .maxstack 3
+ .locals init (valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct* V_0,
+ int32 V_1)
IL_0000: ldarg.1
IL_0001: ldc.i4.2
IL_0002: mul.ovf
@@ -1003,12 +1004,41 @@
IL_0017: mul.ovf.un
IL_0018: localloc
IL_001a: pop
- IL_001b: ldarg.0
- IL_001c: ldloc.0
- IL_001d: ldflda float64 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::Y
- IL_0022: conv.u
- IL_0023: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UsePointer(float64*)
- IL_0028: ret
+ IL_001b: ldloc.0
+ IL_001c: ldarg.1
+ IL_001d: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::X
+ IL_0022: ldloc.0
+ IL_0023: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
+ IL_0029: add
+ IL_002a: ldloc.0
+ IL_002b: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::X
+ IL_0030: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::X
+ IL_0035: ldc.i4.2
+ IL_0036: stloc.1
+ IL_0037: br.s IL_004e
+
+ IL_0039: ldloc.0
+ IL_003a: ldloc.1
+ IL_003b: conv.i
+ IL_003c: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
+ IL_0042: mul
+ IL_0043: add
+ IL_0044: ldarg.1
+ IL_0045: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::X
+ IL_004a: ldloc.1
+ IL_004b: ldc.i4.1
+ IL_004c: add
+ IL_004d: stloc.1
+ IL_004e: ldloc.1
+ IL_004f: ldc.i4.s 10
+ IL_0051: blt.s IL_0039
+
+ IL_0053: ldarg.0
+ IL_0054: ldloc.0
+ IL_0055: ldflda float64 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::Y
+ IL_005a: conv.u
+ IL_005b: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UsePointer(float64*)
+ IL_0060: ret
} // end of method UnsafeCode::StackAllocStruct
.method family hidebysig virtual instance void
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.opt.roslyn.il
index a4831768c..19c2a8b81 100644
--- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.opt.roslyn.il
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.opt.roslyn.il
@@ -25,14 +25,14 @@
.ver 0:0:0:0
}
.module UnsafeCode.dll
-// MVID: {DD1630B5-221C-4D3A-8171-7BFFD65CA0F2}
+// MVID: {6E613246-08C3-4B77-B500-576D8782513A}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
-// Image base: 0x01320000
+// Image base: 0x030D0000
// =============== CLASS MEMBERS DECLARATION ===================
@@ -991,9 +991,10 @@
.method public hidebysig instance string
StackAllocStruct(int32 count) cil managed
{
- // Code size 41 (0x29)
- .maxstack 2
- .locals init (valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct* V_0)
+ // Code size 97 (0x61)
+ .maxstack 3
+ .locals init (valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct* V_0,
+ int32 V_1)
IL_0000: ldarg.1
IL_0001: ldc.i4.2
IL_0002: mul.ovf
@@ -1008,12 +1009,41 @@
IL_0017: mul.ovf.un
IL_0018: localloc
IL_001a: pop
- IL_001b: ldarg.0
- IL_001c: ldloc.0
- IL_001d: ldflda float64 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::Y
- IL_0022: conv.u
- IL_0023: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UsePointer(float64*)
- IL_0028: ret
+ IL_001b: ldloc.0
+ IL_001c: ldarg.1
+ IL_001d: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::X
+ IL_0022: ldloc.0
+ IL_0023: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
+ IL_0029: add
+ IL_002a: ldloc.0
+ IL_002b: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::X
+ IL_0030: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::X
+ IL_0035: ldc.i4.2
+ IL_0036: stloc.1
+ IL_0037: br.s IL_004e
+
+ IL_0039: ldloc.0
+ IL_003a: ldloc.1
+ IL_003b: conv.i
+ IL_003c: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
+ IL_0042: mul
+ IL_0043: add
+ IL_0044: ldarg.1
+ IL_0045: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::X
+ IL_004a: ldloc.1
+ IL_004b: ldc.i4.1
+ IL_004c: add
+ IL_004d: stloc.1
+ IL_004e: ldloc.1
+ IL_004f: ldc.i4.s 10
+ IL_0051: blt.s IL_0039
+
+ IL_0053: ldarg.0
+ IL_0054: ldloc.0
+ IL_0055: ldflda float64 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::Y
+ IL_005a: conv.u
+ IL_005b: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UsePointer(float64*)
+ IL_0060: ret
} // end of method UnsafeCode::StackAllocStruct
.method family hidebysig virtual instance void
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.roslyn.il
index 8cee9896b..d1f786100 100644
--- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.roslyn.il
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.roslyn.il
@@ -25,14 +25,14 @@
.ver 0:0:0:0
}
.module UnsafeCode.dll
-// MVID: {34A4C476-B60D-4D44-9CF4-288026720E1B}
+// MVID: {E02FB293-0E44-4F82-B549-8BAB6E8A9750}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
-// Image base: 0x00AC0000
+// Image base: 0x006B0000
// =============== CLASS MEMBERS DECLARATION ===================
@@ -1242,11 +1242,13 @@
.method public hidebysig instance string
StackAllocStruct(int32 count) cil managed
{
- // Code size 46 (0x2e)
- .maxstack 2
+ // Code size 110 (0x6e)
+ .maxstack 3
.locals init (valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct* V_0,
valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct* V_1,
- string V_2)
+ int32 V_2,
+ bool V_3,
+ string V_4)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldc.i4.2
@@ -1262,16 +1264,50 @@
IL_0018: mul.ovf.un
IL_0019: localloc
IL_001b: stloc.1
- IL_001c: ldarg.0
- IL_001d: ldloc.0
- IL_001e: ldflda float64 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::Y
- IL_0023: conv.u
- IL_0024: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UsePointer(float64*)
- IL_0029: stloc.2
- IL_002a: br.s IL_002c
-
- IL_002c: ldloc.2
- IL_002d: ret
+ IL_001c: ldloc.0
+ IL_001d: ldarg.1
+ IL_001e: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::X
+ IL_0023: ldloc.0
+ IL_0024: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
+ IL_002a: add
+ IL_002b: ldloc.0
+ IL_002c: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::X
+ IL_0031: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::X
+ IL_0036: ldc.i4.2
+ IL_0037: stloc.2
+ IL_0038: br.s IL_0051
+
+ IL_003a: nop
+ IL_003b: ldloc.0
+ IL_003c: ldloc.2
+ IL_003d: conv.i
+ IL_003e: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
+ IL_0044: mul
+ IL_0045: add
+ IL_0046: ldarg.1
+ IL_0047: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::X
+ IL_004c: nop
+ IL_004d: ldloc.2
+ IL_004e: ldc.i4.1
+ IL_004f: add
+ IL_0050: stloc.2
+ IL_0051: ldloc.2
+ IL_0052: ldc.i4.s 10
+ IL_0054: clt
+ IL_0056: stloc.3
+ IL_0057: ldloc.3
+ IL_0058: brtrue.s IL_003a
+
+ IL_005a: ldarg.0
+ IL_005b: ldloc.0
+ IL_005c: ldflda float64 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::Y
+ IL_0061: conv.u
+ IL_0062: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UsePointer(float64*)
+ IL_0067: stloc.s V_4
+ IL_0069: br.s IL_006b
+
+ IL_006b: ldloc.s V_4
+ IL_006d: ret
} // end of method UnsafeCode::StackAllocStruct
.method family hidebysig virtual instance void
diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
index 73f564d5c..da07fc688 100644
--- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
+++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
@@ -810,6 +810,10 @@ namespace ICSharpCode.Decompiler.CSharp
}
return Translate(countOffsetInst);
}
+ } else if (byteOffsetInst.UnwrapConv(ConversionKind.SignExtend) is SizeOf sizeOf && sizeOf.Type.Equals(pointerType.ElementType)) {
+ return new PrimitiveExpression(1)
+ .WithILInstruction(byteOffsetInst)
+ .WithRR(new ConstantResolveResult(compilation.FindType(KnownTypeCode.Int32), 1));
} else if (byteOffsetInst.MatchLdcI(out long val)) {
// If the offset is a constant, it's possible that the compiler
// constant-folded the multiplication.
@@ -1540,9 +1544,14 @@ namespace ICSharpCode.Decompiler.CSharp
if (!TypeUtils.IsCompatibleTypeForMemoryAccess(target.Type, inst.Type)) {
target = target.ConvertTo(new PointerType(inst.Type), this);
}
- result = new UnaryOperatorExpression(UnaryOperatorType.Dereference, target.Expression)
- .WithoutILInstruction()
- .WithRR(new ResolveResult(((TypeWithElementType)target.Type).ElementType));
+ if (target.Expression is UnaryOperatorExpression uoe && uoe.Operator == UnaryOperatorType.AddressOf) {
+ // *&ptr -> ptr
+ result = target.UnwrapChild(uoe.Expression);
+ } else {
+ result = new UnaryOperatorExpression(UnaryOperatorType.Dereference, target.Expression)
+ .WithoutILInstruction()
+ .WithRR(new ResolveResult(((TypeWithElementType)target.Type).ElementType));
+ }
}
var value = Translate(inst.Value, typeHint: result.Type);
return Assignment(result, value).WithILInstruction(inst);
diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUnsafeModifier.cs b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUnsafeModifier.cs
index 10d16c823..f5fa6f30e 100644
--- a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUnsafeModifier.cs
+++ b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUnsafeModifier.cs
@@ -104,6 +104,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
pre.MemberName = memberReferenceExpression.MemberName;
memberReferenceExpression.TypeArguments.MoveTo(pre.TypeArguments);
pre.CopyAnnotationsFrom(uoe);
+ pre.RemoveAnnotations(); // only copy the ResolveResult from the MRE
pre.CopyAnnotationsFrom(memberReferenceExpression);
memberReferenceExpression.ReplaceWith(pre);
}
diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.nuspec.template b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.nuspec.template
index c4c9f57bd..7a473cdd3 100644
--- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.nuspec.template
+++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.nuspec.template
@@ -17,8 +17,8 @@
-
-
+
+
diff --git a/ICSharpCode.Decompiler/IL/BlockBuilder.cs b/ICSharpCode.Decompiler/IL/BlockBuilder.cs
index 9e23a194a..ff2b80818 100644
--- a/ICSharpCode.Decompiler/IL/BlockBuilder.cs
+++ b/ICSharpCode.Decompiler/IL/BlockBuilder.cs
@@ -117,7 +117,7 @@ namespace ICSharpCode.Decompiler.IL
foreach (var inst in instructions) {
cancellationToken.ThrowIfCancellationRequested();
int start = inst.ILRange.Start;
- if (currentBlock == null || incomingBranches[start]) {
+ if (currentBlock == null || (incomingBranches[start] && !IsStackAdjustment(inst))) {
// Finish up the previous block
FinalizeCurrentBlock(start, fallthrough: true);
// Leave nested containers if necessary
@@ -158,6 +158,11 @@ namespace ICSharpCode.Decompiler.IL
ConnectBranches(mainContainer, cancellationToken);
}
+ static bool IsStackAdjustment(ILInstruction inst)
+ {
+ return inst is StLoc stloc && stloc.IsStackAdjustment;
+ }
+
private void FinalizeCurrentBlock(int currentILOffset, bool fallthrough)
{
if (currentBlock == null)
diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs b/ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs
index a6b9db9ba..87719cb20 100644
--- a/ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs
+++ b/ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs
@@ -93,6 +93,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
var headBlock = (Block)h.UserData;
context.Step($"Construct loop with head {headBlock.Label}", headBlock);
// loop now is the union of all natural loops with loop head h.
+
+ // Ensure any block included into nested loops is also considered part of this loop:
+ IncludeNestedContainers(loop);
// Try to extend the loop to reduce the number of exit points:
ExtendLoop(h, loop, out var exitPoint);
@@ -109,24 +112,46 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
}
///
- /// Recurse into the dominator tree and find back edges/natural loops.
+ /// For each block in the input loop that is the head of a nested loop or switch,
+ /// include all blocks from the nested container into the loop.
+ ///
+ /// This ensures that all blocks that were included into inner loops are also
+ /// included into the outer loop, thus keeping our loops well-nested.
///
///
+ /// More details for why this is necessary are here:
+ /// https://github.com/icsharpcode/ILSpy/issues/915
///
- /// Preconditions:
- /// * dominance was computed for h
- /// * all blocks in the dominator subtree starting at h are in the same BlockContainer
- /// * the visited flag is set to false
+ /// Pre+Post-Condition: node.Visited iff loop.Contains(node)
///
- void FindLoops(ControlFlowNode h)
+ void IncludeNestedContainers(List loop)
{
- // Recurse into the dominator tree to find other possible loop heads
- foreach (var child in h.DominatorTreeChildren) {
- FindLoops(child);
+ for (int i = 0; i < loop.Count; i++) {
+ IncludeBlock((Block)loop[i].UserData);
}
+ void IncludeBlock(Block block)
+ {
+ if (block.Instructions[0] is BlockContainer nestedContainer) {
+ // Just in case the block has multiple nested containers (e.g. due to loop and switch),
+ // also check the entry point:
+ IncludeBlock(nestedContainer.EntryPoint);
+ // Use normal processing for all non-entry-point blocks
+ // (the entry-point itself doesn't have a CFG node, because it's newly created by this transform)
+ for (int i = 1; i < nestedContainer.Blocks.Count; i++) {
+ var node = context.ControlFlowGraph.GetNode(nestedContainer.Blocks[i]);
+ Debug.Assert(loop[0].Dominates(node));
+ if (!node.Visited) {
+ node.Visited = true;
+ loop.Add(node);
+ // note: this block will be re-visited when the "i < loop.Count"
+ // gets around to the new entry
+ }
+ }
+ }
+ }
}
-
+
#region ExtendLoop
///
/// Given a natural loop, add additional CFG nodes to the loop in order
diff --git a/ICSharpCode.Decompiler/IL/ILReader.cs b/ICSharpCode.Decompiler/IL/ILReader.cs
index 7d13b4e29..1fb82890d 100644
--- a/ICSharpCode.Decompiler/IL/ILReader.cs
+++ b/ICSharpCode.Decompiler/IL/ILReader.cs
@@ -64,6 +64,7 @@ namespace ICSharpCode.Decompiler.IL
Dictionary> stackByOffset;
Dictionary variableByExceptionHandler;
UnionFind unionFind;
+ List<(ILVariable, ILVariable)> stackMismatchPairs;
IEnumerable stackVariables;
void Init(Cil.MethodBody body)
@@ -74,8 +75,9 @@ namespace ICSharpCode.Decompiler.IL
this.debugInfo = body.Method.DebugInformation;
this.currentInstruction = null;
this.nextInstructionIndex = 0;
- this.currentStack = System.Collections.Immutable.ImmutableStack.Empty;
+ this.currentStack = ImmutableStack.Empty;
this.unionFind = new UnionFind();
+ this.stackMismatchPairs = new List<(ILVariable, ILVariable)>();
this.methodReturnStackType = typeSystem.Resolve(body.Method.ReturnType).GetStackType();
InitParameterVariables();
this.localVariables = body.Variables.SelectArray(CreateILVariable);
@@ -84,7 +86,7 @@ namespace ICSharpCode.Decompiler.IL
v.HasInitialValue = true;
}
}
- mainContainer = new BlockContainer(expectedResultType: methodReturnStackType);
+ this.mainContainer = new BlockContainer(expectedResultType: methodReturnStackType);
this.instructionBuilder = new List();
this.isBranchTarget = new BitArray(body.CodeSize);
this.stackByOffset = new Dictionary>();
@@ -186,35 +188,87 @@ namespace ICSharpCode.Decompiler.IL
Warnings.Add(string.Format("IL_{0:x4}: {1}", currentInstruction.Offset, message));
}
- void MergeStacks(ImmutableStack a, ImmutableStack b)
+ ImmutableStack MergeStacks(ImmutableStack a, ImmutableStack b)
{
- var enum1 = a.GetEnumerator();
- var enum2 = b.GetEnumerator();
- bool ok1 = enum1.MoveNext();
- bool ok2 = enum2.MoveNext();
- while (ok1 && ok2) {
- if (enum1.Current.StackType != enum2.Current.StackType) {
- Warn("Incompatible stack types: " + enum1.Current.StackType + " vs " + enum2.Current.StackType);
+ if (CheckStackCompatibleWithoutAdjustments(a, b)) {
+ // We only need to union the input variables, but can
+ // otherwise re-use the existing stack.
+ ImmutableStack output = a;
+ while (!a.IsEmpty && !b.IsEmpty) {
+ Debug.Assert(a.Peek().StackType == b.Peek().StackType);
+ unionFind.Merge(a.Peek(), b.Peek());
+ a = a.Pop();
+ b = b.Pop();
}
- unionFind.Merge(enum1.Current, enum2.Current);
- ok1 = enum1.MoveNext();
- ok2 = enum2.MoveNext();
- }
- if (ok1 || ok2) {
+ return output;
+ } else if (a.Count() != b.Count()) {
+ // Let's not try to merge mismatched stacks.
Warn("Incompatible stack heights: " + a.Count() + " vs " + b.Count());
+ return a;
+ } else {
+ // The more complex case where the stacks don't match exactly.
+ var output = new List();
+ while (!a.IsEmpty && !b.IsEmpty) {
+ var varA = a.Peek();
+ var varB = b.Peek();
+ if (varA.StackType == varB.StackType) {
+ unionFind.Merge(varA, varB);
+ output.Add(varA);
+ } else {
+ if (!IsValidTypeStackTypeMerge(varA.StackType, varB.StackType)) {
+ Warn("Incompatible stack types: " + varA.StackType + " vs " + varB.StackType);
+ }
+ if (varA.StackType > varB.StackType) {
+ output.Add(varA);
+ // every store to varB should also store to varA
+ stackMismatchPairs.Add((varB, varA));
+ } else {
+ output.Add(varB);
+ // every store to varA should also store to varB
+ stackMismatchPairs.Add((varA, varB));
+ }
+ }
+ a = a.Pop();
+ b = b.Pop();
+ }
+ // because we built up output by popping from the input stacks, we need to reverse it to get back the original order
+ output.Reverse();
+ return ImmutableStack.CreateRange(output);
}
}
+ static bool CheckStackCompatibleWithoutAdjustments(ImmutableStack a, ImmutableStack b)
+ {
+ while (!a.IsEmpty && !b.IsEmpty) {
+ if (a.Peek().StackType != b.Peek().StackType)
+ return false;
+ a = a.Pop();
+ b = b.Pop();
+ }
+ return a.IsEmpty && b.IsEmpty;
+ }
+
+ private bool IsValidTypeStackTypeMerge(StackType stackType1, StackType stackType2)
+ {
+ if (stackType1 == StackType.I && stackType2 == StackType.I4)
+ return true;
+ if (stackType1 == StackType.I4 && stackType2 == StackType.I)
+ return true;
+ // allow merging unknown type with any other type
+ return stackType1 == StackType.Unknown || stackType2 == StackType.Unknown;
+ }
+
void StoreStackForOffset(int offset, ImmutableStack stack)
{
- ImmutableStack existing;
- if (stackByOffset.TryGetValue(offset, out existing)) {
- MergeStacks(existing, stack);
+ if (stackByOffset.TryGetValue(offset, out var existing)) {
+ var newStack = MergeStacks(existing, stack);
+ if (newStack != existing)
+ stackByOffset[offset] = newStack;
} else {
stackByOffset.Add(offset, stack);
}
}
-
+
void ReadInstructions(CancellationToken cancellationToken)
{
// Fill isBranchTarget and branchStackDict based on exception handlers
@@ -272,6 +326,44 @@ namespace ICSharpCode.Decompiler.IL
instructionBuilder[i] = instructionBuilder[i].AcceptVisitor(visitor);
}
stackVariables = visitor.variables;
+ InsertStackAdjustments();
+ }
+
+ void InsertStackAdjustments()
+ {
+ if (stackMismatchPairs.Count == 0)
+ return;
+ var dict = new MultiDictionary();
+ foreach (var (origA, origB) in stackMismatchPairs) {
+ var a = unionFind.Find(origA);
+ var b = unionFind.Find(origB);
+ Debug.Assert(a.StackType < b.StackType);
+ // For every store to a, insert a converting store to b.
+ if (!dict[a].Contains(b))
+ dict.Add(a, b);
+ }
+ var newInstructions = new List();
+ foreach (var inst in instructionBuilder) {
+ newInstructions.Add(inst);
+ if (inst is StLoc store) {
+ foreach (var additionalVar in dict[store.Variable]) {
+ ILInstruction value = new LdLoc(store.Variable);
+ switch (additionalVar.StackType) {
+ case StackType.I:
+ value = new Conv(value, PrimitiveType.I, false, Sign.None);
+ break;
+ case StackType.I8:
+ value = new Conv(value, PrimitiveType.I8, false, Sign.None);
+ break;
+ }
+ newInstructions.Add(new StLoc(additionalVar, value) {
+ IsStackAdjustment = true,
+ ILRange = inst.ILRange
+ });
+ }
+ }
+ }
+ instructionBuilder = newInstructions;
}
///
@@ -282,6 +374,12 @@ namespace ICSharpCode.Decompiler.IL
Init(body);
ReadInstructions(cancellationToken);
foreach (var inst in instructionBuilder) {
+ if (inst is StLoc stloc && stloc.IsStackAdjustment) {
+ output.Write(" ");
+ inst.WriteTo(output, new ILAstWritingOptions());
+ output.WriteLine();
+ continue;
+ }
output.Write(" [");
bool isFirstElement = true;
foreach (var element in stackByOffset[inst.ILRange.Start]) {
diff --git a/ICSharpCode.Decompiler/IL/Instructions.cs b/ICSharpCode.Decompiler/IL/Instructions.cs
index d96dc841a..9b60134b7 100644
--- a/ICSharpCode.Decompiler/IL/Instructions.cs
+++ b/ICSharpCode.Decompiler/IL/Instructions.cs
@@ -2317,6 +2317,8 @@ namespace ICSharpCode.Decompiler.IL
clone.Value = this.value.Clone();
return clone;
}
+ /// If true, this stloc represents a stack type adjustment. This field is only used in ILReader and BlockBuilder, and should be ignored by ILAst transforms.
+ internal bool IsStackAdjustment;
public override StackType ResultType { get { return variable.StackType; } }
protected override InstructionFlags ComputeFlags()
{
diff --git a/ICSharpCode.Decompiler/IL/Instructions.tt b/ICSharpCode.Decompiler/IL/Instructions.tt
index d29ea9d68..1a28b8151 100644
--- a/ICSharpCode.Decompiler/IL/Instructions.tt
+++ b/ICSharpCode.Decompiler/IL/Instructions.tt
@@ -153,6 +153,9 @@
new OpCode("stloc", "Stores a value into a local variable. (IL: starg/stloc)" + Environment.NewLine
+ "Evaluates to the value that was stored (for byte/short variables: evaluates to the truncated value, sign/zero extended back to I4 based on variable.Type.GetSign())",
CustomClassName("StLoc"), HasVariableOperand("Store"), CustomArguments("value"),
+ AdditionalMember(
+ "/// If true, this stloc represents a stack type adjustment. This field is only used in ILReader and BlockBuilder, and should be ignored by ILAst transforms." + Environment.NewLine
+ + "internal bool IsStackAdjustment;"),
ResultType("variable.StackType")),
new OpCode("addressof", "Stores the value into an anonymous temporary variable, and returns the address of that variable.",
CustomClassName("AddressOf"), CustomArguments("value"), ResultType("Ref")),
@@ -571,6 +574,13 @@ namespace ICSharpCode.Decompiler.IL
};
}
+ static Action AdditionalMember(string declaration)
+ {
+ return opCode => {
+ opCode.Members.Add(declaration);
+ };
+ }
+
// ResultType trait: the instruction has the specified result type.
static Action ResultType(string type)
{
diff --git a/ICSharpCode.Decompiler/IL/StackType.cs b/ICSharpCode.Decompiler/IL/StackType.cs
index b2a4381a1..b5a5b4d60 100644
--- a/ICSharpCode.Decompiler/IL/StackType.cs
+++ b/ICSharpCode.Decompiler/IL/StackType.cs
@@ -24,6 +24,15 @@ namespace ICSharpCode.Decompiler.IL
///
public enum StackType : byte
{
+ // Note: the numeric of these enum members is relevant for ILReader.MergeStacks:
+ // when two branches meet where a stack slot has different types, the type after
+ // the branch is the one with the higher numeric value.
+
+ ///
+ /// The stack type is unknown; for example a call returning an unknown type
+ /// because an assembly reference isn't loaded.
+ /// Can also occur with invalid IL.
+ ///
Unknown,
/// 32-bit integer
///
@@ -33,23 +42,24 @@ namespace ICSharpCode.Decompiler.IL
/// and any enums with one of the above as underlying type.
///
I4,
+ /// native-size integer, or unmanaged pointer
+ ///
+ /// Used for C# IntPtr, UIntPtr and any native pointer types (void* etc.)
+ /// Also used for IL function pointer types.
+ ///
+ I,
/// 64-bit integer
///
/// Used for C# long, ulong,
/// and any enums with one of the above as underlying type.
///
I8,
- /// native-size integer, or unmanaged pointer
- ///
- /// Used for C# IntPtr, UIntPtr and any native pointer types (void* etc.)
- ///
- I,
/// Floating point number
///
/// Used for C# float and double.
///
F,
- /// Another stack type. Includes objects, value types, function pointers, ...
+ /// Another stack type. Includes objects, value types, ...
O,
/// A managed pointer
Ref,
diff --git a/ILSpy/Properties/AssemblyInfo.template.cs b/ILSpy/Properties/AssemblyInfo.template.cs
index 140434136..ea8c2ffc4 100644
--- a/ILSpy/Properties/AssemblyInfo.template.cs
+++ b/ILSpy/Properties/AssemblyInfo.template.cs
@@ -42,7 +42,7 @@ internal static class RevisionClass
public const string Minor = "0";
public const string Build = "0";
public const string Revision = "$INSERTREVISION$";
- public const string VersionName = "beta1";
+ public const string VersionName = "beta2";
public const string FullVersion = Major + "." + Minor + "." + Build + ".$INSERTREVISION$$INSERTBRANCHPOSTFIX$$INSERTVERSIONNAMEPOSTFIX$";
}
diff --git a/appveyor.yml b/appveyor.yml
index ad8006791..3dab27be5 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -18,6 +18,10 @@ test:
- 'ILSpy.BamlDecompiler.Tests\bin\%configuration%\net461\ILSpy.BamlDecompiler.Tests.dll'
after_test:
- python BuildTools\tidy.py
+for:
+- branches:
+ only:
+ - master
artifacts:
- path: ILSpy_binaries.zip
name: ILSpy %APPVEYOR_REPO_BRANCH% %ILSPY_VERSION_NUMBER% binaries