Trace indirect field accesses from InitClass instructions in repackaging

Bug: 165783399
Change-Id: Ie6e531208cc1046e50c53ad62d8f632a07ac697e
diff --git a/src/main/java/com/android/tools/r8/repackaging/RepackagingUseRegistry.java b/src/main/java/com/android/tools/r8/repackaging/RepackagingUseRegistry.java
index b27182d..57361d3 100644
--- a/src/main/java/com/android/tools/r8/repackaging/RepackagingUseRegistry.java
+++ b/src/main/java/com/android/tools/r8/repackaging/RepackagingUseRegistry.java
@@ -15,6 +15,7 @@
 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.InitClassLens;
 import com.android.tools.r8.graph.InnerClassAttribute;
 import com.android.tools.r8.graph.MemberResolutionResult;
 import com.android.tools.r8.graph.ProgramDefinition;
@@ -32,6 +33,7 @@
   private final AppInfoWithLiveness appInfo;
   private final RepackagingConstraintGraph constraintGraph;
   private final ProgramDefinition context;
+  private final InitClassLens initClassLens;
   private final RepackagingConstraintGraph.Node node;
 
   public RepackagingUseRegistry(
@@ -42,6 +44,7 @@
     this.appInfo = appView.appInfo();
     this.constraintGraph = constraintGraph;
     this.context = context;
+    this.initClassLens = appView.initClassLens();
     this.node = constraintGraph.getNode(context.getDefinition());
   }
 
@@ -145,7 +148,7 @@
 
   @Override
   public void registerInitClass(DexType type) {
-    registerTypeAccess(type);
+    registerFieldAccess(initClassLens.getInitClassField(type));
   }
 
   @Override
diff --git a/src/test/java/com/android/tools/r8/R8TestBuilder.java b/src/test/java/com/android/tools/r8/R8TestBuilder.java
index 1ad8f28..de56e20 100644
--- a/src/test/java/com/android/tools/r8/R8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/R8TestBuilder.java
@@ -452,10 +452,18 @@
   }
 
   public T enableMemberValuePropagationAnnotations() {
-    if (!enableMemberValuePropagationAnnotations) {
-      enableMemberValuePropagationAnnotations = true;
-      addInternalKeepRules(
-          "-neverpropagatevalue class * { @com.android.tools.r8.NeverPropagateValue *; }");
+    return enableMemberValuePropagationAnnotations(true);
+  }
+
+  public T enableMemberValuePropagationAnnotations(boolean enable) {
+    if (enable) {
+      if (!enableMemberValuePropagationAnnotations) {
+        enableMemberValuePropagationAnnotations = true;
+        addInternalKeepRules(
+            "-neverpropagatevalue class * { @com.android.tools.r8.NeverPropagateValue *; }");
+      }
+    } else {
+      assert !enableMemberValuePropagationAnnotations;
     }
     return self();
   }
diff --git a/src/test/java/com/android/tools/r8/repackage/RepackageTestBase.java b/src/test/java/com/android/tools/r8/repackage/RepackageTestBase.java
index 8eb3d77..c68d18b 100644
--- a/src/test/java/com/android/tools/r8/repackage/RepackageTestBase.java
+++ b/src/test/java/com/android/tools/r8/repackage/RepackageTestBase.java
@@ -62,6 +62,10 @@
     return isRepackagedAsExpected(inspector, null, eligibleForRepackaging);
   }
 
