Browse Source

Merge pull request #2873 from icsharpcode/net-7.0

pull/2993/head
Siegfried Pammer 2 years ago committed by GitHub
parent
commit
83f4fdcc47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      ICSharpCode.Decompiler.TestRunner/ICSharpCode.Decompiler.TestRunner.csproj
  2. 7
      ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs
  3. 11
      ICSharpCode.Decompiler.Tests/Helpers/Tester.cs
  4. 13
      ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
  5. 31
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/OverloadResolution.cs
  6. 18
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ConstantsTests.cs
  7. 7
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.cs
  8. 14
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/FunctionPointers.cs
  9. 4
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs
  10. 36
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/NativeInts.cs
  11. 7
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/PInvoke.cs
  12. 17
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs
  13. 25
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  14. 15
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  15. 21
      ICSharpCode.Decompiler/DecompilerSettings.cs
  16. 17
      ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs
  17. 2
      ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs
  18. 14
      ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
  19. 2
      ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs
  20. 5
      ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs
  21. 2
      ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs
  22. 9
      ILSpy/Properties/Resources.Designer.cs
  23. 3
      ILSpy/Properties/Resources.resx
  24. 6
      README.md
  25. 2
      global.json

2
ICSharpCode.Decompiler.TestRunner/ICSharpCode.Decompiler.TestRunner.csproj

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>

7
ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs

@ -317,7 +317,7 @@ namespace ICSharpCode.Decompiler.Tests @@ -317,7 +317,7 @@ namespace ICSharpCode.Decompiler.Tests
public async Task StackTests()
{
// IL contains .corflags = 32BITREQUIRED
await RunIL("StackTests.il", asmOptions: AssemblerOptions.Force32Bit);
await RunIL("StackTests.il", CompilerOptions.Force32Bit, AssemblerOptions.Force32Bit);
}
[Test]
@ -483,6 +483,11 @@ namespace ICSharpCode.Decompiler.Tests @@ -483,6 +483,11 @@ namespace ICSharpCode.Decompiler.Tests
string outputFile = null;
CompilerResults decompiledOutputFile = null;
bool optionsForce32Bit = options.HasFlag(CompilerOptions.Force32Bit);
bool asmOptionsForce32Bit = asmOptions.HasFlag(AssemblerOptions.Force32Bit);
Assert.AreEqual(optionsForce32Bit, asmOptionsForce32Bit, "Inconsistent architecture.");
try
{
options |= CompilerOptions.UseTestRunner;

11
ICSharpCode.Decompiler.Tests/Helpers/Tester.cs

@ -105,9 +105,9 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -105,9 +105,9 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
TesterPath = Path.GetDirectoryName(typeof(Tester).Assembly.Location);
TestCasePath = Path.Combine(TesterPath, "../../../../TestCases");
#if DEBUG
testRunnerBasePath = Path.Combine(TesterPath, "../../../../../ICSharpCode.Decompiler.TestRunner/bin/Debug/net6.0-windows");
testRunnerBasePath = Path.Combine(TesterPath, "../../../../../ICSharpCode.Decompiler.TestRunner/bin/Debug/net7.0");
#else
testRunnerBasePath = Path.Combine(TesterPath, "../../../../../ICSharpCode.Decompiler.TestRunner/bin/Release/net6.0-windows");
testRunnerBasePath = Path.Combine(TesterPath, "../../../../../ICSharpCode.Decompiler.TestRunner/bin/Release/net7.0");
#endif
packagesPropsFile = Path.Combine(TesterPath, "../../../../../packages.props");
roslynLatestVersion = XDocument.Load(packagesPropsFile).XPathSelectElement("//RoslynVersion").Value;
@ -270,8 +270,8 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -270,8 +270,8 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
}
static readonly string coreRefAsmPath = new DotNetCorePathFinder(TargetFrameworkIdentifier.NET,
new Version(6, 0), "Microsoft.NETCore.App")
.GetReferenceAssemblyPath(".NETCoreApp,Version=v6.0");
new Version(7, 0), "Microsoft.NETCore.App")
.GetReferenceAssemblyPath(".NETCoreApp,Version=v7.0");
public static readonly string RefAsmPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86),
@"Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2");
@ -308,7 +308,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -308,7 +308,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
const string targetFrameworkAttributeSnippet = @"
[assembly: System.Runtime.Versioning.TargetFramework("".NETCoreApp,Version=v6.0"", FrameworkDisplayName = """")]
[assembly: System.Runtime.Versioning.TargetFramework("".NETCoreApp,Version=v7.0"", FrameworkDisplayName = """")]
";
@ -343,6 +343,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -343,6 +343,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
{
preprocessorSymbols.Add("NETCORE");
preprocessorSymbols.Add("NET60");
preprocessorSymbols.Add("NET70");
}
preprocessorSymbols.Add("ROSLYN");
preprocessorSymbols.Add("CS60");

13
ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs

@ -321,12 +321,11 @@ namespace ICSharpCode.Decompiler.Tests @@ -321,12 +321,11 @@ namespace ICSharpCode.Decompiler.Tests
[Test]
public async Task Loops([ValueSource(nameof(defaultOptionsWithMcs))] CompilerOptions cscOptions)
{
await RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings {
// legacy csc generates a dead store in debug builds
RemoveDeadStores = (cscOptions == CompilerOptions.None),
UseExpressionBodyForCalculatedGetterOnlyProperties = false,
FileScopedNamespaces = false,
});
DecompilerSettings settings = Tester.GetSettings(cscOptions);
// legacy csc generates a dead store in debug builds
settings.RemoveDeadStores = (cscOptions == CompilerOptions.None);
settings.UseExpressionBodyForCalculatedGetterOnlyProperties = false;
await RunForLibrary(cscOptions: cscOptions, decompilerSettings: settings);
}
[Test]
@ -486,7 +485,7 @@ namespace ICSharpCode.Decompiler.Tests @@ -486,7 +485,7 @@ namespace ICSharpCode.Decompiler.Tests
}
[Test]
public async Task NativeInts([ValueSource(nameof(roslyn3OrNewerOptions))] CompilerOptions cscOptions)
public async Task NativeInts([ValueSource(nameof(roslyn3OrNewerWithNet40Options))] CompilerOptions cscOptions)
{
await RunForLibrary(cscOptions: cscOptions);
}

