Additional tests for <clinit> rewriting
Bug: 67468748
Change-Id: I05a6efaf207e3520a1cee2d2103e53791d3f6db5
diff --git a/src/test/java/com/android/tools/r8/TestBase.java b/src/test/java/com/android/tools/r8/TestBase.java
index dde13ae..645bf2b 100644
--- a/src/test/java/com/android/tools/r8/TestBase.java
+++ b/src/test/java/com/android/tools/r8/TestBase.java
@@ -289,6 +289,13 @@
/**
* Run application on Art with the specified main class.
*/
+ protected String runOnArt(AndroidApp app, String mainClass) throws IOException {
+ return runOnArtRaw(app, mainClass).stdout;
+ }
+
+ /**
+ * Run application on Art with the specified main class.
+ */
protected String runOnArt(AndroidApp app, Class mainClass) throws IOException {
return runOnArtRaw(app, mainClass).stdout;
}
diff --git a/src/test/java/com/android/tools/r8/jasmin/JasminBuilder.java b/src/test/java/com/android/tools/r8/jasmin/JasminBuilder.java
index 8f3ace3..0db6991 100644
--- a/src/test/java/com/android/tools/r8/jasmin/JasminBuilder.java
+++ b/src/test/java/com/android/tools/r8/jasmin/JasminBuilder.java
@@ -24,12 +24,18 @@
public static class ClassBuilder {
public final String name;
+ public final String superName;
private final List<String> methods = new ArrayList<>();
private final List<String> fields = new ArrayList<>();
private boolean makeInit = false;
public ClassBuilder(String name) {
+ this(name, "java/lang/Object");
+ }
+
+ public ClassBuilder(String name, String superName) {
this.name = name;
+ this.superName = superName;
}
public MethodSignature addVirtualMethod(
@@ -105,14 +111,14 @@
StringBuilder builder = new StringBuilder();
builder.append(".source ").append(name).append(".j\n");
builder.append(".class public ").append(name).append("\n");
- builder.append(".super java/lang/Object\n");
+ builder.append(".super ").append(superName).append("\n");
if (makeInit) {
builder
.append(".method public <init>()V\n")
.append(".limit locals 1\n")
.append(".limit stack 1\n")
.append(" aload 0\n")
- .append(" invokespecial java/lang/Object/<init>()V\n")
+ .append(" invokespecial ").append(superName).append("/<init>()V\n")
.append(" return\n")
.append(".end method\n");
}
@@ -136,6 +142,12 @@
return builder;
}
+ public ClassBuilder addClass(String name, String superName) {
+ ClassBuilder builder = new ClassBuilder(name, superName);
+ classes.add(builder);
+ return builder;
+ }
+
public ImmutableList<ClassBuilder> getClasses() {
return ImmutableList.copyOf(classes);
}
diff --git a/src/test/java/com/android/tools/r8/rewrite/staticvalues/B67468748.java b/src/test/java/com/android/tools/r8/rewrite/staticvalues/B67468748.java
index 6d9f582..e27b5b9 100644
--- a/src/test/java/com/android/tools/r8/rewrite/staticvalues/B67468748.java
+++ b/src/test/java/com/android/tools/r8/rewrite/staticvalues/B67468748.java
@@ -17,7 +17,42 @@
public class B67468748 extends JasminTestBase {
@Test
- public void jarInput() throws Exception {
+ public void initializeStaticFieldInSuper() throws Exception {
+ final String SUPER_NAME = "Super";
+ final String CLASS_NAME = "Test";
+
+ JasminBuilder builder = new JasminBuilder();
+
+ // Simple super class with just a static field.
+ JasminBuilder.ClassBuilder zuper = builder.addClass(SUPER_NAME);
+ zuper.addStaticField("intField", "I", null);
+
+ JasminBuilder.ClassBuilder clazz = builder.addClass(CLASS_NAME, SUPER_NAME);
+
+ // The static field Test/intField is actually defined on the super class.
+ clazz.addStaticMethod("<clinit>", ImmutableList.of(), "V",
+ ".limit stack 1",
+ ".limit locals 1",
+ "iconst_1",
+ "putstatic Test/intField I",
+ "return");
+
+ clazz.addMainMethod(
+ ".limit stack 2",
+ ".limit locals 1",
+ "getstatic java/lang/System/out Ljava/io/PrintStream;",
+ "getstatic Test/intField I",
+ "invokevirtual java/io/PrintStream/print(I)V",
+ "return");
+
+ // Run in release mode to turn on initializer defaults rewriting.
+ AndroidApp application = compileWithD8(builder, options -> options.debug = false);
+ String result = runOnArt(application, CLASS_NAME);
+ assertEquals("1", result);
+ }
+
+ @Test
+ public void invalidCode() throws Exception {
final String CLASS_NAME = "Test";
JasminBuilder builder = new JasminBuilder();
diff --git a/src/test/java/com/android/tools/r8/rewrite/staticvalues/StaticValuesTest.java b/src/test/java/com/android/tools/r8/rewrite/staticvalues/StaticValuesTest.java
index 1d26039..4d1d619 100644
--- a/src/test/java/com/android/tools/r8/rewrite/staticvalues/StaticValuesTest.java
+++ b/src/test/java/com/android/tools/r8/rewrite/staticvalues/StaticValuesTest.java
@@ -574,7 +574,42 @@
}
@Test
- public void b67468748() throws Exception {
+ public void b67468748InitializeStaticFieldInSuper() throws Exception {
+ final String SUPER_NAME = "Super";
+ final String CLASS_NAME = "Test";
+
+ SmaliBuilder builder = new SmaliBuilder();
+ builder.addClass(SUPER_NAME);
+ builder.addStaticField("intField", "I");
+
+ // The static field LTest;->intField:I is not defined even though it is written in the
+ // <clinit> code. This class cannot load, but we can still process it to output which still
+ // cannot load.
+ builder.addClass(CLASS_NAME, SUPER_NAME);
+ builder.addStaticInitializer(
+ 2,
+ "const v0, 3",
+ "sput v0, LTest;->intField:I",
+ "return-void"
+ );
+ builder.addMainMethod(
+ 3,
+ "sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;",
+ "sget v1, LTest;->intField:I",
+ "invoke-virtual { v0, v1 }, Ljava/io/PrintStream;->print(I)V",
+ "return-void"
+ );
+
+ AndroidApp application = builder.build();
+
+ // Run in release mode to turn on initializer defaults rewriting.
+ application = compileWithD8(application, options -> options.debug = false);
+ String result = runOnArt(application, CLASS_NAME);
+ assertEquals(result, "3");
+ }
+
+ @Test
+ public void b67468748InvalidCode() throws Exception {
final String CLASS_NAME = "Test";
SmaliBuilder builder = new SmaliBuilder(CLASS_NAME);
@@ -592,7 +627,7 @@
3,
"sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;",
"sget v1, LTest;->intField:I",
- "invoke-virtual { v0, v1 }, Ljava/io/PrintStream;->println(I)V",
+ "invoke-virtual { v0, v1 }, Ljava/io/PrintStream;->print(I)V",
"return-void"
);