Browse Source

Remove IsRef, IsOut and IsIn flags from IParameter and Replace ParameterModifiers with ReferenceKind.

pull/3239/head
Siegfried Pammer 11 months ago
parent
commit
4bf9487ecd
  1. 8
      ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs
  2. 13
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  3. 2
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  4. 2
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  5. 4
      ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs
  6. 20
      ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs
  7. 6
      ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs
  8. 4
      ICSharpCode.Decompiler/CSharp/Resolver/CSharpConversions.cs
  9. 50
      ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ParameterDeclaration.cs
  10. 30
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  11. 2
      ICSharpCode.Decompiler/CSharp/Transforms/IntroduceQueryExpressions.cs
  12. 4
      ICSharpCode.Decompiler/FlowAnalysis/DefiniteAssignmentVisitor.cs
  13. 2
      ICSharpCode.Decompiler/IL/ILReader.cs
  14. 2
      ICSharpCode.Decompiler/IL/Instructions/MatchInstruction.cs
  15. 4
      ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs
  16. 1
      ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs
  17. 10
      ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
  18. 18
      ICSharpCode.Decompiler/TypeSystem/IParameter.cs
  19. 17
      ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultParameter.cs
  20. 11
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs
  21. 3
      ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedParameter.cs

8
ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs

@ -1390,18 +1390,18 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
{ {
ITypeDefinition impl = GetTypeDefinition(typeof(ExplicitGenericInterfaceImplementation)); ITypeDefinition impl = GetTypeDefinition(typeof(ExplicitGenericInterfaceImplementation));
IType genericInterfaceOfString = compilation.FindType(typeof(IGenericInterface<string>)); IType genericInterfaceOfString = compilation.FindType(typeof(IGenericInterface<string>));
IMethod implMethod1 = impl.Methods.Single(m => !m.IsConstructor && !m.Parameters[1].IsRef); IMethod implMethod1 = impl.Methods.Single(m => !m.IsConstructor && m.Parameters[1].ReferenceKind == ReferenceKind.None);
IMethod implMethod2 = impl.Methods.Single(m => !m.IsConstructor && m.Parameters[1].IsRef); IMethod implMethod2 = impl.Methods.Single(m => !m.IsConstructor && m.Parameters[1].ReferenceKind == ReferenceKind.Ref);
Assert.That(implMethod1.IsExplicitInterfaceImplementation); Assert.That(implMethod1.IsExplicitInterfaceImplementation);
Assert.That(implMethod2.IsExplicitInterfaceImplementation); Assert.That(implMethod2.IsExplicitInterfaceImplementation);
IMethod interfaceMethod1 = (IMethod)implMethod1.ExplicitlyImplementedInterfaceMembers.Single(); IMethod interfaceMethod1 = (IMethod)implMethod1.ExplicitlyImplementedInterfaceMembers.Single();
Assert.That(interfaceMethod1.DeclaringType, Is.EqualTo(genericInterfaceOfString)); Assert.That(interfaceMethod1.DeclaringType, Is.EqualTo(genericInterfaceOfString));
Assert.That(!interfaceMethod1.Parameters[1].IsRef); Assert.That(interfaceMethod1.Parameters[1].ReferenceKind == ReferenceKind.None);
IMethod interfaceMethod2 = (IMethod)implMethod2.ExplicitlyImplementedInterfaceMembers.Single(); IMethod interfaceMethod2 = (IMethod)implMethod2.ExplicitlyImplementedInterfaceMembers.Single();
Assert.That(interfaceMethod2.DeclaringType, Is.EqualTo(genericInterfaceOfString)); Assert.That(interfaceMethod2.DeclaringType, Is.EqualTo(genericInterfaceOfString));
Assert.That(interfaceMethod2.Parameters[1].IsRef); Assert.That(interfaceMethod2.Parameters[1].ReferenceKind == ReferenceKind.Ref);
} }
[Test] [Test]