31
ICSharpCode.Decompiler.Tests/TestCases/Correctness/OverloadResolution.cs

@ -36,6 +36,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -36,6 +36,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Issue1747();
CallAmbiguousOutParam();
CallWithInParam();
#if CS90
NativeIntTests(new IntPtr(1), 2);
#endif
Issue2444.M2();
Issue2741.B.Test(new Issue2741.C());
}
@ -337,6 +340,34 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -337,6 +340,34 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
#endif
#endregion
#if CS90
static void NativeIntTests(IntPtr i1, nint i2)
{
Console.WriteLine("NativeIntTests(i1):");
ObjectOrLong((object)i1);
ObjectOrLong((long)i1);
Console.WriteLine("NativeIntTests(i2):");
ObjectOrLong((object)i2);
ObjectOrLong((long)i2);
Console.WriteLine("NativeIntTests(new IntPtr):");
ObjectOrLong((object)new IntPtr(3));
ObjectOrLong((long)new IntPtr(3));
Console.WriteLine("NativeIntTests(IntPtr.Zero):");
ObjectOrLong((object)IntPtr.Zero);
ObjectOrLong((long)IntPtr.Zero);
}
static void ObjectOrLong(object o)
{
Console.WriteLine("object " + o);
}
static void ObjectOrLong(long l)
{
Console.WriteLine("long " + l);
}
#endif
#region #2444
public struct Issue2444
{

18
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ConstantsTests.cs

@ -1,10 +1,25 @@ @@ -1,10 +1,25 @@
using System;
#if !(CS110 && NET70)
using System;
#endif
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
internal class ConstantsTests
{
#if CS90
public nint? NullableNInt()
{
return null;
}
public nuint? NullableNUInt()
{
return null;
}
#endif
#if !(CS110 && NET70)
public IntPtr? NullableIntPtr()
{
return null;
@ -14,6 +29,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -14,6 +29,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
return null;
}
#endif
public ulong Issue1308(ulong u = 8uL)
{

7
ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.cs

@ -436,10 +436,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -436,10 +436,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
return true.Equals(a);
}
#if CS110 && NET70
private static nint NewIntPtr(dynamic a)
{
return new nint(a);
}
#else
private static IntPtr NewIntPtr(dynamic a)
{
return new IntPtr(a);
}
#endif
private static dynamic GetDynamic(int i)
{

14
ICSharpCode.Decompiler.Tests/TestCases/Pretty/FunctionPointers.cs

@ -1,4 +1,6 @@ @@ -1,4 +1,6 @@
using System;
#if !(CS110 && NET70)
using System;
#endif
using System.Text;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
@ -17,10 +19,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -17,10 +19,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
return &Overloaded;
}
#if !(CS110 && NET70)
public unsafe IntPtr GetAddressAsIntPtr()
{
return (IntPtr)(delegate*<void>)(&Overloaded);
}
#endif
public unsafe nint GetAddressAsNInt()
{
return (nint)(delegate*<void>)(&Overloaded);
}
public unsafe void* GetAddressAsVoidPtr()
{
@ -93,6 +102,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -93,6 +102,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
internal class FunctionPointersWithNativeIntegerTypes
{
public unsafe delegate*<nint, nint, nint> F1;
#if !(CS110 && NET70)
public unsafe delegate*<IntPtr, IntPtr, nint> F2;
public unsafe delegate*<nint, IntPtr, IntPtr> F3;
public unsafe delegate*<IntPtr, nint, IntPtr> F4;
@ -100,6 +110,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -100,6 +110,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public unsafe delegate*<nint, delegate*<IntPtr, IntPtr, IntPtr>> F6;
public unsafe delegate*<delegate*<IntPtr, IntPtr, nint>, IntPtr> F7;
public unsafe delegate*<IntPtr, delegate*<IntPtr, nint, IntPtr>> F8;
public unsafe delegate*<IntPtr, delegate*<IntPtr, IntPtr, IntPtr>> F9;
#endif
}
internal class FunctionPointersWithRefParams

4
ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs

@ -844,10 +844,10 @@ namespace LocalFunctions @@ -844,10 +844,10 @@ namespace LocalFunctions
#if CS90
public void Issue2196()
{
EnumWindows(IntPtr.Zero, IntPtr.Zero);
EnumWindows(0L, 0L);
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "EnumWindows")]
static extern int EnumWindows(IntPtr hWnd, IntPtr lParam);
static extern int EnumWindows(long hWnd, long lParam);
}
#endif
}

