Merge "Remove enclosing method attrs that reference pruned items."
diff --git a/src/main/java/com/android/tools/r8/graph/DexClass.java b/src/main/java/com/android/tools/r8/graph/DexClass.java
index f69251b..c76865e 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -482,6 +482,12 @@
enclosingMethod = null;
}
+ public void removeEnclosingMethod(Predicate<EnclosingMethodAttribute> predicate) {
+ if (enclosingMethod != null && predicate.test(enclosingMethod)) {
+ enclosingMethod = null;
+ }
+ }
+
public void clearInnerClasses() {
innerClasses.clear();
}
diff --git a/src/main/java/com/android/tools/r8/shaking/TreePruner.java b/src/main/java/com/android/tools/r8/shaking/TreePruner.java
index c012898..6cf0da0 100644
--- a/src/main/java/com/android/tools/r8/shaking/TreePruner.java
+++ b/src/main/java/com/android/tools/r8/shaking/TreePruner.java
@@ -8,8 +8,10 @@
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.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.EnclosingMethodAttribute;
import com.android.tools.r8.graph.InnerClassAttribute;
import com.android.tools.r8.graph.KeyedDexItem;
import com.android.tools.r8.graph.PresortedComparable;
@@ -102,15 +104,44 @@
clazz.setInstanceFields(reachableFields(clazz.instanceFields()));
clazz.setStaticFields(reachableFields(clazz.staticFields()));
clazz.removeInnerClasses(this::isAttributeReferencingPrunedType);
+ clazz.removeEnclosingMethod(this::isAttributeReferencingPrunedItem);
usagePrinter.visited();
}
}
return newClasses;
}
+ private boolean isAttributeReferencingPrunedItem(EnclosingMethodAttribute attr) {
+ return
+ (attr.getEnclosingClass() != null
+ && !appInfo.liveTypes.contains(attr.getEnclosingClass()))
+ || (attr.getEnclosingMethod() != null
+ && !appInfo.liveMethods.contains(attr.getEnclosingMethod()));
+ }
+
private boolean isAttributeReferencingPrunedType(InnerClassAttribute attr) {
- return (attr.getInner() != null && !appInfo.liveTypes.contains(attr.getInner()))
- || (attr.getOuter() != null && !appInfo.liveTypes.contains(attr.getOuter()));
+ if (!appInfo.liveTypes.contains(attr.getInner())) {
+ return true;
+ }
+ DexType context = attr.getOuter();
+ if (context == null) {
+ DexClass inner = appInfo.definitionFor(attr.getInner());
+ if (inner != null && inner.getEnclosingMethod() != null) {
+ EnclosingMethodAttribute enclosingMethodAttribute = inner.getEnclosingMethod();
+ if (enclosingMethodAttribute.getEnclosingClass() != null) {
+ context = enclosingMethodAttribute.getEnclosingClass();
+ } else {
+ DexMethod enclosingMethod = enclosingMethodAttribute.getEnclosingMethod();
+ if (!appInfo.liveMethods.contains(enclosingMethod)) {
+ // EnclosingMethodAttribute will be pruned as it references the pruned method.
+ // Hence, removal of the current InnerClassAttribute too.
+ return true;
+ }
+ context = enclosingMethod.getHolder();
+ }
+ }
+ }
+ return context == null || !appInfo.liveTypes.contains(context);
}
private <S extends PresortedComparable<S>, T extends KeyedDexItem<S>> int firstUnreachableIndex(
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetNameTest.java b/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetNameTest.java
index 9cc69fa..54f9df3 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetNameTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetNameTest.java
@@ -263,7 +263,7 @@
.addKeepRules("-keepattributes InnerClasses,EnclosingMethod")
.addKeepRules("-printmapping " + createNewMappingPath().toAbsolutePath().toString());
if (!enableMinification) {
- builder.addKeepRules("-dontobfuscate");
+ builder.noMinification();
}
TestRunResult result =
builder
@@ -284,7 +284,7 @@
.addKeepRules("-keepattributes InnerClasses,EnclosingMethod")
.addKeepRules("-printmapping " + createNewMappingPath().toAbsolutePath().toString());
if (!enableMinification) {
- builder.addKeepRules("-dontobfuscate");
+ builder.noMinification();
}
TestRunResult result =
builder
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetSimpleNameTest.java b/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetSimpleNameTest.java
index b75e4ee..5a9ca75 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetSimpleNameTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetSimpleNameTest.java
@@ -124,7 +124,7 @@
"Inner",
"Inner"
);
- private static final String OUTPUT_WITH_SHRUNK_ATTRIBUTE = StringUtils.lines(
+ private static final String OUTPUT_WITH_SHRUNK_ATTRIBUTES = StringUtils.lines(
"Local_t03",
"InnerLocal",
"$",
@@ -211,7 +211,7 @@
.addKeepRules("-keepattributes InnerClasses,EnclosingMethod")
.addKeepRules("-printmapping " + createNewMappingPath().toAbsolutePath().toString());
if (!enableMinification) {
- builder.addKeepRules("-dontobfuscate");
+ builder.noMinification();
}
TestRunResult result =
builder
@@ -231,12 +231,12 @@
.addKeepRules("-keep,allowobfuscation class **.ClassGetSimpleName*")
// See b/119471127: some old VMs are not resilient to broken attributes.
// Comment out the following line to reproduce b/120130435
- // then use OUTPUT_WITH_SHRUNK_ATTRIBUTE
+ // then use OUTPUT_WITH_SHRUNK_ATTRIBUTES
.addKeepRules("-keep,allowobfuscation class **.Outer*")
.addKeepRules("-keepattributes InnerClasses,EnclosingMethod")
.addKeepRules("-printmapping " + createNewMappingPath().toAbsolutePath().toString());
if (!enableMinification) {
- builder.addKeepRules("-dontobfuscate");
+ builder.noMinification();
}
R8TestRunResult result =
builder
diff --git a/src/test/java/com/android/tools/r8/shaking/EnclosingMethodTest.java b/src/test/java/com/android/tools/r8/shaking/EnclosingMethodTest.java
index c14cef5..4e121a8 100644
--- a/src/test/java/com/android/tools/r8/shaking/EnclosingMethodTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/EnclosingMethodTest.java
@@ -49,6 +49,8 @@
private final boolean enableMinification;
private Collection<Path> classPaths;
private static final String JAVA_OUTPUT = "-Returned-null-" + System.lineSeparator();
+ private static final String OUTPUT_WITH_SHRUNK_ATTRIBUTES =
+ "com.android.tools.r8.shaking.GetNameClass$1" + System.lineSeparator();
private static final Class<?> MAIN = GetNameMain.class;
@Parameterized.Parameters(name = "Backend: {0} minification: {1}")
@@ -88,18 +90,10 @@
.addKeepRules("-keep class **.GetName*")
.addKeepRules("-keepattributes InnerClasses,EnclosingMethod");
if (!enableMinification) {
- builder.addKeepRules("-dontobfuscate");
+ builder.noMinification();
}
R8TestRunResult result = builder.run(MAIN);
- if (backend == Backend.DEX) {
- if (ToolHelper.getDexVm().getVersion().isNewerThan(Version.V4_4_4)
- && ToolHelper.getDexVm().getVersion().isOlderThanOrEqual(Version.V6_0_1)) {
- result.assertFailureWithErrorThatMatches(containsString("IncompatibleClassChangeError"));
- return;
- }
- }
-
- result.assertSuccessWithOutput(JAVA_OUTPUT);
+ result.assertSuccessWithOutput(OUTPUT_WITH_SHRUNK_ATTRIBUTES);
}
}