Commit c508e72c authored by Skylot's avatar Skylot

core: fixed types for arguments from overloaded methods

parent 940de240
...@@ -523,8 +523,30 @@ public class InsnGen { ...@@ -523,8 +523,30 @@ public class InsnGen {
break; break;
} }
code.add(callMth.getName()); code.add(callMth.getName());
if (callMthNode != null && callMthNode.isArgsOverload()) {
int argsCount = insn.getArgsCount();
List<ArgType> originalType = callMth.getArgumentsTypes();
int origPos = 0;
code.add('(');
for (int i = k; i < argsCount; i++) {
InsnArg arg = insn.getArg(i);
ArgType origType = originalType.get(origPos);
if (!arg.getType().equals(origType)) {
code.add('(').add(useType(origType)).add(')').add(arg(arg));
} else {
code.add(arg(arg));
}
if (i < argsCount - 1) {
code.add(", ");
}
origPos++;
}
code.add(')');
} else {
addArgs(code, insn, k); addArgs(code, insn, k);
} }
}
private void inlineMethod(MethodNode callMthNode, InvokeNode insn, CodeWriter code) throws CodegenException { private void inlineMethod(MethodNode callMthNode, InvokeNode insn, CodeWriter code) throws CodegenException {
IAttribute mia = callMthNode.getAttributes().get(AttributeType.METHOD_INLINE); IAttribute mia = callMthNode.getAttributes().get(AttributeType.METHOD_INLINE);
...@@ -566,11 +588,14 @@ public class InsnGen { ...@@ -566,11 +588,14 @@ public class InsnGen {
} }
private void addArgs(CodeWriter code, InsnNode insn, int k) throws CodegenException { private void addArgs(CodeWriter code, InsnNode insn, int k) throws CodegenException {
int argsCount = insn.getArgsCount();
code.add('('); code.add('(');
for (int i = k; i < insn.getArgsCount(); i++) { if (k < argsCount) {
code.add(arg(insn, i)); code.add(arg(insn, k));
if (i < insn.getArgsCount() - 1) for (int i = k + 1; i < argsCount; i++) {
code.add(", "); code.add(", ");
code.add(arg(insn, i));
}
} }
code.add(')'); code.add(')');
} }
......
...@@ -455,8 +455,23 @@ public class MethodNode extends LineAttrNode implements ILoadable { ...@@ -455,8 +455,23 @@ public class MethodNode extends LineAttrNode implements ILoadable {
return exceptionHandlers; return exceptionHandlers;
} }
public boolean isMethodOverloaded() { /**
// TODO * Return true if exists method with same name and arguments count
*/
public boolean isArgsOverload() {
int argsCount = mthInfo.getArgumentsTypes().size();
if (argsCount == 0) {
return false;
}
String name = getName();
List<MethodNode> methods = parentClass.getMethods();
for (MethodNode method : methods) {
if (this != method
&& method.getName().equals(name)
&& method.mthInfo.getArgumentsTypes().size() == argsCount)
return true;
}
return false; return false;
} }
......
...@@ -19,11 +19,11 @@ public class FinishTypeResolver extends AbstractVisitor { ...@@ -19,11 +19,11 @@ public class FinishTypeResolver extends AbstractVisitor {
int i = 0; int i = 0;
do { do {
change = false; change = false;
for (BlockNode block : mth.getBasicBlocks()) for (BlockNode block : mth.getBasicBlocks()) {
for (InsnNode insn : block.getInstructions()) for (InsnNode insn : block.getInstructions())
if (PostTypeResolver.visit(insn)) if (PostTypeResolver.visit(mth, insn))
change = true; change = true;
}
i++; i++;
if (i > 1000) if (i > 1000)
break; break;
......
package jadx.core.dex.visitors.typeresolver.finish; package jadx.core.dex.visitors.typeresolver.finish;
import jadx.core.dex.info.MethodInfo;
import jadx.core.dex.instructions.IfNode; import jadx.core.dex.instructions.IfNode;
import jadx.core.dex.instructions.InvokeNode;
import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.instructions.args.InsnArg; import jadx.core.dex.instructions.args.InsnArg;
import jadx.core.dex.instructions.args.LiteralArg; import jadx.core.dex.instructions.args.LiteralArg;
import jadx.core.dex.instructions.args.RegisterArg; import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.nodes.InsnNode; import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PostTypeResolver { public class PostTypeResolver {
private static final Logger LOG = LoggerFactory.getLogger(PostTypeResolver.class);
public static boolean visit(InsnNode insn) { public static boolean visit(MethodNode mth, InsnNode insn) {
switch (insn.getType()) { switch (insn.getType()) {
case CONST: case CONST:
if (insn.getArgsCount() > 0) {
RegisterArg res = insn.getResult(); RegisterArg res = insn.getResult();
LiteralArg litArg = (LiteralArg) insn.getArg(0); LiteralArg litArg = (LiteralArg) insn.getArg(0);
if (res.getType().isObject()) { if (res.getType().isObject()) {
...@@ -28,8 +36,6 @@ public class PostTypeResolver { ...@@ -28,8 +36,6 @@ public class PostTypeResolver {
} }
// return litArg.getTypedVar().forceSetType(res.getType()); // return litArg.getTypedVar().forceSetType(res.getType());
return litArg.merge(res); return litArg.merge(res);
}
break;
case MOVE: { case MOVE: {
boolean change = false; boolean change = false;
...@@ -58,6 +64,27 @@ public class PostTypeResolver { ...@@ -58,6 +64,27 @@ public class PostTypeResolver {
return change; return change;
} }
// check argument types for overloaded methods
case INVOKE: {
boolean change = false;
InvokeNode inv = (InvokeNode) insn;
MethodInfo callMth = inv.getCallMth();
MethodNode node = mth.dex().resolveMethod(callMth);
if (node != null && node.isArgsOverload()) {
List<ArgType> args = callMth.getArgumentsTypes();
int j = inv.getArgsCount() - 1;
for (int i = args.size() - 1; i >= 0; i--) {
ArgType argType = args.get(i);
InsnArg insnArg = inv.getArg(j--);
if (insnArg.isRegister() && !argType.equals(insnArg.getType())) {
insnArg.getTypedVar().forceSetType(argType);
change = true;
}
}
}
return change;
}
default: default:
break; break;
} }
......
package jadx.samples;
/**
* Code example from
* <a href="http://stackoverflow.com/questions/2840183/is-there-any-java-decompiler-that-can-correctly-decompile-calls-to-overloaded-me">
* stackoverflow question</a>
*/
public class TestTypeResolver2 extends AbstractTest {
private static String result = "";
public void testOverloadedMethods() {
Object s1 = "The";
Object s2 = "answer";
doPrint((Object) "You should know:");
for (int i = 0; i < 2; i++) {
doPrint(s1);
doPrint(s2);
s1 = "is";
s2 = new Integer(42);
}
}
private static void doPrint(String s1) {
// incorrect call
assertTrue(false);
}
private static void doPrint(Integer s1) {
// incorrect call
assertTrue(false);
}
private static void doPrint(Object s1) {
// correct call
result += s1 + " ";
}
@Override
public boolean testRun() throws Exception {
testOverloadedMethods();
assertEquals(result, "You should know: The answer is 42 ");
return true;
}
public static void main(String[] args) throws Exception {
(new TestTypeResolver2()).testRun();
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment