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

4
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

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

32
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

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

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

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

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

@ -2084,7 +2084,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -2084,7 +2084,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
// create the parameter:
ByReferenceResolveResult brrr = arguments[i] as ByReferenceResolveResult;
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 {
// argument might be a lambda or delegate type, so we have to try to guess the delegate type
IType type = arguments[i].Type;

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

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

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

@ -513,9 +513,9 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -513,9 +513,9 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
for (int i = 0; i < args.Length; i++) {
IParameter param = m.Parameters[i];
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;
args[i] = new ByReferenceResolveResult(parameterType, param.IsOut);
args[i] = new ByReferenceResolveResult(parameterType, param.ReferenceKind);
} else {
args[i] = new ResolveResult(parameterType);
}

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

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

4
ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs

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

20
ICSharpCode.Decompiler/Semantics/ByReferenceResolveResult.cs

@ -24,25 +24,27 @@ using ICSharpCode.Decompiler.TypeSystem; @@ -24,25 +24,27 @@ using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.Semantics
{
/// <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>
public class ByReferenceResolveResult : ResolveResult
{
public bool IsOut { get; private set; }
public bool IsRef { get { return !IsOut;} }
public ReferenceKind ReferenceKind { get; }
public bool IsOut => ReferenceKind == ReferenceKind.Out;
public bool IsRef => ReferenceKind == ReferenceKind.Ref;
public bool IsIn => ReferenceKind == ReferenceKind.In;
public readonly ResolveResult ElementResult;
public ByReferenceResolveResult(ResolveResult elementResult, bool isOut)
: this(elementResult.Type, isOut)
public ByReferenceResolveResult(ResolveResult elementResult, ReferenceKind kind)
: this(elementResult.Type, kind)
{
this.ElementResult = elementResult;
}
public ByReferenceResolveResult(IType elementType, bool isOut)
public ByReferenceResolveResult(IType elementType, ReferenceKind kind)
: base(new ByReferenceType(elementType))
{
this.IsOut = isOut;
this.ReferenceKind = kind;
}
public IType ElementType {
@ -59,7 +61,7 @@ namespace ICSharpCode.Decompiler.Semantics @@ -59,7 +61,7 @@ namespace ICSharpCode.Decompiler.Semantics
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 @@ -42,7 +42,7 @@ namespace ICSharpCode.Decompiler.Semantics
IType type = variable.Type;
if (type.Kind == TypeKind.ByReference) {
IParameter p = variable as IParameter;
if (p != null && (p.IsRef || p.IsOut))
if (p != null && p.ReferenceKind != ReferenceKind.None)
return ((ByReferenceType)type).ElementType;
}
return type;

16
ICSharpCode.Decompiler/TypeSystem/IParameter.cs

@ -21,12 +21,28 @@ using System.Collections.Generic; @@ -21,12 +21,28 @@ using System.Collections.Generic;
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
{
/// <summary>
/// Gets the attributes on this parameter.
/// </summary>
IEnumerable<IAttribute> GetAttributes();
/// <summary>
/// Gets the reference kind of this parameter.
/// </summary>
ReferenceKind ReferenceKind { get; }
/// <summary>
/// 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 @@ -31,7 +31,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
readonly IType type;
readonly string name;
readonly IReadOnlyList<IAttribute> attributes;
readonly bool isRef, isOut, isIn, isParams, isOptional;
readonly ReferenceKind referenceKind;
readonly bool isParams, isOptional;
readonly object defaultValue;
readonly IParameterizedMember owner;
@ -47,7 +48,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -47,7 +48,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
}
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)
throw new ArgumentNullException("type");
@ -57,9 +58,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -57,9 +58,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
this.name = name;
this.owner = owner;
this.attributes = attributes ?? EmptyList<IAttribute>.Instance;
this.isRef = isRef;
this.isOut = isOut;
this.isIn = isIn;
this.referenceKind = referenceKind;
this.isParams = isParams;
this.isOptional = isOptional;
this.defaultValue = defaultValue;
@ -74,27 +73,16 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -74,27 +73,16 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
}
public IEnumerable<IAttribute> GetAttributes() => attributes;
public bool IsRef {
get { return isRef; }
}
public bool IsOut {
get { return isOut; }
}
public bool IsIn {
get { return isIn; }
}
public bool IsParams {
get { return isParams; }
}
public bool IsOptional {
get { return isOptional; }
}
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 IsOptional => isOptional;
public string Name {
get { return name; }
}
@ -128,6 +116,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -128,6 +116,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
b.Append("ref ");
if (parameter.IsOut)
b.Append("out ");
if (parameter.IsIn)
b.Append("in ");
if (parameter.IsParams)
b.Append("params ");
b.Append(parameter.Name);

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

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

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

@ -81,25 +81,26 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -81,25 +81,26 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
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 IsIn => DetectRefKind() == CSharp.Syntax.ParameterModifier.In;
public bool IsIn => DetectRefKind() == ReferenceKind.In;
public bool IsOptional => (attributes & ParameterAttributes.Optional) != 0;
CSharp.Syntax.ParameterModifier DetectRefKind()
ReferenceKind DetectRefKind()
{
if (Type.Kind != TypeKind.ByReference)
return CSharp.Syntax.ParameterModifier.None;
return ReferenceKind.None;
if ((attributes & inOut) == ParameterAttributes.Out)
return CSharp.Syntax.ParameterModifier.Out;
return ReferenceKind.Out;
if ((module.TypeSystemOptions & TypeSystemOptions.ReadOnlyStructsAndParameters) != 0) {
var metadata = module.metadata;
var parameterDef = metadata.GetParameter(handle);
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 {

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

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

6
ICSharpCode.Decompiler/TypeSystem/ParameterListComparer.cs

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

Loading…
Cancel
Save