Raise an error if the given pg-map is incomplete.
Even <init> to <init> mappings should be present in the pg-map,
which have been missed at the test pg-map.
Since <clinit> may be omitted, it is handled exceptionally:
unmapped <clinit> is not regarded as incomplete pg-map.
Bug: 71621001
Change-Id: I93f76c66a40bef11f09da95566c1a66a6d5ef6da
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMapApplier.java b/src/main/java/com/android/tools/r8/naming/ProguardMapApplier.java
index 1a2551e..3fad0d4 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapApplier.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapApplier.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.naming;
+import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.graph.DexAnnotation;
import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexClass;
@@ -10,6 +11,7 @@
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.DexItem;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexType;
@@ -21,8 +23,8 @@
import com.android.tools.r8.utils.ArrayUtils;
import com.android.tools.r8.utils.ThrowingConsumer;
import com.android.tools.r8.utils.Timing;
+import com.google.common.collect.Sets;
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
-import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
@@ -131,12 +133,15 @@
DexClass clazz = appInfo.definitionFor(from);
if (clazz == null) return;
- Set<MemberNaming> appliedMemberNaming = new HashSet<>();
+ final Set<DexItem> membersNotMapped = Sets.newIdentityHashSet();
+ final Set<MemberNaming> appliedMemberNaming = Sets.newIdentityHashSet();
clazz.forEachField(encodedField -> {
MemberNaming memberNaming = classNaming.lookupByOriginalItem(encodedField.field);
if (memberNaming != null) {
appliedMemberNaming.add(memberNaming);
applyFieldMapping(encodedField.field, memberNaming);
+ } else if (clazz.isLibraryClass()) {
+ membersNotMapped.add(encodedField.field);
}
});
@@ -145,9 +150,26 @@
if (memberNaming != null) {
appliedMemberNaming.add(memberNaming);
applyMethodMapping(encodedMethod.method, memberNaming);
+ } else if (clazz.isLibraryClass()) {
+ // <clinit> mapping could be omitted.
+ if (encodedMethod.isClassInitializer()) {
+ return;
+ }
+ membersNotMapped.add(encodedMethod.method);
}
});
+ // The presence of members that are not mapped indicates incomplete mappings for libraries.
+ if (!membersNotMapped.isEmpty()) {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Incomplete mappings:");
+ for (DexItem member : membersNotMapped) {
+ builder.append(System.lineSeparator()).append(" ").append(member);
+ }
+ builder.append(System.lineSeparator());
+ throw new CompilationError(builder.toString(), clazz.origin);
+ }
+
// We need to handle a lib class that extends another lib class where some members are not
// overridden, resulting in absence of definitions. References to those members need to be
// redirected via lense as well.
@@ -309,11 +331,12 @@
for (int i = 0; i < methods.length; i++) {
DexEncodedMethod encodedMethod = methods[i];
DexMethod appliedMethod = appliedLense.lookupMethod(encodedMethod.method, encodedMethod);
+ DexType newHolderType = substituteType(appliedMethod.holder, encodedMethod);
DexProto newProto = substituteTypesIn(appliedMethod.proto, encodedMethod);
DexMethod newMethod;
- if (newProto != appliedMethod.proto) {
+ if (newHolderType != appliedMethod.holder || newProto != appliedMethod.proto) {
newMethod = appInfo.dexItemFactory.createMethod(
- substituteType(appliedMethod.holder, encodedMethod), newProto, appliedMethod.name);
+ substituteType(newHolderType, encodedMethod), newProto, appliedMethod.name);
lenseBuilder.map(encodedMethod.method, newMethod);
} else {
newMethod = appliedMethod;
@@ -331,11 +354,12 @@
for (int i = 0; i < fields.length; i++) {
DexEncodedField encodedField = fields[i];
DexField appliedField = appliedLense.lookupField(encodedField.field, null);
- DexType newType = substituteType(appliedField.type, null);
+ DexType newHolderType = substituteType(appliedField.clazz, null);
+ DexType newFieldType = substituteType(appliedField.type, null);
DexField newField;
- if (newType != appliedField.type) {
+ if (newHolderType != appliedField.clazz || newFieldType != appliedField.type) {
newField = appInfo.dexItemFactory.createField(
- substituteType(appliedField.clazz, null), newType, appliedField.name);
+ substituteType(newHolderType, null), newFieldType, appliedField.name);
lenseBuilder.map(encodedField.field, newField);
} else {
newField = appliedField;
diff --git a/src/test/examples/applymapping044/AsubB.java b/src/test/examples/applymapping044/AsubB.java
index 2c5fd0c..3df11e4 100644
--- a/src/test/examples/applymapping044/AsubB.java
+++ b/src/test/examples/applymapping044/AsubB.java
@@ -7,7 +7,11 @@
import naming044.sub.SubB;
public class AsubB extends SubB {
+ public AsubB(int f) {
+ super(f);
+ }
+
public int boo(A a) {
- return f(a) * 3;
+ return f(a) * f;
}
}
diff --git a/src/test/examples/applymapping044/Main.java b/src/test/examples/applymapping044/Main.java
index 9d5f577..a0389e8 100644
--- a/src/test/examples/applymapping044/Main.java
+++ b/src/test/examples/applymapping044/Main.java
@@ -14,7 +14,9 @@
A a = new A();
B b = new B();
b.f(a);
- AsubB subB = new AsubB();
+ AsubB aSubB = new AsubB(3);
+ aSubB.f(a);
+ SubB subB = new SubB(3);
subB.f(a);
}
}
diff --git a/src/test/examples/applymapping044/test-mapping.txt b/src/test/examples/applymapping044/test-mapping.txt
index 41c2c5c..0a7d25f 100644
--- a/src/test/examples/applymapping044/test-mapping.txt
+++ b/src/test/examples/applymapping044/test-mapping.txt
@@ -1,9 +1,15 @@
naming044.A -> naming044.x:
+ void <init>() -> <init>
int f -> o
naming044.B -> naming044.y:
+ void <init>() -> <init>
int m() -> n
int f(naming044.A) -> p
naming044.sub.SubA -> naming044.z.x:
+ void <init>() -> <init>
int f -> q
naming044.sub.SubB -> naming044.z.y:
+ void <init>() -> <init>
+ void <init>(int) -> <init>
int n() -> m
+ int f -> r
diff --git a/src/test/examples/naming044/sub/SubB.java b/src/test/examples/naming044/sub/SubB.java
index 823de8c..75d12a0 100644
--- a/src/test/examples/naming044/sub/SubB.java
+++ b/src/test/examples/naming044/sub/SubB.java
@@ -6,6 +6,12 @@
import naming044.B;
public class SubB extends B {
+ protected int f;
+
+ public SubB(int f) {
+ this.f = f;
+ }
+
public static int n() {
return SubA.f;
}
diff --git a/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java b/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java
index 9f8061b..64c553e 100644
--- a/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java
+++ b/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java
@@ -30,7 +30,6 @@
import java.util.Iterator;
import java.util.concurrent.ExecutionException;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
@@ -62,7 +61,6 @@
}
@Test
- @Ignore("b/71621001")
public void test044_obfuscate_and_apply() throws Exception {
// keep rules that allow obfuscations while keeping everything.
Path flagForObfuscation =
@@ -121,7 +119,7 @@
DexType a1 = f.invokedMethod().proto.parameters.values[0];
assertNotEquals("naming044.A", a1.toString());
assertEquals("naming044.A", mapperFromApp.deobfuscateClassName(a1.toString()));
- assertNotEquals("f", f.invokedMethod().name.toSourceString());
+ assertNotEquals("f", f.invokedMethod().name.toString());
// Skip AsubB#<init>
iterator.next();
// AsubB#f(A)
@@ -130,9 +128,20 @@
DexType a2 = aSubB_f.proto.parameters.values[0];
assertNotEquals("naming044.A", a2.toString());
assertEquals("naming044.A", mapperFromApp.deobfuscateClassName(a2.toString()));
- assertNotEquals("f", overloaded_f.invokedMethod().name.toSourceString());
+ assertNotEquals("f", aSubB_f.name.toString());
// B#f == AsubB#f
assertEquals(f.invokedMethod().name.toString(), aSubB_f.name.toString());
+ // sub.SubB#<init>(int)
+ InvokeInstructionSubject subBinit = iterator.next();
+ assertNotEquals("naming044.sub.SubB", subBinit.holder().toString());
+ assertEquals("naming044.sub.SubB",
+ mapperFromApp.deobfuscateClassName(subBinit.holder().toString()));
+ // sub.SubB#f(A)
+ InvokeInstructionSubject original_f = iterator.next();
+ DexMethod subB_f = original_f.invokedMethod();
+ DexType a3 = subB_f.proto.parameters.values[0];
+ assertEquals(a2, a3);
+ assertNotEquals("f", original_f.invokedMethod().name.toString());
}
@Test
@@ -153,11 +162,11 @@
// B#m() -> y#n()
InvokeInstructionSubject m = iterator.next();
assertEquals("naming044.y", m.holder().toString());
- assertEquals("n", m.invokedMethod().name.toSourceString());
+ assertEquals("n", m.invokedMethod().name.toString());
// sub.SubB#n() -> z.y#m()
InvokeInstructionSubject n = iterator.next();
assertEquals("naming044.z.y", n.holder().toString());
- assertEquals("m", n.invokedMethod().name.toSourceString());
+ assertEquals("m", n.invokedMethod().name.toString());
// Skip A#<init>
iterator.next();
// Skip B#<init>
@@ -166,7 +175,7 @@
InvokeInstructionSubject f = iterator.next();
DexType a1 = f.invokedMethod().proto.parameters.values[0];
assertEquals("naming044.x", a1.toString());
- assertEquals("p", f.invokedMethod().name.toSourceString());
+ assertEquals("p", f.invokedMethod().name.toString());
// Skip AsubB#<init>
iterator.next();
// AsubB#f(A) -> AsubB#p(x)
@@ -174,9 +183,18 @@
DexMethod aSubB_f = overloaded_f.invokedMethod();
DexType a2 = aSubB_f.proto.parameters.values[0];
assertEquals("naming044.x", a2.toString());
- assertEquals("p", aSubB_f.name.toSourceString());
+ assertEquals("p", aSubB_f.name.toString());
// B#f == AsubB#f
assertEquals(f.invokedMethod().name.toString(), aSubB_f.name.toString());
+ // sub.SubB#<init>(int) -> z.y<init>(int)
+ InvokeInstructionSubject subBinit = iterator.next();
+ assertEquals("naming044.z.y", subBinit.holder().toString());
+ // sub.SubB#f(A) -> SubB#p(x)
+ InvokeInstructionSubject original_f = iterator.next();
+ DexMethod subB_f = original_f.invokedMethod();
+ DexType a3 = subB_f.proto.parameters.values[0];
+ assertEquals(a2, a3);
+ assertEquals("p", original_f.invokedMethod().name.toString());
}
@Test