Browse Source

Fix #2120: An expression tree may not contain a base access

pull/2126/head
Siegfried Pammer 5 years ago
parent
commit
55842e4bfc
  1. 13
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  2. 21
      ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs

13
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -2061,7 +2061,7 @@ namespace ICSharpCode.Decompiler.CSharp
// If references are missing member.IsStatic might not be set correctly. // If references are missing member.IsStatic might not be set correctly.
// Additionally check target for null, in order to avoid a crash. // Additionally check target for null, in order to avoid a crash.
if (!memberStatic && target != null) { if (!memberStatic && target != null) {
if (nonVirtualInvocation && MatchLdThis(target) && memberDeclaringType.GetDefinition() != resolver.CurrentTypeDefinition) { if (ShouldUseBaseReference()) {
return new BaseReferenceExpression() return new BaseReferenceExpression()
.WithILInstruction(target) .WithILInstruction(target)
.WithRR(new ThisResolveResult(memberDeclaringType, nonVirtualInvocation)); .WithRR(new ThisResolveResult(memberDeclaringType, nonVirtualInvocation));
@ -2097,6 +2097,17 @@ namespace ICSharpCode.Decompiler.CSharp
.WithRR(new TypeResolveResult(memberDeclaringType)); .WithRR(new TypeResolveResult(memberDeclaringType));
} }
bool ShouldUseBaseReference()
{
if (!nonVirtualInvocation)
return false;
if (!MatchLdThis(target))
return false;
if (memberDeclaringType.GetDefinition() == resolver.CurrentTypeDefinition)
return false;
return true;
}
bool MatchLdThis(ILInstruction inst) bool MatchLdThis(ILInstruction inst)
{ {
// ldloc this // ldloc this

21
ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs

@ -512,7 +512,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms
} }
switch (member) { switch (member) {
case IMethod method: case IMethod method:
return (targetVariable => new Call(method) { Arguments = { new LdLoc(targetVariable), value() } }, method.ReturnType); if (method.IsStatic)
return (targetVariable => new Call(method) { Arguments = { new LdLoc(targetVariable), value() } }, method.ReturnType);
else
return (targetVariable => new CallVirt(method) { Arguments = { new LdLoc(targetVariable), value() } }, method.ReturnType);
case IField field: case IField field:
return (targetVariable => new StObj(new LdFlda(new LdLoc(targetVariable), (IField)member) { DelayExceptions = true }, value(), member.ReturnType), field.ReturnType); return (targetVariable => new StObj(new LdFlda(new LdLoc(targetVariable), (IField)member) { DelayExceptions = true }, value(), member.ReturnType), field.ReturnType);
} }
@ -560,10 +563,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms
CallInstruction BuildCall() CallInstruction BuildCall()
{ {
CallInstruction call; CallInstruction call;
if (method.IsAbstract || method.IsVirtual || method.IsOverride) { if (method.IsStatic) {
call = new CallVirt(method);
} else {
call = new Call(method); call = new Call(method);
} else {
call = new CallVirt(method);
} }
if (targetConverter != null) { if (targetConverter != null) {
call.Arguments.Add(PrepareCallTarget(method.DeclaringType, targetConverter(), targetType)); call.Arguments.Add(PrepareCallTarget(method.DeclaringType, targetConverter(), targetType));
@ -749,7 +752,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms
ILInstruction BuildCall() ILInstruction BuildCall()
{ {
CallInstruction call = new Call((IMethod)member); CallInstruction call = member.IsStatic
? (CallInstruction)new Call((IMethod)member)
: new CallVirt((IMethod)member);
call.Arguments.AddRange(args.Select(f => f())); call.Arguments.AddRange(args.Select(f => f()));
return call; return call;
} }
@ -1123,10 +1128,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms
ILInstruction BuildProperty() ILInstruction BuildProperty()
{ {
CallInstruction call; CallInstruction call;
if (member.IsAbstract || member.IsVirtual || member.IsOverride) { if (member.IsStatic) {
call = new CallVirt((IMethod)member);
} else {
call = new Call((IMethod)member); call = new Call((IMethod)member);
} else {
call = new CallVirt((IMethod)member);
} }
if (targetConverter != null) { if (targetConverter != null) {
call.Arguments.Add(PrepareCallTarget(member.DeclaringType, targetConverter(), targetType)); call.Arguments.Add(PrepareCallTarget(member.DeclaringType, targetConverter(), targetType));

Loading…
Cancel
Save