diff --git a/jode/jode/decompiler/ClassAnalyzer.java b/jode/jode/decompiler/ClassAnalyzer.java index aeacc1e..f92bdb4 100644 --- a/jode/jode/decompiler/ClassAnalyzer.java +++ b/jode/jode/decompiler/ClassAnalyzer.java @@ -31,7 +31,7 @@ import jode.flow.TransformConstructors; public class ClassAnalyzer implements Analyzer { JodeEnvironment env; - Analyzer[] analyzers; + Analyzer[] analyzers; MethodAnalyzer staticConstructor; MethodAnalyzer[] constructors; @@ -64,6 +64,10 @@ public class ClassAnalyzer implements Analyzer { return false; } + public Class getClazz() { + return clazz; + } + public void analyze() { int numFields = 0; int i = 0; diff --git a/jode/jode/expr/InvokeOperator.java b/jode/jode/expr/InvokeOperator.java index 104bb6a..59ea6e5 100644 --- a/jode/jode/expr/InvokeOperator.java +++ b/jode/jode/expr/InvokeOperator.java @@ -88,6 +88,20 @@ public final class InvokeOperator extends Operator { return methodName.equals(""); } + public boolean isThis() { + Class clazz = codeAnalyzer.method.classAnalyzer.getClazz(); + return (classType.equals(Type.tType(clazz))); + } + + public boolean isSuperOrThis() { + Class clazz = codeAnalyzer.method.classAnalyzer.getClazz(); + while (clazz != null + && !classType.equals(Type.tType(clazz))) { + clazz = clazz.getSuperclass(); + } + return (clazz != null); + } + public String toString(String[] operands) { String object = null; if (specialFlag) { @@ -101,11 +115,11 @@ public final class InvokeOperator extends Operator { } if (clazz == null) - object = "SPECIAL"; + object = "NON VIRTUAL this"; } else if (classType.equals(Type.tType(clazz))) object = operands[0]; else - object = "SPECIAL "+operands[0]; + object = "NON VIRTUAL "+operands[0]; } object = (object != null) ? object diff --git a/jode/jode/flow/TransformConstructors.java b/jode/jode/flow/TransformConstructors.java index b19f33a..4fd2130 100644 --- a/jode/jode/flow/TransformConstructors.java +++ b/jode/jode/flow/TransformConstructors.java @@ -35,29 +35,55 @@ public class TransformConstructors { if (cons.length == 0) return; - InstructionBlock[] superCall = new InstructionBlock[cons.length]; - StructuredBlock[] start = new StructuredBlock[cons.length]; - StructuredBlock[] sb = new StructuredBlock[cons.length]; - for (int i=0; i< sb.length; i++) { + int constrCount = cons.length; + StructuredBlock[] sb = new StructuredBlock[constrCount]; + for (int i=0; i< constrCount; ) { sb[i] = cons[i].getMethodHeader().block; - if (sb[i] == null) - return; - if (!isStatic && - sb[i] instanceof SequentialBlock - && sb[i].getSubBlocks()[0] instanceof InstructionBlock) { - superCall[i] = (InstructionBlock) sb[i].getSubBlocks()[0]; - - if (!(superCall[i].getInstruction().getOperator() - instanceof InvokeOperator) - || !((InvokeOperator)superCall[i].getInstruction() - .getOperator()).isConstructor()) - superCall[i] = null; + if (!isStatic) { + InstructionBlock ib; + if (sb[i] instanceof InstructionBlock) + ib = (InstructionBlock)sb[i]; + else if (sb[i] instanceof SequentialBlock + && (sb[i].getSubBlocks()[0] + instanceof InstructionBlock)) + ib = (InstructionBlock) sb[i].getSubBlocks()[0]; else - /* skip super call */ + return; + + Expression instr = ib.getInstruction(); + + if (!(instr instanceof ComplexExpression) + || !(instr.getOperator() instanceof InvokeOperator) + || !(((ComplexExpression)instr) + .getSubExpressions()[0].toString().equals("this"))) + return; + + InvokeOperator invoke = (InvokeOperator) instr.getOperator(); + if (!invoke.isConstructor() || !invoke.isSuperOrThis()) + return; + + if (invoke.isThis()) { + /* This constructor calls another constructor, so we + * can skip it. + */ + sb[i] = sb[--constrCount]; + continue; + } + /* This constructor begins with a super call, as + * expected. If the super() has no parameters, we + * can remove it as it is implicit. + */ + if (invoke.getMethodType().getParameterTypes().length == 0) + ib.removeBlock(); + if (sb[i] instanceof SequentialBlock) sb[i] = sb[i].getSubBlocks()[1]; + else + sb[i] = new EmptyBlock(); } + i++; } - for (int i=0; i< sb.length; i++) + StructuredBlock[] start = new StructuredBlock[constrCount]; + for (int i=0; i< constrCount; i++) start[i] = sb[i]; big_loop: for (;;) { @@ -94,7 +120,7 @@ public class TransformConstructors { break big_loop; } - for (int i=1; i< sb.length; i++) { + for (int i=1; i< constrCount; i++) { ib = (sb[0] instanceof SequentialBlock) ? sb[0].getSubBlocks()[0] : sb[0]; @@ -112,31 +138,23 @@ public class TransformConstructors { } - for (int i=0; i< sb.length; i++) { + for (int i=0; i< constrCount; i++) { if (sb[i] instanceof SequentialBlock) sb[i] = sb[i].getSubBlocks()[1]; else sb[i] = null; } - for (int i=0; i< sb.length; i++) + for (int i=0; i< constrCount; i++) if (sb[i] == null) { // System.err.println("constr "+i+" is over"); break big_loop; } } - for (int i=0; i< superCall.length; i++) { + for (int i=0; i< constrCount; i++) { if (sb[i] == null) start[i].removeBlock(); else sb[i].replace(start[i]); - if (superCall[i] != null) { - InvokeOperator op = - (InvokeOperator) superCall[i].getInstruction() - .getOperator(); - /* super() is implicit */ - if (op.getMethodType().getParameterTypes().length == 0) - superCall[i].removeBlock(); - } } } }