Browse Source

Fixed some bugs in DeclareVariables.

pull/100/head
Daniel Grunwald 15 years ago
parent
commit
cca7547789
  1. 4
      ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
  2. 45
      ICSharpCode.Decompiler/Ast/Transforms/DeclareVariables.cs
  3. 6
      ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs
  4. 20
      ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs

4
ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -88,9 +88,11 @@ namespace ICSharpCode.Decompiler.Ast @@ -88,9 +88,11 @@ namespace ICSharpCode.Decompiler.Ast
context.CancellationToken.ThrowIfCancellationRequested();
Ast.BlockStatement astBlock = TransformBlock(ilMethod);
CommentStatement.ReplaceAll(astBlock); // convert CommentStatements to Comments
Statement insertionPoint = astBlock.Statements.FirstOrDefault();
foreach (ILVariable v in localVariablesToDefine) {
var newVarDecl = new VariableDeclarationStatement(AstBuilder.ConvertType(v.Type), v.Name);
astBlock.Statements.InsertAfter(null, newVarDecl);
astBlock.Statements.InsertBefore(insertionPoint, newVarDecl);
}
return astBlock;

45
ICSharpCode.Decompiler/Ast/Transforms/DeclareVariables.cs

@ -92,14 +92,22 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -92,14 +92,22 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
if (TryConvertAssignmentExpressionIntoVariableDeclaration((Expression)usingStmt.ResourceAcquisition, type, variableName))
continue;
}
foreach (BlockStatement subBlock in stmt.Children.OfType<BlockStatement>()) {
DeclareVariableInBlock(daa, subBlock, type, variableName, allowPassIntoLoops);
foreach (AstNode child in stmt.Children) {
BlockStatement subBlock = child as BlockStatement;
if (subBlock != null) {
DeclareVariableInBlock(daa, subBlock, type, variableName, allowPassIntoLoops);
} else if (HasNestedBlocks(child)) {
foreach (BlockStatement nestedSubBlock in child.Children.OfType<BlockStatement>()) {
DeclareVariableInBlock(daa, nestedSubBlock, type, variableName, allowPassIntoLoops);
}
}
}
}
} else {
// Try converting an assignment expression into a VariableDeclarationStatement
if (!TryConvertAssignmentExpressionIntoVariableDeclaration(declarationPoint, type, variableName)) {
// Declare the variable in front of declarationPoint
block.Statements.InsertBefore(
declarationPoint,
new VariableDeclarationStatement((AstType)type.Clone(), variableName)
@ -117,9 +125,11 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -117,9 +125,11 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
if (ae != null && ae.Operator == AssignmentOperatorType.Assign) {
IdentifierExpression ident = ae.Left as IdentifierExpression;
if (ident != null && ident.Identifier == variableName) {
// We clone the right expression so that it doesn't get removed from the old ExpressionStatement,
// which might be still in use by the definite assignment graph.
declarationPoint.ReplaceWith(new VariableDeclarationStatement {
Type = (AstType)type.Clone(),
Variables = { new VariableInitializer(variableName, ae.Right.Detach()).CopyAnnotationsFrom(ae) }
Variables = { new VariableInitializer(variableName, ae.Right.Clone()).CopyAnnotationsFrom(ae) }
}.CopyAnnotationsFrom(es).WithAnnotation(new DeclaredVariableAnnotation(es)));
return true;
}
@ -136,7 +146,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -136,7 +146,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
if (ident != null && ident.Identifier == variableName) {
expression.ReplaceWith(new VariableDeclarationStatement {
Type = (AstType)type.Clone(),
Variables = { new VariableInitializer(variableName, ae.Right.Detach()).CopyAnnotationsFrom(ae) }
Variables = { new VariableInitializer(variableName, ae.Right.Clone()).CopyAnnotationsFrom(ae) }
}.WithAnnotation(declaredVariableAnnotation));
return true;
}
@ -179,7 +189,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -179,7 +189,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
return false;
}
// If we can move the variable into the sub-block, we need to ensure that the remaining code
// does not use the value that was assigend by the first sub-block
// does not use the value that was assigned by the first sub-block
Statement nextStatement = stmt.NextStatement;
// The next statement might be a variable declaration that we inserted, and thus does not exist
// in the definite assignment graph. Thus we need to look up the corresponding instruction
@ -239,14 +249,28 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -239,14 +249,28 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
}
}
// We can move the variable into a sub-block only if the variable is used in only that sub-block
// We can move the variable into a sub-block only if the variable is used in only that sub-block (and not in expressions such as the loop condition)
for (AstNode child = stmt.FirstChild; child != null; child = child.NextSibling) {
if (!(child is BlockStatement) && UsesVariable(child, variableName))
return false;
if (!(child is BlockStatement) && UsesVariable(child, variableName)) {
if (HasNestedBlocks(child)) {
// catch clauses/switch sections can contain nested blocks
for (AstNode grandchild = child.FirstChild; grandchild != null; grandchild = grandchild.NextSibling) {
if (!(grandchild is BlockStatement) && UsesVariable(grandchild, variableName))
return false;
}
} else {
return false;
}
}
}
return true;
}
static bool HasNestedBlocks(AstNode node)
{
return node is CatchClause || node is SwitchSection;
}
static bool UsesVariable(AstNode node, string variableName)
{
IdentifierExpression ie = node as IdentifierExpression;
@ -278,6 +302,11 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -278,6 +302,11 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
}
}
CatchClause catchClause = node as CatchClause;
if (catchClause != null && catchClause.VariableName == variableName) {
return false; // no need to introduce the variable here
}
for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
if (UsesVariable(child, variableName))
return true;

