diff --git a/ICSharpCode.Decompiler.TestRunner/ICSharpCode.Decompiler.TestRunner.csproj b/ICSharpCode.Decompiler.TestRunner/ICSharpCode.Decompiler.TestRunner.csproj
index c60a25481..8c8d40ddc 100644
--- a/ICSharpCode.Decompiler.TestRunner/ICSharpCode.Decompiler.TestRunner.csproj
+++ b/ICSharpCode.Decompiler.TestRunner/ICSharpCode.Decompiler.TestRunner.csproj
@@ -2,7 +2,7 @@
Exe
- net6.0-windows
+ net7.0
enable
diff --git a/ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs b/ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs
index d06c6768e..ed4a3f2bb 100644
--- a/ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs
+++ b/ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs
@@ -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
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;
diff --git a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs
index 3d35779e1..6219c2a1a 100644
--- a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs
+++ b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs
@@ -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
}
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
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
{
preprocessorSymbols.Add("NETCORE");
preprocessorSymbols.Add("NET60");
+ preprocessorSymbols.Add("NET70");
}
preprocessorSymbols.Add("ROSLYN");
preprocessorSymbols.Add("CS60");
diff --git a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
index d1dfd0774..c4027fc39 100644
--- a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
+++ b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
@@ -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
}
[Test]
- public async Task NativeInts([ValueSource(nameof(roslyn3OrNewerOptions))] CompilerOptions cscOptions)
+ public async Task NativeInts([ValueSource(nameof(roslyn3OrNewerWithNet40Options))] CompilerOptions cscOptions)
{
await RunForLibrary(cscOptions: cscOptions);
}
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/OverloadResolution.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/OverloadResolution.cs
index 6d829ce95..e206872a5 100644
--- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/OverloadResolution.cs
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/OverloadResolution.cs
@@ -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
#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
{
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ConstantsTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ConstantsTests.cs
index 8032484ce..5df746cc0 100644
--- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ConstantsTests.cs
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ConstantsTests.cs
@@ -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
{
return null;
}
+#endif
public ulong Issue1308(ulong u = 8uL)
{
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.cs
index c56524281..01edd50d2 100644
--- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.cs
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.cs
@@ -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)
{
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/FunctionPointers.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/FunctionPointers.cs
index faa752bcf..9423c4254 100644
--- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/FunctionPointers.cs
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/FunctionPointers.cs
@@ -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
return &Overloaded;
}
+#if !(CS110 && NET70)
public unsafe IntPtr GetAddressAsIntPtr()
{
return (IntPtr)(delegate*)(&Overloaded);
}
+#endif
+
+ public unsafe nint GetAddressAsNInt()
+ {
+ return (nint)(delegate*)(&Overloaded);
+ }
public unsafe void* GetAddressAsVoidPtr()
{
@@ -93,6 +102,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
internal class FunctionPointersWithNativeIntegerTypes
{
public unsafe delegate* F1;
+ #if !(CS110 && NET70)
public unsafe delegate* F2;
public unsafe delegate* F3;
public unsafe delegate* F4;
@@ -100,6 +110,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public unsafe delegate*> F6;
public unsafe delegate*, IntPtr> F7;
public unsafe delegate*> F8;
+ public unsafe delegate*> F9;
+ #endif
}
internal class FunctionPointersWithRefParams
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs
index c4d784fd4..677f6ebaf 100644
--- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs
@@ -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
}
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NativeInts.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NativeInts.cs
index 549fd42ee..2cb9f7a26 100644
--- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NativeInts.cs
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NativeInts.cs
@@ -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 dict1;
private Dictionary dict2;
private Dictionary dict3;
private Dictionary dict4;
+#endif
+ private Dictionary 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
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
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
{
GetInstance(3).u *= 2u;
}
+#if !(CS110 && NET70)
GetInstance(4).intptr += (nint)i32;
checked
{
@@ -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
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
intptr = intPtr;
i = num + 1;
+#endif
}
public nint NegateUnsigned(nuint x)
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/PInvoke.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/PInvoke.cs
index b8483ecc1..877c8e393 100644
--- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/PInvoke.cs
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/PInvoke.cs
@@ -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;
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs
index 2bb122eb3..9901fd69e 100644
--- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs
@@ -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
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
{
return (void*)intptr;
}
+#endif
private unsafe static void* CastToVoidPtr(int* intptr)
{
diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
index d89d77648..86ae6bf22 100644
--- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
+++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
@@ -1406,6 +1406,7 @@ namespace ICSharpCode.Decompiler.CSharp
attr.Remove();
}
}
+ RemoveCompilerFeatureRequiredAttribute(typeDecl, "RefStructs");
}
if (settings.RequiredMembers)
{
@@ -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;
diff --git a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs
index 3d53263cd..d256cf625 100644
--- a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs
+++ b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs
@@ -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
));
}
}
diff --git a/ICSharpCode.Decompiler/DecompilerSettings.cs b/ICSharpCode.Decompiler/DecompilerSettings.cs
index 4ce0c44c0..fe4789422 100644
--- a/ICSharpCode.Decompiler/DecompilerSettings.cs
+++ b/ICSharpCode.Decompiler/DecompilerSettings.cs
@@ -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
}
}
+ bool numericIntPtr = true;
+
+ ///
+ /// Treat IntPtr/UIntPtr as nint/nuint.
+ ///
+ [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;
///
diff --git a/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs
index c2a84f46c..ee3b705ea 100644
--- a/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs
+++ b/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs
@@ -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;
diff --git a/ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs b/ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs
index 5235da470..a6ba7ef15 100644
--- a/ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs
@@ -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;
diff --git a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
index b20d1bb0e..5898fa32e 100644
--- a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
@@ -125,11 +125,17 @@ namespace ICSharpCode.Decompiler.TypeSystem
///
LifetimeAnnotations = 0x4000,
///
+ /// 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.
+ ///
+ NativeIntegersWithoutAttribute = 0x8000,
+ ///
/// Default settings: typical options for the decompiler, with all C# languages features enabled.
///
Default = Dynamic | Tuple | ExtensionMethods | DecimalConstants | ReadOnlyStructsAndParameters
| RefStructs | UnmanagedConstraints | NullabilityAnnotations | ReadOnlyMethods
- | NativeIntegers | FunctionPointers | LifetimeAnnotations
+ | NativeIntegers | FunctionPointers | LifetimeAnnotations | NativeIntegersWithoutAttribute
}
///
@@ -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
}
}
+ 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.
diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs
index d6d99977a..31fba0891 100644
--- a/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs
@@ -33,6 +33,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
None,
CompilerGenerated,
+ CompilerFeatureRequired,
///
/// Marks a method as extension method; or a class as containing extension methods.
///
@@ -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)),
diff --git a/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs b/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs
index cf6ae1be5..3481ac1c8 100644
--- a/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs
@@ -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;
diff --git a/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs b/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs
index 9da26dbe7..3ce5d0180 100644
--- a/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs
+++ b/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs
@@ -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;
}
diff --git a/ILSpy/Properties/Resources.Designer.cs b/ILSpy/Properties/Resources.Designer.cs
index 94c50345b..60123a44f 100644
--- a/ILSpy/Properties/Resources.Designer.cs
+++ b/ILSpy/Properties/Resources.Designer.cs
@@ -1108,6 +1108,15 @@ namespace ICSharpCode.ILSpy.Properties {
}
}
+ ///
+ /// Looks up a localized string similar to Treat (U)IntPtr as n(u)int.
+ ///
+ public static string DecompilerSettings_NumericIntPtr {
+ get {
+ return ResourceManager.GetString("DecompilerSettings.NumericIntPtr", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Object/collection initializer expressions.
///
diff --git a/ILSpy/Properties/Resources.resx b/ILSpy/Properties/Resources.resx
index 82d434c12..186665d73 100644
--- a/ILSpy/Properties/Resources.resx
+++ b/ILSpy/Properties/Resources.resx
@@ -393,6 +393,9 @@ Are you sure you want to continue?
Nullable reference types
+
+ Treat (U)IntPtr as n(u)int
+
Object/collection initializer expressions
diff --git a/README.md b/README.md
index 19d4a4dc8..92b843aaf 100644
--- a/README.md
+++ b/README.md
@@ -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
- 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
- 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).
diff --git a/global.json b/global.json
index 68d9ecef8..1fcfe4fee 100644
--- a/global.json
+++ b/global.json
@@ -1,6 +1,6 @@
{
"sdk": {
- "version": "6.0.200",
+ "version": "7.0.100",
"rollForward": "major",
"allowPrerelease": true
}