@ -3784,7 +3784,9 @@ namespace ICSharpCode.Decompiler.CSharp
// on a mutable lvalue, we would end up modifying the original lvalue, not just the copy.
// on a mutable lvalue, we would end up modifying the original lvalue, not just the copy.
// We solve this by introducing a "redundant" cast. Casts are classified as rvalue
// We solve this by introducing a "redundant" cast. Casts are classified as rvalue
// and ensure that the C# compiler will also create a copy.
// and ensure that the C# compiler will also create a copy.
if ( classification = = ExpressionClassification . MutableLValue & & value . Expression is not CastExpression )
if ( classification = = ExpressionClassification . MutableLValue
& & ! CanIgnoreCopy ( )
& & value . Expression is not CastExpression )
{
{
value = new CastExpression ( ConvertType ( inst . Type ) , value . Expression )
value = new CastExpression ( ConvertType ( inst . Type ) , value . Expression )
. WithoutILInstruction ( )
. WithoutILInstruction ( )
@ -3793,6 +3795,21 @@ namespace ICSharpCode.Decompiler.CSharp
return new DirectionExpression ( FieldDirection . Ref , value )
return new DirectionExpression ( FieldDirection . Ref , value )
. WithILInstruction ( inst )
. WithILInstruction ( inst )
. WithRR ( new ByReferenceResolveResult ( value . ResolveResult , ReferenceKind . Ref ) ) ;
. WithRR ( new ByReferenceResolveResult ( value . ResolveResult , ReferenceKind . Ref ) ) ;
bool CanIgnoreCopy ( )
{
ILInstruction loadAddress = inst ;
while ( loadAddress . Parent is LdFlda parent )
{
loadAddress = parent ;
}
if ( loadAddress . Parent is LdObj )
{
// Ignore copy, never introduce a cast
return true ;
}
return false ;
}
}
}
protected internal override TranslatedExpression VisitAwait ( Await inst , TranslationContext context )
protected internal override TranslatedExpression VisitAwait ( Await inst , TranslationContext context )