Skip to content

Commit 6e58580

Browse files
authored
Improve CHABuilder precision via resolving callees using the type of the receiver variable (#197)
1 parent 523aec2 commit 6e58580

File tree

3 files changed

+46
-1
lines changed

3 files changed

+46
-1
lines changed

src/main/java/pascal/taie/analysis/graph/callgraph/CHABuilder.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525
import org.apache.logging.log4j.LogManager;
2626
import org.apache.logging.log4j.Logger;
2727
import pascal.taie.World;
28+
import pascal.taie.analysis.pta.plugin.util.InvokeUtils;
2829
import pascal.taie.config.ConfigException;
30+
import pascal.taie.ir.exp.Var;
2931
import pascal.taie.ir.proginfo.MemberRef;
3032
import pascal.taie.ir.proginfo.MethodRef;
3133
import pascal.taie.ir.stmt.Invoke;
@@ -34,6 +36,8 @@
3436
import pascal.taie.language.classes.JClass;
3537
import pascal.taie.language.classes.JMethod;
3638
import pascal.taie.language.classes.Subsignature;
39+
import pascal.taie.language.type.ClassType;
40+
import pascal.taie.language.type.NullType;
3741
import pascal.taie.util.AnalysisException;
3842
import pascal.taie.util.collection.Maps;
3943
import pascal.taie.util.collection.TwoKeyMap;
@@ -151,7 +155,15 @@ private Set<JMethod> resolveCalleesOf(Invoke callSite) {
151155
if (ignoreObjectMethods && isObjectMethod(methodRef)) {
152156
yield Set.of();
153157
}
154-
JClass cls = methodRef.getDeclaringClass();
158+
Var base = InvokeUtils.getVar(callSite, InvokeUtils.BASE);
159+
JClass cls;
160+
if (base.getType() instanceof ClassType classType) {
161+
cls = classType.getJClass();
162+
} else if (base.getType() instanceof NullType) {
163+
yield Set.of();
164+
} else {
165+
cls = methodRef.getDeclaringClass();
166+
}
155167
Set<JMethod> callees = resolveTable.get(cls, methodRef);
156168
if (callees == null) {
157169
callees = hierarchy.getAllSubclassesOf(cls)

src/test/java/pascal/taie/analysis/graph/callgraph/cha/CHATest.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,21 @@
2222

2323
package pascal.taie.analysis.graph.callgraph.cha;
2424

25+
import org.junit.jupiter.api.Test;
2526
import org.junit.jupiter.params.ParameterizedTest;
2627
import org.junit.jupiter.params.provider.ValueSource;
28+
import pascal.taie.Main;
29+
import pascal.taie.World;
2730
import pascal.taie.analysis.Tests;
31+
import pascal.taie.analysis.graph.callgraph.CallGraph;
32+
import pascal.taie.analysis.graph.callgraph.CallGraphBuilder;
33+
import pascal.taie.ir.stmt.Invoke;
34+
import pascal.taie.language.classes.JMethod;
35+
36+
import java.util.List;
37+
38+
import static org.junit.jupiter.api.Assertions.assertEquals;
39+
import static org.junit.jupiter.api.Assertions.assertFalse;
2840

2941
public class CHATest {
3042

@@ -45,4 +57,18 @@ void testFull(String mainClass) {
4557
test(mainClass);
4658
}
4759

60+
@Test
61+
void testArray() {
62+
Main.main("-pp",
63+
"-cp", CLASS_PATH,
64+
"-m", "Array",
65+
"-a", "cg=algorithm:cha-full");
66+
CallGraph<Invoke, JMethod> callGraph = World.get().getResult(CallGraphBuilder.ID);
67+
JMethod main = World.get().getMainMethod();
68+
List<Invoke> invokes = main.getIR().invokes(false).toList();
69+
assertEquals(2, invokes.size());
70+
assertFalse(callGraph.getCalleesOf(invokes.get(0)).isEmpty());
71+
assertFalse(callGraph.getCalleesOf(invokes.get(1)).isEmpty());
72+
}
73+
4874
}

src/test/resources/cha/Array.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
public class Array {
2+
public static void main(String[] args) {
3+
Object[] array = new Object[114];
4+
String s = array.toString();
5+
int hashCode = array.hashCode();
6+
}
7+
}

0 commit comments

Comments
 (0)