13
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -1167,7 +1167,7 @@ namespace ICSharpCode.Decompiler.CSharp
Roles.Comment); Roles.Comment);
var forwardingCall = new InvocationExpression(new MemberReferenceExpression(new ThisReferenceExpression(), memberDecl.Name, var forwardingCall = new InvocationExpression(new MemberReferenceExpression(new ThisReferenceExpression(), memberDecl.Name,
methodDecl.TypeParameters.Select(tp => new SimpleType(tp.Name))), methodDecl.TypeParameters.Select(tp => new SimpleType(tp.Name))),
methodDecl.Parameters.Select(p => ForwardParameter(p)) methodDecl.Parameters.Select(ForwardParameter)
); );
if (m.ReturnType.IsKnownType(KnownTypeCode.Void)) if (m.ReturnType.IsKnownType(KnownTypeCode.Void))
{ {
@ -1185,12 +1185,17 @@ namespace ICSharpCode.Decompiler.CSharp
{ {
switch (p.ParameterModifier) switch (p.ParameterModifier)
{ {
case ParameterModifier.Ref: case ReferenceKind.None:
return new IdentifierExpression(p.Name);
case ReferenceKind.Ref:
case ReferenceKind.RefReadOnly:
return new DirectionExpression(FieldDirection.Ref, new IdentifierExpression(p.Name)); return new DirectionExpression(FieldDirection.Ref, new IdentifierExpression(p.Name));
case ParameterModifier.Out: case ReferenceKind.Out:
return new DirectionExpression(FieldDirection.Out, new IdentifierExpression(p.Name)); return new DirectionExpression(FieldDirection.Out, new IdentifierExpression(p.Name));
case ReferenceKind.In:
return new DirectionExpression(FieldDirection.In, new IdentifierExpression(p.Name));
default: default:
return new IdentifierExpression(p.Name); throw new NotSupportedException();
} }
} }

2
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -78,7 +78,7 @@ namespace ICSharpCode.Decompiler.CSharp
ResolveResult GetResolveResult(int index, TranslatedExpression expression) ResolveResult GetResolveResult(int index, TranslatedExpression expression)
{ {
var param = expectedParameters[index]; var param = expectedParameters[index];
if (useImplicitlyTypedOut && param.IsOut && expression.Type is ByReferenceType brt) if (useImplicitlyTypedOut && param.ReferenceKind == ReferenceKind.Out && expression.Type is ByReferenceType brt)
return new OutVarResolveResult(brt.ElementType); return new OutVarResolveResult(brt.ElementType);
return expression.ResolveResult; return expression.ResolveResult;
} }

2
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -2409,7 +2409,7 @@ namespace ICSharpCode.Decompiler.CSharp
// C# 10 lambdas can have attributes, but anonymous methods cannot // C# 10 lambdas can have attributes, but anonymous methods cannot
isLambda = true; isLambda = true;
} }
else if (settings.UseLambdaSyntax && ame.Parameters.All(p => p.ParameterModifier == ParameterModifier.None)) else if (settings.UseLambdaSyntax && ame.Parameters.All(p => p.ParameterModifier == ReferenceKind.None && !p.IsParams))
{ {
// otherwise use lambda only if an expression lambda is possible // otherwise use lambda only if an expression lambda is possible
isLambda = (body.Statements.Count == 1 && body.Statements.Single() is ReturnStatement); isLambda = (body.Statements.Count == 1 && body.Statements.Single() is ReturnStatement);

4
ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs

@ -135,7 +135,9 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{ {
if ((ConversionFlags & ConversionFlags.ShowParameterModifiers) == 0) if ((ConversionFlags & ConversionFlags.ShowParameterModifiers) == 0)
{ {
param.ParameterModifier = ParameterModifier.None; param.ParameterModifier = ReferenceKind.None;
param.IsScopedRef = false;
param.IsParams = false;
} }
if ((ConversionFlags & ConversionFlags.ShowParameterDefaultValues) == 0) if ((ConversionFlags & ConversionFlags.ShowParameterDefaultValues) == 0)
{ {

20
ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs

@ -1077,7 +1077,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
return true; return true;
} }
var p = lambdaExpression.Parameters.Single(); var p = lambdaExpression.Parameters.Single();
return !(p.Type.IsNull && p.ParameterModifier == ParameterModifier.None); return !(p.Type.IsNull && p.ParameterModifier == ReferenceKind.None && !p.IsParams);
} }
public virtual void VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression) public virtual void VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression)
@ -2608,6 +2608,11 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
WriteKeyword(ParameterDeclaration.ThisModifierRole); WriteKeyword(ParameterDeclaration.ThisModifierRole);
Space(); Space();
} }
if (parameterDeclaration.IsParams)
{
WriteKeyword(ParameterDeclaration.ParamsModifierRole);
Space();
}
if (parameterDeclaration.IsScopedRef) if (parameterDeclaration.IsScopedRef)
{ {
WriteKeyword(ParameterDeclaration.ScopedRefRole); WriteKeyword(ParameterDeclaration.ScopedRefRole);
@ -2615,19 +2620,20 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
} }
switch (parameterDeclaration.ParameterModifier) switch (parameterDeclaration.ParameterModifier)
{ {
case ParameterModifier.Ref: case ReferenceKind.Ref:
WriteKeyword(ParameterDeclaration.RefModifierRole); WriteKeyword(ParameterDeclaration.RefModifierRole);
Space(); Space();
break; break;
case ParameterModifier.Out: case ReferenceKind.RefReadOnly:
WriteKeyword(ParameterDeclaration.OutModifierRole); WriteKeyword(ParameterDeclaration.RefModifierRole);
WriteKeyword(ParameterDeclaration.ReadonlyModifierRole);
Space(); Space();
break; break;
case ParameterModifier.Params: case ReferenceKind.Out:
WriteKeyword(ParameterDeclaration.ParamsModifierRole); WriteKeyword(ParameterDeclaration.OutModifierRole);
Space(); Space();
break; break;
case ParameterModifier.In: case ReferenceKind.In:
WriteKeyword(ParameterDeclaration.InModifierRole); WriteKeyword(ParameterDeclaration.InModifierRole);
Space(); Space();
break; break;

6
ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs

@ -196,7 +196,7 @@ namespace ICSharpCode.Decompiler.CSharp
return false; return false;
if (!target.MatchLdThis()) if (!target.MatchLdThis())
return false; return false;
if (method.Parameters[i].IsIn) if (method.Parameters[i].ReferenceKind is ReferenceKind.In or ReferenceKind.RefReadOnly)
{ {
if (!valueInst.MatchLdObj(out valueInst, out _)) if (!valueInst.MatchLdObj(out valueInst, out _))
return false; return false;
@ -1012,11 +1012,11 @@ namespace ICSharpCode.Decompiler.CSharp
var deconstruct = method.Parameters[i]; var deconstruct = method.Parameters[i];
var ctor = primaryCtor.Parameters[i]; var ctor = primaryCtor.Parameters[i];
if (!deconstruct.IsOut) if (deconstruct.ReferenceKind != ReferenceKind.Out)
return false; return false;
IType ctorType = ctor.Type; IType ctorType = ctor.Type;
if (ctor.IsIn) if (ctor.ReferenceKind is ReferenceKind.In or ReferenceKind.RefReadOnly)
ctorType = ((ByReferenceType)ctorType).ElementType; ctorType = ((ByReferenceType)ctorType).ElementType;
if (!ctorType.Equals(((ByReferenceType)deconstruct.Type).ElementType)) if (!ctorType.Equals(((ByReferenceType)deconstruct.Type).ElementType))
return false; return false;

4
ICSharpCode.Decompiler/CSharp/Resolver/CSharpConversions.cs

@ -1128,7 +1128,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
foreach (IMethod op in operators) foreach (IMethod op in operators)
{ {
IType sourceType = op.Parameters[0].Type; IType sourceType = op.Parameters[0].Type;
if (sourceType.Kind == TypeKind.ByReference && op.Parameters[0].IsIn && fromType.Kind != TypeKind.ByReference) if (sourceType.Kind == TypeKind.ByReference && op.Parameters[0].ReferenceKind == ReferenceKind.In && fromType.Kind != TypeKind.ByReference)
{ {
sourceType = ((ByReferenceType)sourceType).ElementType; sourceType = ((ByReferenceType)sourceType).ElementType;
} }
@ -1235,7 +1235,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
// type, as long as no parameter of D has the out parameter modifier. // type, as long as no parameter of D has the out parameter modifier.
foreach (IParameter p in d.Parameters) foreach (IParameter p in d.Parameters)
{ {
if (p.IsOut) if (p.ReferenceKind == ReferenceKind.Out)
return Conversion.None; return Conversion.None;
} }
} }

50
ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ParameterDeclaration.cs

@ -26,32 +26,19 @@
#nullable enable #nullable enable
using System; using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.CSharp.Syntax namespace ICSharpCode.Decompiler.CSharp.Syntax
{ {
public enum ParameterModifier
{
None,
Ref,
Out,
Params,
In,
Scoped
}
public class ParameterDeclaration : AstNode public class ParameterDeclaration : AstNode
{ {
public static readonly Role<AttributeSection> AttributeRole = EntityDeclaration.AttributeRole; public static readonly Role<AttributeSection> AttributeRole = EntityDeclaration.AttributeRole;
public static readonly TokenRole ThisModifierRole = new TokenRole("this"); public static readonly TokenRole ThisModifierRole = new TokenRole("this");
public static readonly TokenRole ScopedRefRole = new TokenRole("scoped"); public static readonly TokenRole ScopedRefRole = new TokenRole("scoped");
[Obsolete("Renamed to ScopedRefRole")]
public static readonly TokenRole RefScopedRole = ScopedRefRole;
public static readonly TokenRole RefModifierRole = new TokenRole("ref"); public static readonly TokenRole RefModifierRole = new TokenRole("ref");
public static readonly TokenRole ReadonlyModifierRole = ComposedType.ReadonlyRole;
public static readonly TokenRole OutModifierRole = new TokenRole("out"); public static readonly TokenRole OutModifierRole = new TokenRole("out");
public static readonly TokenRole InModifierRole = new TokenRole("in"); public static readonly TokenRole InModifierRole = new TokenRole("in");
[Obsolete("C# 11 preview: \"ref scoped\" no longer supported")]
public static readonly TokenRole ValueScopedRole = new TokenRole("scoped");
public static readonly TokenRole ParamsModifierRole = new TokenRole("params"); public static readonly TokenRole ParamsModifierRole = new TokenRole("params");
#region PatternPlaceholder #region PatternPlaceholder
@ -107,6 +94,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
} }
bool hasThisModifier; bool hasThisModifier;
bool isParams;
bool isScopedRef; bool isScopedRef;
public CSharpTokenNode ThisKeyword { public CSharpTokenNode ThisKeyword {
@ -127,16 +115,15 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
} }
} }
public bool IsScopedRef { public bool IsParams {
get { return isScopedRef; } get { return isParams; }
set { set {
ThrowIfFrozen(); ThrowIfFrozen();
isScopedRef = value; isParams = value;
} }
} }
[Obsolete("Renamed to IsScopedRef")] public bool IsScopedRef {
public bool IsRefScoped {
get { return isScopedRef; } get { return isScopedRef; }
set { set {
ThrowIfFrozen(); ThrowIfFrozen();
@ -144,15 +131,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
} }
} }
[Obsolete("C# 11 preview: \"ref scoped\" no longer supported")] ReferenceKind parameterModifier;
public bool IsValueScoped {
get { return false; }
set { }
}
ParameterModifier parameterModifier; public ReferenceKind ParameterModifier {
public ParameterModifier ParameterModifier {
get { return parameterModifier; } get { return parameterModifier; }
set { set {
ThrowIfFrozen(); ThrowIfFrozen();
@ -240,19 +221,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{ {
} }
public ParameterDeclaration(AstType type, string name, ParameterModifier modifier = ParameterModifier.None)
{
Type = type;
Name = name;
ParameterModifier = modifier;
}
public ParameterDeclaration(string name, ParameterModifier modifier = ParameterModifier.None)
{
Name = name;
ParameterModifier = modifier;
}
public new ParameterDeclaration Clone() public new ParameterDeclaration Clone()
{ {
return (ParameterDeclaration)base.Clone(); return (ParameterDeclaration)base.Clone();

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

@ -372,14 +372,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
for (int i = 0; i < fpt.ParameterTypes.Length; i++) for (int i = 0; i < fpt.ParameterTypes.Length; i++)
{ {
var paramDecl = new ParameterDeclaration(); var paramDecl = new ParameterDeclaration();
paramDecl.ParameterModifier = fpt.ParameterReferenceKinds[i] switch { paramDecl.ParameterModifier = fpt.ParameterReferenceKinds[i];
ReferenceKind.In => ParameterModifier.In,
ReferenceKind.Ref => ParameterModifier.Ref,
ReferenceKind.Out => ParameterModifier.Out,
_ => ParameterModifier.None,
};
IType parameterType = fpt.ParameterTypes[i]; IType parameterType = fpt.ParameterTypes[i];
if (paramDecl.ParameterModifier != ParameterModifier.None && parameterType is ByReferenceType brt) if (paramDecl.ParameterModifier != ReferenceKind.None && parameterType is ByReferenceType brt)
{ {
paramDecl.Type = ConvertType(brt.ElementType); paramDecl.Type = ConvertType(brt.ElementType);
} }
@ -1649,22 +1644,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
if (parameter == null) if (parameter == null)
throw new ArgumentNullException(nameof(parameter)); throw new ArgumentNullException(nameof(parameter));
ParameterDeclaration decl = new ParameterDeclaration(); ParameterDeclaration decl = new ParameterDeclaration();
if (parameter.IsRef) decl.ParameterModifier = parameter.ReferenceKind;
{ decl.IsParams = parameter.IsParams;
decl.ParameterModifier = ParameterModifier.Ref;
}
else if (parameter.IsOut)
{
decl.ParameterModifier = ParameterModifier.Out;
}
else if (parameter.IsIn)
{
decl.ParameterModifier = ParameterModifier.In;
}
else if (parameter.IsParams)
{
decl.ParameterModifier = ParameterModifier.Params;
}
decl.IsScopedRef = parameter.Lifetime.ScopedRef; decl.IsScopedRef = parameter.Lifetime.ScopedRef;
if (ShowAttributes) if (ShowAttributes)
{ {
@ -1685,7 +1666,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{ {
decl.Name = parameter.Name; decl.Name = parameter.Name;
} }
if (parameter.IsOptional && decl.ParameterModifier is ParameterModifier.None or ParameterModifier.In && parameter.HasConstantValueInSignature && this.ShowConstantValues) if (parameter.IsOptional && decl.ParameterModifier is ReferenceKind.None or ReferenceKind.In or ReferenceKind.RefReadOnly
&& parameter.HasConstantValueInSignature && this.ShowConstantValues)
{ {
try try
{ {

2
ICSharpCode.Decompiler/CSharp/Transforms/IntroduceQueryExpressions.cs

@ -389,7 +389,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
private static bool ValidateParameter(ParameterDeclaration p) private static bool ValidateParameter(ParameterDeclaration p)
{ {
return p.ParameterModifier == ParameterModifier.None && p.Attributes.Count == 0; return p.ParameterModifier == Decompiler.TypeSystem.ReferenceKind.None && p.Attributes.Count == 0;
} }
} }
} }

4
ICSharpCode.Decompiler/FlowAnalysis/DefiniteAssignmentVisitor.cs

@ -262,7 +262,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
bool hasOutArgs = false; bool hasOutArgs = false;
foreach (var arg in call.Arguments) foreach (var arg in call.Arguments)
{ {
if (arg.MatchLdLoca(out var v) && call.GetParameter(arg.ChildIndex)?.IsOut == true) if (arg.MatchLdLoca(out var v) && call.GetParameter(arg.ChildIndex)?.ReferenceKind == ReferenceKind.Out)
{ {
// Visiting ldloca would require the variable to be initialized, // Visiting ldloca would require the variable to be initialized,
// but we don't need out arguments to be initialized. // but we don't need out arguments to be initialized.
@ -278,7 +278,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
{ {
foreach (var arg in call.Arguments) foreach (var arg in call.Arguments)
{ {
if (arg.MatchLdLoca(out var v) && call.GetParameter(arg.ChildIndex)?.IsOut == true) if (arg.MatchLdLoca(out var v) && call.GetParameter(arg.ChildIndex)?.ReferenceKind == ReferenceKind.Out)
{ {
HandleStore(v); HandleStore(v);
} }

2
ICSharpCode.Decompiler/IL/ILReader.cs

@ -285,7 +285,7 @@ namespace ICSharpCode.Decompiler.IL
{ {
IParameter parameter = method.Parameters[paramIndex - offset]; IParameter parameter = method.Parameters[paramIndex - offset];
ILVariable ilVar = CreateILVariable(paramIndex - offset, parameter.Type, parameter.Name); ILVariable ilVar = CreateILVariable(paramIndex - offset, parameter.Type, parameter.Name);
ilVar.IsRefReadOnly = parameter.IsIn; ilVar.IsRefReadOnly = parameter.ReferenceKind is ReferenceKind.In or ReferenceKind.RefReadOnly;
parameterVariables[paramIndex] = ilVar; parameterVariables[paramIndex] = ilVar;
paramIndex++; paramIndex++;
} }

2
ICSharpCode.Decompiler/IL/Instructions/MatchInstruction.cs

@ -267,7 +267,7 @@ namespace ICSharpCode.Decompiler.IL
for (int i = firstOutParam; i < method.Parameters.Count; i++) for (int i = firstOutParam; i < method.Parameters.Count; i++)
{ {
if (!method.Parameters[i].IsOut) if (method.Parameters[i].ReferenceKind != ReferenceKind.Out)
return false; return false;
} }

4
ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs

@ -556,9 +556,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms
internal static bool IsClosureParameter(IParameter parameter, ITypeResolveContext context) internal static bool IsClosureParameter(IParameter parameter, ITypeResolveContext context)
{ {
if (!parameter.IsRef) if (parameter.Type is not ByReferenceType brt)
return false; return false;
var type = ((ByReferenceType)parameter.Type).ElementType.GetDefinition(); var type = brt.ElementType.GetDefinition();
return type != null return type != null
&& type.Kind == TypeKind.Struct && type.Kind == TypeKind.Struct
&& TransformDisplayClassUsage.IsPotentialClosure(context.CurrentTypeDefinition, type); && TransformDisplayClassUsage.IsPotentialClosure(context.CurrentTypeDefinition, type);

1
ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs

@ -343,6 +343,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
ReferenceKind.Ref => 1, ReferenceKind.Ref => 1,
ReferenceKind.Out => 2, // in/out also count the modreq ReferenceKind.Out => 2, // in/out also count the modreq
ReferenceKind.In => 2, ReferenceKind.In => 2,
ReferenceKind.RefReadOnly => 2, // counts the modopt
_ => throw new NotSupportedException() _ => throw new NotSupportedException()
}; };
parameters[i] = type.ParameterTypes[i].AcceptVisitor(this); parameters[i] = type.ParameterTypes[i].AcceptVisitor(this);

10
ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs

@ -124,8 +124,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// will be reported as custom attribute. /// will be reported as custom attribute.
/// </summary> /// </summary>
ScopedRef = 0x4000, ScopedRef = 0x4000,
[Obsolete("Use ScopedRef instead")]
LifetimeAnnotations = ScopedRef,
/// <summary> /// <summary>
/// Replace 'IntPtr' types with the 'nint' type even in absence of [NativeIntegerAttribute]. /// Replace 'IntPtr' types with the 'nint' type even in absence of [NativeIntegerAttribute].
/// Note: DecompilerTypeSystem constructor removes this setting from the options if /// Note: DecompilerTypeSystem constructor removes this setting from the options if
@ -133,11 +131,19 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// </summary> /// </summary>
NativeIntegersWithoutAttribute = 0x8000, NativeIntegersWithoutAttribute = 0x8000,
/// <summary> /// <summary>
/// If this option is active, [RequiresLocationAttribute] on parameters is removed
/// and parameters are marked as ref readonly.
/// Otherwise, the attribute is preserved but the parameters are not marked
/// as if it was a ref parameter without any attributes.
/// </summary>
RefReadOnlyParameters = 0x10000,
/// <summary>
/// Default settings: typical options for the decompiler, with all C# languages features enabled. /// Default settings: typical options for the decompiler, with all C# languages features enabled.
/// </summary> /// </summary>
Default = Dynamic | Tuple | ExtensionMethods | DecimalConstants | ReadOnlyStructsAndParameters Default = Dynamic | Tuple | ExtensionMethods | DecimalConstants | ReadOnlyStructsAndParameters
| RefStructs | UnmanagedConstraints | NullabilityAnnotations | ReadOnlyMethods | RefStructs | UnmanagedConstraints | NullabilityAnnotations | ReadOnlyMethods
| NativeIntegers | FunctionPointers | ScopedRef | NativeIntegersWithoutAttribute | NativeIntegers | FunctionPointers | ScopedRef | NativeIntegersWithoutAttribute
| RefReadOnlyParameters
} }
/// <summary> /// <summary>

18
ICSharpCode.Decompiler/TypeSystem/IParameter.cs

@ -32,7 +32,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
None, None,
Out, Out,
Ref, Ref,
In In,
RefReadOnly,
} }
public struct LifetimeAnnotation public struct LifetimeAnnotation
@ -71,21 +72,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// </summary> /// </summary>
LifetimeAnnotation Lifetime { get; } LifetimeAnnotation Lifetime { get; }
/// <summary>
/// Gets whether this parameter is a C# 'ref' parameter.
/// </summary>
bool IsRef { get; }
/// <summary>
/// Gets whether this parameter is a C# 'out' parameter.
/// </summary>
bool IsOut { get; }
/// <summary>
/// Gets whether this parameter is a C# 'in' parameter.
/// </summary>
bool IsIn { get; }
/// <summary> /// <summary>
/// Gets whether this parameter is a C# 'params' parameter. /// Gets whether this parameter is a C# 'params' parameter.
/// </summary> /// </summary>

17
ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultParameter.cs

@ -76,9 +76,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public IEnumerable<IAttribute> GetAttributes() => attributes; public IEnumerable<IAttribute> GetAttributes() => attributes;
public ReferenceKind ReferenceKind => referenceKind; public ReferenceKind ReferenceKind => referenceKind;
public bool IsRef => referenceKind == ReferenceKind.Ref;
public bool IsOut => referenceKind == ReferenceKind.Out;
public bool IsIn => referenceKind == ReferenceKind.In;
public bool IsParams => isParams; public bool IsParams => isParams;
@ -115,12 +112,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public static string ToString(IParameter parameter) public static string ToString(IParameter parameter)
{ {
StringBuilder b = new StringBuilder(); StringBuilder b = new StringBuilder();
if (parameter.IsRef) b.Append(parameter.ReferenceKind switch {
b.Append("ref "); ReferenceKind.None => "",
if (parameter.IsOut) ReferenceKind.Ref => "ref ",
b.Append("out "); ReferenceKind.Out => "out ",
if (parameter.IsIn) ReferenceKind.In => "in ",
b.Append("in "); ReferenceKind.RefReadOnly => "ref readonly ",
_ => throw new NotSupportedException()
});
if (parameter.IsParams) if (parameter.IsParams)
b.Append("params "); b.Append("params ");
b.Append(parameter.Name); b.Append(parameter.Name);

11
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs

@ -21,7 +21,6 @@ using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335; using System.Reflection.Metadata.Ecma335;
using System.Text;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
@ -76,13 +75,10 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
b.Add(KnownAttribute.DefaultParameterValue, KnownTypeCode.Object, GetConstantValue(throwOnInvalidMetadata: false)); b.Add(KnownAttribute.DefaultParameterValue, KnownTypeCode.Object, GetConstantValue(throwOnInvalidMetadata: false));
} }
if (!IsOut && !IsIn) if ((attributes & ParameterAttributes.In) == ParameterAttributes.In && ReferenceKind is not (ReferenceKind.In or ReferenceKind.RefReadOnly))
{
if ((attributes & ParameterAttributes.In) == ParameterAttributes.In)
b.Add(KnownAttribute.In); b.Add(KnownAttribute.In);
if ((attributes & ParameterAttributes.Out) == ParameterAttributes.Out) if ((attributes & ParameterAttributes.Out) == ParameterAttributes.Out && ReferenceKind != ReferenceKind.Out)
b.Add(KnownAttribute.Out); b.Add(KnownAttribute.Out);
}
b.Add(parameter.GetCustomAttributes(), SymbolKind.Parameter); b.Add(parameter.GetCustomAttributes(), SymbolKind.Parameter);
b.AddMarshalInfo(parameter.GetMarshallingDescriptor()); b.AddMarshalInfo(parameter.GetMarshallingDescriptor());
@ -93,9 +89,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
const ParameterAttributes inOut = ParameterAttributes.In | ParameterAttributes.Out; const ParameterAttributes inOut = ParameterAttributes.In | ParameterAttributes.Out;
public ReferenceKind ReferenceKind => DetectRefKind(); public ReferenceKind ReferenceKind => DetectRefKind();
public bool IsRef => DetectRefKind() == ReferenceKind.Ref;
public bool IsOut => Type.Kind == TypeKind.ByReference && (attributes & inOut) == ParameterAttributes.Out;
public bool IsIn => DetectRefKind() == ReferenceKind.In;
public bool IsOptional => (attributes & ParameterAttributes.Optional) != 0; public bool IsOptional => (attributes & ParameterAttributes.Optional) != 0;

3
ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedParameter.cs

@ -37,9 +37,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
IEnumerable<IAttribute> IParameter.GetAttributes() => baseParameter.GetAttributes(); IEnumerable<IAttribute> IParameter.GetAttributes() => baseParameter.GetAttributes();
ReferenceKind IParameter.ReferenceKind => baseParameter.ReferenceKind; ReferenceKind IParameter.ReferenceKind => baseParameter.ReferenceKind;
bool IParameter.IsRef => baseParameter.IsRef;
bool IParameter.IsOut => baseParameter.IsOut;
bool IParameter.IsIn => baseParameter.IsIn;
bool IParameter.IsParams => baseParameter.IsParams; bool IParameter.IsParams => baseParameter.IsParams;
bool IParameter.IsOptional => baseParameter.IsOptional; bool IParameter.IsOptional => baseParameter.IsOptional;
bool IParameter.HasConstantValueInSignature => baseParameter.HasConstantValueInSignature; bool IParameter.HasConstantValueInSignature => baseParameter.HasConstantValueInSignature;

Loading…
Cancel
Save