36
ICSharpCode.Decompiler.Tests/TestCases/Pretty/NativeInts.cs

@ -26,23 +26,36 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -26,23 +26,36 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
private const nint nint_const = 42;
private const nuint nuint_const = 99u;
#if CS110 && NET70
// C#11 on .NET7 no longer uses NativeIntegerAttribute,
// instead nint+IntPtr are considered to be the same type.
private nint intptr;
private nuint uintptr;
#else
private IntPtr intptr;
private UIntPtr uintptr;
#endif
private nint i;
private nuint u;
private int i32;
private uint u32;
private long i64;
private ulong u64;
#if !(CS110 && NET70)
private (IntPtr, nint, UIntPtr, nuint) tuple_field;
private (object, int, IntPtr, nint, UIntPtr, nuint) tuple_field2;
private Dictionary<nint, IntPtr> dict1;
private Dictionary<IntPtr, nint> dict2;
private Dictionary<IntPtr?, nint?> dict3;
private Dictionary<IntPtr, nint[]> dict4;
#endif
private Dictionary<nuint, nint[]> dict5;
public void Convert()
{
i = (nint)u;
u = (nuint)i;
#if !(CS110 && NET70)
intptr = i;
intptr = (nint)u;
intptr = (nint)(nuint)uintptr;
@ -58,15 +71,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -58,15 +71,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
u = (nuint)i;
u = uintptr;
u = (nuint)(nint)intptr;
#endif
}
public void Convert2()
{
i32 = (int)i;
i = i32;
#if !(CS110 && NET70)
intptr = (IntPtr)i32;
i64 = (long)intptr;
#endif
i64 = i;
i = (nint)i64;
@ -79,7 +95,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -79,7 +95,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void Arithmetic()
{
#if !(CS110 && NET70)
Console.WriteLine((nint)intptr * 2);
#endif
Console.WriteLine(i * 2);
Console.WriteLine(i + (nint)u);
@ -155,6 +173,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -155,6 +173,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
GetInstance(3).u *= 2u;
}
#if !(CS110 && NET70)
GetInstance(4).intptr += (nint)i32;
checked
{
@ -164,10 +183,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -164,10 +183,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
// multiplication results in compiler-error without the cast
GetInstance(6).intptr *= (nint)2;
#endif
GetInstance(7).i <<= i32;
GetInstance(7).i += i32;
GetInstance(8).i <<= i32;
}
#if !(CS110 && NET70)
public void LocalTypeFromStore()
{
nint num = 42;
@ -188,10 +210,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -188,10 +210,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
intptr = num3;
intptr = intPtr;
}
#endif
public void LocalTypeFromUse()
{
#if CS110 && NET70
nint num = intptr;
nint num2 = intptr;
Console.WriteLine();
intptr = num;
i = num2 + 1;
#else
IntPtr intPtr = intptr;
nint num = intptr;
@ -199,6 +230,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -199,6 +230,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
intptr = intPtr;
i = num + 1;
#endif
}
public nint NegateUnsigned(nuint x)

7
ICSharpCode.Decompiler.Tests/TestCases/Pretty/PInvoke.cs

@ -89,9 +89,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -89,9 +89,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
}
#if CS110 && NET70
[DllImport("ws2_32.dll", SetLastError = true)]
internal static extern IntPtr ioctlsocket([In] IntPtr socketHandle, [In] int cmd, [In][Out] ref int argp);
internal static extern nint ioctlsocket([In] nint socketHandle, [In] int cmd, [In][Out] ref int argp);
#else
[DllImport("ws2_32.dll", SetLastError = true)]
internal static extern IntPtr ioctlsocket([In] IntPtr socketHandle, [In] int cmd, [In][Out] ref int argp);
#endif
public void CallMethodWithInOutParameter()
{
int argp = 0;

17
ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs

@ -30,7 +30,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -30,7 +30,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
public static object StaticObj;
#if CS110 && NET70
public nint A;
#else
public IntPtr A;
#endif
}
private struct UnmanagedStruct
@ -605,6 +609,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -605,6 +609,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
return value.Integers[(int)s];
}
#if CS90
private unsafe static void* CastNIntToVoidPtr(nint intptr)
{
return (void*)intptr;
}
private unsafe static void* CastNIntToVoidPtr(nuint intptr)
{
return (void*)intptr;
}
#endif
#if !(CS110 && NET70)
private unsafe static void* CastToVoidPtr(IntPtr intptr)
{
return (void*)intptr;
@ -614,6 +630,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -614,6 +630,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
return (void*)intptr;
}
#endif
private unsafe static void* CastToVoidPtr(int* intptr)
{

25
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -1406,6 +1406,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1406,6 +1406,7 @@ namespace ICSharpCode.Decompiler.CSharp
attr.Remove();
}
}
RemoveCompilerFeatureRequiredAttribute(typeDecl, "RefStructs");
}
if (settings.RequiredMembers)
{
@ -1851,6 +1852,30 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1851,6 +1852,30 @@ namespace ICSharpCode.Decompiler.CSharp
return found;
}
internal static bool RemoveCompilerFeatureRequiredAttribute(EntityDeclaration entityDecl, string feature)
{
bool found = false;
foreach (var section in entityDecl.Attributes)
{
foreach (var attr in section.Attributes)
{
var symbol = attr.Type.GetSymbol();
if (symbol is ITypeDefinition td && td.FullTypeName == KnownAttribute.CompilerFeatureRequired.GetTypeName()
&& attr.Arguments.Count == 1 && attr.Arguments.SingleOrDefault() is PrimitiveExpression pe
&& pe.Value is string s && s == feature)
{
attr.Remove();
found = true;
}
}
if (section.Attributes.Count == 0)
{
section.Remove();
}
}
return found;
}
bool FindAttribute(EntityDeclaration entityDecl, KnownAttribute attributeType, out Syntax.Attribute attribute)
{
attribute = null;

15
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -1553,12 +1553,25 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1553,12 +1553,25 @@ namespace ICSharpCode.Decompiler.CSharp
CastArguments(argumentList.Arguments, argumentList.ExpectedParameters);
break; // make sure that we don't not end up in an infinite loop
}
IType returnTypeOverride = null;
if (typeSystem.MainModule.TypeSystemOptions.HasFlag(TypeSystemOptions.NativeIntegersWithoutAttribute))
{
// For DeclaringType, we don't use nint/nuint (so that DeclaringType.GetConstructors etc. works),
// but in NativeIntegersWithoutAttribute mode we must use nint/nuint for expression types,
// so that the appropriate set of conversions is used for further overload resolution.
if (method.DeclaringType.IsKnownType(KnownTypeCode.IntPtr))
returnTypeOverride = SpecialType.NInt;
else if (method.DeclaringType.IsKnownType(KnownTypeCode.UIntPtr))
returnTypeOverride = SpecialType.NUInt;
}
return new ObjectCreateExpression(
expressionBuilder.ConvertType(method.DeclaringType),
argumentList.GetArgumentExpressions()
).WithRR(new CSharpInvocationResolveResult(
target, method, argumentList.GetArgumentResolveResults().ToArray(),
isExpandedForm: argumentList.IsExpandedForm, argumentToParameterMap: argumentList.ArgumentToParameterMap
isExpandedForm: argumentList.IsExpandedForm,
argumentToParameterMap: argumentList.ArgumentToParameterMap,
returnTypeOverride: returnTypeOverride
));
}
}

