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 @@ @@ -9,7 +9,7 @@
<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>
<GenerateAssemblyFileVersionAttribute>False</GenerateAssemblyFileVersionAttribute>
@ -33,11 +33,11 @@ @@ -33,11 +33,11 @@
</PropertyGroup>
<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 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>
<Import Project="..\packages.props" />
@ -220,6 +220,7 @@ @@ -220,6 +220,7 @@
<None Include="TestCases\Pretty\MemberTests.cs" />
<Compile Include="TestCases\Pretty\NamedArguments.cs" />
<Compile Include="TestCases\Pretty\QualifierTests.cs" />
<None Include="TestCases\Pretty\RefFields.cs" />
<Compile Include="TestCases\Pretty\RefLocalsAndReturns.cs" />
<Compile Include="TestCases\Pretty\TupleTests.cs" />
<Compile Include="TestCases\Pretty\WellKnownConstants.cs" />

6
ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs

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

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

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

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

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

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

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

5
ICSharpCode.Decompiler/TypeSystem/IField.cs

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

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

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

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

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

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

@ -189,6 +189,13 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -189,6 +189,13 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
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 ReflectionName => $"{DeclaringType?.ReflectionName}.{Name}";
public string Namespace => DeclaringType?.Namespace ?? string.Empty;

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

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

Loading…
Cancel
Save