Define distinct access-flag types for classes, methods and fields.

Change-Id: Ia2b5d28f1d4a5ea478b529915227dcf0d4b0afd3
diff --git a/src/main/java/com/android/tools/r8/dex/Constants.java b/src/main/java/com/android/tools/r8/dex/Constants.java
index 50af413..12ae77f 100644
--- a/src/main/java/com/android/tools/r8/dex/Constants.java
+++ b/src/main/java/com/android/tools/r8/dex/Constants.java
@@ -115,6 +115,7 @@
   public static final int ACC_PROTECTED = 0x4;
   public static final int ACC_STATIC = 0x8;
   public static final int ACC_FINAL = 0x10;
+  public static final int ACC_SUPER = 0x20;
   public static final int ACC_SYNCHRONIZED = 0x20;
   public static final int ACC_VOLATILE = 0x40;
   public static final int ACC_BRIDGE = 0x40;
diff --git a/src/main/java/com/android/tools/r8/dex/DexFileReader.java b/src/main/java/com/android/tools/r8/dex/DexFileReader.java
index 64909cc..4b0d6e2 100644
--- a/src/main/java/com/android/tools/r8/dex/DexFileReader.java
+++ b/src/main/java/com/android/tools/r8/dex/DexFileReader.java
@@ -12,9 +12,9 @@
 import com.android.tools.r8.Resource.PathOrigin;
 import com.android.tools.r8.code.Instruction;
 import com.android.tools.r8.code.InstructionFactory;
+import com.android.tools.r8.graph.ClassAccessFlags;
 import com.android.tools.r8.graph.ClassKind;
 import com.android.tools.r8.graph.Descriptor;
-import com.android.tools.r8.graph.DexAccessFlags;
 import com.android.tools.r8.graph.DexAnnotation;
 import com.android.tools.r8.graph.DexAnnotationElement;
 import com.android.tools.r8.graph.DexAnnotationSet;
@@ -50,6 +50,8 @@
 import com.android.tools.r8.graph.DexValue.DexValueMethodType;
 import com.android.tools.r8.graph.DexValue.DexValueNull;
 import com.android.tools.r8.graph.DexValue.DexValueString;
+import com.android.tools.r8.graph.FieldAccessFlags;
+import com.android.tools.r8.graph.MethodAccessFlags;
 import com.android.tools.r8.graph.OffsetToObjectMapping;
 import com.android.tools.r8.logging.Log;
 import com.android.tools.r8.utils.ProgramResource.Kind;