21
ICSharpCode.Decompiler/DecompilerSettings.cs

@ -152,12 +152,13 @@ namespace ICSharpCode.Decompiler @@ -152,12 +152,13 @@ namespace ICSharpCode.Decompiler
parameterNullCheck = false;
lifetimeAnnotations = false;
requiredMembers = false;
numericIntPtr = false;
}
}
public CSharp.LanguageVersion GetMinimumRequiredVersion()
{
if (parameterNullCheck || lifetimeAnnotations || requiredMembers)
if (parameterNullCheck || lifetimeAnnotations || requiredMembers || numericIntPtr)
return CSharp.LanguageVersion.CSharp11_0;
if (fileScopedNamespaces || recordStructs)
return CSharp.LanguageVersion.CSharp10_0;
@ -211,6 +212,24 @@ namespace ICSharpCode.Decompiler @@ -211,6 +212,24 @@ namespace ICSharpCode.Decompiler
}
}
bool numericIntPtr = true;
/// <summary>
/// Treat <c>IntPtr</c>/<c>UIntPtr</c> as <c>nint</c>/<c>nuint</c>.
/// </summary>
[Category("C# 11.0 / VS 2022.4")]
[Description("DecompilerSettings.NumericIntPtr")]
public bool NumericIntPtr {
get { return numericIntPtr; }
set {
if (numericIntPtr != value)
{
numericIntPtr = value;
OnPropertyChanged();
}
}
}
bool covariantReturns = true;
/// <summary>