+  protected Matcher<Class<?>> isNotRepackaged(CodeInspector inspector) {
+    return isRepackagedAsExpected(inspector, null, false);
+  }
+
   /**
    * Checks that the class of interest is repackaged as expected.
    *
diff --git a/src/test/java/com/android/tools/r8/repackage/RepackageWithInitClassTest.java b/src/test/java/com/android/tools/r8/repackage/RepackageWithInitClassTest.java
index 9bc8115..e548bcf 100644
--- a/src/test/java/com/android/tools/r8/repackage/RepackageWithInitClassTest.java
+++ b/src/test/java/com/android/tools/r8/repackage/RepackageWithInitClassTest.java
@@ -4,23 +4,43 @@
 
 package com.android.tools.r8.repackage;
 
+import static com.android.tools.r8.shaking.ProguardConfigurationParser.FLATTEN_PACKAGE_HIERARCHY;
+import static com.android.tools.r8.shaking.ProguardConfigurationParser.REPACKAGE_CLASSES;
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
 import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.MatcherAssert.assertThat;
 
+import com.android.tools.r8.NeverPropagateValue;
 import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
 
 @RunWith(Parameterized.class)
 public class RepackageWithInitClassTest extends RepackageTestBase {
 
+  private final boolean enableMemberValuePropagationAnnotations;
+
+  @Parameters(name = "{2}, kind: {1}, @NeverPropagateValue: {0}")
+  public static List<Object[]> data() {
+    return buildParameters(
+        BooleanUtils.values(),
+        ImmutableList.of(FLATTEN_PACKAGE_HIERARCHY, REPACKAGE_CLASSES),
+        getTestParameters().withAllRuntimesAndApiLevels().build());
+  }
+
   public RepackageWithInitClassTest(
-      String flattenPackageHierarchyOrRepackageClasses, TestParameters parameters) {
+      boolean enableMemberValuePropagationAnnotations,
+      String flattenPackageHierarchyOrRepackageClasses,
+      TestParameters parameters) {
     super(flattenPackageHierarchyOrRepackageClasses, parameters);
+    this.enableMemberValuePropagationAnnotations = enableMemberValuePropagationAnnotations;
   }
 
   @Test
@@ -30,6 +50,7 @@
         .addClassObfuscationDictionary("a")
         .addKeepMainRule(TestClass.class)
         .apply(this::configureRepackaging)
+        .enableMemberValuePropagationAnnotations(enableMemberValuePropagationAnnotations)
         .setMinApi(parameters.getApiLevel())
         .compile()
         .inspect(this::inspect)
@@ -41,28 +62,45 @@
     ClassSubject repackagedClassSubject = inspector.clazz(StaticMemberValuePropagation.class);
     assertThat(repackagedClassSubject, isPresent());
 
-    // Verify that a $r8$clinit field was synthesized.
     String clinitFieldName = inspector.getFactory().objectMembers.clinitField.name.toSourceString();
-    assertThat(repackagedClassSubject.uniqueFieldWithName(clinitFieldName), isPresent());
-    assertThat(repackagedClassSubject.uniqueFieldWithName("GREETING"), not(isPresent()));
+    if (enableMemberValuePropagationAnnotations) {
+      // No $r8$clinit field should have been synthesized since we can use the HELLO field.
+      assertThat(repackagedClassSubject.uniqueFieldWithName(clinitFieldName), not(isPresent()));
+      assertThat(repackagedClassSubject.uniqueFieldWithName("HELLO"), isPresent());
 
-    // Verify that the class was repackaged.
-    assertThat(StaticMemberValuePropagation.class, isRepackaged(inspector));
+      // Verify that the WORLD field has been removed.
+      assertThat(repackagedClassSubject.uniqueFieldWithName("WORLD"), not(isPresent()));
+
+      // Verify that the class was not repackaged.
+      assertThat(StaticMemberValuePropagation.class, isNotRepackaged(inspector));
+    } else {
+      // Verify that a $r8$clinit field was synthesized.
+      assertThat(repackagedClassSubject.uniqueFieldWithName(clinitFieldName), isPresent());
+
+      // Verify that both fields have been removed.
+      assertThat(repackagedClassSubject.uniqueFieldWithName("HELLO"), not(isPresent()));
+      assertThat(repackagedClassSubject.uniqueFieldWithName("WORLD"), not(isPresent()));
+
+      // Verify that the class was repackaged.
+      assertThat(StaticMemberValuePropagation.class, isRepackaged(inspector));
+    }
   }
 
   static class TestClass {
 
     public static void main(String[] args) {
-      System.out.println(StaticMemberValuePropagation.GREETING);
+      System.out.println(StaticMemberValuePropagation.WORLD);
     }
   }
 
   public static class StaticMemberValuePropagation {
 
-    public static String GREETING = " world!";
+    @NeverPropagateValue static String HELLO = "Hello";
+
+    public static String WORLD = " world!";
 
     static {
-      System.out.print("Hello");
+      System.out.print(HELLO);
     }
   }
 }