From 7c7328df3291378118be29e1855ced305f3e5086 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 29 Mar 2020 12:21:23 +0200 Subject: [PATCH] Fix #1955: struct 'base' access to ValueType mis-decompiles --- .../TestCases/Pretty/QualifierTests.cs | 11 ++++++++++ .../CSharp/ExpressionBuilder.cs | 20 ++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/QualifierTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/QualifierTests.cs index b09df51e7..35c042533 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/QualifierTests.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/QualifierTests.cs @@ -74,6 +74,17 @@ namespace ICSharpCode.Decompiler.Tests.Pretty { } + + public string ThisQualifierWithCast() + { + return ((object)this).ToString(); + } + + public override string ToString() + { + // decompiled as return ((ValueType)this).ToString(); + return base.ToString(); + } } internal class Parent diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index 9856960d4..cb0047375 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -1999,7 +1999,7 @@ namespace ICSharpCode.Decompiler.CSharp // If references are missing member.IsStatic might not be set correctly. // Additionally check target for null, in order to avoid a crash. if (!memberStatic && target != null) { - if (nonVirtualInvocation && target.MatchLdThis() && memberDeclaringType.GetDefinition() != resolver.CurrentTypeDefinition) { + if (nonVirtualInvocation && MatchLdThis(target) && memberDeclaringType.GetDefinition() != resolver.CurrentTypeDefinition) { return new BaseReferenceExpression() .WithILInstruction(target) .WithRR(new ThisResolveResult(memberDeclaringType, nonVirtualInvocation)); @@ -2034,6 +2034,24 @@ namespace ICSharpCode.Decompiler.CSharp .WithoutILInstruction() .WithRR(new TypeResolveResult(memberDeclaringType)); } + + bool MatchLdThis(ILInstruction inst) + { + // ldloc this + if (inst.MatchLdThis()) + return true; + if (resolver.CurrentTypeDefinition.Kind == TypeKind.Struct) { + // box T(ldobj T(ldloc this)) + if (!inst.MatchBox(out var arg, out var type)) + return false; + if (!arg.MatchLdObj(out var arg2, out var type2)) + return false; + if (!type.Equals(type2) || !type.Equals(resolver.CurrentTypeDefinition)) + return false; + return arg2.MatchLdThis(); + } + return false; + } } private TranslatedExpression EnsureTargetNotNullable(TranslatedExpression expr)