17
ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs

@ -388,7 +388,22 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -388,7 +388,22 @@ namespace ICSharpCode.Decompiler.IL.Transforms
isInlinedIsInst = false;
if (condition.MatchCompNotEquals(out var left, out var right))
{
if (left.MatchIsInst(out var arg, out var type) && type.IsKnownType(disposeType))
if (left.MatchStLoc(out var inlineAssignVar, out var inlineAssignVal))
{
if (!inlineAssignVal.MatchIsInst(out var arg, out var type) && type.IsKnownType(disposeType))
return false;
if (!inlineAssignVar.IsSingleDefinition || inlineAssignVar.LoadCount != 1)
return false;
if (!inlineAssignVar.Type.IsKnownType(disposeType))
return false;
isInlinedIsInst = true;
left = arg;
if (!left.MatchLdLoc(objVar) || !right.MatchLdNull())
return false;
objVar = inlineAssignVar;
return true;
}
else if (left.MatchIsInst(out var arg, out var type) && type.IsKnownType(disposeType))
{
isInlinedIsInst = true;
left = arg;

2
ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs

@ -44,7 +44,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -44,7 +44,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
{
bool hasDynamicAttribute = false;
bool[] dynamicAttributeData = null;
bool hasNativeIntegersAttribute = false;
bool hasNativeIntegersAttribute = (options & TypeSystemOptions.NativeIntegersWithoutAttribute) != 0;
bool[] nativeIntegersAttributeData = null;
string[] tupleElementNames = null;
Nullability nullability;

14
ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs

@ -125,11 +125,17 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -125,11 +125,17 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// </summary>
LifetimeAnnotations = 0x4000,
/// <summary>
/// Replace 'IntPtr' types with the 'nint' type even in absence of [NativeIntegerAttribute].
/// Note: DecompilerTypeSystem constructor removes this setting from the options if
/// not targeting .NET 7 or later.
/// </summary>
NativeIntegersWithoutAttribute = 0x8000,
/// <summary>
/// Default settings: typical options for the decompiler, with all C# languages features enabled.
/// </summary>
Default = Dynamic | Tuple | ExtensionMethods | DecimalConstants | ReadOnlyStructsAndParameters
| RefStructs | UnmanagedConstraints | NullabilityAnnotations | ReadOnlyMethods
| NativeIntegers | FunctionPointers | LifetimeAnnotations
| NativeIntegers | FunctionPointers | LifetimeAnnotations | NativeIntegersWithoutAttribute
}
/// <summary>
@ -167,6 +173,8 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -167,6 +173,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
typeSystemOptions |= TypeSystemOptions.FunctionPointers;
if (settings.LifetimeAnnotations)
typeSystemOptions |= TypeSystemOptions.LifetimeAnnotations;
if (settings.NumericIntPtr)
typeSystemOptions |= TypeSystemOptions.NativeIntegersWithoutAttribute;
return typeSystemOptions;
}
@ -304,6 +312,10 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -304,6 +312,10 @@ namespace ICSharpCode.Decompiler.TypeSystem
}
}
if (!(identifier == TargetFrameworkIdentifier.NET && version >= new Version(7, 0)))
{
typeSystemOptions &= ~TypeSystemOptions.NativeIntegersWithoutAttribute;
}
var mainModuleWithOptions = mainModule.WithOptions(typeSystemOptions);
var referencedAssembliesWithOptions = referencedAssemblies.Select(file => file.WithOptions(typeSystemOptions));
// Primitive types are necessary to avoid assertions in ILReader.