@@ -555,7 +557,7 @@
     for (int i = 0; i < size; i++) {
       fieldIndex += file.getUleb128();
       DexField field = indexedItems.getField(fieldIndex);
-      DexAccessFlags accessFlags = new DexAccessFlags(file.getUleb128());
+      FieldAccessFlags accessFlags = FieldAccessFlags.fromDexAccessFlags(file.getUleb128());
       DexAnnotationSet fieldAnnotations = annotationIterator.getNextFor(field);
       DexValue staticValue = null;
       if (accessFlags.isStatic()) {
@@ -580,7 +582,7 @@
         new MemberAnnotationIterator<>(parameters, DexAnnotationSetRefList::empty);
     for (int i = 0; i < size; i++) {
       methodIndex += file.getUleb128();
-      DexAccessFlags accessFlags = new DexAccessFlags(file.getUleb128());
+      MethodAccessFlags accessFlags = MethodAccessFlags.fromDexAccessFlags(file.getUleb128());
       int codeOff = file.getUleb128();
       DexCode code = null;
       if (!skipCodes) {
@@ -633,7 +635,7 @@
       DexString source = srcIdx == NO_INDEX ? null : indexedItems.getString(srcIdx);
       // fix annotations.
       DexType type = indexedItems.getType(classIndices[i]);
-      DexAccessFlags flags = new DexAccessFlags(accessFlags[i]);
+      ClassAccessFlags flags = ClassAccessFlags.fromDexAccessFlags(accessFlags[i]);
       DexClass clazz;
       DexEncodedField[] staticFields = DexEncodedField.EMPTY_ARRAY;
       DexEncodedField[] instanceFields = DexEncodedField.EMPTY_ARRAY;
diff --git a/src/main/java/com/android/tools/r8/dex/FileWriter.java b/src/main/java/com/android/tools/r8/dex/FileWriter.java
index dccf887..27dedb1 100644
--- a/src/main/java/com/android/tools/r8/dex/FileWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/FileWriter.java
@@ -405,7 +405,7 @@
 
   private void writeClassDefItem(DexProgramClass clazz) {
     dest.putInt(mapping.getOffsetFor(clazz.type));
-    dest.putInt(clazz.accessFlags.get());
+    dest.putInt(clazz.accessFlags.getAsDexAccessFlags());
     dest.putInt(
         clazz.superType == null ? Constants.NO_INDEX : mapping.getOffsetFor(clazz.superType));
     dest.putInt(mixedSectionOffsets.getOffsetFor(clazz.interfaces));
@@ -553,7 +553,7 @@
       assert nextOffset - currentOffset >= 0;
       dest.putUleb128(nextOffset - currentOffset);
       currentOffset = nextOffset;
-      dest.putUleb128(field.accessFlags.get());
+      dest.putUleb128(field.accessFlags.getAsDexAccessFlags());
     }
   }
 
@@ -565,7 +565,7 @@
       assert nextOffset - currentOffset >= 0;
       dest.putUleb128(nextOffset - currentOffset);
       currentOffset = nextOffset;
-      dest.putUleb128(method.accessFlags.get());
+      dest.putUleb128(method.accessFlags.getAsDexAccessFlags());
       if (method.getCode() == null) {
         assert method.accessFlags.isAbstract() || method.accessFlags.isNative();
         dest.putUleb128(0);
diff --git a/src/main/java/com/android/tools/r8/graph/AccessFlags.java b/src/main/java/com/android/tools/r8/graph/AccessFlags.java
new file mode 100644
index 0000000..9f0471e
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/AccessFlags.java
@@ -0,0 +1,187 @@
+// Copyright (c) 2017, 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.graph;
+
+import com.android.tools.r8.dex.Constants;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import java.util.function.BooleanSupplier;
+
+/** Access flags common to classes, methods and fields. */
+public abstract class AccessFlags {
+
+  protected static final int BASE_FLAGS
+      = Constants.ACC_PUBLIC
+      | Constants.ACC_PRIVATE
+      | Constants.ACC_PROTECTED
+      | Constants.ACC_STATIC
+      | Constants.ACC_FINAL
+      | Constants.ACC_SYNTHETIC;
+
+  // Ordered list of flag names. Must be consistent with getPredicates.
+  private static final List<String> NAMES = ImmutableList.of(
+      "public",
+      "private",
+      "protected",
+      "static",
+      "final",
+      "synthetic"
+  );
+
+  // Get ordered list of flag predicates. Must be consistent with getNames.
+  protected List<BooleanSupplier> getPredicates() {
+    return ImmutableList.of(
+        this::isPublic,
+        this::isPrivate,
+        this::isProtected,
+        this::isStatic,
+        this::isFinal,
+        this::isSynthetic);
+  }
+
+  // Get ordered list of flag names. Must be consistent with getPredicates.
+  protected List<String> getNames() {
+    return NAMES;
+  }
+
+  protected int flags;
+
+  protected AccessFlags(int flags) {
+    this.flags = flags;
+  }
+
+  public abstract int getAsCfAccessFlags();
+
+  public abstract int getAsDexAccessFlags();
+
+  @Override
+  public boolean equals(Object other) {
+    if (other instanceof AccessFlags) {
+      return flags == ((AccessFlags) other).flags;
+    }
+    return false;
+  }
+
+  @Override
+  public int hashCode() {
+    return flags;
+  }
+
+  public boolean isPublic() {
+    return isSet(Constants.ACC_PUBLIC);
+  }
+
+  public void setPublic() {
+    assert !isPrivate() && !isProtected();
+    set(Constants.ACC_PUBLIC);
+  }
+
+  public void unsetPublic() {
+    unset(Constants.ACC_PUBLIC);
+  }
+
+  public boolean isPrivate() {
+    return isSet(Constants.ACC_PRIVATE);
+  }
+
+  public void setPrivate() {
+    assert !isPublic() && !isProtected();
+    set(Constants.ACC_PRIVATE);
+  }
+
+  public void unsetPrivate() {
+    unset(Constants.ACC_PRIVATE);
+  }
+
+  public boolean isProtected() {
+    return isSet(Constants.ACC_PROTECTED);
+  }
+
+  public void setProtected() {
+    assert !isPublic() && !isPrivate();
+    set(Constants.ACC_PROTECTED);
+  }
+
+  public void unsetProtected() {
+    unset(Constants.ACC_PROTECTED);
+  }
+
+  public boolean isStatic() {
+    return isSet(Constants.ACC_STATIC);
+  }
+
+  public void setStatic() {
+    set(Constants.ACC_STATIC);
+  }
+
+  public boolean isFinal() {
+    return isSet(Constants.ACC_FINAL);
+  }
+
+  public void setFinal() {
+    set(Constants.ACC_FINAL);
+  }
+
+  public void unsetFinal() {
+    unset(Constants.ACC_FINAL);
+  }
+
+  public boolean isSynthetic() {
+    return isSet(Constants.ACC_SYNTHETIC);
+  }
+
+  public void setSynthetic() {
+    set(Constants.ACC_SYNTHETIC);
+  }
+
+  public void unsetSynthetic() {
+    unset(Constants.ACC_SYNTHETIC);
+  }
+
+  public void promoteNonPrivateToPublic() {
+    if (!isPrivate()) {
+      unsetProtected();
+      setPublic();
+    }
+  }
+
+  public void promoteToPublic() {
+    unsetProtected();
+    unsetPrivate();
+    setPublic();
+  }
+
+  protected boolean isSet(int flag) {
+    return (flags & flag) != 0;
+  }
+
+  protected void set(int flag) {
+    flags |= flag;
+  }
+
+  protected void unset(int flag) {
+    flags &= ~flag;
+  }
+
+
+  public String toSmaliString() {
+    return toString();
+  }
+
+  @Override
+  public String toString() {
+    List<String> names = getNames();
+    List<BooleanSupplier> predicates = getPredicates();
+    StringBuilder builder = new StringBuilder();
+    for (int i = 0; i < names.size(); i++) {
+      if (predicates.get(i).getAsBoolean()) {
+        if (builder.length() > 0) {
+          builder.append(' ');
+        }
+        builder.append(names.get(i));
+      }
+    }
+    return builder.toString();
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/ClassAccessFlags.java b/src/main/java/com/android/tools/r8/graph/ClassAccessFlags.java
new file mode 100644
index 0000000..6430924
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/ClassAccessFlags.java
@@ -0,0 +1,134 @@
+// Copyright (c) 2017, 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.graph;
+
+import com.android.tools.r8.dex.Constants;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import java.util.function.BooleanSupplier;
+
+public class ClassAccessFlags extends AccessFlags {
+
+  // List of valid flags for both DEX and Java.
+  private static final int SHARED_FLAGS
+      = AccessFlags.BASE_FLAGS
+      | Constants.ACC_INTERFACE
+      | Constants.ACC_ABSTRACT
+      | Constants.ACC_ANNOTATION
+      | Constants.ACC_ENUM;
+
+  private static final int DEX_FLAGS
+      = SHARED_FLAGS;
+
+  private static final int CF_FLAGS
+      = SHARED_FLAGS
+      | Constants.ACC_SUPER;
+
+  @Override
+  protected List<String> getNames() {
+    return new ImmutableList.Builder<String>()
+        .addAll(super.getNames())
+        .add("interface")
+        .add("abstract")
+        .add("annotation")
+        .add("enum")
+        .build();
+  }
+
+  @Override
+  protected List<BooleanSupplier> getPredicates() {
+    return new ImmutableList.Builder<BooleanSupplier>()
+        .addAll(super.getPredicates())
+        .add(this::isInterface)
+        .add(this::isAbstract)
+        .add(this::isAnnotation)
+        .add(this::isEnum)
+        .build();
+  }
+
+  private ClassAccessFlags(int flags) {
+    super(flags);
+  }
+
+  public static ClassAccessFlags fromSharedAccessFlags(int access) {
+    assert (access & SHARED_FLAGS) == access;
+    assert SHARED_FLAGS == DEX_FLAGS;
+    return fromDexAccessFlags(access);
+  }
+
+  public static ClassAccessFlags fromDexAccessFlags(int access) {
+    // Assume that the SUPER flag should be set (behaviour for Java versions > 1.1).
+    return new ClassAccessFlags((access & DEX_FLAGS) | Constants.ACC_SUPER);
+  }
+
+  public static ClassAccessFlags fromCfAccessFlags(int access) {
+    return new ClassAccessFlags(access & CF_FLAGS);
+  }
+
+  public ClassAccessFlags copy() {
+    return new ClassAccessFlags(flags);
+  }
+
+  @Override
+  public int getAsDexAccessFlags() {
+    return flags & ~Constants.ACC_SUPER;
+  }
+
+  @Override
+  public int getAsCfAccessFlags() {
+    return flags;
+  }
+
+  public boolean isInterface() {
+    return isSet(Constants.ACC_INTERFACE);
+  }
+
+  public void setInterface() {
+    set(Constants.ACC_INTERFACE);
+  }
+
+  public void unsetInterface() {
+    unset(Constants.ACC_INTERFACE);
+  }
+
+  public boolean isAbstract() {
+    return isSet(Constants.ACC_ABSTRACT);
+  }
+
+  public void setAbstract() {
+    set(Constants.ACC_ABSTRACT);
+  }
+
+  public void unsetAbstract() {
+    unset(Constants.ACC_ABSTRACT);
+  }
+
+  public boolean isAnnotation() {
+    return isSet(Constants.ACC_ANNOTATION);
+  }
+
+  public void setAnnotation() {
+    set(Constants.ACC_ANNOTATION);
+  }
+
+  public boolean isEnum() {
+    return isSet(Constants.ACC_ENUM);
+  }
+
+  public void setEnum() {
+    set(Constants.ACC_ENUM);
+  }
+
+  public boolean isSuper() {
+    return isSet(Constants.ACC_SUPER);
+  }
+
+  public void setSuper() {
+    set(Constants.ACC_SUPER);
+  }
+
+  public void unsetSuper() {
+    unset(Constants.ACC_SUPER);
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/ClassKind.java b/src/main/java/com/android/tools/r8/graph/ClassKind.java
index 90644e5..f8c4cbd 100644
--- a/src/main/java/com/android/tools/r8/graph/ClassKind.java
+++ b/src/main/java/com/android/tools/r8/graph/ClassKind.java
@@ -16,7 +16,7 @@
         DexType type,
         ProgramResource.Kind kind,
         Origin origin,
-        DexAccessFlags accessFlags,
+        ClassAccessFlags accessFlags,
         DexType superType,
         DexTypeList interfaces,
         DexString sourceFile,
@@ -39,7 +39,7 @@
       DexType type,
       ProgramResource.Kind kind,
       Origin origin,
-      DexAccessFlags accessFlags,
+      ClassAccessFlags accessFlags,
       DexType superType,
       DexTypeList interfaces,
       DexString sourceFile,
diff --git a/src/main/java/com/android/tools/r8/graph/DexAccessFlags.java b/src/main/java/com/android/tools/r8/graph/DexAccessFlags.java
deleted file mode 100644
index a8f9526..0000000
--- a/src/main/java/com/android/tools/r8/graph/DexAccessFlags.java
+++ /dev/null
@@ -1,310 +0,0 @@
-// Copyright (c) 2016, 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.graph;
-
-import com.android.tools.r8.dex.Constants;
-
-public class DexAccessFlags {
-
-  private static final String[] ACC_NAMES = {
-      "public",
-      "private",
-      "protected",
-      "static",
-      "final",
-      "synchronized",
-      "volatile(bridge)",
-      "transient(varargs)",
-      "native",
-      "interface",
-      "abstract",
-      "strictfp",
-      "synthetic",
-      "annotation",
-      "enum",
-      "<unused>",
-      "<init>",
-      "synchronized",
-  };
-
-  private int flags;
-
-  public DexAccessFlags(int flags) {
-    this.flags = flags;
-  }
-
-  public DexAccessFlags(int... flags) {
-    this(combineFlags(flags));
-  }
-
-  private static int combineFlags(int[] flags) {
-    int combined = 0;
-    for (int flag : flags) {
-      combined |= flag;
-    }
-    return combined;
-  }
-
-  @Override
-  public boolean equals(Object other) {
-    if (other instanceof DexAccessFlags) {
-      return flags == ((DexAccessFlags) other).flags;
-    }
-    return false;
-  }
-
-  @Override
-  public int hashCode() {
-    return get();
-  }
-
-  public int get() {
-    return flags;
-  }
-
-  public boolean containsAllOf(DexAccessFlags other) {
-    return (flags & other.get()) == other.get();
-  }
-
-  public boolean containsNoneOf(DexAccessFlags other) {
-    return (flags & other.get()) == 0;
-  }
-
-  public boolean isPublic() {
-    return isSet(Constants.ACC_PUBLIC);
-  }
-
-  public void setPublic() {
-    set(Constants.ACC_PUBLIC);
-  }
-
-  public void unsetPublic() {
-    unset(Constants.ACC_PUBLIC);
-  }
-
-  public boolean isPrivate() {
-    return isSet(Constants.ACC_PRIVATE);
-  }
-
-  public void setPrivate() {
-    set(Constants.ACC_PRIVATE);
-  }
-
-  public void unsetPrivate() {
-    unset(Constants.ACC_PRIVATE);
-  }
-
-  public boolean isProtected() {
-    return isSet(Constants.ACC_PROTECTED);
-  }
-
-  public void setProtected() {
-    set(Constants.ACC_PROTECTED);
-  }
-
-  public void unsetProtected() {
-    unset(Constants.ACC_PROTECTED);
-  }
-
-  public boolean isStatic() {
-    return isSet(Constants.ACC_STATIC);
-  }
-
-  public void setStatic() {
-    set(Constants.ACC_STATIC);
-  }
-
-  public boolean isFinal() {
-    return isSet(Constants.ACC_FINAL);
-  }
-
-  public void setFinal() {
-    set(Constants.ACC_FINAL);
-  }
-
-  public void unsetFinal() {
-    unset(Constants.ACC_FINAL);
-  }
-
-  public boolean isSynchronized() {
-    return isSet(Constants.ACC_SYNCHRONIZED);
-  }
-
-  public void setSynchronized() {
-    set(Constants.ACC_SYNCHRONIZED);
-  }
-
-  public void unsetSynchronized() {
-    unset(Constants.ACC_SYNCHRONIZED);
-  }
-
-  public boolean isVolatile() {
-    return isSet(Constants.ACC_VOLATILE);
-  }
-
-  public void setVolatile() {
-    set(Constants.ACC_VOLATILE);
-  }
-
-  public boolean isBridge() {
-    return isSet(Constants.ACC_BRIDGE);
-  }
-
-  public void setBridge() {
-    set(Constants.ACC_BRIDGE);
-  }
-
-  public void unsetBridge() {
-    unset(Constants.ACC_BRIDGE);
-  }
-
-  public boolean isTransient() {
-    return isSet(Constants.ACC_TRANSIENT);
-  }
-
-  public void setTransient() {
-    set(Constants.ACC_TRANSIENT);
-  }
-
-  public boolean isVarargs() {
-    return isSet(Constants.ACC_VARARGS);
-  }
-
-  public void setVarargs() {
-    set(Constants.ACC_VARARGS);
-  }
-
-  public boolean isNative() {
-    return isSet(Constants.ACC_NATIVE);
-  }
-
-  public void setNative() {
-    set(Constants.ACC_NATIVE);
-  }
-
-  public boolean isInterface() {
-    return isSet(Constants.ACC_INTERFACE);
-  }
-
-  public void setInterface() {
-    set(Constants.ACC_INTERFACE);
-  }
-
-  public void unsetInterface() {
-    unset(Constants.ACC_INTERFACE);
-  }
-
-  public boolean isAbstract() {
-    return isSet(Constants.ACC_ABSTRACT);
-  }
-
-  public void setAbstract() {
-    set(Constants.ACC_ABSTRACT);
-  }
-
-  public void unsetAbstract() {
-    unset(Constants.ACC_ABSTRACT);
-  }
-
-  public boolean isStrict() {
-    return isSet(Constants.ACC_STRICT);
-  }
-
-  public void setStrict() {
-    set(Constants.ACC_STRICT);
-  }
-
-  public boolean isSynthetic() {
-    return isSet(Constants.ACC_SYNTHETIC);
-  }
-
-  public void setSynthetic() {
-    set(Constants.ACC_SYNTHETIC);
-  }
-
-  public void unsetSynthetic() {
-    unset(Constants.ACC_SYNTHETIC);
-  }
-
-  public boolean isAnnotation() {
-    return isSet(Constants.ACC_ANNOTATION);
-  }
-
-  public void setAnnotation() {
-    set(Constants.ACC_ANNOTATION);
-  }
-
-  public boolean isEnum() {
-    return isSet(Constants.ACC_ENUM);
-  }
-
-  public void setEnum() {
-    set(Constants.ACC_ENUM);
-  }
-
-  public boolean isConstructor() {
-    return isSet(Constants.ACC_CONSTRUCTOR);
-  }
-
-  public void setConstructor() {
-    set(Constants.ACC_CONSTRUCTOR);
-  }
-
-  public void unsetConstructor() {
-    unset(Constants.ACC_CONSTRUCTOR);
-  }
-
-  public boolean isDeclaredSynchronized() {
-    return isSet(Constants.ACC_DECLARED_SYNCHRONIZED);
-  }
-
-  public void setDeclaredSynchronized() {
-    set(Constants.ACC_DECLARED_SYNCHRONIZED);
-  }
-
-  public void promoteNonPrivateToPublic() {
-    if (!isPrivate()) {
-      flags &= ~Constants.ACC_PROTECTED;
-      flags |= Constants.ACC_PUBLIC;
-    }
-  }
-
-  public void promoteToPublic() {
-    flags &= ~Constants.ACC_PROTECTED & ~Constants.ACC_PRIVATE;
-    flags |= Constants.ACC_PUBLIC;
-  }
-
-  private boolean isSet(int flag) {
-    return (flags & flag) != 0;
-  }
-
-  private void set(int flag) {
-    flags |= flag;
-  }
-
-  private void unset(int flag) {
-    flags &= ~flag;
-  }
-
-  @Override
-  public String toString() {
-    StringBuilder builder = new StringBuilder();
-    int flags = this.flags;
-    flags &= ~Constants.ACC_CONSTRUCTOR;  // Don't include the constructor flag in the string.
-    for (int i = 0; i < ACC_NAMES.length && flags != 0; i++, flags >>= 1) {
-      if ((flags & 0x1) != 0) {
-        if (builder.length() > 0) {
-          builder.append(' ');
-        }
-        builder.append(ACC_NAMES[i]);
-      }
-    }
-    assert flags == 0;
-    return builder.toString();
-  }
-
-  public String toSmaliString() {
-    return toString();
-  }
-}
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 5050711..2aba23b 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -19,7 +19,7 @@
 
   public final Origin origin;
   public final DexType type;
-  public final DexAccessFlags accessFlags;
+  public final ClassAccessFlags accessFlags;
   public DexType superType;
   public DexTypeList interfaces;
   public DexString sourceFile;
@@ -45,7 +45,7 @@
   public DexClass(
       DexString sourceFile,
       DexTypeList interfaces,
-      DexAccessFlags accessFlags,
+      ClassAccessFlags accessFlags,
       DexType superType,
       DexType type,
       DexEncodedField[] staticFields,
diff --git a/src/main/java/com/android/tools/r8/graph/DexClasspathClass.java b/src/main/java/com/android/tools/r8/graph/DexClasspathClass.java
index d39763e..292b368 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClasspathClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClasspathClass.java
@@ -17,7 +17,7 @@
       DexType type,
       ProgramResource.Kind kind,
       Origin origin,
-      DexAccessFlags accessFlags,
+      ClassAccessFlags accessFlags,
       DexType superType,
       DexTypeList interfaces,
       DexString sourceFile,
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedField.java b/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
index 1ba7755..bdfadfc 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
@@ -13,11 +13,14 @@
   public static final DexEncodedField[] EMPTY_ARRAY = new DexEncodedField[]{};
 
   public final DexField field;
-  public final DexAccessFlags accessFlags;
+  public final FieldAccessFlags accessFlags;
   public DexAnnotationSet annotations;
   public DexValue staticValue;
 
-  public DexEncodedField(DexField field, DexAccessFlags accessFlags, DexAnnotationSet annotations,
+  public DexEncodedField(
+      DexField field,
+      FieldAccessFlags accessFlags,
+      DexAnnotationSet annotations,
       DexValue staticValue) {
     assert !accessFlags.isStatic() || staticValue != null;
     this.field = field;
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index 1974397..9c0c39c 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -85,7 +85,7 @@
       new DexEncodedMethod(null, null, null, null, null);
 
   public final DexMethod method;
-  public final DexAccessFlags accessFlags;
+  public final MethodAccessFlags accessFlags;
   public DexAnnotationSet annotations;
   public DexAnnotationSetRefList parameterAnnotations;
   private Code code;
@@ -186,8 +186,12 @@
 
   public List<DebugPositionRange> debugPositionRangeList = null;
 
-  public DexEncodedMethod(DexMethod method, DexAccessFlags accessFlags,
-      DexAnnotationSet annotations, DexAnnotationSetRefList parameterAnnotations, Code code) {
+  public DexEncodedMethod(
+      DexMethod method,
+      MethodAccessFlags accessFlags,
+      DexAnnotationSet annotations,
+      DexAnnotationSetRefList parameterAnnotations,
+      Code code) {
     this.method = method;
     this.accessFlags = accessFlags;
     this.annotations = annotations;
@@ -667,7 +671,7 @@
   private static class Builder {
 
     private DexMethod method;
-    private DexAccessFlags accessFlags;
+    private MethodAccessFlags accessFlags;
     private DexAnnotationSet annotations;
     private DexAnnotationSetRefList parameterAnnotations;
     private Code code;
@@ -677,7 +681,7 @@
     private Builder(DexEncodedMethod from) {
       // Copy all the mutable state of a DexEncodedMethod here.
       method = from.method;
-      accessFlags = new DexAccessFlags(from.accessFlags.get());
+      accessFlags = from.accessFlags.copy();
       annotations = from.annotations;
       parameterAnnotations = from.parameterAnnotations;
       code = from.code;
diff --git a/src/main/java/com/android/tools/r8/graph/DexLibraryClass.java b/src/main/java/com/android/tools/r8/graph/DexLibraryClass.java
index 3c9cbdd..f2e262b 100644
--- a/src/main/java/com/android/tools/r8/graph/DexLibraryClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexLibraryClass.java
@@ -17,7 +17,7 @@
       DexType type,
       ProgramResource.Kind kind,
       Origin origin,
-      DexAccessFlags accessFlags,
+      ClassAccessFlags accessFlags,
       DexType superType,
       DexTypeList interfaces,
       DexString sourceFile,
diff --git a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
index ad1af10..4d16548 100644
--- a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
@@ -31,7 +31,7 @@
       DexType type,
       ProgramResource.Kind originKind,
       Origin origin,
-      DexAccessFlags accessFlags,
+      ClassAccessFlags accessFlags,
       DexType superType,
       DexTypeList interfaces,
       DexString sourceFile,
@@ -60,7 +60,7 @@
       DexType type,
       ProgramResource.Kind originKind,
       Origin origin,
-      DexAccessFlags accessFlags,
+      ClassAccessFlags accessFlags,
       DexType superType,
       DexTypeList interfaces,
       DexString sourceFile,
diff --git a/src/main/java/com/android/tools/r8/graph/FieldAccessFlags.java b/src/main/java/com/android/tools/r8/graph/FieldAccessFlags.java
new file mode 100644
index 0000000..b56e60f
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/FieldAccessFlags.java
@@ -0,0 +1,93 @@
+// Copyright (c) 2017, 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.graph;
+
+import com.android.tools.r8.dex.Constants;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import java.util.function.BooleanSupplier;
+
+public class FieldAccessFlags extends AccessFlags {
+
+  private static final int FLAGS
+      = AccessFlags.BASE_FLAGS
+      | Constants.ACC_VOLATILE
+      | Constants.ACC_TRANSIENT
+      | Constants.ACC_ENUM;
+
+  @Override
+  protected List<String> getNames() {
+    return new ImmutableList.Builder<String>()
+        .addAll(super.getNames())
+        .add("volatile")
+        .add("transient")
+        .add("enum")
+        .build();
+  }
+
+  @Override
+  protected List<BooleanSupplier> getPredicates() {
+    return new ImmutableList.Builder<BooleanSupplier>()
+        .addAll(super.getPredicates())
+        .add(this::isVolatile)
+        .add(this::isTransient)
+        .add(this::isEnum)
+        .build();
+  }
+
+  private FieldAccessFlags(int flags) {
+    super(flags);
+  }
+
+  public FieldAccessFlags copy() {
+    return new FieldAccessFlags(flags);
+  }
+
+  public static FieldAccessFlags fromSharedAccessFlags(int access) {
+    assert (access & FLAGS) == access;
+    return new FieldAccessFlags(access & FLAGS);
+  }
+
+  public static FieldAccessFlags fromDexAccessFlags(int access) {
+    return new FieldAccessFlags(access & FLAGS);
+  }
+
+  public static FieldAccessFlags fromCfAccessFlags(int access) {
+    return new FieldAccessFlags(access & FLAGS);
+  }
+
+  @Override
+  public int getAsCfAccessFlags() {
+    return flags;
+  }
+
+  @Override
+  public int getAsDexAccessFlags() {
+    return flags;
+  }
+
+  public boolean isVolatile() {
+    return isSet(Constants.ACC_VOLATILE);
+  }
+
+  public void setVolatile() {
+    set(Constants.ACC_VOLATILE);
+  }
+
+  public boolean isTransient() {
+    return isSet(Constants.ACC_TRANSIENT);
+  }
+
+  public void setTransient() {
+    set(Constants.ACC_TRANSIENT);
+  }
+
+  public boolean isEnum() {
+    return isSet(Constants.ACC_ENUM);
+  }
+
+  public void setEnum() {
+    set(Constants.ACC_ENUM);
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
index 9742df7..46f7966 100644
--- a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
+++ b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
@@ -40,7 +40,6 @@
 import org.objectweb.asm.FieldVisitor;
 import org.objectweb.asm.Label;
 import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
 import org.objectweb.asm.Type;
 import org.objectweb.asm.TypePath;
 
@@ -67,9 +66,9 @@
         origin, classKind, reader.b, application, classConsumer), SKIP_FRAMES);
   }
 
-  private static DexAccessFlags createAccessFlags(int access) {
-    // Clear the "synthetic attribute" and "deprecated" flags if preset.
-    return new DexAccessFlags(access & ~ACC_SYNTHETIC_ATTRIBUTE & ~ACC_DEPRECATED);
+  private static int cleanAccessFlags(int access) {
+    // Clear the "synthetic attribute" and "deprecated" attribute-flags if present.
+    return access & ~ACC_SYNTHETIC_ATTRIBUTE & ~ACC_DEPRECATED;
   }
 
   private static AnnotationVisitor createAnnotationVisitor(String desc, boolean visible,
@@ -103,7 +102,7 @@
     // DexClass data.
     private int version;
     private DexType type;
-    private DexAccessFlags accessFlags;
+    private ClassAccessFlags accessFlags;
     private DexType superType;
     private DexTypeList interfaces;
     private DexString sourceFile;
@@ -176,10 +175,7 @@
     public void visit(int version, int access, String name, String signature, String superName,
         String[] interfaces) {
       this.version = version;
-      accessFlags = createAccessFlags(access);
-      // Unset the (in dex) non-existent ACC_SUPER flag on the class.
-      assert Constants.ACC_SYNCHRONIZED == Opcodes.ACC_SUPER;
-      accessFlags.unsetSynchronized();
+      accessFlags = ClassAccessFlags.fromCfAccessFlags(cleanAccessFlags(access));
       type = application.getTypeFromName(name);
       assert superName != null || name.equals(Constants.JAVA_LANG_OBJECT_NAME);
       superType = superName == null ? null : application.getTypeFromName(superName);
@@ -332,7 +328,7 @@
 
     @Override
     public void visitEnd() {
-      DexAccessFlags flags = createAccessFlags(access);
+      FieldAccessFlags flags = FieldAccessFlags.fromCfAccessFlags(cleanAccessFlags(access));
       DexField dexField = parent.application.getField(parent.type, name, desc);
       DexAnnotationSet annotationSet = createAnnotationSet(annotations);
       DexValue staticValue = flags.isStatic() ? getStaticValue(value, dexField.type) : null;
@@ -514,7 +510,7 @@
     @Override
     public void visitEnd() {
       DexMethod method = parent.application.getMethod(parent.type, name, desc);
-      DexAccessFlags flags = createMethodAccessFlags(access);
+      MethodAccessFlags flags = createMethodAccessFlags(access);
       Code code = null;
       if (!flags.isAbstract()
           && !flags.isNative()
@@ -567,20 +563,11 @@
       getAnnotations().add(annotation);
     }
 
-    private DexAccessFlags createMethodAccessFlags(int access) {
-      DexAccessFlags flags = createAccessFlags(access);
-      // Set just the dex specific declared-synchronized flag if the method is synchronized.
-      // TODO(zerny): Should declared sync also be set if it is native?
-      if (flags.isSynchronized() && !flags.isNative()) {
-        flags.unsetSynchronized();
-        flags.setDeclaredSynchronized();
-      }
-      // Set the constructor bit on instance and class initializers.
-      if (name.equals(Constants.INSTANCE_INITIALIZER_NAME) || name.equals(
-          Constants.CLASS_INITIALIZER_NAME)) {
-        flags.setConstructor();
-      }
-      return flags;
+    private MethodAccessFlags createMethodAccessFlags(int access) {
+      boolean isConstructor =
+          name.equals(Constants.INSTANCE_INITIALIZER_NAME)
+              || name.equals(Constants.CLASS_INITIALIZER_NAME);
+      return MethodAccessFlags.fromCfAccessFlags(cleanAccessFlags(access), isConstructor);
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/graph/MethodAccessFlags.java b/src/main/java/com/android/tools/r8/graph/MethodAccessFlags.java
new file mode 100644
index 0000000..37a6fac
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/MethodAccessFlags.java
@@ -0,0 +1,184 @@
+// Copyright (c) 2017, 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.graph;
+
+import com.android.tools.r8.dex.Constants;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import java.util.function.BooleanSupplier;
+
+public class MethodAccessFlags extends AccessFlags {
+
+  private static final int SHARED_FLAGS
+      = AccessFlags.BASE_FLAGS
+      | Constants.ACC_SYNCHRONIZED
+      | Constants.ACC_BRIDGE
+      | Constants.ACC_VARARGS
+      | Constants.ACC_NATIVE
+      | Constants.ACC_ABSTRACT
+      | Constants.ACC_STRICT;
+
+  private static final int CF_FLAGS
+      = SHARED_FLAGS;
+
+  private static final int DEX_FLAGS
+      = SHARED_FLAGS
+      | Constants.ACC_CONSTRUCTOR
+      | Constants.ACC_DECLARED_SYNCHRONIZED;
+
+  @Override
+  protected List<String> getNames() {
+    return new ImmutableList.Builder<String>()
+        .addAll(super.getNames())
+        .add("synchronized")
+        .add("bridge")
+        .add("varargs")
+        .add("native")
+        .add("abstract")
+        .add("strictfp")
+        .build();
+  }
+
+  @Override
+  protected List<BooleanSupplier> getPredicates() {
+    return new ImmutableList.Builder<BooleanSupplier>()
+        .addAll(super.getPredicates())
+        .add(this::isSynchronized)
+        .add(this::isBridge)
+        .add(this::isVarargs)
+        .add(this::isNative)
+        .add(this::isAbstract)
+        .add(this::isStrict)
+        .build();
+  }
+
+  private MethodAccessFlags(int flags) {
+    super(flags);
+  }
+
+  public MethodAccessFlags copy() {
+    return new MethodAccessFlags(flags);
+  }
+
+  public static MethodAccessFlags fromSharedAccessFlags(int access, boolean isConstructor) {
+    assert (access & SHARED_FLAGS) == access;
+    assert CF_FLAGS == SHARED_FLAGS;
+    return fromCfAccessFlags(access, isConstructor);
+  }
+
+  public static MethodAccessFlags fromCfAccessFlags(int access, boolean isConstructor) {
+    return new MethodAccessFlags(
+        (access & CF_FLAGS) | (isConstructor ? Constants.ACC_CONSTRUCTOR : 0));
+  }
+
+  public static MethodAccessFlags fromDexAccessFlags(int access) {
+    MethodAccessFlags flags = new MethodAccessFlags(access & DEX_FLAGS);
+    if (flags.isDeclaredSynchronized()) {
+      flags.setSynchronized();
+      flags.unsetDeclaredSynchronized();
+    }
+    return flags;
+  }
+
+  @Override
+  public int getAsDexAccessFlags() {
+    MethodAccessFlags copy = copy();
+    if (copy.isSynchronized() && !copy.isNative()) {
+      copy.unsetSynchronized();
+      copy.setDeclaredSynchronized();
+    }
+    return copy.flags;
+  }
+
+  @Override
+  public int getAsCfAccessFlags() {
+    return flags & ~Constants.ACC_CONSTRUCTOR;
+  }
+
+  public boolean isSynchronized() {
+    return isSet(Constants.ACC_SYNCHRONIZED);
+  }
+
+  public void setSynchronized() {
+    set(Constants.ACC_SYNCHRONIZED);
+  }
+
+  public void unsetSynchronized() {
+    unset(Constants.ACC_SYNCHRONIZED);
+  }
+
+  public boolean isBridge() {
+    return isSet(Constants.ACC_BRIDGE);
+  }
+
+  public void setBridge() {
+    set(Constants.ACC_BRIDGE);
+  }
+
+  public void unsetBridge() {
+    unset(Constants.ACC_BRIDGE);
+  }
+
+  public boolean isVarargs() {
+    return isSet(Constants.ACC_VARARGS);
+  }
+
+  public void setVarargs() {
+    set(Constants.ACC_VARARGS);
+  }
+
+  public boolean isNative() {
+    return isSet(Constants.ACC_NATIVE);
+  }
+
+  public void setNative() {
+    set(Constants.ACC_NATIVE);
+  }
+
+  public boolean isAbstract() {
+    return isSet(Constants.ACC_ABSTRACT);
+  }
+
+  public void setAbstract() {
+    set(Constants.ACC_ABSTRACT);
+  }
+
+  public void unsetAbstract() {
+    unset(Constants.ACC_ABSTRACT);
+  }
+
+  public boolean isStrict() {
+    return isSet(Constants.ACC_STRICT);
+  }
+
+  public void setStrict() {
+    set(Constants.ACC_STRICT);
+  }
+
+  public boolean isConstructor() {
+    return isSet(Constants.ACC_CONSTRUCTOR);
+  }
+
+  public void setConstructor() {
+    set(Constants.ACC_CONSTRUCTOR);
+  }
+
+  public void unsetConstructor() {
+    unset(Constants.ACC_CONSTRUCTOR);
+  }
+
+  // DEX only declared-synchronized flag.
+
+  private boolean isDeclaredSynchronized() {
+    return isSet(Constants.ACC_DECLARED_SYNCHRONIZED);
+  }
+
+  private void setDeclaredSynchronized() {
+    set(Constants.ACC_DECLARED_SYNCHRONIZED);
+  }
+
+  private void unsetDeclaredSynchronized() {
+    unset(Constants.ACC_DECLARED_SYNCHRONIZED);
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java
index a71f326..4bafe62 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java
@@ -29,7 +29,6 @@
 import com.android.tools.r8.code.Throw;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DebugLocalInfo;
-import com.android.tools.r8.graph.DexAccessFlags;
 import com.android.tools.r8.graph.DexCode;
 import com.android.tools.r8.graph.DexCode.Try;
 import com.android.tools.r8.graph.DexCode.TryHandler;
@@ -40,6 +39,7 @@
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexProto;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.MethodAccessFlags;
 import com.android.tools.r8.ir.code.CatchHandlers;
 import com.android.tools.r8.ir.code.MoveType;
 import com.android.tools.r8.ir.code.Position;
@@ -53,7 +53,7 @@
 public class DexSourceCode implements SourceCode {
 
   private final DexCode code;
-  private final DexAccessFlags accessFlags;
+  private final MethodAccessFlags accessFlags;
   private final DexProto proto;
 
   // Mapping from instruction offset to instruction index in the DexCode instruction array.
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/AccessorMethodSourceCode.java b/src/main/java/com/android/tools/r8/ir/desugar/AccessorMethodSourceCode.java
index 1cf64fd..2460798 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/AccessorMethodSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/AccessorMethodSourceCode.java
@@ -5,11 +5,11 @@
 package com.android.tools.r8.ir.desugar;
 
 import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.DexAccessFlags;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexMethodHandle;
 import com.android.tools.r8.graph.DexProto;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.MethodAccessFlags;
 import com.android.tools.r8.ir.code.Invoke;
 import com.android.tools.r8.ir.code.MoveType;
 import com.android.tools.r8.ir.conversion.IRBuilder;
@@ -57,7 +57,7 @@
   private boolean isPrivateMethod() {
     // We should be able to find targets for all private impl-methods, so
     // we can rely on knowing accessibility flags for them.
-    DexAccessFlags flags = descriptor().getAccessibility();
+    MethodAccessFlags flags = descriptor().getAccessibility();
     return flags != null && flags.isPrivate();
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
index 09371f7..fa0958b 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
@@ -5,11 +5,11 @@
 package com.android.tools.r8.ir.desugar;
 
 import com.android.tools.r8.errors.CompilationError;
-import com.android.tools.r8.graph.DexAccessFlags;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.MethodAccessFlags;
 import com.android.tools.r8.ir.code.Invoke;
 import com.android.tools.r8.ir.synthetic.ForwardMethodSourceCode;
 import com.android.tools.r8.ir.synthetic.SynthesizedCode;
@@ -109,7 +109,7 @@
     // New method will have the same name, proto, and also all the flags of the
     // default method, including bridge flag.
     DexMethod newMethod = rewriter.factory.createMethod(clazz.type, method.proto, method.name);
-    DexAccessFlags newFlags = new DexAccessFlags(defaultMethod.accessFlags.get());
+    MethodAccessFlags newFlags = defaultMethod.accessFlags.copy();
     return new DexEncodedMethod(newMethod, newFlags,
         defaultMethod.annotations, defaultMethod.parameterAnnotations,
         new SynthesizedCode(new ForwardMethodSourceCode(
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
index fb3507b..1714b93 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
@@ -6,8 +6,8 @@
 
 import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.errors.Unimplemented;
+import com.android.tools.r8.graph.ClassAccessFlags;
 import com.android.tools.r8.graph.Code;
-import com.android.tools.r8.graph.DexAccessFlags;
 import com.android.tools.r8.graph.DexAnnotationSet;
 import com.android.tools.r8.graph.DexCode;
 import com.android.tools.r8.graph.DexEncodedField;
@@ -16,6 +16,7 @@
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.DexTypeList;
+import com.android.tools.r8.graph.MethodAccessFlags;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.IdentityHashMap;
@@ -56,7 +57,7 @@
               + "interface method: " + virtual.method.toSourceString());
         }
 
-        DexAccessFlags newFlags = new DexAccessFlags(virtual.accessFlags.get());
+        MethodAccessFlags newFlags = virtual.accessFlags.copy();
         newFlags.unsetBridge();
         newFlags.setStatic();
         DexCode dexCode = code.asDexCode();
@@ -115,7 +116,7 @@
       return; // No methods to create, companion class not needed.
     }
 
-    DexAccessFlags companionClassFlags = new DexAccessFlags(iface.accessFlags.get());
+    ClassAccessFlags companionClassFlags = iface.accessFlags.copy();
     companionClassFlags.unsetAbstract();
     companionClassFlags.unsetInterface();
     companionClassFlags.setFinal();
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
index 569d088..43548c2 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
@@ -8,7 +8,7 @@
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.errors.Unimplemented;
 import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.DexAccessFlags;
+import com.android.tools.r8.graph.ClassAccessFlags;
 import com.android.tools.r8.graph.DexAnnotationSet;
 import com.android.tools.r8.graph.DexAnnotationSetRefList;
 import com.android.tools.r8.graph.DexClass;
@@ -25,6 +25,8 @@
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.DexTypeList;
 import com.android.tools.r8.graph.DexValue.DexValueNull;
+import com.android.tools.r8.graph.FieldAccessFlags;
+import com.android.tools.r8.graph.MethodAccessFlags;
 import com.android.tools.r8.ir.code.Invoke;
 import com.android.tools.r8.ir.synthetic.SynthesizedCode;
 import java.util.ArrayList;
@@ -121,7 +123,7 @@
         type,
         null,
         null,
-        new DexAccessFlags(Constants.ACC_FINAL | Constants.ACC_SYNTHETIC),
+        ClassAccessFlags.fromDexAccessFlags(Constants.ACC_FINAL | Constants.ACC_SYNTHETIC),
         rewriter.factory.objectType,
         buildInterfaces(),
         rewriter.factory.createString("lambda"),
@@ -155,24 +157,31 @@
     // Synthesize main method.
     DexMethod mainMethod = rewriter.factory
         .createMethod(type, descriptor.erasedProto, descriptor.name);
-    methods[index++] = new DexEncodedMethod(
-        mainMethod,
-        new DexAccessFlags(Constants.ACC_PUBLIC | Constants.ACC_FINAL),
-        DexAnnotationSet.empty(),
-        DexAnnotationSetRefList.empty(),
-        new SynthesizedCode(new LambdaMainMethodSourceCode(this, mainMethod)));
+    methods[index++] =
+        new DexEncodedMethod(
+            mainMethod,
+            MethodAccessFlags.fromSharedAccessFlags(
+                Constants.ACC_PUBLIC | Constants.ACC_FINAL, false),
+            DexAnnotationSet.empty(),
+            DexAnnotationSetRefList.empty(),
+            new SynthesizedCode(new LambdaMainMethodSourceCode(this, mainMethod)));
 
     // Synthesize bridge methods.
     for (DexProto bridgeProto : descriptor.bridges) {
       DexMethod bridgeMethod = rewriter.factory.createMethod(type, bridgeProto, descriptor.name);
-      methods[index++] = new DexEncodedMethod(
-          bridgeMethod,
-          new DexAccessFlags(Constants.ACC_PUBLIC | Constants.ACC_FINAL
-              | Constants.ACC_SYNTHETIC | Constants.ACC_BRIDGE),
-          DexAnnotationSet.empty(),
-          DexAnnotationSetRefList.empty(),
-          new SynthesizedCode(
-              new LambdaBridgeMethodSourceCode(this, mainMethod, bridgeMethod)));
+      methods[index++] =
+          new DexEncodedMethod(
+              bridgeMethod,
+              MethodAccessFlags.fromSharedAccessFlags(
+                  Constants.ACC_PUBLIC
+                      | Constants.ACC_FINAL
+                      | Constants.ACC_SYNTHETIC
+                      | Constants.ACC_BRIDGE,
+                  false),
+              DexAnnotationSet.empty(),
+              DexAnnotationSetRefList.empty(),
+              new SynthesizedCode(
+                  new LambdaBridgeMethodSourceCode(this, mainMethod, bridgeMethod)));
     }
     return methods;
   }
@@ -183,23 +192,27 @@
     DexEncodedMethod[] methods = new DexEncodedMethod[stateless ? 2 : 1];
 
     // Constructor.
-    methods[0] = new DexEncodedMethod(
-        constructor,
-        new DexAccessFlags((stateless ? Constants.ACC_PRIVATE : Constants.ACC_PUBLIC) |
-            Constants.ACC_SYNTHETIC | Constants.ACC_CONSTRUCTOR),
-        DexAnnotationSet.empty(),
-        DexAnnotationSetRefList.empty(),
-        new SynthesizedCode(new LambdaConstructorSourceCode(this)));
+    methods[0] =
+        new DexEncodedMethod(
+            constructor,
+            MethodAccessFlags.fromSharedAccessFlags(
+                (stateless ? Constants.ACC_PRIVATE : Constants.ACC_PUBLIC)
+                    | Constants.ACC_SYNTHETIC,
+                true),
+            DexAnnotationSet.empty(),
+            DexAnnotationSetRefList.empty(),
+            new SynthesizedCode(new LambdaConstructorSourceCode(this)));
 
     // Class constructor for stateless lambda classes.
     if (stateless) {
-      methods[1] = new DexEncodedMethod(
-          classConstructor,
-          new DexAccessFlags(
-              Constants.ACC_SYNTHETIC | Constants.ACC_CONSTRUCTOR | Constants.ACC_STATIC),
-          DexAnnotationSet.empty(),
-          DexAnnotationSetRefList.empty(),
-          new SynthesizedCode(new LambdaClassConstructorSourceCode(this)));
+      methods[1] =
+          new DexEncodedMethod(
+              classConstructor,
+              MethodAccessFlags.fromSharedAccessFlags(
+                  Constants.ACC_SYNTHETIC | Constants.ACC_STATIC, true),
+              DexAnnotationSet.empty(),
+              DexAnnotationSetRefList.empty(),
+              new SynthesizedCode(new LambdaClassConstructorSourceCode(this)));
     }
     return methods;
   }
@@ -210,8 +223,9 @@
     int fieldCount = fieldTypes.length;
     DexEncodedField[] fields = new DexEncodedField[fieldCount];
     for (int i = 0; i < fieldCount; i++) {
-      DexAccessFlags accessFlags = new DexAccessFlags(
-          Constants.ACC_FINAL | Constants.ACC_SYNTHETIC | Constants.ACC_PRIVATE);
+      FieldAccessFlags accessFlags =
+          FieldAccessFlags.fromSharedAccessFlags(
+              Constants.ACC_FINAL | Constants.ACC_SYNTHETIC | Constants.ACC_PRIVATE);
       fields[i] = new DexEncodedField(
           getCaptureField(i), accessFlags, DexAnnotationSet.empty(), null);
     }
@@ -227,12 +241,16 @@
     // Create instance field for stateless lambda.
     assert this.instanceField != null;
     DexEncodedField[] fields = new DexEncodedField[1];
-    fields[0] = new DexEncodedField(
-        this.instanceField,
-        new DexAccessFlags(Constants.ACC_PUBLIC | Constants.ACC_FINAL
-            | Constants.ACC_SYNTHETIC | Constants.ACC_STATIC),
-        DexAnnotationSet.empty(),
-        DexValueNull.NULL);
+    fields[0] =
+        new DexEncodedField(
+            this.instanceField,
+            FieldAccessFlags.fromSharedAccessFlags(
+                Constants.ACC_PUBLIC
+                    | Constants.ACC_FINAL
+                    | Constants.ACC_SYNTHETIC
+                    | Constants.ACC_STATIC),
+            DexAnnotationSet.empty(),
+            DexValueNull.NULL);
     return fields;
   }
 
@@ -497,9 +515,12 @@
       DexProgramClass accessorClass = programDefinitionFor(callTarget.holder);
       assert accessorClass != null;
 
-      DexAccessFlags accessorFlags = new DexAccessFlags(
-          Constants.ACC_SYNTHETIC | Constants.ACC_STATIC |
-              (accessorClass.isInterface() ? Constants.ACC_PUBLIC : 0));
+      MethodAccessFlags accessorFlags =
+          MethodAccessFlags.fromSharedAccessFlags(
+              Constants.ACC_SYNTHETIC
+                  | Constants.ACC_STATIC
+                  | (accessorClass.isInterface() ? Constants.ACC_PUBLIC : 0),
+              false);
       DexEncodedMethod accessorEncodedMethod = new DexEncodedMethod(
           callTarget, accessorFlags, DexAnnotationSet.empty(), DexAnnotationSetRefList.empty(),
           new SynthesizedCode(new AccessorMethodSourceCode(LambdaClass.this)));
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaDescriptor.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaDescriptor.java
index bba7b23..5d52523 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaDescriptor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaDescriptor.java
@@ -6,7 +6,6 @@
 
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppInfo;
-import com.android.tools.r8.graph.DexAccessFlags;
 import com.android.tools.r8.graph.DexCallSite;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexItemFactory;
@@ -17,6 +16,7 @@
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.DexTypeList;
 import com.android.tools.r8.graph.DexValue;
+import com.android.tools.r8.graph.MethodAccessFlags;
 import com.google.common.collect.Sets;
 import java.util.ArrayList;
 import java.util.List;
@@ -140,7 +140,7 @@
     return encodedMethod.accessFlags.isPrivate() && isInstanceMethod(encodedMethod);
   }
 
-  final DexAccessFlags getAccessibility() {
+  final MethodAccessFlags getAccessibility() {
     return targetMethod == null ? null : targetMethod.accessFlags;
   }
 
@@ -198,7 +198,7 @@
       return true;
     }
 
-    DexAccessFlags flags = targetMethod.accessFlags;
+    MethodAccessFlags flags = targetMethod.accessFlags;
 
     // Private methods always need accessors.
     if (flags.isPrivate()) {
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 ad4639e..b15d254 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
@@ -4,8 +4,8 @@
 package com.android.tools.r8.ir.optimize;
 
 import com.android.tools.r8.ApiLevelException;
+import com.android.tools.r8.graph.AccessFlags;
 import com.android.tools.r8.graph.AppInfoWithSubtyping;
-import com.android.tools.r8.graph.DexAccessFlags;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexEncodedField;
 import com.android.tools.r8.graph.DexEncodedMethod;
@@ -91,7 +91,7 @@
     return isVisibleWithFlags(target.method.holder, method.method.holder, targetClass.accessFlags);
   }
 
-  private boolean isVisibleWithFlags(DexType target, DexType context, DexAccessFlags flags) {
+  private boolean isVisibleWithFlags(DexType target, DexType context, AccessFlags flags) {
     if (flags.isPublic()) {
       return true;
     }
@@ -166,8 +166,11 @@
       assert SUBCLASS.ordinal() < ALWAYS.ordinal();
     }
 
-    public static Constraint deriveConstraint(DexType contextHolder, DexType targetHolder,
-        DexAccessFlags flags, AppInfoWithSubtyping appInfo) {
+    public static Constraint deriveConstraint(
+        DexType contextHolder,
+        DexType targetHolder,
+        AccessFlags flags,
+        AppInfoWithSubtyping appInfo) {
       if (flags.isPublic()) {
         return ALWAYS;
       } else if (flags.isPrivate()) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
index 74afdcd..d799e7d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
@@ -8,9 +8,9 @@
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.ClassAccessFlags;
 import com.android.tools.r8.graph.Code;
 import com.android.tools.r8.graph.DebugLocalInfo;
-import com.android.tools.r8.graph.DexAccessFlags;
 import com.android.tools.r8.graph.DexAnnotationSet;
 import com.android.tools.r8.graph.DexAnnotationSetRefList;
 import com.android.tools.r8.graph.DexClass;
@@ -23,6 +23,7 @@
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.DexTypeList;
+import com.android.tools.r8.graph.MethodAccessFlags;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.code.Add;
 import com.android.tools.r8.ir.code.BasicBlock;
@@ -1058,7 +1059,9 @@
     List<Outline> outlines = new ArrayList<>(candidates.keySet());
     outlines.sort(Comparator.naturalOrder());
     for (Outline outline : outlines) {
-      DexAccessFlags methodAccess = new DexAccessFlags(Constants.ACC_PUBLIC, Constants.ACC_STATIC);
+      MethodAccessFlags methodAccess =
+          MethodAccessFlags.fromSharedAccessFlags(
+              Constants.ACC_PUBLIC | Constants.ACC_STATIC, false);
       DexString methodName = dexItemFactory.createString(options.outline.methodPrefix + count);
       DexMethod method = outline.buildMethod(type, methodName);
       direct[count] = new DexEncodedMethod(method, methodAccess, DexAnnotationSet.empty(),
@@ -1072,7 +1075,7 @@
     DexType superType = dexItemFactory.createType("Ljava/lang/Object;");
     DexTypeList interfaces = DexTypeList.empty();
     DexString sourceFile = dexItemFactory.createString("outline");
-    DexAccessFlags accessFlags = new DexAccessFlags(Constants.ACC_PUBLIC);
+    ClassAccessFlags accessFlags = ClassAccessFlags.fromSharedAccessFlags(Constants.ACC_PUBLIC);
     DexProgramClass clazz = new DexProgramClass(
         type,
         null,
diff --git a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
index 4662cd0..95e6e6a 100644
--- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -3,11 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.jar;
 
-import static org.objectweb.asm.Opcodes.ACC_SUPER;
-
 import com.android.tools.r8.OutputSink;
 import com.android.tools.r8.errors.Unimplemented;
-import com.android.tools.r8.graph.DexAccessFlags;
 import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexProgramClass;
@@ -53,7 +50,7 @@
     ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
     writer.visitSource(clazz.sourceFile.toString(), null);
     int version = clazz.getClassFileVersion();
-    int access = classAndInterfaceAccessFlags(clazz.accessFlags);
+    int access = clazz.accessFlags.getAsCfAccessFlags();
     String desc = clazz.type.toDescriptorString();
     String name = internalName(clazz.type);
     String signature = null; // TODO(zerny): Support generic signatures.
@@ -72,7 +69,7 @@
   }
 
   private void writeMethod(DexEncodedMethod method, ClassWriter writer) {
-    int access = method.accessFlags.get();
+    int access = method.accessFlags.getAsCfAccessFlags();
     String name = method.method.name.toString();
     String desc = method.descriptor();
     String signature = null; // TODO(zerny): Support generic signatures.
@@ -81,13 +78,6 @@
     method.getCode().asJarCode().writeTo(visitor);
   }
 
-  private static int classAndInterfaceAccessFlags(DexAccessFlags accessFlags) {
-    // TODO(zerny): Refactor access flags to account for the union of both DEX and Java flags.
-    int access = accessFlags.get();
-    access |= ACC_SUPER;
-    return access;
-  }
-
   private static String internalName(DexType type) {
     return Type.getType(type.toDescriptorString()).getInternalName();
   }
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardAccessFlags.java b/src/main/java/com/android/tools/r8/shaking/ProguardAccessFlags.java
new file mode 100644
index 0000000..749ce83
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardAccessFlags.java
@@ -0,0 +1,176 @@
+// Copyright (c) 2017, 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;
+
+import com.android.tools.r8.dex.Constants;
+import com.android.tools.r8.graph.AccessFlags;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import java.util.function.BooleanSupplier;
+
+public class ProguardAccessFlags {
+
+  private int flags = 0;
+
+  // Ordered list of flag names. Must be consistent with getPredicates.
+  private static final List<String> NAMES = ImmutableList.of(
+      "public",
+      "private",
+      "protected",
+      "static",
+      "final",
+      "abstract",
+      "volatile",
+      "transient",
+      "synchronized",
+      "native",
+      "strictfp"
+  );
+
+  // Get ordered list of flag predicates. Must be consistent with getNames.
+  private List<BooleanSupplier> getPredicates() {
+    return ImmutableList.of(
+        this::isPublic,
+        this::isPrivate,
+        this::isProtected,
+        this::isStatic,
+        this::isFinal,
+        this::isAbstract,
+        this::isVolatile,
+        this::isTransient,
+        this::isSynchronized,
+        this::isNative,
+        this::isStrict);
+  }
+
+  private boolean containsAll(int other) {
+    return (flags & other) == flags;
+  }
+
+  private boolean containsNone(int other) {
+    return (flags & other) == 0;
+  }
+
+  public boolean containsAll(AccessFlags other) {
+    return containsAll(other.getAsCfAccessFlags());
+  }
+
+  public boolean containsNone(AccessFlags other) {
+    return containsNone(other.getAsCfAccessFlags());
+  }
+
+  public void setPublic() {
+    set(Constants.ACC_PUBLIC);
+  }
+
+  public boolean isPublic() {
+    return isSet(Constants.ACC_PUBLIC);
+  }
+
+  public void setPrivate() {
+    set(Constants.ACC_PRIVATE);
+  }
+
+  public boolean isPrivate() {
+    return isSet(Constants.ACC_PRIVATE);
+  }
+
+  public void setProtected() {
+    set(Constants.ACC_PROTECTED);
+  }
+
+  public boolean isProtected() {
+    return isSet(Constants.ACC_PROTECTED);
+  }
+
+  public void setStatic() {
+    set(Constants.ACC_STATIC);
+  }
+
+  public boolean isStatic() {
+    return isSet(Constants.ACC_STATIC);
+  }
+
+  public void setFinal() {
+    set(Constants.ACC_FINAL);
+  }
+
+  public boolean isFinal() {
+    return isSet(Constants.ACC_FINAL);
+  }
+
+  public void setAbstract() {
+    set(Constants.ACC_ABSTRACT);
+  }
+
+  public boolean isAbstract() {
+    return isSet(Constants.ACC_ABSTRACT);
+  }
+
+  public void setVolatile() {
+    set(Constants.ACC_VOLATILE);
+  }
+
+  public boolean isVolatile() {
+    return isSet(Constants.ACC_VOLATILE);
+  }
+
+  public void setTransient() {
+    set(Constants.ACC_TRANSIENT);
+  }
+
+  public boolean isTransient() {
+    return isSet(Constants.ACC_TRANSIENT);
+  }
+
+  public void setSynchronized() {
+    set(Constants.ACC_SYNCHRONIZED);
+  }
+
+  public boolean isSynchronized() {
+    return isSet(Constants.ACC_SYNCHRONIZED);
+  }
+
+  public void setNative() {
+    set(Constants.ACC_NATIVE);
+  }
+
+  public boolean isNative() {
+    return isSet(Constants.ACC_NATIVE);
+  }
+
+  public void setStrict() {
+    set(Constants.ACC_STRICT);
+  }
+
+  public boolean isStrict() {
+    return isSet(Constants.ACC_STRICT);
+  }
+
+  private boolean isSet(int flag) {
+    return (flags & flag) != 0;
+  }
+
+  private void set(int flag) {
+    flags |= flag;
+  }
+
+  @Override
+  public String toString() {
+    List<BooleanSupplier> predicates = getPredicates();
+    StringBuilder builder = new StringBuilder();
+    boolean space = false;
+    for (int i = 0; i < NAMES.size(); i++) {
+      if (predicates.get(i).getAsBoolean()) {
+        if (space) {
+          builder.append(' ');
+        } else {
+          space = true;
+        }
+        builder.append(NAMES.get(i));
+      }
+    }
+    return builder.toString();
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardAlwaysInlineRule.java b/src/main/java/com/android/tools/r8/shaking/ProguardAlwaysInlineRule.java
index 524afd2..ab8342d 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardAlwaysInlineRule.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardAlwaysInlineRule.java
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.shaking;
 
-import com.android.tools.r8.graph.DexAccessFlags;
 import java.util.Set;
 
 public class ProguardAlwaysInlineRule extends ProguardConfigurationRule {
@@ -22,8 +21,8 @@
 
   private ProguardAlwaysInlineRule(
       ProguardTypeMatcher classAnnotation,
-      DexAccessFlags classAccessFlags,
-      DexAccessFlags negatedClassAccessFlags,
+      ProguardAccessFlags classAccessFlags,
+      ProguardAccessFlags negatedClassAccessFlags,
       boolean classTypeNegated,
       ProguardClassType classType,
       ProguardClassNameList classNames,
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardAssumeNoSideEffectRule.java b/src/main/java/com/android/tools/r8/shaking/ProguardAssumeNoSideEffectRule.java
index a01dd89..736c778 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardAssumeNoSideEffectRule.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardAssumeNoSideEffectRule.java
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.shaking;
 
-import com.android.tools.r8.graph.DexAccessFlags;
 import java.util.Set;
 
 public class ProguardAssumeNoSideEffectRule extends ProguardConfigurationRule {
@@ -21,8 +20,8 @@
 
   private ProguardAssumeNoSideEffectRule(
       ProguardTypeMatcher classAnnotation,
-      DexAccessFlags classAccessFlags,
-      DexAccessFlags negatedClassAccessFlags,
+      ProguardAccessFlags classAccessFlags,
+      ProguardAccessFlags negatedClassAccessFlags,
       boolean classTypeNegated,
       ProguardClassType classType,
       ProguardClassNameList classNames,
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardAssumeValuesRule.java b/src/main/java/com/android/tools/r8/shaking/ProguardAssumeValuesRule.java
index 94cf758..97cb5c3 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardAssumeValuesRule.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardAssumeValuesRule.java
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.shaking;
 
-import com.android.tools.r8.graph.DexAccessFlags;
 import java.util.Set;
 
 public class ProguardAssumeValuesRule extends ProguardConfigurationRule {
@@ -20,8 +19,8 @@
 
   private ProguardAssumeValuesRule(
       ProguardTypeMatcher classAnnotation,
-      DexAccessFlags classAccessFlags,
-      DexAccessFlags negatedClassAccessFlags,
+      ProguardAccessFlags classAccessFlags,
+      ProguardAccessFlags negatedClassAccessFlags,
       boolean classTypeNegated,
       ProguardClassType classType,
       ProguardClassNameList classNames,
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardCheckDiscardRule.java b/src/main/java/com/android/tools/r8/shaking/ProguardCheckDiscardRule.java
index 7f69e18..da5bb26 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardCheckDiscardRule.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardCheckDiscardRule.java
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.shaking;
 
-import com.android.tools.r8.graph.DexAccessFlags;
 import java.util.Set;
 
 public class ProguardCheckDiscardRule extends ProguardConfigurationRule {
@@ -22,8 +21,8 @@
 
   private ProguardCheckDiscardRule(
       ProguardTypeMatcher classAnnotation,
-      DexAccessFlags classAccessFlags,
-      DexAccessFlags negatedClassAccessFlags,
+      ProguardAccessFlags classAccessFlags,
+      ProguardAccessFlags negatedClassAccessFlags,
       boolean classTypeNegated,
       ProguardClassType classType,
       ProguardClassNameList classNames,
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardClassSpecification.java b/src/main/java/com/android/tools/r8/shaking/ProguardClassSpecification.java
index b8006d3..8e981a7 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardClassSpecification.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardClassSpecification.java
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.shaking;
 
-import com.android.tools.r8.graph.DexAccessFlags;
 import com.android.tools.r8.utils.StringUtils;
 import java.util.Collections;
 import java.util.LinkedHashSet;
@@ -15,8 +14,8 @@
   public static class Builder {
 
     protected ProguardTypeMatcher classAnnotation;
-    protected DexAccessFlags classAccessFlags = new DexAccessFlags(0);
-    protected DexAccessFlags negatedClassAccessFlags = new DexAccessFlags(0);
+    protected ProguardAccessFlags classAccessFlags = new ProguardAccessFlags();
+    protected ProguardAccessFlags negatedClassAccessFlags = new ProguardAccessFlags();
     protected boolean classTypeNegated = false;
     protected ProguardClassType classType;
     protected ProguardClassNameList classNames;
@@ -88,19 +87,19 @@
       this.classTypeNegated = classTypeNegated;
     }
 
-    public DexAccessFlags getClassAccessFlags() {
+    public ProguardAccessFlags getClassAccessFlags() {
       return classAccessFlags;
     }
 
-    public void setClassAccessFlags(DexAccessFlags flags) {
+    public void setClassAccessFlags(ProguardAccessFlags flags) {
       classAccessFlags = flags;
     }
 
-    public DexAccessFlags getNegatedClassAccessFlags() {
+    public ProguardAccessFlags getNegatedClassAccessFlags() {
       return negatedClassAccessFlags;
     }
 
-    public void setNegatedClassAccessFlags(DexAccessFlags flags) {
+    public void setNegatedClassAccessFlags(ProguardAccessFlags flags) {
       negatedClassAccessFlags = flags;
     }
 
@@ -119,8 +118,8 @@
   }
 
   private final ProguardTypeMatcher classAnnotation;
-  private final DexAccessFlags classAccessFlags;
-  private final DexAccessFlags negatedClassAccessFlags;
+  private final ProguardAccessFlags classAccessFlags;
+  private final ProguardAccessFlags negatedClassAccessFlags;
   private final boolean classTypeNegated;
   private final ProguardClassType classType;
   private final ProguardClassNameList classNames;
@@ -131,8 +130,8 @@
 
   protected ProguardClassSpecification(
       ProguardTypeMatcher classAnnotation,
-      DexAccessFlags classAccessFlags,
-      DexAccessFlags negatedClassAccessFlags,
+      ProguardAccessFlags classAccessFlags,
+      ProguardAccessFlags negatedClassAccessFlags,
       boolean classTypeNegated,
       ProguardClassType classType,
       ProguardClassNameList classNames,
@@ -184,11 +183,11 @@
     return classTypeNegated;
   }
 
-  public DexAccessFlags getClassAccessFlags() {
+  public ProguardAccessFlags getClassAccessFlags() {
     return classAccessFlags;
   }
 
-  public DexAccessFlags getNegatedClassAccessFlags() {
+  public ProguardAccessFlags getNegatedClassAccessFlags() {
     return negatedClassAccessFlags;
   }
 
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
index d24a357..7997b44 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
@@ -6,7 +6,6 @@
 import com.android.tools.r8.CompilationException;
 import com.android.tools.r8.DiagnosticsHandler;
 import com.android.tools.r8.dex.Constants;
-import com.android.tools.r8.graph.DexAccessFlags;
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexString;
@@ -561,9 +560,10 @@
           assert builder.getClassAnnotation() == null;
           builder.setClassAnnotation(annotation);
         } else {
-          DexAccessFlags flags =
-              parseNegation() ? builder.getNegatedClassAccessFlags() :
-                  builder.getClassAccessFlags();
+          ProguardAccessFlags flags =
+              parseNegation()
+                  ? builder.getNegatedClassAccessFlags()
+                  : builder.getClassAccessFlags();
           skipWhitespace();
           if (acceptString("public")) {
             flags.setPublic();
@@ -636,7 +636,7 @@
       boolean found = true;
       while (found && !eof()) {
         found = false;
-        DexAccessFlags flags =
+        ProguardAccessFlags flags =
             parseNegation() ? ruleBuilder.getNegatedAccessFlags() : ruleBuilder.getAccessFlags();
         skipWhitespace();
         switch (peekChar()) {
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationRule.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationRule.java
index 1021f67..223307c 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationRule.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationRule.java
@@ -3,15 +3,14 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.shaking;
 
-import com.android.tools.r8.graph.DexAccessFlags;
 import com.android.tools.r8.utils.StringUtils;
 import java.util.Set;
 
 public abstract class ProguardConfigurationRule extends ProguardClassSpecification {
   ProguardConfigurationRule(
       ProguardTypeMatcher classAnnotation,
-      DexAccessFlags classAccessFlags,
-      DexAccessFlags negatedClassAccessFlags,
+      ProguardAccessFlags classAccessFlags,
+      ProguardAccessFlags negatedClassAccessFlags,
       boolean classTypeNegated,
       ProguardClassType classType,
       ProguardClassNameList classNames,
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardIdentifierNameStringRule.java b/src/main/java/com/android/tools/r8/shaking/ProguardIdentifierNameStringRule.java
index 6cfd154..e006bd4 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardIdentifierNameStringRule.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardIdentifierNameStringRule.java
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.shaking;
 
-import com.android.tools.r8.graph.DexAccessFlags;
 import java.util.Set;
 
 public class ProguardIdentifierNameStringRule extends ProguardConfigurationRule {
@@ -21,8 +20,8 @@
 
   private ProguardIdentifierNameStringRule(
       ProguardTypeMatcher classAnnotation,
-      DexAccessFlags classAccessFlags,
-      DexAccessFlags negatedClassAccessFlags,
+      ProguardAccessFlags classAccessFlags,
+      ProguardAccessFlags negatedClassAccessFlags,
       boolean classTypeNegated,
       ProguardClassType classType,
       ProguardClassNameList classNames,
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardKeepPackageNamesRule.java b/src/main/java/com/android/tools/r8/shaking/ProguardKeepPackageNamesRule.java
index f6db326..c4731c6 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardKeepPackageNamesRule.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardKeepPackageNamesRule.java
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.shaking;
 
-import com.android.tools.r8.graph.DexAccessFlags;
 import java.util.Set;
 
 public class ProguardKeepPackageNamesRule extends ProguardConfigurationRule {
@@ -22,8 +21,8 @@
 
   private ProguardKeepPackageNamesRule(
       ProguardTypeMatcher classAnnotation,
-      DexAccessFlags classAccessFlags,
-      DexAccessFlags negatedClassAccessFlags,
+      ProguardAccessFlags classAccessFlags,
+      ProguardAccessFlags negatedClassAccessFlags,
       boolean classTypeNegated,
       ProguardClassType classType,
       ProguardClassNameList classNames,
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardKeepRule.java b/src/main/java/com/android/tools/r8/shaking/ProguardKeepRule.java
index 59acd46..7edceed 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardKeepRule.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardKeepRule.java
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.shaking;
 
-import com.android.tools.r8.graph.DexAccessFlags;
 import java.util.Set;
 
 public class ProguardKeepRule extends ProguardConfigurationRule {
@@ -36,8 +35,8 @@
 
   private ProguardKeepRule(
       ProguardTypeMatcher classAnnotation,
-      DexAccessFlags classAccessFlags,
-      DexAccessFlags negatedClassAccessFlags,
+      ProguardAccessFlags classAccessFlags,
+      ProguardAccessFlags negatedClassAccessFlags,
       boolean classTypeNegated,
       ProguardClassType classType,
       ProguardClassNameList classNames,
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardMemberRule.java b/src/main/java/com/android/tools/r8/shaking/ProguardMemberRule.java
index 121641b..5fb5cb2 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardMemberRule.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardMemberRule.java
@@ -4,7 +4,6 @@
 package com.android.tools.r8.shaking;
 
 import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.DexAccessFlags;
 import com.android.tools.r8.graph.DexEncodedField;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexType;
@@ -17,8 +16,8 @@
   public static class Builder {
 
     private ProguardTypeMatcher annotation;
-    private DexAccessFlags accessFlags = new DexAccessFlags(0);
-    private DexAccessFlags negatedAccessFlags = new DexAccessFlags(0);
+    private ProguardAccessFlags accessFlags = new ProguardAccessFlags();
+    private ProguardAccessFlags negatedAccessFlags = new ProguardAccessFlags();
     private ProguardMemberType ruleType;
     private ProguardNameMatcher name;
     private ProguardTypeMatcher type;
@@ -31,19 +30,19 @@
       this.annotation = annotation;
     }
 
-    public DexAccessFlags getAccessFlags() {
+    public ProguardAccessFlags getAccessFlags() {
       return accessFlags;
     }
 
-    public void setAccessFlags(DexAccessFlags flags) {
+    public void setAccessFlags(ProguardAccessFlags flags) {
       accessFlags = flags;
     }
 
-    public DexAccessFlags getNegatedAccessFlags() {
+    public ProguardAccessFlags getNegatedAccessFlags() {
       return negatedAccessFlags;
     }
 
-    public void setNegatedAccessFlags(DexAccessFlags flags) {
+    public void setNegatedAccessFlags(ProguardAccessFlags flags) {
       negatedAccessFlags = flags;
     }
 
@@ -83,8 +82,8 @@
   }
 
   private final ProguardTypeMatcher annotation;
-  private final DexAccessFlags accessFlags;
-  private final DexAccessFlags negatedAccessFlags;
+  private final ProguardAccessFlags accessFlags;
+  private final ProguardAccessFlags negatedAccessFlags;
   private final ProguardMemberType ruleType;
   private final ProguardNameMatcher name;
   private final ProguardTypeMatcher type;
@@ -93,8 +92,8 @@
 
   private ProguardMemberRule(
       ProguardTypeMatcher annotation,
-      DexAccessFlags accessFlags,
-      DexAccessFlags negatedAccessFlags,
+      ProguardAccessFlags accessFlags,
+      ProguardAccessFlags negatedAccessFlags,
       ProguardMemberType ruleType,
       ProguardNameMatcher name,
       ProguardTypeMatcher type,
@@ -121,11 +120,11 @@
     return annotation;
   }
 
-  public DexAccessFlags getAccessFlags() {
+  public ProguardAccessFlags getAccessFlags() {
     return accessFlags;
   }
 
-  public DexAccessFlags getNegatedAccessFlags() {
+  public ProguardAccessFlags getNegatedAccessFlags() {
     return negatedAccessFlags;
   }
 
@@ -162,8 +161,8 @@
       case ALL:
       case ALL_FIELDS:
         // Access flags check.
-        if (!field.accessFlags.containsAllOf(getAccessFlags()) ||
-            !field.accessFlags.containsNoneOf(getNegatedAccessFlags())) {
+        if (!getAccessFlags().containsAll(field.accessFlags)
+            || !getNegatedAccessFlags().containsNone(field.accessFlags)) {
           break;
         }
         // Annotations check.
@@ -175,8 +174,8 @@
           break;
         }
         // Access flags check.
-        if (!(field.accessFlags.containsAllOf(getAccessFlags()) &&
-            field.accessFlags.containsNoneOf(getNegatedAccessFlags()))) {
+        if (!getAccessFlags().containsAll(field.accessFlags)
+            || !getNegatedAccessFlags().containsNone(field.accessFlags)) {
           break;
         }
         // Type check.
@@ -206,8 +205,8 @@
         // Fall through for all other methods.
       case ALL:
         // Access flags check.
-        if (!method.accessFlags.containsAllOf(getAccessFlags()) ||
-            !method.accessFlags.containsNoneOf(getNegatedAccessFlags())) {
+        if (!getAccessFlags().containsAll(method.accessFlags)
+            || !getNegatedAccessFlags().containsNone(method.accessFlags)) {
           break;
         }
         // Annotations check.
@@ -226,8 +225,8 @@
           break;
         }
         // Access flags check.
-        if (!(method.accessFlags.containsAllOf(getAccessFlags()) &&
-            method.accessFlags.containsNoneOf(getNegatedAccessFlags()))) {
+        if (!getAccessFlags().containsAll(method.accessFlags)
+            || !getNegatedAccessFlags().containsNone(method.accessFlags)) {
           break;
         }
         // Annotations check.
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardWhyAreYouKeepingRule.java b/src/main/java/com/android/tools/r8/shaking/ProguardWhyAreYouKeepingRule.java
index e029b77..ef83926 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardWhyAreYouKeepingRule.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardWhyAreYouKeepingRule.java
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.shaking;
 
-import com.android.tools.r8.graph.DexAccessFlags;
 import java.util.Set;
 
 public class ProguardWhyAreYouKeepingRule extends ProguardConfigurationRule {
@@ -22,8 +21,8 @@
 
   private ProguardWhyAreYouKeepingRule(
       ProguardTypeMatcher classAnnotation,
-      DexAccessFlags classAccessFlags,
-      DexAccessFlags negatedClassAccessFlags,
+      ProguardAccessFlags classAccessFlags,
+      ProguardAccessFlags negatedClassAccessFlags,
       boolean classTypeNegated,
       ProguardClassType classType,
       ProguardClassNameList classNames,
diff --git a/src/main/java/com/android/tools/r8/shaking/ReasonPrinter.java b/src/main/java/com/android/tools/r8/shaking/ReasonPrinter.java
index 47893e5..604cf51 100644
--- a/src/main/java/com/android/tools/r8/shaking/ReasonPrinter.java
+++ b/src/main/java/com/android/tools/r8/shaking/ReasonPrinter.java
@@ -112,11 +112,7 @@
   private void printReasonFor(DexEncodedField item) {
     KeepReason reason = liveFields.get(item);
     if (reason == null) {
-      if (item.accessFlags.isAbstract()) {
-        printOnlyAbstractShell(item, formatter);
-      } else {
-        printNoIdeaWhy(item.field, formatter);
-      }
+      printNoIdeaWhy(item.field, formatter);
     } else {
       formatter.startItem(item.field);
       formatter.pushIsLivePrefix();
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 177493a..bb8c08a 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
@@ -117,10 +117,10 @@
 
   // Process a class with the keep rule.
   private void process(DexClass clazz, ProguardConfigurationRule rule) {
-    if (!clazz.accessFlags.containsAllOf(rule.getClassAccessFlags())) {
+    if (!rule.getClassAccessFlags().containsAll(clazz.accessFlags)) {
       return;
     }
-    if (!clazz.accessFlags.containsNoneOf(rule.getNegatedClassAccessFlags())) {
+    if (!rule.getNegatedClassAccessFlags().containsNone(clazz.accessFlags)) {
       return;
     }
     if (!containsAnnotation(rule.getClassAnnotation(), clazz.annotations)) {
diff --git a/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java b/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java
index 98f1071..e3e9ea0 100644
--- a/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java
+++ b/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java
@@ -12,12 +12,12 @@
 import com.android.tools.r8.code.IfNez;
 import com.android.tools.r8.code.Instruction;
 import com.android.tools.r8.code.ReturnVoid;
-import com.android.tools.r8.graph.DexAccessFlags;
 import com.android.tools.r8.graph.DexCode;
 import com.android.tools.r8.graph.DexCode.Try;
 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.MethodAccessFlags;
 import com.android.tools.r8.naming.NamingLens;
 import java.util.ArrayList;
 import java.util.List;
@@ -99,8 +99,7 @@
         null,
         null,
         null);
-    DexAccessFlags flags = new DexAccessFlags(0);
-    flags.setPublic();
+    MethodAccessFlags flags = MethodAccessFlags.fromSharedAccessFlags(Constants.ACC_PUBLIC, false);
     DexEncodedMethod method = new DexEncodedMethod(null, flags, null, null, code);
     new JumboStringRewriter(method, string, factory).rewrite();
     return method.getCode().asDexCode();
diff --git a/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java b/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java
index add8637..e0d97b1 100644
--- a/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java
+++ b/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java
@@ -8,7 +8,7 @@
 import com.android.tools.r8.code.ReturnVoid;
 import com.android.tools.r8.errors.DexOverflowException;
 import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.DexAccessFlags;
+import com.android.tools.r8.graph.ClassAccessFlags;
 import com.android.tools.r8.graph.DexAnnotationSet;
 import com.android.tools.r8.graph.DexAnnotationSetRefList;
 import com.android.tools.r8.graph.DexApplication;
@@ -23,6 +23,7 @@
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.DexTypeList;
 import com.android.tools.r8.graph.DirectMappedDexApplication;
+import com.android.tools.r8.graph.MethodAccessFlags;
 import com.android.tools.r8.naming.NamingLens;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.IgnoreContentsOutputSink;
@@ -72,10 +73,13 @@
     instructions[stringCount] = new ReturnVoid();
     DexCode code = new DexCode(1, 0, 0, instructions, new Try[0], new TryHandler[0], null,
         strings[startOffset + stringCount - 1]);
-    return new DexEncodedMethod(dexItemFactory
-        .createMethod(holder, dexItemFactory.createProto(dexItemFactory.voidType), "theMethod"),
-        new DexAccessFlags(Constants.ACC_PUBLIC), DexAnnotationSet.empty(),
-        DexAnnotationSetRefList.empty(), code);
+    return new DexEncodedMethod(
+        dexItemFactory.createMethod(
+            holder, dexItemFactory.createProto(dexItemFactory.voidType), "theMethod"),
+        MethodAccessFlags.fromSharedAccessFlags(Constants.ACC_PUBLIC, false),
+        DexAnnotationSet.empty(),
+        DexAnnotationSetRefList.empty(),
+        code);
   }
 
   private DexProgramClass makeClass(String name, int stringCount, int startOffset,
@@ -86,7 +90,7 @@
         type,
         null,
         null,
-        new DexAccessFlags(Constants.ACC_PUBLIC),
+        ClassAccessFlags.fromSharedAccessFlags(Constants.ACC_PUBLIC),
         dexItemFactory.objectType,
         DexTypeList.empty(),
         null,
@@ -94,7 +98,7 @@
         DexEncodedField.EMPTY_ARRAY,
         DexEncodedField.EMPTY_ARRAY,
         DexEncodedMethod.EMPTY_ARRAY,
-        new DexEncodedMethod[]{makeMethod(type, stringCount, startOffset)},
+        new DexEncodedMethod[] {makeMethod(type, stringCount, startOffset)},
         synthesizedFrom);
   }
 
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
index a358e26..2929996 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
@@ -21,10 +21,9 @@
 import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.errors.DexOverflowException;
 import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
+import com.android.tools.r8.graph.ClassAccessFlags;
 import com.android.tools.r8.graph.Code;
 import com.android.tools.r8.graph.DebugLocalInfo;
-import com.android.tools.r8.graph.DexAccessFlags;
 import com.android.tools.r8.graph.DexAnnotationSet;
 import com.android.tools.r8.graph.DexAnnotationSetRefList;
 import com.android.tools.r8.graph.DexApplication;
@@ -36,6 +35,7 @@
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.DexTypeList;
 import com.android.tools.r8.graph.DirectMappedDexApplication;
+import com.android.tools.r8.graph.MethodAccessFlags;
 import com.android.tools.r8.ir.code.CatchHandlers;
 import com.android.tools.r8.ir.code.IRCode;
 import com.android.tools.r8.ir.code.Position;
@@ -577,7 +577,7 @@
       DexType type = factory.createType(desc);
       DexEncodedMethod[] directMethods = new DexEncodedMethod[methodCount];
       for (int i = 0; i < methodCount; i++) {
-        DexAccessFlags access = new DexAccessFlags();
+        MethodAccessFlags access = MethodAccessFlags.fromSharedAccessFlags(0, false);
         access.setPublic();
         access.setStatic();
         Code code = new SynthesizedCode(new ReturnVoidCode());
@@ -602,7 +602,7 @@
               type,
               null,
               null,
-              new DexAccessFlags(),
+              ClassAccessFlags.fromSharedAccessFlags(0),
               factory.objectType,
               DexTypeList.empty(),
               null,
diff --git a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
index 6dc19aa..d119423 100644
--- a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
@@ -14,8 +14,10 @@
 import com.android.tools.r8.DiagnosticsHandler;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.graph.DexAccessFlags;
+import com.android.tools.r8.graph.ClassAccessFlags;
 import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.FieldAccessFlags;
+import com.android.tools.r8.graph.MethodAccessFlags;
 import com.android.tools.r8.utils.DefaultDiagnosticsHandler;
 import com.android.tools.r8.utils.FileUtils;
 import com.android.tools.r8.utils.InternalOptions.PackageObfuscationMode;
@@ -224,33 +226,39 @@
     List<ProguardConfigurationRule> rules = parser.getConfig().getRules();
     assertEquals(1, rules.size());
     ProguardConfigurationRule rule = rules.get(0);
-    DexAccessFlags publicAndFinalFlags = new DexAccessFlags(0);
+    ClassAccessFlags publicAndFinalFlags = ClassAccessFlags.fromSharedAccessFlags(0);
     publicAndFinalFlags.setPublic();
     publicAndFinalFlags.setFinal();
-    assertTrue(rule.getClassAccessFlags().containsNoneOf(publicAndFinalFlags));
-    assertTrue(rule.getNegatedClassAccessFlags().containsAllOf(publicAndFinalFlags));
-    DexAccessFlags abstractFlags = new DexAccessFlags(0);
+    assertTrue(rule.getClassAccessFlags().containsNone(publicAndFinalFlags));
+    assertTrue(rule.getNegatedClassAccessFlags().containsAll(publicAndFinalFlags));
+    ClassAccessFlags abstractFlags = ClassAccessFlags.fromSharedAccessFlags(0);
     abstractFlags.setAbstract();
-    assertTrue(rule.getClassAccessFlags().containsAllOf(abstractFlags));
-    assertTrue(rule.getNegatedClassAccessFlags().containsNoneOf(abstractFlags));
+    assertTrue(rule.getClassAccessFlags().containsAll(abstractFlags));
+    assertTrue(rule.getNegatedClassAccessFlags().containsNone(abstractFlags));
     for (ProguardMemberRule member : rule.getMemberRules()) {
       if (member.getRuleType() == ProguardMemberType.ALL_FIELDS) {
-        DexAccessFlags publicFlags = new DexAccessFlags(0);
-        publicAndFinalFlags.setPublic();
-        assertTrue(member.getAccessFlags().containsAllOf(publicFlags));
-        assertTrue(member.getNegatedAccessFlags().containsNoneOf(publicFlags));
-        DexAccessFlags staticFlags = new DexAccessFlags(0);
+        FieldAccessFlags publicFlags = FieldAccessFlags.fromSharedAccessFlags(0);
+        publicFlags.setPublic();
+        assertTrue(member.getAccessFlags().containsAll(publicFlags));
+        assertTrue(member.getNegatedAccessFlags().containsNone(publicFlags));
+        FieldAccessFlags staticFlags = FieldAccessFlags.fromSharedAccessFlags(0);
         staticFlags.setStatic();
-        assertTrue(member.getAccessFlags().containsNoneOf(staticFlags));
-        assertTrue(member.getNegatedAccessFlags().containsAllOf(staticFlags));
+        assertTrue(member.getAccessFlags().containsNone(staticFlags));
+        assertTrue(member.getNegatedAccessFlags().containsAll(staticFlags));
       } else {
         assertTrue(member.getRuleType() == ProguardMemberType.ALL_METHODS);
-        DexAccessFlags publicProtectedVolatileFlags = new DexAccessFlags(0);
-        publicProtectedVolatileFlags.setPublic();
-        publicProtectedVolatileFlags.setProtected();
-        publicProtectedVolatileFlags.setVolatile();
-        assertTrue(member.getAccessFlags().containsNoneOf(publicProtectedVolatileFlags));
-        assertTrue(member.getNegatedAccessFlags().containsAllOf(publicProtectedVolatileFlags));
+
+        MethodAccessFlags publicNativeFlags = MethodAccessFlags.fromSharedAccessFlags(0, false);
+        publicNativeFlags.setPublic();
+        publicNativeFlags.setNative();
+        assertTrue(member.getAccessFlags().containsAll(publicNativeFlags));
+        assertFalse(member.getNegatedAccessFlags().containsNone(publicNativeFlags));
+
+        MethodAccessFlags protectedNativeFlags = MethodAccessFlags.fromSharedAccessFlags(0, false);
+        protectedNativeFlags.setProtected();
+        protectedNativeFlags.setNative();
+        assertTrue(member.getAccessFlags().containsAll(protectedNativeFlags));
+        assertFalse(member.getNegatedAccessFlags().containsNone(protectedNativeFlags));
       }
     }
   }
diff --git a/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java b/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java
index b285ac0..32cfb14 100644
--- a/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java
@@ -9,8 +9,6 @@
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.ArtCommandBuilder;
-import com.android.tools.r8.dex.Constants;
-import com.android.tools.r8.graph.DexAccessFlags;
 import com.android.tools.r8.naming.MemberNaming.FieldSignature;
 import com.android.tools.r8.naming.MemberNaming.MethodSignature;
 import com.android.tools.r8.utils.AndroidApp;
@@ -196,14 +194,13 @@
 
   private static void hasNoPrivateMethods(DexInspector inspector) {
     inspector.forAllClasses(clazz -> clazz.forAllMethods(
-        method -> Assert.assertTrue(method.hasNone(new DexAccessFlags(Constants.ACC_PRIVATE)))
-    ));
+        method -> Assert.assertTrue(!method.getMethod().accessFlags.isPrivate())));
   }
 
   private static void hasNoPublicMethodsButPrivate(DexInspector inspector) {
     inspector.forAllClasses(clazz -> clazz.forAllMethods(method -> {
       if (!method.isStatic() && !method.isFinal()) {
-        Assert.assertTrue(method.hasNone(new DexAccessFlags(Constants.ACC_PUBLIC)));
+        Assert.assertTrue(!method.getMethod().accessFlags.isPublic());
       }
     }));
     Assert.assertTrue(inspector.clazz("shaking6.Superclass")
@@ -255,7 +252,7 @@
   private static void shaking7HasOnlyPublicFields(DexInspector inspector) {
     inspector.forAllClasses(clazz -> {
       clazz.forAllFields(field -> {
-        Assert.assertTrue(field.hasAll(new DexAccessFlags(Constants.ACC_PUBLIC)));
+        Assert.assertTrue(field.getField().accessFlags.isPublic());
       });
     });
     ClassSubject subclass = inspector.clazz("shaking7.Subclass");
@@ -283,7 +280,7 @@
   private static void shaking7HasOnlyPublicFieldsNamedTheDoubleField(DexInspector inspector) {
     inspector.forAllClasses(clazz -> {
       clazz.forAllFields(field -> {
-        Assert.assertTrue(field.hasAll(new DexAccessFlags(Constants.ACC_PUBLIC)));
+        Assert.assertTrue(field.getField().accessFlags.isPublic());
       });
     });
     ClassSubject subclass = inspector.clazz("shaking7.Subclass");
@@ -297,7 +294,7 @@
   private static void shaking7HasOnlyPublicFieldsNamedTheIntField(DexInspector inspector) {
     inspector.forAllClasses(clazz -> {
       clazz.forAllFields(field -> {
-        Assert.assertTrue(field.hasAll(new DexAccessFlags(Constants.ACC_PUBLIC)));
+        Assert.assertTrue(field.getField().accessFlags.isPublic());
       });
     });
     ClassSubject subclass = inspector.clazz("shaking7.Subclass");
diff --git a/src/test/java/com/android/tools/r8/utils/DexInspector.java b/src/test/java/com/android/tools/r8/utils/DexInspector.java
index 612043e..e70f6f7 100644
--- a/src/test/java/com/android/tools/r8/utils/DexInspector.java
+++ b/src/test/java/com/android/tools/r8/utils/DexInspector.java
@@ -43,7 +43,6 @@
 import com.android.tools.r8.code.SputShort;
 import com.android.tools.r8.code.SputWide;
 import com.android.tools.r8.dex.ApplicationReader;
-import com.android.tools.r8.graph.DexAccessFlags;
 import com.android.tools.r8.graph.DexAnnotation;
 import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.graph.DexClass;
@@ -503,10 +502,6 @@
 
   public abstract class MemberSubject extends Subject {
 
-    public abstract boolean hasAll(DexAccessFlags flags);
-
-    public abstract boolean hasNone(DexAccessFlags flags);
-
     public abstract boolean isStatic();
 
     public abstract boolean isFinal();
@@ -551,16 +546,6 @@
     }
 
     @Override
-    public boolean hasAll(DexAccessFlags flags) {
-      return false;
-    }
-
-    @Override
-    public boolean hasNone(DexAccessFlags flags) {
-      return true;
-    }
-
-    @Override
     public boolean isStatic() {
       return false;
     }
@@ -622,16 +607,6 @@
     }
 
     @Override
-    public boolean hasAll(DexAccessFlags flags) {
-      return dexMethod.accessFlags.containsAllOf(flags);
-    }
-
-    @Override
-    public boolean hasNone(DexAccessFlags flags) {
-      return dexMethod.accessFlags.containsNoneOf(flags);
-    }
-
-    @Override
     public boolean isStatic() {
       return dexMethod.accessFlags.isStatic();
     }
@@ -704,16 +679,6 @@
   public class AbsentFieldSubject extends FieldSubject {
 
     @Override
-    public boolean hasAll(DexAccessFlags flags) {
-      return false;
-    }
-
-    @Override
-    public boolean hasNone(DexAccessFlags flags) {
-      return true;
-    }
-
-    @Override
     public boolean isStatic() {
       return false;
     }
@@ -770,16 +735,6 @@
     }
 
     @Override
-    public boolean hasAll(DexAccessFlags flags) {
-      return dexField.accessFlags.containsAllOf(flags);
-    }
-
-    @Override
-    public boolean hasNone(DexAccessFlags flags) {
-      return dexField.accessFlags.containsNoneOf(flags);
-    }
-
-    @Override
     public boolean isStatic() {
       return dexField.accessFlags.isStatic();
     }
diff --git a/src/test/proguard/valid/access-flags.flags b/src/test/proguard/valid/access-flags.flags
index 8096b59..8d47c33 100644
--- a/src/test/proguard/valid/access-flags.flags
+++ b/src/test/proguard/valid/access-flags.flags
@@ -1,4 +1,4 @@
 -keep !public abstract !final @com.company.Something class * {
   public !static <fields>;
-  !public !protected ! volatile <methods>;
+  !public !protected ! native <methods>;
 }
\ No newline at end of file