Browse Source

Introduce ReferenceKind in IParameter and ByReferenceResolveResult.

pull/1596/head
Siegfried Pammer 6 years ago
parent
commit
9c1bf7fbdf
  1. 45
      ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs
  2. 4
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  3. 32
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  4. 16
      ICSharpCode.Decompiler/CSharp/Resolver/CSharpConversions.cs
  5. 2
      ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs
  6. 4
      ICSharpCode.Decompiler/CSharp/Resolver/OverloadResolution.cs
  7. 4
      ICSharpCode.Decompiler/CSharp/Resolver/TypeInference.cs
  8. 4
      ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs
  9. 4
      ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs
  10. 20
      ICSharpCode.Decompiler/Semantics/ByReferenceResolveResult.cs
  11. 2
      ICSharpCode.Decompiler/Semantics/LocalResolveResult.cs
  12. 16
      ICSharpCode.Decompiler/TypeSystem/IParameter.cs
  13. 40
      ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultParameter.cs
  14. 4
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs
  15. 15
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs
  16. 1
      ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedParameter.cs
  17. 6
      ICSharpCode.Decompiler/TypeSystem/ParameterListComparer.cs

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

@ -707,8 +707,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
public void InOutParametersOnRefMethod() public void InOutParametersOnRefMethod()
{ {
IParameter p = GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod").Parameters.Single(); IParameter p = GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod").Parameters.Single();
Assert.IsTrue(p.IsRef); Assert.AreEqual(ReferenceKind.Ref, p.ReferenceKind);
Assert.IsFalse(p.IsOut);
var attr = p.GetAttributes().ToList(); var attr = p.GetAttributes().ToList();
Assert.AreEqual(2, attr.Count); Assert.AreEqual(2, attr.Count);
Assert.AreEqual("System.Runtime.InteropServices.InAttribute", attr[0].AttributeType.FullName); Assert.AreEqual("System.Runtime.InteropServices.InAttribute", attr[0].AttributeType.FullName);
@ -728,9 +727,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
{ {
IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithOutParameter").Parameters.Single(); IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithOutParameter").Parameters.Single();
Assert.IsFalse(p.IsOptional); Assert.IsFalse(p.IsOptional);
Assert.IsFalse(p.IsRef); Assert.AreEqual(ReferenceKind.Out, p.ReferenceKind);
Assert.IsTrue(p.IsOut);
Assert.IsFalse(p.IsIn);
Assert.AreEqual(0, p.GetAttributes().Count()); Assert.AreEqual(0, p.GetAttributes().Count());
Assert.IsTrue(p.Type.Kind == TypeKind.ByReference); Assert.IsTrue(p.Type.Kind == TypeKind.ByReference);
} }
@ -740,9 +737,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
{ {
IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithRefParameter").Parameters.Single(); IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithRefParameter").Parameters.Single();
Assert.IsFalse(p.IsOptional); Assert.IsFalse(p.IsOptional);
Assert.IsTrue(p.IsRef); Assert.AreEqual(ReferenceKind.Ref, p.ReferenceKind);
Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsIn);
Assert.AreEqual(0, p.GetAttributes().Count()); Assert.AreEqual(0, p.GetAttributes().Count());
Assert.IsTrue(p.Type.Kind == TypeKind.ByReference); Assert.IsTrue(p.Type.Kind == TypeKind.ByReference);
} }
@ -752,9 +747,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
{ {
IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithInParameter").Parameters.Single(); IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithInParameter").Parameters.Single();
Assert.IsFalse(p.IsOptional); Assert.IsFalse(p.IsOptional);
Assert.IsFalse(p.IsRef); Assert.AreEqual(ReferenceKind.In, p.ReferenceKind);
Assert.IsFalse(p.IsOut);
Assert.IsTrue(p.IsIn);
Assert.AreEqual(0, p.GetAttributes().Count()); Assert.AreEqual(0, p.GetAttributes().Count());
Assert.IsTrue(p.Type.Kind == TypeKind.ByReference); Assert.IsTrue(p.Type.Kind == TypeKind.ByReference);
} }
@ -764,8 +757,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
{ {
IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithParamsArray").Parameters.Single(); IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithParamsArray").Parameters.Single();
Assert.IsFalse(p.IsOptional); Assert.IsFalse(p.IsOptional);
Assert.IsFalse(p.IsRef); Assert.AreEqual(ReferenceKind.None, p.ReferenceKind);
Assert.IsFalse(p.IsOut);
Assert.IsTrue(p.IsParams); Assert.IsTrue(p.IsParams);
Assert.AreEqual(0, p.GetAttributes().Count()); Assert.AreEqual(0, p.GetAttributes().Count());
Assert.IsTrue(p.Type.Kind == TypeKind.Array); Assert.IsTrue(p.Type.Kind == TypeKind.Array);
@ -776,8 +768,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
{ {
IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithOptionalParameter").Parameters.Single(); IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithOptionalParameter").Parameters.Single();
Assert.IsTrue(p.IsOptional); Assert.IsTrue(p.IsOptional);
Assert.IsFalse(p.IsRef); Assert.AreEqual(ReferenceKind.None, p.ReferenceKind);
Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams); Assert.IsFalse(p.IsParams);
Assert.IsTrue(p.HasConstantValueInSignature); Assert.IsTrue(p.HasConstantValueInSignature);
Assert.AreEqual(0, p.GetAttributes().Count()); Assert.AreEqual(0, p.GetAttributes().Count());
@ -789,8 +780,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
{ {
IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithExplicitOptionalParameter").Parameters.Single(); IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithExplicitOptionalParameter").Parameters.Single();
Assert.IsTrue(p.IsOptional); Assert.IsTrue(p.IsOptional);
Assert.IsFalse(p.IsRef); Assert.AreEqual(ReferenceKind.None, p.ReferenceKind);
Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams); Assert.IsFalse(p.IsParams);
Assert.IsFalse(p.HasConstantValueInSignature); Assert.IsFalse(p.HasConstantValueInSignature);
// explicit optional parameter appears in type system if it's read from C#, but not when read from IL // explicit optional parameter appears in type system if it's read from C#, but not when read from IL
@ -802,8 +792,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
{ {
IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithEnumOptionalParameter").Parameters.Single(); IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithEnumOptionalParameter").Parameters.Single();
Assert.IsTrue(p.IsOptional); Assert.IsTrue(p.IsOptional);
Assert.IsFalse(p.IsRef); Assert.AreEqual(ReferenceKind.None, p.ReferenceKind);
Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams); Assert.IsFalse(p.IsParams);
Assert.IsTrue(p.HasConstantValueInSignature); Assert.IsTrue(p.HasConstantValueInSignature);
Assert.AreEqual(0, p.GetAttributes().Count()); Assert.AreEqual(0, p.GetAttributes().Count());
@ -815,8 +804,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
{ {
IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithOptionalNullableParameter").Parameters.Single(); IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithOptionalNullableParameter").Parameters.Single();
Assert.IsTrue(p.IsOptional); Assert.IsTrue(p.IsOptional);
Assert.IsFalse(p.IsRef); Assert.AreEqual(ReferenceKind.None, p.ReferenceKind);
Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams); Assert.IsFalse(p.IsParams);
Assert.IsTrue(p.HasConstantValueInSignature); Assert.IsTrue(p.HasConstantValueInSignature);
Assert.AreEqual(0, p.GetAttributes().Count()); Assert.AreEqual(0, p.GetAttributes().Count());
@ -828,8 +816,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
{ {
IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithOptionalLongParameter").Parameters.Single(); IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithOptionalLongParameter").Parameters.Single();
Assert.IsTrue(p.IsOptional); Assert.IsTrue(p.IsOptional);
Assert.IsFalse(p.IsRef); Assert.AreEqual(ReferenceKind.None, p.ReferenceKind);
Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams); Assert.IsFalse(p.IsParams);
Assert.IsTrue(p.HasConstantValueInSignature); Assert.IsTrue(p.HasConstantValueInSignature);
Assert.AreEqual(1L, p.GetConstantValue()); Assert.AreEqual(1L, p.GetConstantValue());
@ -841,8 +828,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
{ {
IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithOptionalNullableLongParameter").Parameters.Single(); IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithOptionalNullableLongParameter").Parameters.Single();
Assert.IsTrue(p.IsOptional); Assert.IsTrue(p.IsOptional);
Assert.IsFalse(p.IsRef); Assert.AreEqual(ReferenceKind.None, p.ReferenceKind);
Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams); Assert.IsFalse(p.IsParams);
Assert.IsTrue(p.HasConstantValueInSignature); Assert.IsTrue(p.HasConstantValueInSignature);
Assert.AreEqual(1L, p.GetConstantValue()); Assert.AreEqual(1L, p.GetConstantValue());
@ -854,8 +840,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
{ {
IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithOptionalDecimalParameter").Parameters.Single(); IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithOptionalDecimalParameter").Parameters.Single();
Assert.IsTrue(p.IsOptional); Assert.IsTrue(p.IsOptional);
Assert.IsFalse(p.IsRef); Assert.AreEqual(ReferenceKind.None, p.ReferenceKind);
Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams); Assert.IsFalse(p.IsParams);
Assert.IsTrue(p.HasConstantValueInSignature); Assert.IsTrue(p.HasConstantValueInSignature);
Assert.AreEqual(1M, p.GetConstantValue()); Assert.AreEqual(1M, p.GetConstantValue());
@ -867,8 +852,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
{ {
IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "VarArgsMethod").Parameters.Single(); IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "VarArgsMethod").Parameters.Single();
Assert.IsFalse(p.IsOptional); Assert.IsFalse(p.IsOptional);
Assert.IsFalse(p.IsRef); Assert.AreEqual(ReferenceKind.None, p.ReferenceKind);
Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams); Assert.IsFalse(p.IsParams);
Assert.AreEqual(TypeKind.ArgList, p.Type.Kind); Assert.AreEqual(TypeKind.ArgList, p.Type.Kind);
Assert.AreEqual("", p.Name); Assert.AreEqual("", p.Name);
@ -879,8 +863,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
{ {
IParameter p = GetTypeDefinition(typeof(VarArgsCtor)).Methods.Single(m => m.IsConstructor).Parameters.Single(); IParameter p = GetTypeDefinition(typeof(VarArgsCtor)).Methods.Single(m => m.IsConstructor).Parameters.Single();
Assert.IsFalse(p.IsOptional); Assert.IsFalse(p.IsOptional);
Assert.IsFalse(p.IsRef); Assert.AreEqual(ReferenceKind.None, p.ReferenceKind);
Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams); Assert.IsFalse(p.IsParams);
Assert.AreEqual(TypeKind.ArgList, p.Type.Kind); Assert.AreEqual(TypeKind.ArgList, p.Type.Kind);
Assert.AreEqual("", p.Name); Assert.AreEqual("", p.Name);

4
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -652,8 +652,8 @@ namespace ICSharpCode.Decompiler.CSharp
arg = arg.ConvertTo(parameterType, expressionBuilder, allowImplicitConversion: arg.Type.Kind != TypeKind.Dynamic); arg = arg.ConvertTo(parameterType, expressionBuilder, allowImplicitConversion: arg.Type.Kind != TypeKind.Dynamic);
if (parameter.IsOut) { if (parameter.ReferenceKind != ReferenceKind.None) {
arg = ExpressionBuilder.ChangeDirectionExpressionToOut(arg); arg = ExpressionBuilder.ChangeDirectionExpressionTo(arg, parameter.ReferenceKind);
} }
arguments.Add(arg); arguments.Add(arg);

32
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -181,7 +181,7 @@ namespace ICSharpCode.Decompiler.CSharp
expr.WithRR(new ILVariableResolveResult(variable, elementType)); expr.WithRR(new ILVariableResolveResult(variable, elementType));
expr = new DirectionExpression(FieldDirection.Ref, expr); expr = new DirectionExpression(FieldDirection.Ref, expr);
return expr.WithRR(new ByReferenceResolveResult(elementType, isOut: false)); return expr.WithRR(new ByReferenceResolveResult(elementType, ReferenceKind.Ref));
} else { } else {
return expr.WithRR(new ILVariableResolveResult(variable, variable.Type)); return expr.WithRR(new ILVariableResolveResult(variable, variable.Type));
} }
@ -604,7 +604,7 @@ namespace ICSharpCode.Decompiler.CSharp
// because the DirectionExpression might get removed by dereferencing instructions such as LdObj // because the DirectionExpression might get removed by dereferencing instructions such as LdObj
return new DirectionExpression(FieldDirection.Ref, expr.Expression) return new DirectionExpression(FieldDirection.Ref, expr.Expression)
.WithoutILInstruction() .WithoutILInstruction()
.WithRR(new ByReferenceResolveResult(expr.ResolveResult, isOut: false)); .WithRR(new ByReferenceResolveResult(expr.ResolveResult, ReferenceKind.Ref));
} }
protected internal override TranslatedExpression VisitStLoc(StLoc inst, TranslationContext context) protected internal override TranslatedExpression VisitStLoc(StLoc inst, TranslationContext context)
@ -1084,7 +1084,7 @@ namespace ICSharpCode.Decompiler.CSharp
.WithILInstruction(inst) .WithILInstruction(inst)
.WithRR(new ResolveResult(elementType)); .WithRR(new ResolveResult(elementType));
return new DirectionExpression(FieldDirection.Ref, expr) return new DirectionExpression(FieldDirection.Ref, expr)
.WithoutILInstruction().WithRR(new ByReferenceResolveResult(expr.Type, isOut: false)); .WithoutILInstruction().WithRR(new ByReferenceResolveResult(expr.Type, ReferenceKind.Ref));
} }
return CallUnsafeIntrinsic(name, new[] { left.Expression, Translate(offsetInst).Expression }, brt, inst); return CallUnsafeIntrinsic(name, new[] { left.Expression, Translate(offsetInst).Expression }, brt, inst);
} else { } else {
@ -1756,7 +1756,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (type.Kind == TypeKind.ByReference) { if (type.Kind == TypeKind.ByReference) {
return new DirectionExpression(FieldDirection.Ref, expr.Expression) return new DirectionExpression(FieldDirection.Ref, expr.Expression)
.WithoutILInstruction() .WithoutILInstruction()
.WithRR(new ByReferenceResolveResult(expr.ResolveResult, isOut: false)); .WithRR(new ByReferenceResolveResult(expr.ResolveResult, ReferenceKind.Ref));
} }
return expr; return expr;
} }
@ -2107,7 +2107,7 @@ namespace ICSharpCode.Decompiler.CSharp
} else { } else {
// ldflda producing managed pointer // ldflda producing managed pointer
return new DirectionExpression(FieldDirection.Ref, expr) return new DirectionExpression(FieldDirection.Ref, expr)
.WithoutILInstruction().WithRR(new ByReferenceResolveResult(expr.ResolveResult, isOut: false)); .WithoutILInstruction().WithRR(new ByReferenceResolveResult(expr.ResolveResult, ReferenceKind.Ref));
} }
} }
@ -2115,7 +2115,7 @@ namespace ICSharpCode.Decompiler.CSharp
{ {
var expr = ConvertField(inst.Field).WithILInstruction(inst); var expr = ConvertField(inst.Field).WithILInstruction(inst);
return new DirectionExpression(FieldDirection.Ref, expr) return new DirectionExpression(FieldDirection.Ref, expr)
.WithoutILInstruction().WithRR(new ByReferenceResolveResult(expr.Type, isOut: false)); .WithoutILInstruction().WithRR(new ByReferenceResolveResult(expr.Type, ReferenceKind.Ref));
} }
protected internal override TranslatedExpression VisitLdElema(LdElema inst, TranslationContext context) protected internal override TranslatedExpression VisitLdElema(LdElema inst, TranslationContext context)
@ -2130,7 +2130,7 @@ namespace ICSharpCode.Decompiler.CSharp
arrayExpr, inst.Indices.Select(i => TranslateArrayIndex(i).Expression) arrayExpr, inst.Indices.Select(i => TranslateArrayIndex(i).Expression)
).WithILInstruction(inst).WithRR(new ResolveResult(arrayType.ElementType)); ).WithILInstruction(inst).WithRR(new ResolveResult(arrayType.ElementType));
return new DirectionExpression(FieldDirection.Ref, expr) return new DirectionExpression(FieldDirection.Ref, expr)
.WithoutILInstruction().WithRR(new ByReferenceResolveResult(expr.Type, isOut: false)); .WithoutILInstruction().WithRR(new ByReferenceResolveResult(expr.Type, ReferenceKind.Ref));
} }
TranslatedExpression TranslateArrayIndex(ILInstruction i) TranslatedExpression TranslateArrayIndex(ILInstruction i)
@ -2188,7 +2188,7 @@ namespace ICSharpCode.Decompiler.CSharp
.WithRR(new ConversionResolveResult(inst.Type, arg.ResolveResult, Conversion.UnboxingConversion)); .WithRR(new ConversionResolveResult(inst.Type, arg.ResolveResult, Conversion.UnboxingConversion));
return new DirectionExpression(FieldDirection.Ref, castExpression) return new DirectionExpression(FieldDirection.Ref, castExpression)
.WithILInstruction(inst) .WithILInstruction(inst)
.WithRR(new ByReferenceResolveResult(castExpression.ResolveResult, isOut: false)); .WithRR(new ByReferenceResolveResult(castExpression.ResolveResult, ReferenceKind.Ref));
} }
protected internal override TranslatedExpression VisitBox(Box inst, TranslationContext context) protected internal override TranslatedExpression VisitBox(Box inst, TranslationContext context)
@ -2248,7 +2248,7 @@ namespace ICSharpCode.Decompiler.CSharp
Arguments = { Translate(inst.Argument).Expression, new TypeReferenceExpression(ConvertType(inst.Type)) } Arguments = { Translate(inst.Argument).Expression, new TypeReferenceExpression(ConvertType(inst.Type)) }
}.WithRR(new ResolveResult(inst.Type)); }.WithRR(new ResolveResult(inst.Type));
return new DirectionExpression(FieldDirection.Ref, expr.WithILInstruction(inst)).WithoutILInstruction() return new DirectionExpression(FieldDirection.Ref, expr.WithILInstruction(inst)).WithoutILInstruction()
.WithRR(new ByReferenceResolveResult(inst.Type, false)); .WithRR(new ByReferenceResolveResult(inst.Type, ReferenceKind.Ref));
} }
protected internal override TranslatedExpression VisitBlock(Block block, TranslationContext context) protected internal override TranslatedExpression VisitBlock(Block block, TranslationContext context)
@ -2732,7 +2732,7 @@ namespace ICSharpCode.Decompiler.CSharp
new ConditionalExpression(condition.Expression, trueBranch.Expression, falseBranch.Expression) new ConditionalExpression(condition.Expression, trueBranch.Expression, falseBranch.Expression)
.WithILInstruction(inst) .WithILInstruction(inst)
.WithRR(conditionalResolveResult) .WithRR(conditionalResolveResult)
).WithoutILInstruction().WithRR(new ByReferenceResolveResult(conditionalResolveResult, isOut: false)); ).WithoutILInstruction().WithRR(new ByReferenceResolveResult(conditionalResolveResult, ReferenceKind.Ref));
} else { } else {
return new ConditionalExpression(condition.Expression, trueBranch.Expression, falseBranch.Expression) return new ConditionalExpression(condition.Expression, trueBranch.Expression, falseBranch.Expression)
.WithILInstruction(inst) .WithILInstruction(inst)
@ -2752,7 +2752,7 @@ namespace ICSharpCode.Decompiler.CSharp
var value = Translate(inst.Value, targetTypeHint); var value = Translate(inst.Value, targetTypeHint);
return new DirectionExpression(FieldDirection.Ref, value) return new DirectionExpression(FieldDirection.Ref, value)
.WithILInstruction(inst) .WithILInstruction(inst)
.WithRR(new ByReferenceResolveResult(value.ResolveResult, false)); .WithRR(new ByReferenceResolveResult(value.ResolveResult, ReferenceKind.Ref));
} }
protected internal override TranslatedExpression VisitAwait(Await inst, TranslationContext context) protected internal override TranslatedExpression VisitAwait(Await inst, TranslationContext context)
@ -2907,7 +2907,7 @@ namespace ICSharpCode.Decompiler.CSharp
translatedExpression = translatedExpression.ConvertTo(typeHint, this); translatedExpression = translatedExpression.ConvertTo(typeHint, this);
} }
if (info.HasFlag(CSharpArgumentInfoFlags.IsOut)) { if (info.HasFlag(CSharpArgumentInfoFlags.IsOut)) {
translatedExpression = ChangeDirectionExpressionToOut(translatedExpression); translatedExpression = ChangeDirectionExpressionTo(translatedExpression, ReferenceKind.Out);
} }
if (info.HasFlag(CSharpArgumentInfoFlags.NamedArgument) && !string.IsNullOrWhiteSpace(info.Name)) { if (info.HasFlag(CSharpArgumentInfoFlags.NamedArgument) && !string.IsNullOrWhiteSpace(info.Name)) {
translatedExpression = new TranslatedExpression(new NamedArgumentExpression(info.Name, translatedExpression.Expression)); translatedExpression = new TranslatedExpression(new NamedArgumentExpression(info.Name, translatedExpression.Expression));
@ -2916,16 +2916,16 @@ namespace ICSharpCode.Decompiler.CSharp
return translatedExpression; return translatedExpression;
} }
internal static TranslatedExpression ChangeDirectionExpressionToOut(TranslatedExpression input) internal static TranslatedExpression ChangeDirectionExpressionTo(TranslatedExpression input, ReferenceKind kind)
{ {
if (!(input.Expression is DirectionExpression dirExpr && input.ResolveResult is ByReferenceResolveResult brrr)) if (!(input.Expression is DirectionExpression dirExpr && input.ResolveResult is ByReferenceResolveResult brrr))
return input; return input;
dirExpr.FieldDirection = FieldDirection.Out; dirExpr.FieldDirection = (FieldDirection)kind;
dirExpr.RemoveAnnotations<ByReferenceResolveResult>(); dirExpr.RemoveAnnotations<ByReferenceResolveResult>();
if (brrr.ElementResult == null) if (brrr.ElementResult == null)
brrr = new ByReferenceResolveResult(brrr.ElementType, isOut: true); brrr = new ByReferenceResolveResult(brrr.ElementType, kind);
else else
brrr = new ByReferenceResolveResult(brrr.ElementResult, isOut: true); brrr = new ByReferenceResolveResult(brrr.ElementResult, kind);
dirExpr.AddAnnotation(brrr); dirExpr.AddAnnotation(brrr);
return new TranslatedExpression(dirExpr); return new TranslatedExpression(dirExpr);
} }

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