2
ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs

@ -33,6 +33,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -33,6 +33,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
None,
CompilerGenerated,
CompilerFeatureRequired,
/// <summary>
/// Marks a method as extension method; or a class as containing extension methods.
/// </summary>
@ -119,6 +120,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -119,6 +120,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
static readonly TopLevelTypeName[] typeNames = new TopLevelTypeName[Count]{
default,
new TopLevelTypeName("System.Runtime.CompilerServices", nameof(CompilerGeneratedAttribute)),
new TopLevelTypeName("System.Runtime.CompilerServices", "CompilerFeatureRequiredAttribute"),
new TopLevelTypeName("System.Runtime.CompilerServices", nameof(ExtensionAttribute)),
new TopLevelTypeName("System.Runtime.CompilerServices", nameof(DynamicAttribute)),
new TopLevelTypeName("System.Runtime.CompilerServices", nameof(TupleElementNamesAttribute)),

5
ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs

@ -402,8 +402,9 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -402,8 +402,9 @@ namespace ICSharpCode.Decompiler.TypeSystem
IType ResolveDeclaringType(EntityHandle declaringTypeReference, GenericContext context)
{
// resolve without substituting dynamic/tuple types
var ty = ResolveType(declaringTypeReference, context,
options & ~(TypeSystemOptions.Dynamic | TypeSystemOptions.Tuple | TypeSystemOptions.NullabilityAnnotations));
const TypeSystemOptions removedOptions = TypeSystemOptions.Dynamic | TypeSystemOptions.Tuple
| TypeSystemOptions.NullabilityAnnotations | TypeSystemOptions.NativeIntegers | TypeSystemOptions.NativeIntegersWithoutAttribute;
var ty = ResolveType(declaringTypeReference, context, options & ~removedOptions);
// but substitute tuple types in type arguments:
ty = ApplyAttributeTypeVisitor.ApplyAttributesToType(ty, Compilation, null, metadata, options, Nullability.Oblivious, typeChildrenOnly: true);
return ty;

2
ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs

@ -239,7 +239,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -239,7 +239,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
bool IsUnmanagedTypeInternal(IType type)
{
if (type.Kind is TypeKind.Enum or TypeKind.Pointer or TypeKind.FunctionPointer)
if (type.Kind is TypeKind.Enum or TypeKind.Pointer or TypeKind.FunctionPointer or TypeKind.NInt or TypeKind.NUInt)
{
return true;
}

9
ILSpy/Properties/Resources.Designer.cs generated

@ -1108,6 +1108,15 @@ namespace ICSharpCode.ILSpy.Properties { @@ -1108,6 +1108,15 @@ namespace ICSharpCode.ILSpy.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Treat (U)IntPtr as n(u)int.
/// </summary>
public static string DecompilerSettings_NumericIntPtr {
get {
return ResourceManager.GetString("DecompilerSettings.NumericIntPtr", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Object/collection initializer expressions.
/// </summary>

3
ILSpy/Properties/Resources.resx

@ -393,6 +393,9 @@ Are you sure you want to continue?</value> @@ -393,6 +393,9 @@ Are you sure you want to continue?</value>
<data name="DecompilerSettings.NullableReferenceTypes" xml:space="preserve">
<value>Nullable reference types</value>
</data>
<data name="DecompilerSettings.NumericIntPtr" xml:space="preserve">
<value>Treat (U)IntPtr as n(u)int</value>
</data>
<data name="DecompilerSettings.ObjectCollectionInitializerExpressions" xml:space="preserve">
<value>Object/collection initializer expressions</value>
</data>

6
README.md

@ -24,7 +24,7 @@ Features @@ -24,7 +24,7 @@ Features
-------
* Decompilation to C# (check out the [language support status](https://github.com/icsharpcode/ILSpy/issues/829))
* Whole-project decompilation (csproj, not sln!)
* Whole-project decompilation
* Search for types/methods/properties (learn about the [options](https://github.com/icsharpcode/ILSpy/wiki/Search-Options))
* Hyperlink-based type/method/property navigation
* Base/Derived types navigation, history
@ -52,7 +52,7 @@ How to build @@ -52,7 +52,7 @@ How to build
- Follow Microsoft's instructions for [importing a configuration](https://docs.microsoft.com/en-us/visualstudio/install/import-export-installation-configurations?view=vs-2022#import-a-configuration), and import the .vsconfig file located at the root of the solution.
- Alternatively, you can open the ILSpy solution (ILSpy.sln) and Visual Studio will [prompt you to install the missing components](https://docs.microsoft.com/en-us/visualstudio/install/import-export-installation-configurations?view=vs-2022#automatically-install-missing-components).
- Finally, you can manually install the necessary components via the Visual Studio Installer. The workloads/components are as follows:
- Workload ".NET Desktop Development". This workload includes the .NET Framework 4.8 SDK and the .NET Framework 4.7.2 targeting pack, as well as the [.NET 6.0 SDK](https://dotnet.microsoft.com/download/dotnet/6.0) (ILSpy.csproj targets .NET 6.0, but we have net472 projects too). _Note: The optional components of this workload are not required for ILSpy_
- Workload ".NET Desktop Development". This workload includes the .NET Framework 4.8 SDK and the .NET Framework 4.7.2 targeting pack, as well as the [.NET 6.0 SDK](https://dotnet.microsoft.com/download/dotnet/6.0) and [.NET 7.0 SDK](https://dotnet.microsoft.com/download/dotnet/7.0) (ILSpy.csproj targets .NET 6.0, but we have net472+net70 projects too). _Note: The optional components of this workload are not required for ILSpy_
- Workload "Visual Studio extension development" (ILSpy.sln contains a VS extension project) _Note: The optional components of this workload are not required for ILSpy_
- Individual Component "MSVC v143 - VS 2022 C++ x64/x86 build tools" (or similar)
- _The VC++ toolset is optional_; if present it is used for `editbin.exe` to modify the stack size used by ILSpy.exe from 1MB to 16MB, because the decompiler makes heavy use of recursion, where small stack sizes lead to problems in very complex methods.
@ -65,7 +65,7 @@ How to build @@ -65,7 +65,7 @@ How to build
- ILSpy.XPlat.slnf: for the cross-platform CLI or PowerShell cmdlets
- ILSpy.AddIn.slnf: for the Visual Studio plugin
**Note:** Visual Studio 16.3 and later include a version of the .NET (Core) SDK that is managed by the Visual Studio installer - once you update, it may get upgraded too.
**Note:** Visual Studio includes a version of the .NET SDK that is managed by the Visual Studio installer - once you update, it may get upgraded too.
Please note that ILSpy is only compatible with the .NET 6.0 SDK and Visual Studio will refuse to load some projects in the solution (and unit tests will fail).
If this problem occurs, please manually install the .NET 6.0 SDK from [here](https://dotnet.microsoft.com/download/dotnet/6.0).

2
global.json

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
{
"sdk": {
"version": "6.0.200",
"version": "7.0.100",
"rollForward": "major",
"allowPrerelease": true
}

Loading…
Cancel
Save