Browse Source

Fix "ref readonly" fields.

pull/2992/head
Daniel Grunwald 2 years ago
parent
commit
475f2b3c28
  1. 7
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  2. 6
      ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
  3. 4
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Records.cs
  4. 36
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/RefFields.cs
  5. 4
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  6. 2
      ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs
  7. 5
      ICSharpCode.Decompiler/TypeSystem/IField.cs
  8. 1
      ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs
  9. 1
      ICSharpCode.Decompiler/TypeSystem/Implementation/FakeMember.cs
  10. 7
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs
  11. 10
      ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedField.cs

7
ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj

@ -9,7 +9,7 @@
<AllowUnsafeBlocks>True</AllowUnsafeBlocks> <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<NoWarn>1701;1702;1705,67,169,1058,728,1720,649,168,251,660,661,675;1998;162;8632</NoWarn> <NoWarn>1701;1702;1705,67,169,1058,728,1720,649,168,251,660,661,675;1998;162;8632;626;8618;8714;8602</NoWarn>
<GenerateAssemblyVersionAttribute>False</GenerateAssemblyVersionAttribute> <GenerateAssemblyVersionAttribute>False</GenerateAssemblyVersionAttribute>
<GenerateAssemblyFileVersionAttribute>False</GenerateAssemblyFileVersionAttribute> <GenerateAssemblyFileVersionAttribute>False</GenerateAssemblyFileVersionAttribute>
@ -33,11 +33,11 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DefineConstants>TRACE;DEBUG;ROSLYN;CS60;CS70;CS71;CS72;CS73;CS80;CS90;CS100</DefineConstants> <DefineConstants>TRACE;DEBUG;ROSLYN;NET60;CS60;CS70;CS71;CS72;CS73;CS80;CS90;CS100</DefineConstants>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DefineConstants>TRACE;ROSLYN;CS60;CS70;CS71;CS72;CS73;CS80;CS90;CS100</DefineConstants> <DefineConstants>TRACE;ROSLYN;NET60;CS60;CS70;CS71;CS72;CS73;CS80;CS90;CS100</DefineConstants>
</PropertyGroup> </PropertyGroup>
<Import Project="..\packages.props" /> <Import Project="..\packages.props" />
@ -220,6 +220,7 @@
<None Include="TestCases\Pretty\MemberTests.cs" /> <None Include="TestCases\Pretty\MemberTests.cs" />
<Compile Include="TestCases\Pretty\NamedArguments.cs" /> <Compile Include="TestCases\Pretty\NamedArguments.cs" />
<Compile Include="TestCases\Pretty\QualifierTests.cs" /> <Compile Include="TestCases\Pretty\QualifierTests.cs" />
<None Include="TestCases\Pretty\RefFields.cs" />
<Compile Include="TestCases\Pretty\RefLocalsAndReturns.cs" /> <Compile Include="TestCases\Pretty\RefLocalsAndReturns.cs" />
<Compile Include="TestCases\Pretty\TupleTests.cs" /> <Compile Include="TestCases\Pretty\TupleTests.cs" />
<Compile Include="TestCases\Pretty\WellKnownConstants.cs" /> <Compile Include="TestCases\Pretty\WellKnownConstants.cs" />

6
ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs

@ -538,6 +538,12 @@ namespace ICSharpCode.Decompiler.Tests
await RunForLibrary(cscOptions: cscOptions); await RunForLibrary(cscOptions: cscOptions);
} }
[Test]
public async Task RefFields([ValueSource(nameof(roslyn4OrNewerOptions))] CompilerOptions cscOptions)
{
await RunForLibrary(cscOptions: cscOptions);
}
[Test] [Test]
public async Task ThrowExpressions([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions) public async Task ThrowExpressions([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
{ {

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

@ -1,5 +1,5 @@
using System; using System;
#if ROSLYN4 #if CS100
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
#endif #endif
@ -242,6 +242,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
} }
#endif #endif
} }
#if !NET60
namespace System.Runtime.CompilerServices namespace System.Runtime.CompilerServices
{ {
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)] [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
@ -261,3 +262,4 @@ namespace System.Runtime.CompilerServices
{ {
} }
} }
#endif

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