@ -1018,7 +1018,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
if (f.IsImplicitlyTyped) { if (f.IsImplicitlyTyped) {
// If F has an implicitly typed parameter list, D has no ref or out parameters. // If F has an implicitly typed parameter list, D has no ref or out parameters.
foreach (IParameter p in d.Parameters) { foreach (IParameter p in d.Parameters) {
if (p.IsOut || p.IsRef) if (p.ReferenceKind != ReferenceKind.None)
return Conversion.None; return Conversion.None;
} }
} else { } else {
@ -1027,7 +1027,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
for (int i = 0; i < f.Parameters.Count; i++) { for (int i = 0; i < f.Parameters.Count; i++) {
IParameter pD = d.Parameters[i]; IParameter pD = d.Parameters[i];
IParameter pF = f.Parameters[i]; IParameter pF = f.Parameters[i];
if (pD.IsRef != pF.IsRef || pD.IsOut != pF.IsOut) if (pD.ReferenceKind != pF.ReferenceKind)
return Conversion.None; return Conversion.None;
if (!IdentityConversion(dParamTypes[i], pF.Type)) if (!IdentityConversion(dParamTypes[i], pF.Type))
return Conversion.None; return Conversion.None;
@ -1071,9 +1071,9 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
for (int i = 0; i < args.Length; i++) { for (int i = 0; i < args.Length; i++) {
IParameter param = invoke.Parameters[i]; IParameter param = invoke.Parameters[i];
IType parameterType = param.Type; IType parameterType = param.Type;
if ((param.IsRef || param.IsOut) && parameterType.Kind == TypeKind.ByReference) { if (param.ReferenceKind != ReferenceKind.None && parameterType.Kind == TypeKind.ByReference) {
parameterType = ((ByReferenceType)parameterType).ElementType; parameterType = ((ByReferenceType)parameterType).ElementType;
args[i] = new ByReferenceResolveResult(parameterType, param.IsOut); args[i] = new ByReferenceResolveResult(parameterType, param.ReferenceKind);
} else { } else {
args[i] = new ResolveResult(parameterType); args[i] = new ResolveResult(parameterType);
} }
@ -1132,11 +1132,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
for (int i = 0; i < invoke.Parameters.Count; i++) { for (int i = 0; i < invoke.Parameters.Count; i++) {
var pm = m.Parameters[firstParameterInM + i]; var pm = m.Parameters[firstParameterInM + i];
var pd = invoke.Parameters[i]; var pd = invoke.Parameters[i];
// ret/out must match // ret/out/in must match
if (pm.IsRef != pd.IsRef || pm.IsOut != pd.IsOut) if (pm.ReferenceKind != pd.ReferenceKind)
return false; return false;
if (pm.IsRef || pm.IsOut) { if (pm.ReferenceKind != ReferenceKind.None) {
// ref/out parameters must have same types // ref/out/in parameters must have same types
if (!pm.Type.Equals(pd.Type)) if (!pm.Type.Equals(pd.Type))
return false; return false;
} else { } else {

2
ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs

@ -2084,7 +2084,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
// create the parameter: // create the parameter:
ByReferenceResolveResult brrr = arguments[i] as ByReferenceResolveResult; ByReferenceResolveResult brrr = arguments[i] as ByReferenceResolveResult;
if (brrr != null) { if (brrr != null) {
list.Add(new DefaultParameter(arguments[i].Type, argumentNames[i], isRef: brrr.IsRef, isOut: brrr.IsOut)); list.Add(new DefaultParameter(arguments[i].Type, argumentNames[i], referenceKind: brrr.ReferenceKind));
} else { } else {
// argument might be a lambda or delegate type, so we have to try to guess the delegate type // argument might be a lambda or delegate type, so we have to try to guess the delegate type
IType type = arguments[i].Type; IType type = arguments[i].Type;

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

@ -589,10 +589,10 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
ByReferenceResolveResult brrr = arguments[i] as ByReferenceResolveResult; ByReferenceResolveResult brrr = arguments[i] as ByReferenceResolveResult;
if (brrr != null) { if (brrr != null) {
if ((brrr.IsOut && !candidate.Parameters[parameterIndex].IsOut) || (brrr.IsRef && !candidate.Parameters[parameterIndex].IsRef)) if (brrr.ReferenceKind != candidate.Parameters[parameterIndex].ReferenceKind)
candidate.AddError(OverloadResolutionErrors.ParameterPassingModeMismatch); candidate.AddError(OverloadResolutionErrors.ParameterPassingModeMismatch);
} else { } else {
if (candidate.Parameters[parameterIndex].IsOut || candidate.Parameters[parameterIndex].IsRef) if (candidate.Parameters[parameterIndex].ReferenceKind != ReferenceKind.None)
candidate.AddError(OverloadResolutionErrors.ParameterPassingModeMismatch); candidate.AddError(OverloadResolutionErrors.ParameterPassingModeMismatch);
} }
IType parameterType = candidate.ParameterTypes[parameterIndex]; IType parameterType = candidate.ParameterTypes[parameterIndex];

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

@ -513,9 +513,9 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
for (int i = 0; i < args.Length; i++) { for (int i = 0; i < args.Length; i++) {
IParameter param = m.Parameters[i]; IParameter param = m.Parameters[i];
IType parameterType = param.Type.AcceptVisitor(substitution); IType parameterType = param.Type.AcceptVisitor(substitution);
if ((param.IsRef || param.IsOut) && parameterType.Kind == TypeKind.ByReference) { if ((param.ReferenceKind != ReferenceKind.None) && parameterType.Kind == TypeKind.ByReference) {
parameterType = ((ByReferenceType)parameterType).ElementType; parameterType = ((ByReferenceType)parameterType).ElementType;
args[i] = new ByReferenceResolveResult(parameterType, param.IsOut); args[i] = new ByReferenceResolveResult(parameterType, param.ReferenceKind);
} else { } else {
args[i] = new ResolveResult(parameterType); args[i] = new ResolveResult(parameterType);
} }

4
ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs

@ -138,9 +138,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
if (!CanTransformToExtensionMethodCall(resolver, method, typeArguments, target, args, argNames)) if (!CanTransformToExtensionMethodCall(resolver, method, typeArguments, target, args, argNames))
return; return;
if (firstArgument is DirectionExpression dirExpr) { if (firstArgument is DirectionExpression dirExpr) {
if (dirExpr.FieldDirection != FieldDirection.Ref) if (!context.Settings.RefExtensionMethods || dirExpr.FieldDirection == FieldDirection.Out)
return;
if (!context.Settings.RefExtensionMethods)
return; return;
firstArgument = dirExpr.Expression; firstArgument = dirExpr.Expression;
target = firstArgument.GetResolveResult(); target = firstArgument.GetResolveResult();

4
ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs

@ -376,7 +376,7 @@ namespace ICSharpCode.Decompiler.CSharp
var convertedTemp = this.UnwrapChild(thisDir.Expression).ConvertTo(elementType, expressionBuilder, checkForOverflow); var convertedTemp = this.UnwrapChild(thisDir.Expression).ConvertTo(elementType, expressionBuilder, checkForOverflow);
return new DirectionExpression(FieldDirection.Ref, convertedTemp) return new DirectionExpression(FieldDirection.Ref, convertedTemp)
.WithILInstruction(this.ILInstructions) .WithILInstruction(this.ILInstructions)
.WithRR(new ByReferenceResolveResult(convertedTemp.ResolveResult, false)); .WithRR(new ByReferenceResolveResult(convertedTemp.ResolveResult, ReferenceKind.Ref));
} }
// Convert from integer/pointer to reference. // Convert from integer/pointer to reference.
// First, convert to the corresponding pointer type: // First, convert to the corresponding pointer type:
@ -396,7 +396,7 @@ namespace ICSharpCode.Decompiler.CSharp
// And then take a reference: // And then take a reference:
return new DirectionExpression(FieldDirection.Ref, expr) return new DirectionExpression(FieldDirection.Ref, expr)
.WithoutILInstruction() .WithoutILInstruction()
.WithRR(new ByReferenceResolveResult(elementRR, false)); .WithRR(new ByReferenceResolveResult(elementRR, ReferenceKind.Ref));
} }
var rr = expressionBuilder.resolver.WithCheckForOverflow(checkForOverflow).ResolveCast(targetType, ResolveResult); var rr = expressionBuilder.resolver.WithCheckForOverflow(checkForOverflow).ResolveCast(targetType, ResolveResult);
if (rr.IsCompileTimeConstant && !rr.IsError) { if (rr.IsCompileTimeConstant && !rr.IsError) {

20
ICSharpCode.Decompiler/Semantics/ByReferenceResolveResult.cs

@ -24,25 +24,27 @@ using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.Semantics namespace ICSharpCode.Decompiler.Semantics
{ {
/// <summary> /// <summary>
/// Represents the resolve result of an 'ref x' or 'out x' expression. /// Represents the resolve result of an 'ref x', 'in x' or 'out x' expression.
/// </summary> /// </summary>
public class ByReferenceResolveResult : ResolveResult public class ByReferenceResolveResult : ResolveResult
{ {
public bool IsOut { get; private set; } public ReferenceKind ReferenceKind { get; }
public bool IsRef { get { return !IsOut;} } public bool IsOut => ReferenceKind == ReferenceKind.Out;
public bool IsRef => ReferenceKind == ReferenceKind.Ref;
public bool IsIn => ReferenceKind == ReferenceKind.In;
public readonly ResolveResult ElementResult; public readonly ResolveResult ElementResult;
public ByReferenceResolveResult(ResolveResult elementResult, bool isOut) public ByReferenceResolveResult(ResolveResult elementResult, ReferenceKind kind)
: this(elementResult.Type, isOut) : this(elementResult.Type, kind)
{ {
this.ElementResult = elementResult; this.ElementResult = elementResult;
} }
public ByReferenceResolveResult(IType elementType, bool isOut) public ByReferenceResolveResult(IType elementType, ReferenceKind kind)
: base(new ByReferenceType(elementType)) : base(new ByReferenceType(elementType))
{ {
this.IsOut = isOut; this.ReferenceKind = kind;
} }
public IType ElementType { public IType ElementType {
@ -59,7 +61,7 @@ namespace ICSharpCode.Decompiler.Semantics
public override string ToString() public override string ToString()
{ {
return string.Format(CultureInfo.InvariantCulture, "[{0} {1} {2}]", GetType().Name, IsOut ? "out" : "ref", ElementType); return string.Format(CultureInfo.InvariantCulture, "[{0} {1} {2}]", GetType().Name, ReferenceKind.ToString().ToLowerInvariant(), ElementType);
} }
} }
} }

2
ICSharpCode.Decompiler/Semantics/LocalResolveResult.cs

@ -42,7 +42,7 @@ namespace ICSharpCode.Decompiler.Semantics
IType type = variable.Type; IType type = variable.Type;
if (type.Kind == TypeKind.ByReference) { if (type.Kind == TypeKind.ByReference) {
IParameter p = variable as IParameter; IParameter p = variable as IParameter;
if (p != null && (p.IsRef || p.IsOut)) if (p != null && p.ReferenceKind != ReferenceKind.None)
return ((ByReferenceType)type).ElementType; return ((ByReferenceType)type).ElementType;
} }
return type; return type;

16
ICSharpCode.Decompiler/TypeSystem/IParameter.cs

@ -21,12 +21,28 @@ using System.Collections.Generic;
namespace ICSharpCode.Decompiler.TypeSystem namespace ICSharpCode.Decompiler.TypeSystem
{ {
/// <remarks>
/// Should match order in <see cref="CSharp.Syntax.FieldDirection"/>.
/// </remarks>
public enum ReferenceKind
{
None,
Out,
Ref,
In
}
public interface IParameter : IVariable public interface IParameter : IVariable
{ {
/// <summary> /// <summary>
/// Gets the attributes on this parameter. /// Gets the attributes on this parameter.
/// </summary> /// </summary>
IEnumerable<IAttribute> GetAttributes(); IEnumerable<IAttribute> GetAttributes();
/// <summary>
/// Gets the reference kind of this parameter.
/// </summary>
ReferenceKind ReferenceKind { get; }
/// <summary> /// <summary>
/// Gets whether this parameter is a C# 'ref' parameter. /// Gets whether this parameter is a C# 'ref' parameter.

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

@ -31,7 +31,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
readonly IType type; readonly IType type;
readonly string name; readonly string name;
readonly IReadOnlyList<IAttribute> attributes; readonly IReadOnlyList<IAttribute> attributes;
readonly bool isRef, isOut, isIn, isParams, isOptional; readonly ReferenceKind referenceKind;
readonly bool isParams, isOptional;
readonly object defaultValue; readonly object defaultValue;
readonly IParameterizedMember owner; readonly IParameterizedMember owner;
@ -47,7 +48,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
} }
public DefaultParameter(IType type, string name, IParameterizedMember owner = null, IReadOnlyList<IAttribute> attributes = null, public DefaultParameter(IType type, string name, IParameterizedMember owner = null, IReadOnlyList<IAttribute> attributes = null,
bool isRef = false, bool isOut = false, bool isIn = false, bool isParams = false, bool isOptional = false, object defaultValue = null) ReferenceKind referenceKind = ReferenceKind.None, bool isParams = false, bool isOptional = false, object defaultValue = null)
{ {
if (type == null) if (type == null)
throw new ArgumentNullException("type"); throw new ArgumentNullException("type");
@ -57,9 +58,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
this.name = name; this.name = name;
this.owner = owner; this.owner = owner;
this.attributes = attributes ?? EmptyList<IAttribute>.Instance; this.attributes = attributes ?? EmptyList<IAttribute>.Instance;
this.isRef = isRef; this.referenceKind = referenceKind;
this.isOut = isOut;
this.isIn = isIn;
this.isParams = isParams; this.isParams = isParams;
this.isOptional = isOptional; this.isOptional = isOptional;
this.defaultValue = defaultValue; this.defaultValue = defaultValue;
@ -74,27 +73,16 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
} }
public IEnumerable<IAttribute> GetAttributes() => attributes; public IEnumerable<IAttribute> GetAttributes() => attributes;
public bool IsRef {
get { return isRef; }
}
public bool IsOut {
get { return isOut; }
}
public bool IsIn { public ReferenceKind ReferenceKind => referenceKind;
get { return isIn; } public bool IsRef => referenceKind == ReferenceKind.Ref;
} public bool IsOut => referenceKind == ReferenceKind.Out;
public bool IsIn => referenceKind == ReferenceKind.In;
public bool IsParams {
get { return isParams; } public bool IsParams => isParams;
}
public bool IsOptional => isOptional;
public bool IsOptional {
get { return isOptional; }
}
public string Name { public string Name {
get { return name; } get { return name; }
} }
@ -128,6 +116,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
b.Append("ref "); b.Append("ref ");
if (parameter.IsOut) if (parameter.IsOut)
b.Append("out "); b.Append("out ");
if (parameter.IsIn)
b.Append("in ");
if (parameter.IsParams) if (parameter.IsParams)
b.Append("params "); b.Append("params ");
b.Append(parameter.Name); b.Append(parameter.Name);

4
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs

@ -197,7 +197,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
parameterType = ApplyAttributeTypeVisitor.ApplyAttributesToType( parameterType = ApplyAttributeTypeVisitor.ApplyAttributesToType(
signature.ParameterTypes[i], module.Compilation, null, metadata, module.TypeSystemOptions, nullableContext); signature.ParameterTypes[i], module.Compilation, null, metadata, module.TypeSystemOptions, nullableContext);
parameters[i] = new DefaultParameter(parameterType, name: string.Empty, owner, parameters[i] = new DefaultParameter(parameterType, name: string.Empty, owner,
isRef: parameterType.Kind == TypeKind.ByReference); referenceKind: parameterType.Kind == TypeKind.ByReference ? ReferenceKind.Ref : ReferenceKind.None);
i++; i++;
} }
parameterType = ApplyAttributeTypeVisitor.ApplyAttributesToType( parameterType = ApplyAttributeTypeVisitor.ApplyAttributesToType(
@ -212,7 +212,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
parameterType = ApplyAttributeTypeVisitor.ApplyAttributesToType( parameterType = ApplyAttributeTypeVisitor.ApplyAttributesToType(
signature.ParameterTypes[i], module.Compilation, null, metadata, module.TypeSystemOptions, nullableContext); signature.ParameterTypes[i], module.Compilation, null, metadata, module.TypeSystemOptions, nullableContext);
parameters[i] = new DefaultParameter(parameterType, name: string.Empty, owner, parameters[i] = new DefaultParameter(parameterType, name: string.Empty, owner,
isRef: parameterType.Kind == TypeKind.ByReference); referenceKind: parameterType.Kind == TypeKind.ByReference ? ReferenceKind.Ref : ReferenceKind.None);
i++; i++;
} }
if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) { if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) {

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

@ -81,25 +81,26 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
const ParameterAttributes inOut = ParameterAttributes.In | ParameterAttributes.Out; const ParameterAttributes inOut = ParameterAttributes.In | ParameterAttributes.Out;
public bool IsRef => DetectRefKind() == CSharp.Syntax.ParameterModifier.Ref; public ReferenceKind ReferenceKind => DetectRefKind();
public bool IsRef => DetectRefKind() == ReferenceKind.Ref;
public bool IsOut => Type.Kind == TypeKind.ByReference && (attributes & inOut) == ParameterAttributes.Out; public bool IsOut => Type.Kind == TypeKind.ByReference && (attributes & inOut) == ParameterAttributes.Out;
public bool IsIn => DetectRefKind() == CSharp.Syntax.ParameterModifier.In; public bool IsIn => DetectRefKind() == ReferenceKind.In;
public bool IsOptional => (attributes & ParameterAttributes.Optional) != 0; public bool IsOptional => (attributes & ParameterAttributes.Optional) != 0;
CSharp.Syntax.ParameterModifier DetectRefKind() ReferenceKind DetectRefKind()
{ {
if (Type.Kind != TypeKind.ByReference) if (Type.Kind != TypeKind.ByReference)
return CSharp.Syntax.ParameterModifier.None; return ReferenceKind.None;
if ((attributes & inOut) == ParameterAttributes.Out) if ((attributes & inOut) == ParameterAttributes.Out)
return CSharp.Syntax.ParameterModifier.Out; return ReferenceKind.Out;
if ((module.TypeSystemOptions & TypeSystemOptions.ReadOnlyStructsAndParameters) != 0) { if ((module.TypeSystemOptions & TypeSystemOptions.ReadOnlyStructsAndParameters) != 0) {
var metadata = module.metadata; var metadata = module.metadata;
var parameterDef = metadata.GetParameter(handle); var parameterDef = metadata.GetParameter(handle);
if (parameterDef.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.IsReadOnly)) if (parameterDef.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.IsReadOnly))
return CSharp.Syntax.ParameterModifier.In; return ReferenceKind.In;
} }
return CSharp.Syntax.ParameterModifier.Ref; return ReferenceKind.Ref;
} }
public bool IsParams { public bool IsParams {

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

@ -36,6 +36,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
} }
IEnumerable<IAttribute> IParameter.GetAttributes() => baseParameter.GetAttributes(); IEnumerable<IAttribute> IParameter.GetAttributes() => baseParameter.GetAttributes();
ReferenceKind IParameter.ReferenceKind => baseParameter.ReferenceKind;
bool IParameter.IsRef => baseParameter.IsRef; bool IParameter.IsRef => baseParameter.IsRef;
bool IParameter.IsOut => baseParameter.IsOut; bool IParameter.IsOut => baseParameter.IsOut;
bool IParameter.IsIn => baseParameter.IsIn; bool IParameter.IsIn => baseParameter.IsIn;

6
ICSharpCode.Decompiler/TypeSystem/ParameterListComparer.cs

@ -66,11 +66,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
return false; return false;
if (includeModifiers) { if (includeModifiers) {
if (a.IsIn != b.IsIn) if (a.ReferenceKind != b.ReferenceKind)
return false;
if (a.IsOut != b.IsOut)
return false;
if (a.IsRef != b.IsRef)
return false; return false;
if (a.IsParams != b.IsParams) if (a.IsParams != b.IsParams)
return false; return false;

Loading…
Cancel
Save