6
ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs

@ -276,11 +276,11 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -276,11 +276,11 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
}
}
// Now insert the variable declarations (we can do this after the replacements only so that the scope detection works):
Statement insertionPoint = blockStatement.Statements.FirstOrDefault();
foreach (var tuple in variablesToDeclare) {
var newVarDecl = new VariableDeclarationStatement(tuple.Item1, tuple.Item2);
if (newVarDecl != null)
newVarDecl.Variables.Single().AddAnnotation(new CapturedVariableAnnotation());
blockStatement.Statements.InsertAfter(null, newVarDecl);
newVarDecl.Variables.Single().AddAnnotation(new CapturedVariableAnnotation());
blockStatement.Statements.InsertBefore(insertionPoint, newVarDecl);
}
}
return null;

20
ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs

@ -445,19 +445,9 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -445,19 +445,9 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
if (exit.Match(assign.Left) == null)
return null;
enter = assign.Right;
// Remove 'exit' variable:
bool ok = false;
for (AstNode tmp = node.NextSibling; tmp != tryCatch; tmp = tmp.NextSibling) {
VariableDeclarationStatement v = (VariableDeclarationStatement)tmp;
if (v.Variables.Single().Name == exit.Identifier) {
ok = true;
v.Remove();
break;
}
}
if (!ok)
return null;
// TODO: verify that 'obj' variable can be removed
}
// TODO: verify that 'flag' variable can be removed
// transform the code into a lock statement:
LockStatement l = new LockStatement();
l.Expression = enter.Detach();
@ -487,17 +477,13 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -487,17 +477,13 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
},
TrueStatement = new AnyNode("dictCreation")
},
new VariableDeclarationStatement {
Type = new PrimitiveType("int"),
Variables = { new NamedNode("intVar", new VariableInitializer()) }
},
new IfElseStatement {
Condition = new Backreference("cachedDict").ToExpression().Invoke(
"TryGetValue",
new NamedNode("switchVar", new IdentifierExpression()),
new DirectionExpression {
FieldDirection = FieldDirection.Out,
Expression = new IdentifierExpressionBackreference("intVar")
Expression = new IdentifierExpression().WithName("intVar")
}),
TrueStatement = new BlockStatement {
Statements = {

Loading…
Cancel
Save