diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/StackTypes.il b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/StackTypes.il index f5506fd42..9c178a2ce 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/StackTypes.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/StackTypes.il @@ -22,6 +22,7 @@ extends [mscorlib]System.Object call void Program::InlineAssignByte() call void Program::Int32OrNativeTests() + call void Program::ByRefInstanceCallWithTypeMismatchTests() ret } // end of method Main @@ -284,4 +285,42 @@ pointless: call void [mscorlib]System.Console::WriteLine(object) ret } + + .method public static void ByRefInstanceCallWithTypeMismatchTests() + { + ldstr "ByRefInstanceCallWithTypeMismatch(0) = {0}" + ldc.i4.0 + call string Program::ByRefInstanceCallWithTypeMismatch(int32) + call void [mscorlib]System.Console::WriteLine(string, object) + + ldstr "ByRefInstanceCallWithTypeMismatch(1) = {0}" + ldc.i4.1 + call string Program::ByRefInstanceCallWithTypeMismatch(int32) + call void [mscorlib]System.Console::WriteLine(string, object) + + ldstr "Issue1333() = {0}" + call string Program::Issue1333() + call void [mscorlib]System.Console::WriteLine(string, object) + + ret + } + + .method public hidebysig static string ByRefInstanceCallWithTypeMismatch(int32 val) cil managed + { + ldarga val + constrained. [mscorlib]System.Boolean + callvirt instance string [mscorlib]System.Object::ToString() + ret + } + + .method public hidebysig static string Issue1333() cil managed + { + .locals (bool) + ldc.i4.0 + stloc.0 + ldloca.s 0 + constrained. [mscorlib]System.Boolean + callvirt instance string [mscorlib]System.Object::ToString() + ret + } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs index 917513287..da5547d19 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Reflection; namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { @@ -230,6 +231,26 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty return a == null; } + public bool CompareType(Type a, Type b) + { + return a == b; + } + + public bool CompareTypeByReference(Type a, Type b) + { + return (object)a == b; + } + + public bool CompareTypeWithNull(Type t) + { + return t == null; + } + + public Attribute CallExtensionMethodViaBaseClass(Type type) + { + return type.GetCustomAttribute(); + } + public decimal ImplicitConversionToDecimal(byte v) { return v; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.il index ca1368caa..c782d8855 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.il @@ -785,6 +785,77 @@ IL_0009: ret } // end of method TypeAnalysisTests::CompareStringWithNull + .method public hidebysig instance bool + CompareType(class [mscorlib]System.Type a, + class [mscorlib]System.Type b) cil managed + { + // Code size 13 (0xd) + .maxstack 2 + .locals init (bool V_0) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldarg.2 + IL_0003: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type, + class [mscorlib]System.Type) + IL_0008: stloc.0 + IL_0009: br.s IL_000b + + IL_000b: ldloc.0 + IL_000c: ret + } // end of method TypeAnalysisTests::CompareType + + .method public hidebysig instance bool + CompareTypeByReference(class [mscorlib]System.Type a, + class [mscorlib]System.Type b) cil managed + { + // Code size 10 (0xa) + .maxstack 2 + .locals init (bool V_0) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldarg.2 + IL_0003: ceq + IL_0005: stloc.0 + IL_0006: br.s IL_0008 + + IL_0008: ldloc.0 + IL_0009: ret + } // end of method TypeAnalysisTests::CompareTypeByReference + + .method public hidebysig instance bool + CompareTypeWithNull(class [mscorlib]System.Type t) cil managed + { + // Code size 13 (0xd) + .maxstack 2 + .locals init (bool V_0) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldnull + IL_0003: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type, + class [mscorlib]System.Type) + IL_0008: stloc.0 + IL_0009: br.s IL_000b + + IL_000b: ldloc.0 + IL_000c: ret + } // end of method TypeAnalysisTests::CompareTypeWithNull + + .method public hidebysig instance class [mscorlib]System.Attribute + CallExtensionMethodViaBaseClass(class [mscorlib]System.Type 'type') cil managed + { + // Code size 12 (0xc) + .maxstack 1 + .locals init (class [mscorlib]System.Attribute V_0) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: call !!0 [mscorlib]System.Reflection.CustomAttributeExtensions::GetCustomAttribute(class [mscorlib]System.Reflection.MemberInfo) + IL_0007: stloc.0 + IL_0008: br.s IL_000a + + IL_000a: ldloc.0 + IL_000b: ret + } // end of method TypeAnalysisTests::CallExtensionMethodViaBaseClass + .method public hidebysig instance valuetype [mscorlib]System.Decimal ImplicitConversionToDecimal(uint8 v) cil managed { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.opt.il index 82382a638..dd4e9ea13 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.opt.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.opt.il @@ -542,6 +542,53 @@ IL_0004: ret } // end of method TypeAnalysisTests::CompareStringWithNull + .method public hidebysig instance bool + CompareType(class [mscorlib]System.Type a, + class [mscorlib]System.Type b) cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.2 + IL_0002: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type, + class [mscorlib]System.Type) + IL_0007: ret + } // end of method TypeAnalysisTests::CompareType + + .method public hidebysig instance bool + CompareTypeByReference(class [mscorlib]System.Type a, + class [mscorlib]System.Type b) cil managed + { + // Code size 5 (0x5) + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.2 + IL_0002: ceq + IL_0004: ret + } // end of method TypeAnalysisTests::CompareTypeByReference + + .method public hidebysig instance bool + CompareTypeWithNull(class [mscorlib]System.Type t) cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldnull + IL_0002: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type, + class [mscorlib]System.Type) + IL_0007: ret + } // end of method TypeAnalysisTests::CompareTypeWithNull + + .method public hidebysig instance class [mscorlib]System.Attribute + CallExtensionMethodViaBaseClass(class [mscorlib]System.Type 'type') cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: call !!0 [mscorlib]System.Reflection.CustomAttributeExtensions::GetCustomAttribute(class [mscorlib]System.Reflection.MemberInfo) + IL_0006: ret + } // end of method TypeAnalysisTests::CallExtensionMethodViaBaseClass + .method public hidebysig instance valuetype [mscorlib]System.Decimal ImplicitConversionToDecimal(uint8 v) cil managed { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.opt.roslyn.il index 0a7d1beb4..7d78eaa65 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.opt.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.opt.roslyn.il @@ -544,6 +544,53 @@ IL_0004: ret } // end of method TypeAnalysisTests::CompareStringWithNull + .method public hidebysig instance bool + CompareType(class [mscorlib]System.Type a, + class [mscorlib]System.Type b) cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.2 + IL_0002: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type, + class [mscorlib]System.Type) + IL_0007: ret + } // end of method TypeAnalysisTests::CompareType + + .method public hidebysig instance bool + CompareTypeByReference(class [mscorlib]System.Type a, + class [mscorlib]System.Type b) cil managed + { + // Code size 5 (0x5) + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.2 + IL_0002: ceq + IL_0004: ret + } // end of method TypeAnalysisTests::CompareTypeByReference + + .method public hidebysig instance bool + CompareTypeWithNull(class [mscorlib]System.Type t) cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldnull + IL_0002: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type, + class [mscorlib]System.Type) + IL_0007: ret + } // end of method TypeAnalysisTests::CompareTypeWithNull + + .method public hidebysig instance class [mscorlib]System.Attribute + CallExtensionMethodViaBaseClass(class [mscorlib]System.Type 'type') cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: call !!0 [mscorlib]System.Reflection.CustomAttributeExtensions::GetCustomAttribute(class [mscorlib]System.Reflection.MemberInfo) + IL_0006: ret + } // end of method TypeAnalysisTests::CallExtensionMethodViaBaseClass + .method public hidebysig instance valuetype [mscorlib]System.Decimal ImplicitConversionToDecimal(uint8 v) cil managed { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.roslyn.il index 58f12ef8d..ab3f048fd 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.roslyn.il @@ -784,6 +784,77 @@ IL_0009: ret } // end of method TypeAnalysisTests::CompareStringWithNull + .method public hidebysig instance bool + CompareType(class [mscorlib]System.Type a, + class [mscorlib]System.Type b) cil managed + { + // Code size 13 (0xd) + .maxstack 2 + .locals init (bool V_0) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldarg.2 + IL_0003: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type, + class [mscorlib]System.Type) + IL_0008: stloc.0 + IL_0009: br.s IL_000b + + IL_000b: ldloc.0 + IL_000c: ret + } // end of method TypeAnalysisTests::CompareType + + .method public hidebysig instance bool + CompareTypeByReference(class [mscorlib]System.Type a, + class [mscorlib]System.Type b) cil managed + { + // Code size 10 (0xa) + .maxstack 2 + .locals init (bool V_0) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldarg.2 + IL_0003: ceq + IL_0005: stloc.0 + IL_0006: br.s IL_0008 + + IL_0008: ldloc.0 + IL_0009: ret + } // end of method TypeAnalysisTests::CompareTypeByReference + + .method public hidebysig instance bool + CompareTypeWithNull(class [mscorlib]System.Type t) cil managed + { + // Code size 13 (0xd) + .maxstack 2 + .locals init (bool V_0) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldnull + IL_0003: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type, + class [mscorlib]System.Type) + IL_0008: stloc.0 + IL_0009: br.s IL_000b + + IL_000b: ldloc.0 + IL_000c: ret + } // end of method TypeAnalysisTests::CompareTypeWithNull + + .method public hidebysig instance class [mscorlib]System.Attribute + CallExtensionMethodViaBaseClass(class [mscorlib]System.Type 'type') cil managed + { + // Code size 12 (0xc) + .maxstack 1 + .locals init (class [mscorlib]System.Attribute V_0) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: call !!0 [mscorlib]System.Reflection.CustomAttributeExtensions::GetCustomAttribute(class [mscorlib]System.Reflection.MemberInfo) + IL_0007: stloc.0 + IL_0008: br.s IL_000a + + IL_000a: ldloc.0 + IL_000b: ret + } // end of method TypeAnalysisTests::CallExtensionMethodViaBaseClass + .method public hidebysig instance valuetype [mscorlib]System.Decimal ImplicitConversionToDecimal(uint8 v) cil managed { diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index 01f8a8abb..b0931cc1a 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -1174,7 +1174,7 @@ namespace ICSharpCode.Decompiler.CSharp entityDecl.AddAnnotation(function); if (function.IsIterator) { - if (!body.Descendants.Any(d => d is YieldReturnStatement || d is YieldBreakStatement)) { + if (localSettings.DecompileMemberBodies && !body.Descendants.Any(d => d is YieldReturnStatement || d is YieldBreakStatement)) { body.Add(new YieldBreakStatement()); } RemoveAttribute(entityDecl, KnownAttribute.IteratorStateMachine); diff --git a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs index 87b9e4651..c395abd46 100644 --- a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs @@ -1185,6 +1185,7 @@ namespace ICSharpCode.Decompiler.CSharp TranslatedExpression HandleDelegateConstruction(CallInstruction inst) { + ILInstruction thisArg = inst.Arguments[0]; ILInstruction func = inst.Arguments[1]; IMethod method; switch (func.OpCode) { @@ -1203,16 +1204,27 @@ namespace ICSharpCode.Decompiler.CSharp bool requireTarget; if (method.IsExtensionMethod && invokeMethod != null && method.Parameters.Count - 1 == invokeMethod.Parameters.Count) { targetType = method.Parameters[0].Type; - target = expressionBuilder.Translate(inst.Arguments[0], targetType); - target = ExpressionBuilder.UnwrapBoxingConversion(target); + if (targetType.Kind == TypeKind.ByReference && thisArg is Box thisArgBox) { + targetType = ((ByReferenceType)targetType).ElementType; + thisArg = thisArgBox.Argument; + } + target = expressionBuilder.Translate(thisArg, targetType); requireTarget = true; } else { targetType = method.DeclaringType; - target = expressionBuilder.TranslateTarget(inst.Arguments[0], + if (targetType.IsReferenceType == false && thisArg is Box thisArgBox) { + // Normal struct instance method calls (which TranslateTarget is meant for) expect a 'ref T', + // but delegate construction uses a 'box T'. + if (thisArgBox.Argument is LdObj ldobj) { + thisArg = ldobj.Target; + } else { + thisArg = new AddressOf(thisArgBox.Argument); + } + } + target = expressionBuilder.TranslateTarget(thisArg, nonVirtualInvocation: func.OpCode == OpCode.LdFtn, memberStatic: method.IsStatic, memberDeclaringType: method.DeclaringType); - target = ExpressionBuilder.UnwrapBoxingConversion(target); requireTarget = expressionBuilder.HidesVariableWithName(method.Name) || (method.IsStatic ? !expressionBuilder.IsCurrentOrContainingType(method.DeclaringTypeDefinition) : !(target.Expression is ThisReferenceExpression)); } diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index 67c26d14d..bb41c68ae 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -1710,9 +1710,12 @@ namespace ICSharpCode.Decompiler.CSharp .WithRR(new ThisResolveResult(memberDeclaringType, nonVirtualInvocation)); } else { var translatedTarget = Translate(target, memberDeclaringType); - if (CallInstruction.ExpectedTypeForThisPointer(memberDeclaringType) == StackType.Ref && translatedTarget.Type.GetStackType().IsIntegerType()) { - // when accessing members on value types, ensure we use a reference and not a pointer - translatedTarget = translatedTarget.ConvertTo(new ByReferenceType(memberDeclaringType), this); + if (CallInstruction.ExpectedTypeForThisPointer(memberDeclaringType) == StackType.Ref) { + // When accessing members on value types, ensure we use a reference of the correct type, + // and not a pointer or a reference to a different type (issue #1333) + if (!(translatedTarget.Type is ByReferenceType brt && NormalizeTypeVisitor.TypeErasure.EquivalentTypes(brt.ElementType, memberDeclaringType))) { + translatedTarget = translatedTarget.ConvertTo(new ByReferenceType(memberDeclaringType), this); + } } if (translatedTarget.Expression is DirectionExpression) { // (ref x).member => x.member @@ -2470,8 +2473,14 @@ namespace ICSharpCode.Decompiler.CSharp protected internal override TranslatedExpression VisitAddressOf(AddressOf inst, TranslationContext context) { + IType targetTypeHint = null; + if (context.TypeHint is ByReferenceType brt) { + targetTypeHint = brt.ElementType; + } else if (context.TypeHint is PointerType pt) { + targetTypeHint = pt.ElementType; + } // HACK: this is only correct if the argument is an R-value; otherwise we're missing the copy to the temporary - var value = Translate(inst.Value); + var value = Translate(inst.Value, targetTypeHint); return new DirectionExpression(FieldDirection.Ref, value) .WithILInstruction(inst) .WithRR(new ByReferenceResolveResult(value.ResolveResult, false)); diff --git a/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs b/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs index 02bc5584b..af1b2b947 100644 --- a/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs +++ b/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs @@ -86,20 +86,23 @@ namespace ICSharpCode.Decompiler.CSharp CollectNamespacesForTypeReference(param.Type, namespaces); } HandleTypeParameters(method.TypeParameters, namespaces); - if (!method.MetadataToken.IsNil && method.HasBody) { + if (!method.MetadataToken.IsNil) { if (mappingInfo == null) mappingInfo = CSharpDecompiler.GetCodeMappingInfo(entity.ParentModule.PEFile, entity.MetadataToken); var reader = module.PEFile.Reader; var parts = mappingInfo.GetMethodParts((MethodDefinitionHandle)method.MetadataToken).ToList(); foreach (var part in parts) { + HandleOverrides(part.GetMethodImplementations(module.metadata), module, namespaces); var methodDef = module.metadata.GetMethodDefinition(part); - MethodBodyBlock body; - try { - body = reader.GetMethodBody(methodDef.RelativeVirtualAddress); - } catch (BadImageFormatException) { - continue; + if (method.HasBody) { + MethodBodyBlock body; + try { + body = reader.GetMethodBody(methodDef.RelativeVirtualAddress); + } catch (BadImageFormatException) { + continue; + } + CollectNamespacesFromMethodBody(body, module, namespaces); } - CollectNamespacesFromMethodBody(body, module, namespaces); } } break; @@ -116,6 +119,16 @@ namespace ICSharpCode.Decompiler.CSharp } } + static void HandleOverrides(ImmutableArray immutableArray, MetadataModule module, HashSet namespaces) + { + foreach (var h in immutableArray) { + var methodImpl = module.metadata.GetMethodImplementation(h); + CollectNamespacesForTypeReference(module.ResolveType(methodImpl.Type, genericContext), namespaces); + CollectNamespacesForMemberReference(module.ResolveMethod(methodImpl.MethodBody, genericContext), module, namespaces); + CollectNamespacesForMemberReference(module.ResolveMethod(methodImpl.MethodDeclaration, genericContext), module, namespaces); + } + } + static void CollectNamespacesForTypeReference(IType type, HashSet namespaces) { switch (type) { diff --git a/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs b/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs index d04015e0c..e2f14d4a6 100644 --- a/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs @@ -348,9 +348,18 @@ namespace ICSharpCode.Decompiler.CSharp return pointerExpr.ConvertTo(targetType, expressionBuilder); } if (targetType.Kind == TypeKind.ByReference) { + var elementType = ((ByReferenceType)targetType).ElementType; + if (this.Expression is DirectionExpression thisDir && this.ILInstructions.Any(i => i.OpCode == OpCode.AddressOf) + && thisDir.Expression.GetResolveResult()?.Type.GetStackType() == elementType.GetStackType()) { + // When converting a reference to a temporary to a different type, + // apply the cast to the temporary instead. + 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)); + } // Convert from integer/pointer to reference. // First, convert to the corresponding pointer type: - var elementType = ((ByReferenceType)targetType).ElementType; var arg = this.ConvertTo(new PointerType(elementType), expressionBuilder, checkForOverflow); Expression expr; ResolveResult elementRR; diff --git a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs index 2b45ff9ac..9a8971100 100644 --- a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs +++ b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs @@ -1150,9 +1150,9 @@ namespace ICSharpCode.Decompiler.Disassembler WriteAttributes(module, propertyDefinition.GetCustomAttributes()); WriteNestedMethod(".get", module, accessors.Getter); WriteNestedMethod(".set", module, accessors.Setter); - /*foreach (var method in property.OtherMethods) { - WriteNestedMethod(".other", method); - }*/ + foreach (var method in accessors.Others) { + WriteNestedMethod(".other", module, method); + } CloseBlock(); } @@ -1213,9 +1213,9 @@ namespace ICSharpCode.Decompiler.Disassembler WriteNestedMethod(".addon", module, accessors.Adder); WriteNestedMethod(".removeon", module, accessors.Remover); WriteNestedMethod(".fire", module, accessors.Raiser); - /*foreach (var method in ev.OtherMethods) { - WriteNestedMethod(".other", method); - }*/ + foreach (var method in accessors.Others) { + WriteNestedMethod(".other", module, method); + } CloseBlock(); } #endregion diff --git a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs index 082344bf2..0fd486a13 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs @@ -343,6 +343,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (parent is ILiftableInstruction liftable && liftable.IsLifted) { return true; // inline into lifted operators } + // decide based on the new parent into which we are inlining: switch (parent.OpCode) { case OpCode.NullCoalescingInstruction: if (NullableType.IsNullable(v.Type)) @@ -362,7 +363,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms case OpCode.LocAllocSpan: return true; // inline size-expressions into localloc.span } - // decide based on the target into which we are inlining + // decide based on the top-level target instruction into which we are inlining: switch (next.OpCode) { case OpCode.Leave: case OpCode.YieldReturn: