Merge commit 'ff08464c7250505223ff73e4d752e06c52ee72a0' into dev-release
diff --git a/.gitignore b/.gitignore
index 76604f8..2b1d423 100644
--- a/.gitignore
+++ b/.gitignore
@@ -144,6 +144,8 @@
 third_party/sample_libraries
 third_party/sample_libraries.tar.gz
 third_party/youtube/*
+third_party/youtube-developer/20200415
+third_party/youtube-developer/20200415.tar.gz
 tmp/
 tools/*.pyc
 tools/*/art
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 3b9bb74..7c9cae3 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -72,14 +72,15 @@
     contents = f.NewContents()
     if (not contents) or (len(contents) == 0):
       continue
-    if not CopyRightInContents(contents):
+    if not CopyRightInContents(f, contents):
       results.append(
           output_api.PresubmitError('Could not find Copyright in file: %s' % f))
   return results
 
-def CopyRightInContents(contents):
+def CopyRightInContents(f, contents):
+  expected = ('#' if f.LocalPath().endswith('.py') else '//') + ' Copyright'
   for content_line in contents:
-    if '// Copyright' in content_line:
+    if expected in content_line:
       return True
   return False
 
diff --git a/src/main/java/com/android/tools/r8/graph/DexDefinitionSupplier.java b/src/main/java/com/android/tools/r8/graph/DexDefinitionSupplier.java
index 8b35b54..3d4e92b 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDefinitionSupplier.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDefinitionSupplier.java
@@ -12,6 +12,12 @@
 
   DexEncodedMethod definitionFor(DexMethod method);
 
+  @SuppressWarnings("unchecked")
+  default <D extends DexEncodedMember<D, R>, R extends DexMember<D, R>>
+      DexEncodedMember<D, R> definitionFor(DexMember<D, R> member) {
+    return (DexEncodedMember<D, R>) definitionFor((DexReference) member);
+  }
+
   DexClass definitionFor(DexType type);
 
   DexProgramClass definitionForProgramType(DexType type);
diff --git a/src/main/java/com/android/tools/r8/graph/MethodAccessFlags.java b/src/main/java/com/android/tools/r8/graph/MethodAccessFlags.java
index 1b8e3a0..c91b62d 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodAccessFlags.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodAccessFlags.java
@@ -144,6 +144,10 @@
     unset(Constants.ACC_BRIDGE);
   }
 
+  public void demoteFromBridge() {
+    demote(Constants.ACC_BRIDGE);
+  }
+
   public boolean isVarargs() {
     return isSet(Constants.ACC_VARARGS);
   }
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/ClassInitializerAssertionEnablingAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/ClassInitializerAssertionEnablingAnalysis.java
index 061cbcf..b41e8fa 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/ClassInitializerAssertionEnablingAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/ClassInitializerAssertionEnablingAnalysis.java
@@ -127,7 +127,7 @@
   }
 
   private boolean hasKotlincClinitAssertionCode(DexEncodedMethod method) {
-    if (method.holder() == dexItemFactory.kotlin.kotlinAssertions) {
+    if (method.holder() == dexItemFactory.kotlin.assertions.type) {
       CfCode code = method.getCode().asCfCode();
       for (int i = 1; i < code.instructions.size(); i++) {
         CfInstruction instruction = code.instructions.get(i - 1);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/AssertionsRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/AssertionsRewriter.java
index a356e8b..68453b8 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/AssertionsRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/AssertionsRewriter.java
@@ -12,6 +12,7 @@
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexString;
+import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.code.IRCode;
 import com.android.tools.r8.ir.code.Instruction;
 import com.android.tools.r8.ir.code.InstructionListIterator;
@@ -77,6 +78,7 @@
   private final DexItemFactory dexItemFactory;
   private final AssertionTransformation defaultTransformation;
   private final List<ConfigurationEntryWithDexString> configuration;
+  private final AssertionsConfiguration.AssertionTransformation kotlinTransformation;
   private final boolean enabled;
 
   public AssertionsRewriter(AppView<?> appView) {
@@ -86,6 +88,7 @@
     if (!enabled) {
       defaultTransformation = null;
       configuration = null;
+      kotlinTransformation = null;
       return;
     }
     // Convert the assertion transformation to the representation used for this rewriter.
@@ -94,6 +97,8 @@
         appView.options().assertionsConfiguration.assertionsConfigurations.stream()
             .map(entry -> new ConfigurationEntryWithDexString(entry, appView.dexItemFactory()))
             .collect(Collectors.toList());
+    kotlinTransformation =
+        getTransformationForType(appView.dexItemFactory().kotlin.assertions.type);
   }
 
   // Static method used by other analyses to see if additional analysis is required to support
@@ -104,6 +109,10 @@
   }
 
   private AssertionTransformation getTransformationForMethod(DexEncodedMethod method) {
+    return getTransformationForType(method.holder());
+  }
+
+  private AssertionTransformation getTransformationForType(DexType type) {
     AssertionTransformation transformation = defaultTransformation;
     for (ConfigurationEntryWithDexString entry : configuration) {
       switch (entry.entry.getScope()) {
@@ -112,18 +121,18 @@
           break;
         case PACKAGE:
           if (entry.value.size == 0) {
-            if (!method.holder().descriptor.contains(dexItemFactory.descriptorSeparator)) {
+            if (!type.descriptor.contains(dexItemFactory.descriptorSeparator)) {
               transformation = entry.entry.getTransformation();
             }
-          } else if (method.holder().descriptor.startsWith(entry.value)) {
+          } else if (type.descriptor.startsWith(entry.value)) {
             transformation = entry.entry.getTransformation();
           }
           break;
         case CLASS:
-          if (method.holder().descriptor.equals(entry.value)) {
+          if (type.descriptor.equals(entry.value)) {
             transformation = entry.entry.getTransformation();
           }
-          if (isDescriptorForClassOrInnerClass(entry.value, method.holder().descriptor)) {
+          if (isDescriptorForClassOrInnerClass(entry.value, type.descriptor)) {
             transformation = entry.entry.getTransformation();
           }
           break;
@@ -317,10 +326,10 @@
       }
       clinit = clazz.getClassInitializer();
     }
-    if (clinit == null || !clinit.getOptimizationInfo().isInitializerEnablingJavaVmAssertions()) {
-      return;
-    }
-
+    // For javac generated code it is assumed that the code in <clinit> will tell if the code
+    // in other methods of the class can have assertion checks.
+    boolean isInitializerEnablingJavaVmAssertions =
+        clinit != null && clinit.getOptimizationInfo().isInitializerEnablingJavaVmAssertions();
     // This code will process the assertion code in all methods including <clinit>.
     InstructionListIterator iterator = code.instructionListIterator();
     while (iterator.hasNext()) {
@@ -328,7 +337,7 @@
       if (current.isInvokeMethod()) {
         InvokeMethod invoke = current.asInvokeMethod();
         if (invoke.getInvokedMethod() == dexItemFactory.classMethods.desiredAssertionStatus) {
-          if (method.holder() == dexItemFactory.kotlin.kotlinAssertions) {
+          if (method.holder() == dexItemFactory.kotlin.assertions.type) {
             rewriteKotlinAssertionEnable(code, transformation, iterator, invoke);
           } else {
             iterator.replaceCurrentInstruction(code.createIntConstant(0));
@@ -341,10 +350,18 @@
         }
       } else if (current.isStaticGet()) {
         StaticGet staticGet = current.asStaticGet();
-        if (staticGet.getField().name == dexItemFactory.assertionsDisabled) {
+        // Rewrite $assertionsDisabled getter (only if the initializer enabled assertions).
+        if (isInitializerEnablingJavaVmAssertions
+            && staticGet.getField().name == dexItemFactory.assertionsDisabled) {
           iterator.replaceCurrentInstruction(
               code.createIntConstant(transformation == AssertionTransformation.DISABLE ? 1 : 0));
         }
+        // Rewrite kotlin._Assertions.ENABLED getter.
+        if (staticGet.getField() == dexItemFactory.kotlin.assertions.enabledField) {
+          iterator.replaceCurrentInstruction(
+              code.createIntConstant(
+                  kotlinTransformation == AssertionTransformation.DISABLE ? 0 : 1));
+        }
       }
     }
   }
@@ -362,7 +379,7 @@
       Instruction nextInstruction = iterator.next();
       if (nextInstruction.isStaticPut()
           && nextInstruction.asStaticPut().getField().holder
-              == dexItemFactory.kotlin.kotlinAssertions
+              == dexItemFactory.kotlin.assertions.type
           && nextInstruction.asStaticPut().getField().name == dexItemFactory.enabledFieldName
           && invoke.outValue().numberOfUsers() == 1
           && invoke.outValue().numberOfPhiUsers() == 0
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
index 55f42ab..40f9b7f 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
@@ -1041,10 +1041,10 @@
 
           // The synthetic and bridge flags are maintained only if the inlinee has also these flags.
           if (context.accessFlags.isBridge() && !inlinee.code.method.accessFlags.isBridge()) {
-            context.accessFlags.unsetBridge();
+            context.accessFlags.demoteFromBridge();
           }
           if (context.accessFlags.isSynthetic() && !inlinee.code.method.accessFlags.isSynthetic()) {
-            context.accessFlags.unsetSynthetic();
+            context.accessFlags.demoteFromSynthetic();
           }
 
           context.copyMetadata(singleTarget);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java b/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java
index 4b50b6e..e25949d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java
@@ -72,7 +72,9 @@
 
   public static boolean shouldRun(AppView<?> appView, IRCode code) {
     return appView.options().enableRedundantFieldLoadElimination
-        && (code.metadata().mayHaveFieldGet() || code.metadata().mayHaveInitClass());
+        && (code.metadata().mayHaveFieldGet() || code.metadata().mayHaveInitClass())
+        // TODO(b/154064966): Remove workaround.
+        && code.blocks.size() < 20000;
   }
 
   private interface FieldValue {
diff --git a/src/main/java/com/android/tools/r8/kotlin/Kotlin.java b/src/main/java/com/android/tools/r8/kotlin/Kotlin.java
index b4308b9..6fe2c18 100644
--- a/src/main/java/com/android/tools/r8/kotlin/Kotlin.java
+++ b/src/main/java/com/android/tools/r8/kotlin/Kotlin.java
@@ -6,6 +6,7 @@
 
 import com.android.tools.r8.DiagnosticsHandler;
 import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexString;
@@ -35,10 +36,10 @@
 
   public final DexItemFactory factory;
 
-  public final DexType kotlinAssertions;
   public final Functional functional;
   public final Intrinsics intrinsics;
   public final Metadata metadata;
+  public final _Assertions assertions;
 
   public static final class ClassClassifiers {
 
@@ -51,10 +52,10 @@
   public Kotlin(DexItemFactory factory) {
     this.factory = factory;
 
-    this.kotlinAssertions = factory.createType(addKotlinPrefix("_Assertions;"));
     this.functional = new Functional();
     this.intrinsics = new Intrinsics();
     this.metadata = new Metadata();
+    this.assertions = new _Assertions();
 
     // See {@link org.jetbrains.kotlin.metadata.jvm.deserialization.ClassMapperLite}
     this.knownTypeConversion =
@@ -172,6 +173,13 @@
     public final DexString extraInt = factory.createString("xi");
   }
 
+  public final class _Assertions {
+    public final DexType type = factory.createType(addKotlinPrefix("_Assertions;"));
+    public final DexString enabledFieldName = factory.createString("ENABLED");
+    public final DexField enabledField =
+        factory.createField(type, factory.booleanType, enabledFieldName);
+  }
+
   // kotlin.jvm.internal.Intrinsics class
   public final class Intrinsics {
     public final DexType type = factory.createType(addKotlinPrefix("jvm/internal/Intrinsics;"));
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index 176f908..8c79dd7 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -2308,6 +2308,13 @@
         : info.isWritten();
   }
 
+  public boolean isMemberLive(DexEncodedMember<?, ?> member) {
+    assert member != null;
+    return member.isDexEncodedField()
+        ? liveFields.contains(member.asDexEncodedField())
+        : liveMethods.contains(member.asDexEncodedMethod());
+  }
+
   public boolean isMethodLive(DexEncodedMethod method) {
     return liveMethods.contains(method);
   }
@@ -3164,12 +3171,33 @@
   }
 
   private void addConsequentRootSet(ConsequentRootSet consequentRootSet, boolean addNoShrinking) {
+    consequentRootSet.forEachClassWithDependentItems(
+        appView,
+        clazz -> {
+          if (isTypeLive(clazz)) {
+            consequentRootSet.forEachDependentInstanceConstructor(
+                clazz, appView, this::enqueueHolderWithDependentInstanceConstructor);
+            consequentRootSet.forEachDependentStaticMember(
+                clazz, appView, this::enqueueDependentItem);
+            if (objectAllocationInfoCollection.isInstantiatedDirectlyOrHasInstantiatedSubtype(
+                clazz)) {
+              consequentRootSet.forEachDependentNonStaticMember(
+                  clazz, appView, this::enqueueDependentItem);
+            }
+            compatEnqueueHolderIfDependentNonStaticMember(
+                clazz, consequentRootSet.getDependentKeepClassCompatRule(clazz.type));
+          }
+        });
+    consequentRootSet.forEachMemberWithDependentItems(
+        appView,
+        member -> {
+          if (isMemberLive(member)) {
+            enqueueRootItems(consequentRootSet.getDependentItems(member));
+          }
+        });
     // TODO(b/132600955): This modifies the root set. Should the consequent be persistent?
     rootSet.addConsequentRootSet(consequentRootSet, addNoShrinking);
     enqueueRootItems(consequentRootSet.noShrinking);
-    // TODO(b/132828740): Seems incorrect that the precondition is not always met here.
-    consequentRootSet.dependentNoShrinking.forEach(
-        (precondition, dependentItems) -> enqueueRootItems(dependentItems));
     // Check for compatibility rules indicating that the holder must be implicitly kept.
     if (forceProguardCompatibility) {
       consequentRootSet.dependentKeepClassCompatRule.forEach(
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
index c89dd04..d8c8b07 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
@@ -3,8 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.shaking;
 
-import static com.android.tools.r8.shaking.ReprocessClassInitializerRule.Type.ALWAYS;
-import static com.android.tools.r8.shaking.ReprocessClassInitializerRule.Type.NEVER;
+import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
 
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.errors.Unreachable;
@@ -1260,15 +1259,120 @@
     }
   }
 
-  public static class RootSet {
+  abstract static class RootSetBase {
 
-    public final Map<DexReference, Set<ProguardKeepRuleBase>> noShrinking;
-    private final Set<DexReference> noObfuscation;
+    final Set<DexMethod> neverInline;
+    final Set<DexType> neverClassInline;
+    final Map<DexReference, Set<ProguardKeepRuleBase>> noShrinking;
+    final Set<DexReference> noObfuscation;
+    final Map<DexReference, Map<DexReference, Set<ProguardKeepRuleBase>>> dependentNoShrinking;
+    final Map<DexType, Set<ProguardKeepRuleBase>> dependentKeepClassCompatRule;
+    final List<DelayedRootSetActionItem> delayedRootSetActionItems;
+
+    RootSetBase(
+        Set<DexMethod> neverInline,
+        Set<DexType> neverClassInline,
+        Map<DexReference, Set<ProguardKeepRuleBase>> noShrinking,
+        Set<DexReference> noObfuscation,
+        Map<DexReference, Map<DexReference, Set<ProguardKeepRuleBase>>> dependentNoShrinking,
+        Map<DexType, Set<ProguardKeepRuleBase>> dependentKeepClassCompatRule,
+        List<DelayedRootSetActionItem> delayedRootSetActionItems) {
+      this.neverInline = neverInline;
+      this.neverClassInline = neverClassInline;
+      this.noShrinking = noShrinking;
+      this.noObfuscation = noObfuscation;
+      this.dependentNoShrinking = dependentNoShrinking;
+      this.dependentKeepClassCompatRule = dependentKeepClassCompatRule;
+      this.delayedRootSetActionItems = delayedRootSetActionItems;
+    }
+
+    public void forEachClassWithDependentItems(
+        DexDefinitionSupplier definitions, Consumer<DexProgramClass> consumer) {
+      for (DexReference reference : dependentNoShrinking.keySet()) {
+        if (reference.isDexType()) {
+          DexType type = reference.asDexType();
+          DexProgramClass clazz = asProgramClassOrNull(definitions.definitionFor(type));
+          if (clazz != null) {
+            consumer.accept(clazz);
+          }
+        }
+      }
+    }
+
+    public void forEachMemberWithDependentItems(
+        DexDefinitionSupplier definitions, Consumer<DexEncodedMember<?, ?>> consumer) {
+      for (DexReference reference : dependentNoShrinking.keySet()) {
+        if (reference.isDexMember()) {
+          DexEncodedMember<?, ?> definition = definitions.definitionFor(reference.asDexMember());
+          if (definition != null) {
+            consumer.accept(definition);
+          }
+        }
+      }
+    }
+
+    public void forEachDependentInstanceConstructor(
+        DexProgramClass clazz,
+        AppView<?> appView,
+        Consumer3<DexProgramClass, DexEncodedMethod, Set<ProguardKeepRuleBase>> fn) {
+      getDependentItems(clazz)
+          .forEach(
+              (reference, reasons) -> {
+                DexDefinition definition = appView.definitionFor(reference);
+                if (definition != null
+                    && definition.isDexEncodedMethod()
+                    && definition.asDexEncodedMethod().isInstanceInitializer()) {
+                  fn.accept(clazz, definition.asDexEncodedMethod(), reasons);
+                }
+              });
+    }
+
+    public void forEachDependentNonStaticMember(
+        DexDefinition item,
+        AppView<?> appView,
+        Consumer3<DexDefinition, DexDefinition, Set<ProguardKeepRuleBase>> fn) {
+      getDependentItems(item)
+          .forEach(
+              (reference, reasons) -> {
+                DexDefinition definition = appView.definitionFor(reference);
+                if (definition != null
+                    && !definition.isDexClass()
+                    && !definition.isStaticMember()) {
+                  fn.accept(item, definition, reasons);
+                }
+              });
+    }
+
+    public void forEachDependentStaticMember(
+        DexDefinition item,
+        AppView<?> appView,
+        Consumer3<DexDefinition, DexDefinition, Set<ProguardKeepRuleBase>> fn) {
+      getDependentItems(item)
+          .forEach(
+              (reference, reasons) -> {
+                DexDefinition definition = appView.definitionFor(reference);
+                if (definition != null && !definition.isDexClass() && definition.isStaticMember()) {
+                  fn.accept(item, definition, reasons);
+                }
+              });
+    }
+
+    Map<DexReference, Set<ProguardKeepRuleBase>> getDependentItems(DexDefinition item) {
+      return Collections.unmodifiableMap(
+          dependentNoShrinking.getOrDefault(item.toReference(), Collections.emptyMap()));
+    }
+
+    Set<ProguardKeepRuleBase> getDependentKeepClassCompatRule(DexType type) {
+      return dependentKeepClassCompatRule.get(type);
+    }
+  }
+
+  public static class RootSet extends RootSetBase {
+
     public final ImmutableList<DexReference> reasonAsked;
     public final ImmutableList<DexReference> checkDiscarded;
     public final Set<DexMethod> alwaysInline;
     public final Set<DexMethod> forceInline;
-    public final Set<DexMethod> neverInline;
     public final Set<DexMethod> bypassClinitForInlining;
     public final Set<DexMethod> whyAreYouNotInlining;
     public final Set<DexMethod> keepConstantArguments;
@@ -1276,18 +1380,13 @@
     public final Set<DexMethod> reprocess;
     public final Set<DexMethod> neverReprocess;
     public final PredicateSet<DexType> alwaysClassInline;
-    public final Set<DexType> neverClassInline;
     public final Set<DexType> neverMerge;
     public final Set<DexReference> neverPropagateValue;
     public final Map<DexReference, ProguardMemberRule> mayHaveSideEffects;
     public final Map<DexReference, ProguardMemberRule> noSideEffects;
     public final Map<DexReference, ProguardMemberRule> assumedValues;
-    private final Map<DexReference, Map<DexReference, Set<ProguardKeepRuleBase>>>
-        dependentNoShrinking;
-    private final Map<DexType, Set<ProguardKeepRuleBase>> dependentKeepClassCompatRule;
     public final Set<DexReference> identifierNameStrings;
     public final Set<ProguardIfRule> ifRules;
-    public final List<DelayedRootSetActionItem> delayedRootSetActionItems;
 
     private RootSet(
         Map<DexReference, Set<ProguardKeepRuleBase>> noShrinking,
@@ -1315,13 +1414,18 @@
         Set<DexReference> identifierNameStrings,
         Set<ProguardIfRule> ifRules,
         List<DelayedRootSetActionItem> delayedRootSetActionItems) {
-      this.noShrinking = noShrinking;
-      this.noObfuscation = noObfuscation;
+      super(
+          neverInline,
+          neverClassInline,
+          noShrinking,
+          noObfuscation,
+          dependentNoShrinking,
+          dependentKeepClassCompatRule,
+          delayedRootSetActionItems);
       this.reasonAsked = reasonAsked;
       this.checkDiscarded = checkDiscarded;
       this.alwaysInline = alwaysInline;
       this.forceInline = forceInline;
-      this.neverInline = neverInline;
       this.bypassClinitForInlining = bypassClinitForInlining;
       this.whyAreYouNotInlining = whyAreYouNotInlining;
       this.keepConstantArguments = keepConstantArguments;
@@ -1329,17 +1433,13 @@
       this.reprocess = reprocess;
       this.neverReprocess = neverReprocess;
       this.alwaysClassInline = alwaysClassInline;
-      this.neverClassInline = neverClassInline;
       this.neverMerge = neverMerge;
       this.neverPropagateValue = neverPropagateValue;
       this.mayHaveSideEffects = mayHaveSideEffects;
       this.noSideEffects = noSideEffects;
       this.assumedValues = assumedValues;
-      this.dependentNoShrinking = dependentNoShrinking;
-      this.dependentKeepClassCompatRule = dependentKeepClassCompatRule;
       this.identifierNameStrings = Collections.unmodifiableSet(identifierNameStrings);
       this.ifRules = Collections.unmodifiableSet(ifRules);
-      this.delayedRootSetActionItems = delayedRootSetActionItems;
     }
 
     public void checkAllRulesAreUsed(InternalOptions options) {
@@ -1384,61 +1484,6 @@
                   .putAll(dependence));
     }
 
-    Set<ProguardKeepRuleBase> getDependentKeepClassCompatRule(DexType type) {
-      return dependentKeepClassCompatRule.get(type);
-    }
-
-    Map<DexReference, Set<ProguardKeepRuleBase>> getDependentItems(DexDefinition item) {
-      return Collections.unmodifiableMap(
-          dependentNoShrinking.getOrDefault(item.toReference(), Collections.emptyMap()));
-    }
-
-    public void forEachDependentStaticMember(
-        DexDefinition item,
-        AppView<?> appView,
-        Consumer3<DexDefinition, DexDefinition, Set<ProguardKeepRuleBase>> fn) {
-      getDependentItems(item)
-          .forEach(
-              (reference, reasons) -> {
-                DexDefinition definition = appView.definitionFor(reference);
-                if (definition != null && !definition.isDexClass() && definition.isStaticMember()) {
-                  fn.accept(item, definition, reasons);
-                }
-              });
-    }
-
-    public void forEachDependentNonStaticMember(
-        DexDefinition item,
-        AppView<?> appView,
-        Consumer3<DexDefinition, DexDefinition, Set<ProguardKeepRuleBase>> fn) {
-      getDependentItems(item)
-          .forEach(
-              (reference, reasons) -> {
-                DexDefinition definition = appView.definitionFor(reference);
-                if (definition != null
-                    && !definition.isDexClass()
-                    && !definition.isStaticMember()) {
-                  fn.accept(item, definition, reasons);
-                }
-              });
-    }
-
-    public void forEachDependentInstanceConstructor(
-        DexProgramClass clazz,
-        AppView<?> appView,
-        Consumer3<DexProgramClass, DexEncodedMethod, Set<ProguardKeepRuleBase>> fn) {
-      getDependentItems(clazz)
-          .forEach(
-              (reference, reasons) -> {
-                DexDefinition definition = appView.definitionFor(reference);
-                if (definition != null
-                    && definition.isDexEncodedMethod()
-                    && definition.asDexEncodedMethod().isInstanceInitializer()) {
-                  fn.accept(clazz, definition.asDexEncodedMethod(), reasons);
-                }
-              });
-    }
-
     public void copy(DexReference original, DexReference rewritten) {
       if (noShrinking.containsKey(original)) {
         noShrinking.put(rewritten, noShrinking.get(original));
@@ -1695,16 +1740,9 @@
 
   // A partial RootSet that becomes live due to the enabled -if rule or the addition of interface
   // keep rules.
-  public static class ConsequentRootSet {
-    final Set<DexMethod> neverInline;
-    final Set<DexType> neverClassInline;
-    final Map<DexReference, Set<ProguardKeepRuleBase>> noShrinking;
-    final Set<DexReference> noObfuscation;
-    final Map<DexReference, Map<DexReference, Set<ProguardKeepRuleBase>>> dependentNoShrinking;
-    final Map<DexType, Set<ProguardKeepRuleBase>> dependentKeepClassCompatRule;
-    final List<DelayedRootSetActionItem> delayedRootSetActionItems;
+  public static class ConsequentRootSet extends RootSetBase {
 
-    private ConsequentRootSet(
+    ConsequentRootSet(
         Set<DexMethod> neverInline,
         Set<DexType> neverClassInline,
         Map<DexReference, Set<ProguardKeepRuleBase>> noShrinking,
@@ -1712,13 +1750,14 @@
         Map<DexReference, Map<DexReference, Set<ProguardKeepRuleBase>>> dependentNoShrinking,
         Map<DexType, Set<ProguardKeepRuleBase>> dependentKeepClassCompatRule,
         List<DelayedRootSetActionItem> delayedRootSetActionItems) {
-      this.neverInline = Collections.unmodifiableSet(neverInline);
-      this.neverClassInline = Collections.unmodifiableSet(neverClassInline);
-      this.noShrinking = Collections.unmodifiableMap(noShrinking);
-      this.noObfuscation = Collections.unmodifiableSet(noObfuscation);
-      this.dependentNoShrinking = Collections.unmodifiableMap(dependentNoShrinking);
-      this.dependentKeepClassCompatRule = Collections.unmodifiableMap(dependentKeepClassCompatRule);
-      this.delayedRootSetActionItems = Collections.unmodifiableList(delayedRootSetActionItems);
+      super(
+          neverInline,
+          neverClassInline,
+          noShrinking,
+          noObfuscation,
+          dependentNoShrinking,
+          dependentKeepClassCompatRule,
+          delayedRootSetActionItems);
     }
   }
 }
diff --git a/src/test/java/com/android/tools/r8/rewrite/assertions/AssertionConfigurationKotlinTest.java b/src/test/java/com/android/tools/r8/rewrite/assertions/AssertionConfigurationKotlinTest.java
index b201ce6..c2fdaa1 100644
--- a/src/test/java/com/android/tools/r8/rewrite/assertions/AssertionConfigurationKotlinTest.java
+++ b/src/test/java/com/android/tools/r8/rewrite/assertions/AssertionConfigurationKotlinTest.java
@@ -21,6 +21,7 @@
 import com.android.tools.r8.ThrowableConsumer;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
+import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.ThrowingConsumer;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -52,17 +53,23 @@
 
   private static final Map<KotlinTargetVersion, Path> kotlinClasses = new HashMap<>();
   private final TestParameters parameters;
+  private final boolean kotlinStdlibAsLibrary;
 
-  @Parameterized.Parameters(name = "{0},{1}")
+  @Parameterized.Parameters(name = "{0}, {1}, kotlin-stdlib as library: {2}")
   public static Collection<Object[]> data() {
     return buildParameters(
-        getTestParameters().withAllRuntimesAndApiLevels().build(), KotlinTargetVersion.values());
+        getTestParameters().withAllRuntimesAndApiLevels().build(),
+        KotlinTargetVersion.values(),
+        BooleanUtils.values());
   }
 
   public AssertionConfigurationKotlinTest(
-      TestParameters parameters, KotlinTargetVersion targetVersion) {
+      TestParameters parameters,
+      KotlinTargetVersion targetVersion,
+      boolean kotlinStdlibAsClasspath) {
     super(targetVersion);
     this.parameters = parameters;
+    this.kotlinStdlibAsLibrary = kotlinStdlibAsClasspath;
   }
 
   @BeforeClass
@@ -76,21 +83,50 @@
     }
   }
 
+  private Path kotlinStdlibLibraryForRuntime() throws Exception {
+    Path kotlinStdlibCf = ToolHelper.getKotlinStdlibJar();
+    if (parameters.getRuntime().isCf()) {
+      return kotlinStdlibCf;
+    }
+
+    Path kotlinStdlibDex = temp.newFolder().toPath().resolve("kotlin-stdlib-dex.jar");
+    testForD8()
+        .addProgramFiles(kotlinStdlibCf)
+        .setMinApi(parameters.getApiLevel())
+        .compile()
+        .writeToZip(kotlinStdlibDex);
+    return kotlinStdlibDex;
+  }
+
   private void runD8Test(
       ThrowableConsumer<D8TestBuilder> builderConsumer,
       ThrowingConsumer<CodeInspector, RuntimeException> inspector,
       List<String> outputLines)
       throws Exception {
-    testForD8()
-        .addProgramFiles(ToolHelper.getKotlinStdlibJar())
-        .addProgramFiles(kotlinClasses.get(targetVersion))
-        .setMinApi(parameters.getApiLevel())
-        .apply(builderConsumer)
-        .run(
-            parameters.getRuntime(),
-            getClass().getPackage().getName() + ".kotlintestclasses.TestClassKt")
-        .inspect(inspector)
-        .assertSuccessWithOutputLines(outputLines);
+    if (kotlinStdlibAsLibrary) {
+      testForD8()
+          .addClasspathFiles(ToolHelper.getKotlinStdlibJar())
+          .addProgramFiles(kotlinClasses.get(targetVersion))
+          .setMinApi(parameters.getApiLevel())
+          .apply(builderConsumer)
+          .addRunClasspathFiles(kotlinStdlibLibraryForRuntime())
+          .run(
+              parameters.getRuntime(),
+              getClass().getPackage().getName() + ".kotlintestclasses.TestClassKt")
+          .inspect(inspector)
+          .assertSuccessWithOutputLines(outputLines);
+    } else {
+      testForD8()
+          .addProgramFiles(ToolHelper.getKotlinStdlibJar())
+          .addProgramFiles(kotlinClasses.get(targetVersion))
+          .setMinApi(parameters.getApiLevel())
+          .apply(builderConsumer)
+          .run(
+              parameters.getRuntime(),
+              getClass().getPackage().getName() + ".kotlintestclasses.TestClassKt")
+          .inspect(inspector)
+          .assertSuccessWithOutputLines(outputLines);
+    }
   }
 
   public void runR8Test(
@@ -108,21 +144,38 @@
       boolean enableJvmAssertions)
       throws Exception {
 
-    testForR8(parameters.getBackend())
-        .addProgramFiles(ToolHelper.getKotlinStdlibJar())
-        .addProgramFiles(kotlinClasses.get(targetVersion))
-        .addKeepMainRule(testClassKt)
-        .addKeepClassAndMembersRules(class1, class2)
-        .setMinApi(parameters.getApiLevel())
-        .apply(builderConsumer)
-        .noMinification()
-        .allowDiagnosticWarningMessages()
-        .compile()
-        .assertAllWarningMessagesMatch(equalTo("Resource 'META-INF/MANIFEST.MF' already exists."))
-        .enableRuntimeAssertions(enableJvmAssertions)
-        .run(parameters.getRuntime(), testClassKt)
-        .inspect(inspector)
-        .assertSuccessWithOutputLines(outputLines);
+    if (kotlinStdlibAsLibrary) {
+      testForR8(parameters.getBackend())
+          .addClasspathFiles(ToolHelper.getKotlinStdlibJar())
+          .addProgramFiles(kotlinClasses.get(targetVersion))
+          .addKeepMainRule(testClassKt)
+          .addKeepClassAndMembersRules(class1, class2)
+          .setMinApi(parameters.getApiLevel())
+          .apply(builderConsumer)
+          .noMinification()
+          .addRunClasspathFiles(kotlinStdlibLibraryForRuntime())
+          .compile()
+          .enableRuntimeAssertions(enableJvmAssertions)
+          .run(parameters.getRuntime(), testClassKt)
+          .inspect(inspector)
+          .assertSuccessWithOutputLines(outputLines);
+    } else {
+      testForR8(parameters.getBackend())
+          .addProgramFiles(ToolHelper.getKotlinStdlibJar())
+          .addProgramFiles(kotlinClasses.get(targetVersion))
+          .addKeepMainRule(testClassKt)
+          .addKeepClassAndMembersRules(class1, class2)
+          .setMinApi(parameters.getApiLevel())
+          .apply(builderConsumer)
+          .noMinification()
+          .allowDiagnosticWarningMessages()
+          .compile()
+          .assertAllWarningMessagesMatch(equalTo("Resource 'META-INF/MANIFEST.MF' already exists."))
+          .enableRuntimeAssertions(enableJvmAssertions)
+          .run(parameters.getRuntime(), testClassKt)
+          .inspect(inspector)
+          .assertSuccessWithOutputLines(outputLines);
+    }
   }
 
   private List<String> allAssertionsExpectedLines() {
@@ -136,6 +189,7 @@
   private void checkAssertionCodeRemoved(ClassSubject subject, boolean isR8) {
     assertThat(subject, isPresent());
     if (subject.getOriginalName().equals("kotlin._Assertions")) {
+      assert !kotlinStdlibAsLibrary;
       // With R8 the static-put of the kotlin._Assertions.INSTANCE field is removed as well,
       // as is not used.
       assertEquals(
@@ -151,9 +205,9 @@
               .streamInstructions()
               .anyMatch(InstructionSubject::isConstNumber));
     } else {
-      // In R8 the false (default) value of kotlin._Assertions.ENABLED is propagated.
-      assertEquals(
-          !isR8,
+      // The value of kotlin._Assertions.ENABLED is propagated from the assertions configuration
+      // for the class kotlin._Assertions.
+      assertFalse(
           subject
               .uniqueMethodWithName("m")
               .streamInstructions()
@@ -168,6 +222,7 @@
   private void checkAssertionCodeEnabled(ClassSubject subject, boolean isR8) {
     assertThat(subject, isPresent());
     if (subject.getOriginalName().equals("kotlin._Assertions")) {
+      assert !kotlinStdlibAsLibrary;
       // With R8 the static-put of the kotlin._Assertions.INSTANCE field is removed as is not used.
       assertEquals(
           (isR8 ? 1 : 2),
@@ -199,6 +254,7 @@
     ClassSubject subject = inspector.clazz(clazz);
     assertThat(subject, isPresent());
     if (subject.getOriginalName().equals("kotlin._Assertions")) {
+      assert !kotlinStdlibAsLibrary;
       // With R8 the static-put of the kotlin._Assertions.INSTANCE field is removed as is not used.
       assertEquals(
           (isR8 ? 1 : 2),
@@ -224,7 +280,7 @@
   private void checkAssertionCodeRemoved(CodeInspector inspector, boolean isR8) {
     if (isR8) {
       assertThat(inspector.clazz("kotlin._Assertions"), not(isPresent()));
-    } else {
+    } else if (!kotlinStdlibAsLibrary) {
       checkAssertionCodeRemoved(inspector, "kotlin._Assertions", isR8);
     }
     checkAssertionCodeRemoved(inspector, class1, isR8);
@@ -234,7 +290,7 @@
   private void checkAssertionCodeEnabled(CodeInspector inspector, boolean isR8) {
     if (isR8) {
       assertThat(inspector.clazz("kotlin._Assertions"), not(isPresent()));
-    } else {
+    } else if (!kotlinStdlibAsLibrary) {
       checkAssertionCodeEnabled(inspector, "kotlin._Assertions", isR8);
     }
     checkAssertionCodeEnabled(inspector, class1, isR8);
@@ -242,7 +298,9 @@
   }
 
   private void checkAssertionCodeLeft(CodeInspector inspector, boolean isR8) {
-    checkAssertionCodeLeft(inspector, "kotlin._Assertions", isR8);
+    if (!kotlinStdlibAsLibrary) {
+      checkAssertionCodeLeft(inspector, "kotlin._Assertions", isR8);
+    }
     checkAssertionCodeLeft(inspector, class1, isR8);
     checkAssertionCodeLeft(inspector, class2, isR8);
   }
diff --git a/src/test/java/com/android/tools/r8/shaking/ifrule/ConsequentRootSetWithSatisfiedDependentItemsTest.java b/src/test/java/com/android/tools/r8/shaking/ifrule/ConsequentRootSetWithSatisfiedDependentItemsTest.java
new file mode 100644
index 0000000..f65d00b
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/shaking/ifrule/ConsequentRootSetWithSatisfiedDependentItemsTest.java
@@ -0,0 +1,80 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.shaking.ifrule;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertFalse;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class ConsequentRootSetWithSatisfiedDependentItemsTest extends TestBase {
+
+  private final TestParameters parameters;
+
+  @Parameterized.Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  public ConsequentRootSetWithSatisfiedDependentItemsTest(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
+  @Test
+  public void test() throws Exception {
+    testForR8(parameters.getBackend())
+        .addInnerClasses(ConsequentRootSetWithSatisfiedDependentItemsTest.class)
+        .addKeepMainRule(TestClass.class)
+        .addKeepRules(
+            "-if class " + A.class.getTypeName(),
+            "-keepclassmembers class " + A.class.getTypeName() + "{",
+            "  <init>();",
+            "}")
+        .setMinApi(parameters.getApiLevel())
+        .compile()
+        .inspect(this::inspect)
+        .run(parameters.getRuntime(), TestClass.class)
+        .assertSuccess();
+  }
+
+  private void inspect(CodeInspector inspector) {
+    ClassSubject aClassSubject = inspector.clazz(A.class);
+    assertThat(aClassSubject, isPresent());
+    assertFalse(aClassSubject.getDexClass().isAbstract());
+  }
+
+  static class TestClass {
+
+    public static void main(String[] args) throws Exception {
+      Class<?> clazz = System.currentTimeMillis() > 0 ? A.class : null;
+      instantiate(clazz);
+    }
+
+    static A instantiate(Class<?> clazz) throws Exception {
+      return (A) clazz.getDeclaredConstructor().newInstance();
+    }
+  }
+
+  static class A {
+
+    int x;
+
+    A() {
+      this(42);
+    }
+
+    A(int x) {
+      this.x = x;
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/shaking/ifrule/IfOnClassTest.java b/src/test/java/com/android/tools/r8/shaking/ifrule/IfOnClassTest.java
index 28588e7..50d64f8 100644
--- a/src/test/java/com/android/tools/r8/shaking/ifrule/IfOnClassTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ifrule/IfOnClassTest.java
@@ -217,6 +217,15 @@
       return;
     }
 
+    if (shrinker.isR8()) {
+      // The -keepclassmembers rule should not keep Dependent nor DependentUser since DependentUser
+      // is never referenced.
+      assertThat(codeInspector.clazz(EmptyMainClassForIfOnClassTests.class), isPresent());
+      assertThat(codeInspector.clazz(Precondition.class), isPresent());
+      assertEquals(2, codeInspector.allClasses().size());
+      return;
+    }
+
     ClassSubject clazz = codeInspector.clazz(DependentUser.class);
     assertThat(clazz, isRenamed());
     MethodSubject m = clazz.method("void", "callFoo", ImmutableList.of());
@@ -257,6 +266,15 @@
       return;
     }
 
+    if (shrinker.isR8()) {
+      // The -keepclassmembers rule should not keep Dependent nor DependentUser since DependentUser
+      // is never referenced.
+      assertThat(codeInspector.clazz(EmptyMainClassForIfOnClassTests.class), isPresent());
+      assertThat(codeInspector.clazz(Precondition.class), isPresent());
+      assertEquals(2, codeInspector.allClasses().size());
+      return;
+    }
+
     ClassSubject clazz = codeInspector.clazz(DependentUser.class);
     assertThat(clazz, isRenamed());
     MethodSubject m = clazz.method("void", "callFoo", ImmutableList.of());
@@ -346,5 +364,4 @@
     FieldSubject f = clazz.field("int", "intField");
     assertThat(f, isRenamed());
   }
-
 }
diff --git a/src/test/java/com/android/tools/r8/shaking/ifrule/NoLongerSatisfiedIfRuleTest.java b/src/test/java/com/android/tools/r8/shaking/ifrule/NoLongerSatisfiedIfRuleTest.java
new file mode 100644
index 0000000..02dde28
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/shaking/ifrule/NoLongerSatisfiedIfRuleTest.java
@@ -0,0 +1,81 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.shaking.ifrule;
+
+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.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class NoLongerSatisfiedIfRuleTest extends TestBase {
+
+  private final TestParameters parameters;
+
+  @Parameterized.Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  public NoLongerSatisfiedIfRuleTest(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
+  @Test
+  public void test() throws Exception {
+    testForR8(parameters.getBackend())
+        .addInnerClasses(NoLongerSatisfiedIfRuleTest.class)
+        .addKeepMainRule(TestClass.class)
+        .addKeepRules(
+            "-if class " + A.class.getTypeName(),
+            "-keep class " + B.class.getTypeName() + " { void m(); }")
+        .setMinApi(parameters.getApiLevel())
+        .compile()
+        .inspect(this::inspect)
+        .run(parameters.getRuntime(), TestClass.class)
+        .assertSuccessWithOutputLines("B");
+  }
+
+  private void inspect(CodeInspector inspector) {
+    assertThat(inspector.clazz(A.class), not(isPresent()));
+
+    ClassSubject bClassSubject = inspector.clazz(B.class);
+    assertThat(bClassSubject, isPresent());
+    // TODO(b/153910208): Should be absent since A is dead.
+    assertThat(bClassSubject.uniqueMethodWithName("m"), isPresent());
+  }
+
+  static class TestClass {
+
+    static boolean alwaysFalse = false;
+
+    public static void main(String[] args) {
+      if (alwaysFalse) {
+        System.out.println(new A());
+      }
+      System.out.println(new B());
+    }
+  }
+
+  static class A {}
+
+  static class B {
+
+    void m() {}
+
+    @Override
+    public String toString() {
+      return "B";
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/shaking/ifrule/NoLongerSyntheticConstructorTest.java b/src/test/java/com/android/tools/r8/shaking/ifrule/NoLongerSyntheticConstructorTest.java
new file mode 100644
index 0000000..ff4f02d
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/shaking/ifrule/NoLongerSyntheticConstructorTest.java
@@ -0,0 +1,76 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.shaking.ifrule;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AccessFlags;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class NoLongerSyntheticConstructorTest extends TestBase {
+
+  private final TestParameters parameters;
+
+  @Parameterized.Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  public NoLongerSyntheticConstructorTest(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
+  @Test
+  public void test() throws Exception {
+    testForR8(parameters.getBackend())
+        .addProgramClasses(TestClass.class, B.class)
+        .addProgramClassFileData(
+            transformer(A.class)
+                .setAccessFlags(A.class.getDeclaredConstructor(), AccessFlags::setSynthetic)
+                .transform())
+        .addKeepMainRule(TestClass.class)
+        .addKeepRules(
+            "-if class " + A.class.getTypeName() + " {",
+            "  synthetic <init>();",
+            "}",
+            "-keep class " + B.class.getTypeName())
+        .setMinApi(parameters.getApiLevel())
+        .compile()
+        .inspect(this::inspect);
+  }
+
+  private void inspect(CodeInspector inspector) {
+    assertThat(inspector.clazz(B.class), isPresent());
+  }
+
+  static class TestClass {
+
+    public static void main(String[] args) {
+      System.out.println(new A());
+    }
+  }
+
+  static class A {
+
+    int x;
+
+    A() {
+      this(42);
+    }
+
+    A(int x) {
+      this.x = x;
+    }
+  }
+
+  static class B {}
+}
diff --git a/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java b/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java
index 7bc8279..38a6346 100644
--- a/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java
+++ b/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java
@@ -18,6 +18,7 @@
 import com.android.tools.r8.transformers.MethodTransformer.MethodContext;
 import com.android.tools.r8.utils.DescriptorUtils;
 import java.io.IOException;
+import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -324,10 +325,19 @@
     return setAccessFlags(method, AccessFlags::setSynthetic);
   }
 
+  public ClassFileTransformer setAccessFlags(
+      Constructor<?> constructor, Consumer<MethodAccessFlags> setter) {
+    return setAccessFlags(Reference.methodFromMethod(constructor), setter);
+  }
+
   public ClassFileTransformer setAccessFlags(Method method, Consumer<MethodAccessFlags> setter) {
+    return setAccessFlags(Reference.methodFromMethod(method), setter);
+  }
+
+  private ClassFileTransformer setAccessFlags(
+      MethodReference methodReference, Consumer<MethodAccessFlags> setter) {
     return addClassTransformer(
         new ClassTransformer() {
-          final MethodReference methodReference = Reference.methodFromMethod(method);
 
           @Override
           public MethodVisitor visitMethod(
diff --git a/third_party/youtube-developer/20200415.tar.gz.sha1 b/third_party/youtube-developer/20200415.tar.gz.sha1
new file mode 100644
index 0000000..f44d810
--- /dev/null
+++ b/third_party/youtube-developer/20200415.tar.gz.sha1
@@ -0,0 +1 @@
+bfc2082c67a28dc43c975ccc3b0e10d3d31cae5d
\ No newline at end of file