Browse Source

Fix #1053: virtual protected base method with 'out', invalid cast-to-base on use.

pull/1072/merge
Siegfried Pammer 7 years ago
parent
commit
3892762e70
  1. 8
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  2. 15
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  3. 3
      ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs

8
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -128,8 +128,14 @@ namespace ICSharpCode.Decompiler.CSharp
arguments.Add(arg.ConvertTo(parameter.Type, expressionBuilder, allowImplicitConversion: true)); arguments.Add(arg.ConvertTo(parameter.Type, expressionBuilder, allowImplicitConversion: true));
if (parameter.IsOut && arguments[i].Expression is DirectionExpression dirExpr) { if (parameter.IsOut && arguments[i].Expression is DirectionExpression dirExpr && arguments[i].ResolveResult is ByReferenceResolveResult brrr) {
dirExpr.FieldDirection = FieldDirection.Out; dirExpr.FieldDirection = FieldDirection.Out;
dirExpr.RemoveAnnotations<ByReferenceResolveResult>();
if (brrr.ElementResult == null)
brrr = new ByReferenceResolveResult(brrr.ElementType, isOut: true);
else
brrr = new ByReferenceResolveResult(brrr.ElementResult, isOut: true);
dirExpr.AddAnnotation(brrr);
} }
} }

15
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -179,7 +179,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 ResolveResult(variable.Type)); return expr.WithRR(new ByReferenceResolveResult(elementType, isOut: false));
} else { } else {
return expr.WithRR(new ILVariableResolveResult(variable, variable.Type)); return expr.WithRR(new ILVariableResolveResult(variable, variable.Type));
} }
@ -1649,7 +1649,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 ResolveResult(new ByReferenceType(expr.Type))); .WithoutILInstruction().WithRR(new ByReferenceResolveResult(expr.Type, isOut: false));
} }
} }
@ -1657,7 +1657,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 ResolveResult(new ByReferenceType(expr.Type))); .WithoutILInstruction().WithRR(new ByReferenceResolveResult(expr.Type, isOut: false));
} }
protected internal override TranslatedExpression VisitLdElema(LdElema inst, TranslationContext context) protected internal override TranslatedExpression VisitLdElema(LdElema inst, TranslationContext context)
@ -1672,7 +1672,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 ResolveResult(new ByReferenceType(expr.Type))); .WithoutILInstruction().WithRR(new ByReferenceResolveResult(expr.Type, isOut: false));
} }
TranslatedExpression TranslateArrayIndex(ILInstruction i) TranslatedExpression TranslateArrayIndex(ILInstruction i)
@ -1720,7 +1720,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 ConversionResolveResult(new ByReferenceType(inst.Type), arg.ResolveResult, Conversion.UnboxingConversion)); .WithRR(new ByReferenceResolveResult(castExpression.ResolveResult, isOut: false));
} }
protected internal override TranslatedExpression VisitBox(Box inst, TranslationContext context) protected internal override TranslatedExpression VisitBox(Box inst, TranslationContext context)
@ -2111,11 +2111,12 @@ namespace ICSharpCode.Decompiler.CSharp
if (rr.Type.Kind == TypeKind.ByReference) { if (rr.Type.Kind == TypeKind.ByReference) {
// C# conditional ref looks like this: // C# conditional ref looks like this:
// ref (arr != null ? ref trueBranch : ref falseBranch); // ref (arr != null ? ref trueBranch : ref falseBranch);
var conditionalResolveResult = new ResolveResult(((ByReferenceType)rr.Type).ElementType);
return new DirectionExpression(FieldDirection.Ref, return new DirectionExpression(FieldDirection.Ref,
new ConditionalExpression(condition.Expression, trueBranch.Expression, falseBranch.Expression) new ConditionalExpression(condition.Expression, trueBranch.Expression, falseBranch.Expression)
.WithILInstruction(inst) .WithILInstruction(inst)
.WithRR(new ResolveResult(((ByReferenceType)rr.Type).ElementType)) .WithRR(conditionalResolveResult)
).WithoutILInstruction().WithRR(rr); ).WithoutILInstruction().WithRR(new ByReferenceResolveResult(conditionalResolveResult, isOut: false));
} else { } else {
return new ConditionalExpression(condition.Expression, trueBranch.Expression, falseBranch.Expression) return new ConditionalExpression(condition.Expression, trueBranch.Expression, falseBranch.Expression)
.WithILInstruction(inst) .WithILInstruction(inst)

3
ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs

@ -616,8 +616,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
new AssignmentExpression { new AssignmentExpression {
Left = new IdentifierExpressionBackreference("var1"), Left = new IdentifierExpressionBackreference("var1"),
Right = new InvocationExpression(new MemberReferenceExpression(new TypeReferenceExpression(new TypePattern(typeof(System.Threading.Interlocked)).ToType()), Right = new InvocationExpression(new MemberReferenceExpression(new TypeReferenceExpression(new TypePattern(typeof(System.Threading.Interlocked)).ToType()),
"CompareExchange", "CompareExchange"),
new AstType[] { new Backreference("type") }), // type argument
new Expression[] { // arguments new Expression[] { // arguments
new DirectionExpression { FieldDirection = FieldDirection.Ref, Expression = new Backreference("field") }, new DirectionExpression { FieldDirection = FieldDirection.Ref, Expression = new Backreference("field") },
new IdentifierExpressionBackreference("var3"), new IdentifierExpressionBackreference("var3"),

Loading…
Cancel
Save