Summary:public Lazy dynamic dispatch handling works as follows: Assuming a call of the form: foo(a); where the static type of `a` is `A`. If during the symbolic execution, the dynamic type of the variable `a` is `B` where `B <: A`, then we create on-demand a copy `foo(B)` of `foo(A)` where all the uses of the typed parameter `a` are replaced with a parameter of type `B`. Especially, if `foo` contains virtual call, say `get` where `a` is the receiver, then the call gets redirected to the overridden method in `B`, which simulates the runtime behavior of Java. This lazy dynamic dispatch mode is only turn on for the tracing mode for now in order to avoid conflicts with sblackshear's approach for sound dynamic dispatch. Reviewed By: sblackshear Differential Revision: D2888922 fb-gh-sync-id: 3250c9e shipit-source-id: 3250c9emaster
parent
82f2b7b6de
commit
082ca6a90a
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2015 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package codetoanalyze.java.tracing;
|
||||
|
||||
class A {
|
||||
|
||||
public T get() {
|
||||
return new T();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
|
||||
public T get() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class LazyDynamicDispatchExample {
|
||||
|
||||
static T foo(A a) {
|
||||
return a.get();
|
||||
}
|
||||
|
||||
static void bar() {
|
||||
B b = new B();
|
||||
foo(b).f();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2015 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
|
||||
package endtoend.java.tracing;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static utils.matchers.ResultContainsExactly.containsExactly;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import utils.InferException;
|
||||
import utils.InferResults;
|
||||
|
||||
public class LazyDynamicDispatchTest {
|
||||
|
||||
public static final String SOURCE_FILE =
|
||||
"infer/tests/codetoanalyze/java/tracing/LazyDynamicDispatchExample.java";
|
||||
|
||||
public static final String NPE =
|
||||
"java.lang.NullPointerException";
|
||||
|
||||
private static InferResults inferResults;
|
||||
|
||||
@BeforeClass
|
||||
public static void loadResults() throws InterruptedException, IOException {
|
||||
inferResults = InferResults.loadTracingResults(
|
||||
LazyDynamicDispatchTest.class,
|
||||
SOURCE_FILE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchErrors()
|
||||
throws IOException, InterruptedException, InferException {
|
||||
String[] methods = {
|
||||
"bar"
|
||||
};
|
||||
assertThat(
|
||||
"Results should contain " + NPE,
|
||||
inferResults,
|
||||
containsExactly(
|
||||
NPE,
|
||||
SOURCE_FILE,
|
||||
methods
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in new issue