diff --git a/BuildTools/appveyor-ilspycmd-install.ps1 b/BuildTools/appveyor-ilspycmd-install.ps1
index 41691695a..0d549c7a7 100644
--- a/BuildTools/appveyor-ilspycmd-install.ps1
+++ b/BuildTools/appveyor-ilspycmd-install.ps1
@@ -3,6 +3,9 @@ $ErrorActionPreference = "Stop"
$baseCommit = "e17b4bfedf4dc747b105396224cd726bdca500ad";
$baseCommitRev = 1;
+# make sure this matches artifacts-only branches list in appveyor.yml!
+$masterBranches = '^(master|release/.+)$';
+
$globalAssemblyInfoTemplateFile = "ILSpy/Properties/AssemblyInfo.template.cs";
$versionParts = @{};
@@ -18,10 +21,10 @@ if ($versionName -ne "null") {
} else {
$versionName = "";
}
-if ($env:APPVEYOR_REPO_BRANCH -ne 'master') {
- $branch = "-$env:APPVEYOR_REPO_BRANCH";
-} else {
+if ($env:APPVEYOR_REPO_BRANCH -match $masterBranches) {
$branch = "";
+} else {
+ $branch = "-$env:APPVEYOR_REPO_BRANCH";
}
$revision = [Int32]::Parse((git rev-list --count "$baseCommit..HEAD")) + $baseCommitRev;
diff --git a/BuildTools/appveyor-install.ps1 b/BuildTools/appveyor-install.ps1
index 0b922deb8..a69ff0732 100644
--- a/BuildTools/appveyor-install.ps1
+++ b/BuildTools/appveyor-install.ps1
@@ -3,8 +3,8 @@ $ErrorActionPreference = "Stop"
$baseCommit = "d779383cb85003d6dabeb976f0845631e07bf463";
$baseCommitRev = 1;
-# make sure this list matches artifacts-only branches list in appveyor.yml!
-$masterBranches = @("master", "5.0.x");
+# make sure this matches artifacts-only branches list in appveyor.yml!
+$masterBranches = '^(master|release/.+)$';
$globalAssemblyInfoTemplateFile = "ILSpy/Properties/AssemblyInfo.template.cs";
@@ -21,7 +21,7 @@ if ($versionName -ne "null") {
} else {
$versionName = "";
}
-if ($masterBranches -contains $env:APPVEYOR_REPO_BRANCH) {
+if ($env:APPVEYOR_REPO_BRANCH -match $masterBranches) {
$branch = "";
} else {
$branch = "-$env:APPVEYOR_REPO_BRANCH";
diff --git a/BuildTools/pipelines-install.ps1 b/BuildTools/pipelines-install.ps1
index 4e3dda35e..7e73f3c60 100644
--- a/BuildTools/pipelines-install.ps1
+++ b/BuildTools/pipelines-install.ps1
@@ -3,8 +3,8 @@ $ErrorActionPreference = "Stop"
$baseCommit = "d779383cb85003d6dabeb976f0845631e07bf463";
$baseCommitRev = 1;
-# make sure this list matches artifacts-only branches list in azure-pipelines.yml!
-$masterBranches = @("master", "5.0.x");
+# make sure this matches artifacts-only branches list in appveyor.yml!
+$masterBranches = '^refs/heads/(master|release/.+)$';
$globalAssemblyInfoTemplateFile = "ILSpy/Properties/AssemblyInfo.template.cs";
@@ -21,7 +21,8 @@ if ($versionName -ne "null") {
} else {
$versionName = "";
}
-if ($masterBranches -contains $env:BUILD_SOURCEBRANCHNAME) {
+
+if ($env:BUILD_SOURCEBRANCH -match $masterBranches) {
$branch = "";
} else {
$branch = "-$env:BUILD_SOURCEBRANCHNAME";
diff --git a/BuildTools/update-assemblyinfo.ps1 b/BuildTools/update-assemblyinfo.ps1
index dbfa5f911..f7fa079b1 100644
--- a/BuildTools/update-assemblyinfo.ps1
+++ b/BuildTools/update-assemblyinfo.ps1
@@ -3,8 +3,8 @@
$baseCommit = "d779383cb85003d6dabeb976f0845631e07bf463";
$baseCommitRev = 1;
-# make sure this list matches artifacts-only branches list in appveyor.yml!
-$masterBranches = @("master", "5.0.x");
+# make sure this matches artifacts-only branches list in appveyor.yml!
+$masterBranches = '^(master|release/.+)$';
$globalAssemblyInfoTemplateFile = "ILSpy/Properties/AssemblyInfo.template.cs";
@@ -112,7 +112,7 @@ try {
$branchName = gitBranch;
$gitCommitHash = gitCommitHash;
- if ($masterBranches -contains $branchName) {
+ if ($branchName -match $masterBranches) {
$postfixBranchName = "";
} else {
$postfixBranchName = "-$branchName";
diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
index 7ae4cf43b..8a6a6d33f 100644
--- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
+++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
@@ -65,6 +65,8 @@
+
+
diff --git a/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs
index 54ce7b5cb..7826d0af2 100644
--- a/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs
+++ b/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs
@@ -146,6 +146,12 @@ namespace ICSharpCode.Decompiler.Tests
Run(settings: new DecompilerSettings { SwitchExpressions = false });
}
+ [Test]
+ public void UnknownTypes()
+ {
+ Run();
+ }
+
[Test]
public void Issue1145()
{
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/UnknownTypes.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/UnknownTypes.cs
new file mode 100644
index 000000000..c77ae5e14
--- /dev/null
+++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/UnknownTypes.cs
@@ -0,0 +1,12 @@
+internal class UnknownTypes
+{
+ private readonly IInterface memberField;
+
+ public override bool CanExecute(CallbackQuery message)
+ {
+ return ((IInterface)(object)memberField).Execute(new SomeClass {
+ ChatId = StaticClass.GetChatId(message),
+ MessageId = StaticClass.GetMessageId(message)
+ });
+ }
+}
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/UnknownTypes.il b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/UnknownTypes.il
new file mode 100644
index 000000000..69c743fa4
--- /dev/null
+++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/UnknownTypes.il
@@ -0,0 +1,59 @@
+#define CORE_ASSEMBLY "System.Runtime"
+
+.assembly extern CORE_ASSEMBLY
+{
+ .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....:
+ .ver 4:0:0:0
+}
+.assembly extern UnknownAssembly
+{
+ .publickeytoken = (01 02 03 04 05 06 07 08 )
+ .ver 1:0:0:0
+}
+
+.class private auto ansi beforefieldinit UnknownTypes
+ extends [System.Private.CoreLib]System.Object
+{
+ .field private initonly class [UnknownAssembly]IInterface memberField
+
+ // Methods
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor () cil managed
+ {
+ // Method begins at RVA 0x206e
+ // Code size 8 (0x8)
+ .maxstack 8
+
+ IL_0000: ldarg.0
+ IL_0001: call instance void [CORE_ASSEMBLY]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method UnknownTypes::.ctor
+
+ .method public hidebysig virtual
+ instance bool CanExecute (
+ class [UnknownAssembly]CallbackQuery message
+ ) cil managed
+ {
+ // Method begins at RVA 0x4dbc
+ // Code size 44 (0x2c)
+ .maxstack 8
+
+ IL_0000: ldarg.0
+ IL_0001: ldfld class [UnknownAssembly]IInterface UnknownTypes::memberField
+ IL_0006: newobj instance void [UnknownAssembly]SomeClass::.ctor()
+ IL_000b: dup
+ IL_000d: ldarg.1
+ IL_000e: call int64 [UnknownAssembly]StaticClass::GetChatId(class [UnknownAssembly]CallbackQuery)
+ IL_0013: stfld int64 [UnknownAssembly]SomeClass::ChatId
+ IL_0018: dup
+ IL_001a: ldarg.1
+ IL_001b: call int32 [UnknownAssembly]StaticClass::GetMessageId(class [UnknownAssembly]CallbackQuery)
+ IL_0020: conv.i8
+ IL_0021: stfld int64 [UnknownAssembly]SomeClass::MessageId
+ IL_0026: callvirt instance !1 class [UnknownAssembly]IInterface`2::Execute(!0)
+ IL_002b: ret
+ } // end of method CanExecute
+
+
+} // end of class UnknownTypes
diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
index 8b798edb1..10c422d3a 100644
--- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
+++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
@@ -286,8 +286,8 @@ namespace ICSharpCode.Decompiler.CSharp
var methodSemantics = module.MethodSemanticsLookup.GetSemantics(methodHandle).Item2;
if (methodSemantics != 0 && methodSemantics != System.Reflection.MethodSemanticsAttributes.Other)
return true;
- if (LocalFunctionDecompiler.IsLocalFunctionMethod(module, methodHandle))
- return settings.LocalFunctions;
+ if (settings.LocalFunctions && LocalFunctionDecompiler.IsLocalFunctionMethod(module, methodHandle))
+ return true;
if (settings.AnonymousMethods && methodHandle.HasGeneratedName(metadata) && methodHandle.IsCompilerGenerated(metadata))
return true;
if (settings.AsyncAwait && AsyncAwaitDecompiler.IsCompilerGeneratedMainMethod(module, methodHandle))
@@ -299,8 +299,8 @@ namespace ICSharpCode.Decompiler.CSharp
name = metadata.GetString(type.Name);
if (!type.GetDeclaringType().IsNil)
{
- if (LocalFunctionDecompiler.IsLocalFunctionDisplayClass(module, typeHandle))
- return settings.LocalFunctions;
+ if (settings.LocalFunctions && LocalFunctionDecompiler.IsLocalFunctionDisplayClass(module, typeHandle))
+ return true;
if (settings.AnonymousMethods && IsClosureType(type, metadata))
return true;
if (settings.YieldReturn && YieldReturnDecompiler.IsCompilerGeneratorEnumerator(typeHandle, metadata))
diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
index c49d167f4..2b28c643d 100644
--- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
+++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
@@ -168,16 +168,19 @@ namespace ICSharpCode.Decompiler.CSharp
}
else if (inst is ILiftableInstruction liftable && liftable.IsLifted)
{
- Debug.Assert(NullableType.IsNullable(cexpr.Type));
- IType underlying = NullableType.GetUnderlyingType(cexpr.Type);
- if (liftable.UnderlyingResultType.IsIntegerType())
+ if (liftable.UnderlyingResultType != StackType.Unknown)
{
- Debug.Assert(underlying.GetStackType().IsIntegerType(), "IL instructions of integer type must convert into C# expressions of integer type");
- Debug.Assert(underlying.GetSign() != Sign.None, "Must have a sign specified for zero/sign-extension");
- }
- else
- {
- Debug.Assert(underlying.GetStackType() == liftable.UnderlyingResultType);
+ Debug.Assert(NullableType.IsNullable(cexpr.Type));
+ IType underlying = NullableType.GetUnderlyingType(cexpr.Type);
+ if (liftable.UnderlyingResultType.IsIntegerType())
+ {
+ Debug.Assert(underlying.GetStackType().IsIntegerType(), "IL instructions of integer type must convert into C# expressions of integer type");
+ Debug.Assert(underlying.GetSign() != Sign.None, "Must have a sign specified for zero/sign-extension");
+ }
+ else
+ {
+ Debug.Assert(underlying.GetStackType() == liftable.UnderlyingResultType);
+ }
}
}
else if (inst.ResultType == StackType.Ref)
diff --git a/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs b/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs
index 41900b0e6..170c4d2db 100644
--- a/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs
+++ b/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs
@@ -502,7 +502,8 @@ namespace ICSharpCode.Decompiler.CSharp
.WithRR(new ByReferenceResolveResult(elementRR, ReferenceKind.Ref));
}
if (this.ResolveResult.IsCompileTimeConstant && this.ResolveResult.ConstantValue != null
- && NullableType.IsNullable(targetType) && !utype.Equals(targetUType))
+ && NullableType.IsNullable(targetType) && !utype.Equals(targetUType)
+ && targetUType.GetStackType().IsIntegerType())
{
// Casts like `(uint?)-1` are only valid in an explicitly unchecked context, but we
// don't have logic to ensure such a context (usually we emit into an implicitly unchecked context).
diff --git a/ICSharpCode.Decompiler/IL/ILReader.cs b/ICSharpCode.Decompiler/IL/ILReader.cs
index 0a889de45..cbfe23e79 100644
--- a/ICSharpCode.Decompiler/IL/ILReader.cs
+++ b/ICSharpCode.Decompiler/IL/ILReader.cs
@@ -1312,7 +1312,8 @@ namespace ICSharpCode.Decompiler.IL
return PopPointer();
default:
// field in unresolved type
- if (PeekStackType() == StackType.O)
+ var stackType = PeekStackType();
+ if (stackType == StackType.O || stackType == StackType.Unknown)
return Pop();
else
return PopPointer();
diff --git a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs
index 0fffa2a28..be3114ace 100644
--- a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs
+++ b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs
@@ -213,6 +213,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var values = new List<(string, ILInstruction)>();
var uniqueValues = new HashSet();
int numberOfUniqueMatchesWithCurrentVariable = 0;
+ HashSet caseBlocks = new HashSet();
+ caseBlocks.Add((Block)instructions[i].Parent);
bool AddSwitchSection(string value, ILInstruction inst)
{
@@ -308,6 +310,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (!AddSwitchSection(value, block))
return false;
}
+ caseBlocks.Add(currentCaseBlock);
currentCaseBlock = nextCaseBlock as Block;
} while (currentCaseBlock != null);
@@ -316,7 +319,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
context.Step(nameof(SimplifyCascadingIfStatements), instructions[i]);
// if the switchValueVar is used in other places as well, do not eliminate the store.
- if (switchValueVar.LoadCount > numberOfUniqueMatchesWithCurrentVariable)
+ if (switchValueVar.LoadCount > numberOfUniqueMatchesWithCurrentVariable || !ValidateUsesOfSwitchValueVariable(switchValueVar, caseBlocks))
{
keepAssignmentBefore = true;
removeExtraLoad = false; // prevent loads from being deleted after detecting that
@@ -355,6 +358,23 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true;
}
+ private bool ValidateUsesOfSwitchValueVariable(ILVariable switchValueVar, HashSet caseBlocks)
+ {
+ foreach (var use in switchValueVar.LoadInstructions)
+ {
+ bool isValid = false;
+ foreach (var caseBlock in caseBlocks)
+ {
+ if (use.IsDescendantOf(caseBlock))
+ isValid = true;
+ }
+ if (!isValid)
+ return false;
+ }
+
+ return true;
+ }
+
bool SimplifyCSharp1CascadingIfStatements(InstructionCollection instructions, ref int i)
{
if (i < 1)
diff --git a/ILSpy/Properties/app.config.template b/ILSpy/Properties/app.config.template
index 1bde4b5e0..7360911a3 100644
--- a/ILSpy/Properties/app.config.template
+++ b/ILSpy/Properties/app.config.template
@@ -14,7 +14,7 @@
-
+
diff --git a/appveyor.yml b/appveyor.yml
index 7bc77bb58..8b9b0dd07 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -45,7 +45,7 @@ for:
- branches:
only:
- master
- - 5.0.x
+ - /release\/*/
artifacts:
- path: ILSpy_binaries.zip
name: ILSpy %APPVEYOR_REPO_BRANCH% %ILSPY_VERSION_NUMBER% binaries
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index e45b45d2d..e087c1aea 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -1,10 +1,10 @@
trigger:
- master
-- 5.0.x
+- release/*
pr:
- master
-- 5.0.x
+- release/*
variables:
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
@@ -52,7 +52,7 @@ jobs:
inputs:
command: 'custom'
custom: 'tool'
- arguments: 'install dotnet-format --tool-path BuildTools'
+ arguments: 'install dotnet-format --tool-path $(Agent.ToolsDirectory)/dotnet-format'
- script: pwsh .\BuildTools\pipelines-install.ps1
displayName: Install
@@ -94,7 +94,7 @@ jobs:
- script: python BuildTools\tidy.py
displayName: Tab check
- - script: .\BuildTools\dotnet-format --check --verbosity diagnostic ILSpy.sln
+ - script: $(Agent.ToolsDirectory)\dotnet-format\dotnet-format --check --verbosity diagnostic ILSpy.sln
displayName: dotnet-format check
- task: CopyFiles@2