@ -0,0 +1,36 @@
using System;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
internal ref struct RefFields
{
private ref int Field0;
private ref readonly int Field1;
private readonly ref int Field2;
private readonly ref readonly int Field3;
public int PropertyAccessingRefFieldByValue {
get {
return Field0;
}
set {
Field0 = value;
}
}
public ref int PropertyReturningRefFieldByReference => ref Field0;
public void Uses(int[] array)
{
Field1 = ref array[0];
Field2 = array[0];
}
public void ReadonlyLocal()
{
ref readonly int field = ref Field1;
Console.WriteLine("No inlining");
field.ToString();
}
}
}

4
ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs

@ -1970,6 +1970,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
decl.AddAnnotation(new MemberResolveResult(null, field)); decl.AddAnnotation(new MemberResolveResult(null, field));
} }
decl.ReturnType = ConvertType(field.ReturnType); decl.ReturnType = ConvertType(field.ReturnType);
if (decl.ReturnType is ComposedType ct && ct.HasRefSpecifier && field.ReturnTypeIsRefReadOnly)
{
ct.HasReadOnlySpecifier = true;
}
Expression initializer = null; Expression initializer = null;
if (field.IsConst && this.ShowConstantValues) if (field.IsConst && this.ShowConstantValues)
{ {

2
ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs

@ -494,6 +494,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// C# doesn't allow mutation of value-type temporaries // C# doesn't allow mutation of value-type temporaries
return true; return true;
default: default:
if (addr.MatchLdFld(out _, out var field))
return field.ReturnTypeIsRefReadOnly;
return false; return false;
} }
} }

5
ICSharpCode.Decompiler/TypeSystem/IField.cs

@ -35,6 +35,11 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// </summary> /// </summary>
bool IsReadOnly { get; } bool IsReadOnly { get; }
/// <summary>
/// Gets whether the field type is 'ref readonly'.
/// </summary>
bool ReturnTypeIsRefReadOnly { get; }
/// <summary> /// <summary>
/// Gets whether this field is volatile. /// Gets whether this field is volatile.
/// </summary> /// </summary>

1
ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs

@ -238,6 +238,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
case SymbolKind.ReturnType: case SymbolKind.ReturnType:
case SymbolKind.Property: case SymbolKind.Property:
case SymbolKind.Indexer: case SymbolKind.Indexer:
case SymbolKind.Field:
return true; // "ref readonly" is currently always active return true; // "ref readonly" is currently always active
default: default:
return false; return false;

1
ICSharpCode.Decompiler/TypeSystem/Implementation/FakeMember.cs

@ -109,6 +109,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
} }
bool IField.IsReadOnly => false; bool IField.IsReadOnly => false;
bool IField.ReturnTypeIsRefReadOnly => false;
bool IField.IsVolatile => false; bool IField.IsVolatile => false;
bool IVariable.IsConst => false; bool IVariable.IsConst => false;

7
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs

@ -189,6 +189,13 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return b.GetAttribute(metadata, def.GetCustomAttributes(), attribute, SymbolKind.Field); return b.GetAttribute(metadata, def.GetCustomAttributes(), attribute, SymbolKind.Field);
} }
public bool ReturnTypeIsRefReadOnly {
get {
var def = module.metadata.GetFieldDefinition(handle);
return def.GetCustomAttributes().HasKnownAttribute(module.metadata, KnownAttribute.IsReadOnly);
}
}
public string FullName => $"{DeclaringType?.FullName}.{Name}"; public string FullName => $"{DeclaringType?.FullName}.{Name}";
public string ReflectionName => $"{DeclaringType?.ReflectionName}.{Name}"; public string ReflectionName => $"{DeclaringType?.ReflectionName}.{Name}";
public string Namespace => DeclaringType?.Namespace ?? string.Empty; public string Namespace => DeclaringType?.Namespace ?? string.Empty;

10
ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedField.cs

@ -45,13 +45,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
AddSubstitution(substitution); AddSubstitution(substitution);
} }
public bool IsReadOnly { public bool IsReadOnly => fieldDefinition.IsReadOnly;
get { return fieldDefinition.IsReadOnly; } public bool ReturnTypeIsRefReadOnly => fieldDefinition.ReturnTypeIsRefReadOnly;
} public bool IsVolatile => fieldDefinition.IsVolatile;
public bool IsVolatile {
get { return fieldDefinition.IsVolatile; }
}
IType IVariable.Type { IType IVariable.Type {
get { return this.ReturnType; } get { return this.ReturnType; }

Loading…
Cancel
Save