@ -395,6 +395,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// - increment block
// - increment block
if ( incrementBlock . Instructions . Count < = 1 | | loop . Blocks . Count < 3 )
if ( incrementBlock . Instructions . Count < = 1 | | loop . Blocks . Count < 3 )
return false ;
return false ;
if ( StoresRefLocalUsedAfterLoop ( loop , incrementBlock ) )
return false ;
context . Step ( "Transform to for loop: " + loop . EntryPoint . Label , loop ) ;
context . Step ( "Transform to for loop: " + loop . EntryPoint . Label , loop ) ;
// move the block to the end of the loop:
// move the block to the end of the loop:
loop . Blocks . MoveElementToEnd ( incrementBlock ) ;
loop . Blocks . MoveElementToEnd ( incrementBlock ) ;
@ -467,6 +469,27 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true ;
return true ;
}
}
static bool StoresRefLocalUsedAfterLoop ( BlockContainer loop , Block incrementBlock )
{
foreach ( var store in incrementBlock . Instructions . SkipLast ( 1 ) . SelectMany ( inst = > inst . Descendants ) . OfType < StLoc > ( ) )
{
var variable = store . Variable ;
if ( variable . Type . IsByRefLike & & IsVariableUsedAfterLoop ( loop , variable ) )
return true ;
}
return false ;
}
static bool IsVariableUsedAfterLoop ( BlockContainer loop , ILVariable variable )
{
foreach ( var use in variable . LoadInstructions . Concat < ILInstruction > ( variable . AddressInstructions ) . Concat ( variable . StoreInstructions . Cast < ILInstruction > ( ) ) )
{
if ( loop . GetCommonParent ( use ) is Block { Kind : BlockKind . ControlFlow } & & loop . IsBefore ( use ) )
return true ;
}
return false ;
}
bool IsAssignment ( ILInstruction inst )
bool IsAssignment ( ILInstruction inst )
{
{
if ( inst is StLoc )
if ( inst is StLoc )