ClassReader.java revision 3348:080e6e093a70
11592Srgrimes/*
21592Srgrimes * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
31592Srgrimes * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
41592Srgrimes *
51592Srgrimes * This code is free software; you can redistribute it and/or modify it
61592Srgrimes * under the terms of the GNU General Public License version 2 only, as
71592Srgrimes * published by the Free Software Foundation.  Oracle designates this
81592Srgrimes * particular file as subject to the "Classpath" exception as provided
91592Srgrimes * by Oracle in the LICENSE file that accompanied this code.
101592Srgrimes *
111592Srgrimes * This code is distributed in the hope that it will be useful, but WITHOUT
121592Srgrimes * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
131592Srgrimes * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
141592Srgrimes * version 2 for more details (a copy is included in the LICENSE file that
151592Srgrimes * accompanied this code).
161592Srgrimes *
171592Srgrimes * You should have received a copy of the GNU General Public License version
181592Srgrimes * 2 along with this work; if not, write to the Free Software Foundation,
191592Srgrimes * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
201592Srgrimes *
211592Srgrimes * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
221592Srgrimes * or visit www.oracle.com if you need additional information or have any
231592Srgrimes * questions.
241592Srgrimes */
251592Srgrimes
261592Srgrimespackage com.sun.tools.javac.jvm;
271592Srgrimes
281592Srgrimesimport java.io.*;
291592Srgrimesimport java.net.URI;
301592Srgrimesimport java.net.URISyntaxException;
311592Srgrimesimport java.nio.CharBuffer;
321592Srgrimesimport java.util.Arrays;
331592Srgrimesimport java.util.EnumSet;
341592Srgrimesimport java.util.HashMap;
3529917Smarkmimport java.util.HashSet;
361592Srgrimesimport java.util.Map;
371592Srgrimesimport java.util.Set;
381592Srgrimes
391592Srgrimesimport javax.lang.model.element.Modifier;
401592Srgrimesimport javax.lang.model.element.NestingKind;
4131490Scharnierimport javax.tools.JavaFileManager;
4229917Smarkmimport javax.tools.JavaFileObject;
4331490Scharnier
4431490Scharnierimport com.sun.tools.javac.comp.Annotate;
4550476Speterimport com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter;
461592Srgrimesimport com.sun.tools.javac.code.*;
471592Srgrimesimport com.sun.tools.javac.code.Directive.*;
481592Srgrimesimport com.sun.tools.javac.code.Lint.LintCategory;
491592Srgrimesimport com.sun.tools.javac.code.Scope.WriteableScope;
501592Srgrimesimport com.sun.tools.javac.code.Symbol.*;
511592Srgrimesimport com.sun.tools.javac.code.Symtab;
521592Srgrimesimport com.sun.tools.javac.code.Type.*;
531592Srgrimesimport com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
541592Srgrimesimport com.sun.tools.javac.file.BaseFileManager;
551592Srgrimesimport com.sun.tools.javac.file.PathFileObject;
561592Srgrimesimport com.sun.tools.javac.jvm.ClassFile.NameAndType;
571592Srgrimesimport com.sun.tools.javac.jvm.ClassFile.Version;
581592Srgrimesimport com.sun.tools.javac.util.*;
591592Srgrimesimport com.sun.tools.javac.util.DefinedBy.Api;
601592Srgrimesimport com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
6122454Simp
621592Srgrimesimport static com.sun.tools.javac.code.Flags.*;
6322454Simpimport static com.sun.tools.javac.code.Kinds.Kind.*;
6441445Sdgimport static com.sun.tools.javac.code.TypeTag.ARRAY;
651592Srgrimesimport static com.sun.tools.javac.code.TypeTag.CLASS;
661592Srgrimesimport static com.sun.tools.javac.code.TypeTag.TYPEVAR;
671592Srgrimesimport static com.sun.tools.javac.jvm.ClassFile.*;
681592Srgrimesimport static com.sun.tools.javac.jvm.ClassFile.Version.*;
691592Srgrimes
7045393Sbrianimport static com.sun.tools.javac.main.Option.*;
711592Srgrimes
721592Srgrimes/** This class provides operations to read a classfile into an internal
731592Srgrimes *  representation. The internal representation is anchored in a
741592Srgrimes *  ClassSymbol which contains in its scope symbol representations
751592Srgrimes *  for all other definitions in the classfile. Top-level Classes themselves
761592Srgrimes *  appear as members of the scopes of PackageSymbols.
771592Srgrimes *
781592Srgrimes *  <p><b>This is NOT part of any supported API.
7925099Sdavidn *  If you write code that depends on this, you do so at your own risk.
8025099Sdavidn *  This code and its internal interfaces are subject to change or
8125099Sdavidn *  deletion without notice.</b>
821592Srgrimes */
8356590Sshinpublic class ClassReader {
8456590Sshin    /** The context key for the class reader. */
8556590Sshin    protected static final Context.Key<ClassReader> classReaderKey = new Context.Key<>();
8656590Sshin
8756590Sshin    public static final int INITIAL_BUFFER_SIZE = 0x0fff0;
881592Srgrimes
891592Srgrimes    private final Annotate annotate;
901592Srgrimes
9141445Sdg    /** Switch: verbose output.
9251433Smarkm     */
9351433Smarkm    boolean verbose;
9451433Smarkm
951592Srgrimes    /** Switch: read constant pool and code sections. This switch is initially
9656590Sshin     *  set to false but can be turned on from outside.
9756590Sshin     */
9856590Sshin    public boolean readAllOfClassFile = false;
9956590Sshin
10056590Sshin    /** Switch: allow simplified varargs.
10156590Sshin     */
10256590Sshin    boolean allowSimplifiedVarargs;
10356590Sshin
10456590Sshin    /** Switch: allow modules.
10556590Sshin     */
10656590Sshin    boolean allowModules;
10756590Sshin
10856590Sshin   /** Lint option: warn about classfile issues
10956590Sshin     */
1101592Srgrimes    boolean lintClassfile;
1111592Srgrimes
1121592Srgrimes    /** Switch: preserve parameter names from the variable table.
1131592Srgrimes     */
1141592Srgrimes    public boolean saveParameterNames;
1151592Srgrimes
11651433Smarkm    /**
11751433Smarkm     * The currently selected profile.
1181592Srgrimes     */
1191592Srgrimes    public final Profile profile;
12051433Smarkm
12151433Smarkm    /** The log to use for verbose output
1221592Srgrimes     */
1231592Srgrimes    final Log log;
1241592Srgrimes
1251592Srgrimes    /** The symbol table. */
1261592Srgrimes    Symtab syms;
1271592Srgrimes
1281592Srgrimes    Types types;
1291592Srgrimes
13056590Sshin    /** The name table. */
1311592Srgrimes    final Names names;
1321592Srgrimes
1331592Srgrimes    /** Access to files
1341592Srgrimes     */
13524349Simp    private final JavaFileManager fileManager;
1361592Srgrimes
1371592Srgrimes    /** Factory for diagnostics
13841860Speter     */
1391592Srgrimes    JCDiagnostic.Factory diagFactory;
1401592Srgrimes
1411592Srgrimes    /** The current scope where type variables are entered.
1421592Srgrimes     */
1431592Srgrimes    protected WriteableScope typevars;
1441592Srgrimes
1451592Srgrimes    private List<InterimUsesDirective> interimUses = List.nil();
1461592Srgrimes    private List<InterimProvidesDirective> interimProvides = List.nil();
1471592Srgrimes
1481592Srgrimes    /** The path name of the class file currently being read.
1491592Srgrimes     */
1501592Srgrimes    protected JavaFileObject currentClassFile = null;
15141445Sdg
15241445Sdg    /** The class or method currently being read.
15341445Sdg     */
1541592Srgrimes    protected Symbol currentOwner = null;
1551592Srgrimes
1561592Srgrimes    /** The module containing the class currently being read.
1571592Srgrimes     */
1581592Srgrimes    protected ModuleSymbol currentModule = null;
1591592Srgrimes
1601592Srgrimes    /** The buffer containing the currently read class file.
1611592Srgrimes     */
1621592Srgrimes    byte[] buf = new byte[INITIAL_BUFFER_SIZE];
1631592Srgrimes
1641592Srgrimes    /** The current input pointer.
1651592Srgrimes     */
1661592Srgrimes    protected int bp;
16751433Smarkm
1681592Srgrimes    /** The objects of the constant pool.
1691592Srgrimes     */
1701592Srgrimes    Object[] poolObj;
1711592Srgrimes
1721592Srgrimes    /** For every constant pool entry, an index into buf where the
1731592Srgrimes     *  defining section of the entry is found.
1741592Srgrimes     */
1751592Srgrimes    int[] poolIdx;
17635728Srnordier
1771592Srgrimes    /** The major version number of the class file being read. */
1781592Srgrimes    int majorVersion;
1791592Srgrimes    /** The minor version number of the class file being read. */
1801592Srgrimes    int minorVersion;
1811592Srgrimes
1821592Srgrimes    /** A table to hold the constant pool indices for method parameter
1831592Srgrimes     * names, as given in LocalVariableTable attributes.
1841592Srgrimes     */
1851592Srgrimes    int[] parameterNameIndices;
1861592Srgrimes
18741445Sdg    /**
18841445Sdg     * Whether or not any parameter names have been found.
18941445Sdg     */
19056590Sshin    boolean haveParameterNameIndices;
1911592Srgrimes
19229917Smarkm    /** Set this to false every time we start reading a method
1931592Srgrimes     * and are saving parameter names.  Set it to true when we see
1941592Srgrimes     * MethodParameters, if it's set when we see a LocalVariableTable,
1951592Srgrimes     * then we ignore the parameter names from the LVT.
1961592Srgrimes     */
1971592Srgrimes    boolean sawMethodParameters;
1981592Srgrimes
1991592Srgrimes    /**
2001592Srgrimes     * The set of attribute names for which warnings have been generated for the current class
2011592Srgrimes     */
2021592Srgrimes    Set<Name> warnedAttrs = new HashSet<>();
2031592Srgrimes
2041592Srgrimes    /**
20556590Sshin     * The prototype @Target Attribute.Compound if this class is an annotation annotated with
2061592Srgrimes     * @Target
2071592Srgrimes     */
2081592Srgrimes    CompoundAnnotationProxy target;
2091592Srgrimes
2101592Srgrimes    /**
2111592Srgrimes     * The prototype @Repetable Attribute.Compound if this class is an annotation annotated with
2121592Srgrimes     * @Repeatable
21345393Sbrian     */
2141592Srgrimes    CompoundAnnotationProxy repeatable;
2151592Srgrimes
21656590Sshin    /** Get the ClassReader instance for this invocation. */
21756590Sshin    public static ClassReader instance(Context context) {
21856590Sshin        ClassReader instance = context.get(classReaderKey);
21951433Smarkm        if (instance == null)
22051433Smarkm            instance = new ClassReader(context);
22151433Smarkm        return instance;
22251433Smarkm    }
22351433Smarkm
22425099Sdavidn    /** Construct a new class reader. */
22525099Sdavidn    protected ClassReader(Context context) {
22625099Sdavidn        context.put(classReaderKey, this);
2271592Srgrimes        annotate = Annotate.instance(context);
2281592Srgrimes        names = Names.instance(context);
2291592Srgrimes        syms = Symtab.instance(context);
2301592Srgrimes        types = Types.instance(context);
23156590Sshin        fileManager = context.get(JavaFileManager.class);
23256590Sshin        if (fileManager == null)
23356590Sshin            throw new AssertionError("FileManager initialization error");
23456590Sshin        diagFactory = JCDiagnostic.Factory.instance(context);
23556590Sshin
23656590Sshin        log = Log.instance(context);
23756590Sshin
2381592Srgrimes        Options options = Options.instance(context);
2391592Srgrimes        verbose         = options.isSet(VERBOSE);
24056590Sshin
24156590Sshin        Source source = Source.instance(context);
24256590Sshin        allowSimplifiedVarargs = source.allowSimplifiedVarargs();
24356590Sshin        allowModules     = source.allowModules();
2441592Srgrimes
24556590Sshin        saveParameterNames = options.isSet("save-parameter-names");
24622454Simp
24722454Simp        profile = Profile.instance(context);
2481592Srgrimes
2491592Srgrimes        typevars = WriteableScope.create(syms.noSymbol);
2501592Srgrimes
2511592Srgrimes        lintClassfile = Lint.instance(context).isEnabled(LintCategory.CLASSFILE);
2521592Srgrimes
2531592Srgrimes        initAttributeReaders();
2541592Srgrimes    }
2551592Srgrimes
25622454Simp    /** Add member to class unless it is synthetic.
25722454Simp     */
25822454Simp    private void enterMember(ClassSymbol c, Symbol sym) {
25922454Simp        // Synthetic members are not entered -- reason lost to history (optimization?).
26031490Scharnier        // Lambda methods must be entered because they may have inner classes (which reference them)
26156590Sshin        if ((sym.flags_field & (SYNTHETIC|BRIDGE)) != SYNTHETIC || sym.name.startsWith(names.lambda))
26222454Simp            c.members_field.enter(sym);
26322454Simp    }
26422454Simp
26522454Simp/************************************************************************
26622454Simp * Error Diagnoses
26722454Simp ***********************************************************************/
2681592Srgrimes
2691592Srgrimes    public ClassFinder.BadClassFile badClassFile(String key, Object... args) {
2701592Srgrimes        return new ClassFinder.BadClassFile (
2711592Srgrimes            currentOwner.enclClass(),
2721592Srgrimes            currentClassFile,
27356590Sshin            diagFactory.fragment(key, args),
27456590Sshin            diagFactory);
27551433Smarkm    }
27651433Smarkm
27756590Sshin    public ClassFinder.BadEnclosingMethodAttr badEnclosingMethod(Object... args) {
27856590Sshin        return new ClassFinder.BadEnclosingMethodAttr (
27951433Smarkm            currentOwner.enclClass(),
28051433Smarkm            currentClassFile,
2811592Srgrimes            diagFactory.fragment("bad.enclosing.method", args),
2821592Srgrimes            diagFactory);
2831592Srgrimes    }
28441860Speter
2851592Srgrimes/************************************************************************
2861592Srgrimes * Buffer Access
2871592Srgrimes ***********************************************************************/
2881592Srgrimes
2891592Srgrimes    /** Read a character.
2901592Srgrimes     */
2911592Srgrimes    char nextChar() {
2921592Srgrimes        return (char)(((buf[bp++] & 0xFF) << 8) + (buf[bp++] & 0xFF));
29341860Speter    }
2941592Srgrimes
2951592Srgrimes    /** Read a byte.
2961592Srgrimes     */
2971592Srgrimes    int nextByte() {
2981592Srgrimes        return buf[bp++] & 0xFF;
2991592Srgrimes    }
3001592Srgrimes
30156590Sshin    /** Read an integer.
3021592Srgrimes     */
3031592Srgrimes    int nextInt() {
3041592Srgrimes        return
3051592Srgrimes            ((buf[bp++] & 0xFF) << 24) +
30651433Smarkm            ((buf[bp++] & 0xFF) << 16) +
30751433Smarkm            ((buf[bp++] & 0xFF) << 8) +
30851433Smarkm            (buf[bp++] & 0xFF);
30951433Smarkm    }
31056590Sshin
31151433Smarkm    /** Extract a character at position bp from buf.
31251433Smarkm     */
31351433Smarkm    char getChar(int bp) {
31456590Sshin        return
31556758Sshin            (char)(((buf[bp] & 0xFF) << 8) + (buf[bp+1] & 0xFF));
3161592Srgrimes    }
3171592Srgrimes
3181592Srgrimes    /** Extract an integer at position bp from buf.
3191592Srgrimes     */
3201592Srgrimes    int getInt(int bp) {
3211592Srgrimes        return
32256590Sshin            ((buf[bp] & 0xFF) << 24) +
32356590Sshin            ((buf[bp+1] & 0xFF) << 16) +
32456590Sshin            ((buf[bp+2] & 0xFF) << 8) +
32545393Sbrian            (buf[bp+3] & 0xFF);
3261592Srgrimes    }
3271592Srgrimes
32856590Sshin
32951433Smarkm    /** Extract a long integer at position bp from buf.
33051433Smarkm     */
33151433Smarkm    long getLong(int bp) {
33251433Smarkm        DataInputStream bufin =
33351433Smarkm            new DataInputStream(new ByteArrayInputStream(buf, bp, 8));
33451433Smarkm        try {
3351592Srgrimes            return bufin.readLong();
3361592Srgrimes        } catch (IOException e) {
33751433Smarkm            throw new AssertionError(e);
33851433Smarkm        }
33951433Smarkm    }
34051433Smarkm
34151433Smarkm    /** Extract a float at position bp from buf.
34251433Smarkm     */
34351433Smarkm    float getFloat(int bp) {
3441592Srgrimes        DataInputStream bufin =
34551433Smarkm            new DataInputStream(new ByteArrayInputStream(buf, bp, 4));
3461592Srgrimes        try {
3471592Srgrimes            return bufin.readFloat();
3481592Srgrimes        } catch (IOException e) {
3491592Srgrimes            throw new AssertionError(e);
3501592Srgrimes        }
3511592Srgrimes    }
3521592Srgrimes
3531592Srgrimes    /** Extract a double at position bp from buf.
35445393Sbrian     */
3551592Srgrimes    double getDouble(int bp) {
3561592Srgrimes        DataInputStream bufin =
3571592Srgrimes            new DataInputStream(new ByteArrayInputStream(buf, bp, 8));
3581592Srgrimes        try {
35925099Sdavidn            return bufin.readDouble();
36025674Sdavidn        } catch (IOException e) {
36125099Sdavidn            throw new AssertionError(e);
3621592Srgrimes        }
36325099Sdavidn    }
36425099Sdavidn
36525099Sdavidn/************************************************************************
36625099Sdavidn * Constant Pool Access
36725099Sdavidn ***********************************************************************/
36845393Sbrian
36925099Sdavidn    /** Index all constant pool entries, writing their start addresses into
37025099Sdavidn     *  poolIdx.
37125099Sdavidn     */
37225099Sdavidn    void indexPool() {
3731592Srgrimes        poolIdx = new int[nextChar()];
3741592Srgrimes        poolObj = new Object[poolIdx.length];
3751592Srgrimes        int i = 1;
3761592Srgrimes        while (i < poolIdx.length) {
37745393Sbrian            poolIdx[i++] = bp;
3781592Srgrimes            byte tag = buf[bp++];
3791592Srgrimes            switch (tag) {
3801592Srgrimes            case CONSTANT_Utf8: case CONSTANT_Unicode: {
38125099Sdavidn                int len = nextChar();
38225099Sdavidn                bp = bp + len;
3831592Srgrimes                break;
3841592Srgrimes            }
38551433Smarkm            case CONSTANT_Class:
38651433Smarkm            case CONSTANT_String:
38751433Smarkm            case CONSTANT_MethodType:
38851433Smarkm                bp = bp + 2;
38951433Smarkm                break;
39051433Smarkm            case CONSTANT_MethodHandle:
3911592Srgrimes                bp = bp + 3;
39251433Smarkm                break;
39351433Smarkm            case CONSTANT_Fieldref:
39451433Smarkm            case CONSTANT_Methodref:
39551433Smarkm            case CONSTANT_InterfaceMethodref:
39651433Smarkm            case CONSTANT_NameandType:
39751433Smarkm            case CONSTANT_Integer:
39851433Smarkm            case CONSTANT_Float:
3991592Srgrimes            case CONSTANT_InvokeDynamic:
4001592Srgrimes                bp = bp + 4;
40110401Smpp                break;
40262643Sbsd            case CONSTANT_Long:
40362643Sbsd            case CONSTANT_Double:
4041592Srgrimes                bp = bp + 8;
4051592Srgrimes                i++;
4061592Srgrimes                break;
40745393Sbrian            default:
4081592Srgrimes                throw badClassFile("bad.const.pool.tag.at",
4091592Srgrimes                                   Byte.toString(tag),
4101592Srgrimes                                   Integer.toString(bp -1));
4111592Srgrimes            }
41245393Sbrian        }
4131592Srgrimes    }
4141592Srgrimes
41527516Swosch    /** Read constant pool entry at start address i, use pool as a cache.
41645393Sbrian     */
4171592Srgrimes    Object readPool(int i) {
4181592Srgrimes        Object result = poolObj[i];
4191592Srgrimes        if (result != null) return result;
4201592Srgrimes
4211592Srgrimes        int index = poolIdx[i];
4221592Srgrimes        if (index == 0) return null;
4231592Srgrimes
42425099Sdavidn        byte tag = buf[index];
42556590Sshin        switch (tag) {
42625099Sdavidn        case CONSTANT_Utf8:
42725099Sdavidn            poolObj[i] = names.fromUtf(buf, index + 3, getChar(index + 1));
42856590Sshin            break;
42925099Sdavidn        case CONSTANT_Unicode:
43025099Sdavidn            throw badClassFile("unicode.str.not.supported");
43125099Sdavidn        case CONSTANT_Class:
43225099Sdavidn            poolObj[i] = readClassOrType(getChar(index + 1));
43325099Sdavidn            break;
43445393Sbrian        case CONSTANT_String:
43525099Sdavidn            // FIXME: (footprint) do not use toString here
43627516Swosch            poolObj[i] = readName(getChar(index + 1)).toString();
43725099Sdavidn            break;
43825099Sdavidn        case CONSTANT_Fieldref: {
43925099Sdavidn            ClassSymbol owner = readClassSymbol(getChar(index + 1));
44025099Sdavidn            NameAndType nt = readNameAndType(getChar(index + 3));
44125099Sdavidn            poolObj[i] = new VarSymbol(0, nt.name, nt.uniqueType.type, owner);
44225099Sdavidn            break;
44325099Sdavidn        }
44425099Sdavidn        case CONSTANT_Methodref:
44512240Speter        case CONSTANT_InterfaceMethodref: {
44612240Speter            ClassSymbol owner = readClassSymbol(getChar(index + 1));
44712240Speter            NameAndType nt = readNameAndType(getChar(index + 3));
44812240Speter            poolObj[i] = new MethodSymbol(0, nt.name, nt.uniqueType.type, owner);
44912240Speter            break;
4501592Srgrimes        }
4511592Srgrimes        case CONSTANT_NameandType:
4521592Srgrimes            poolObj[i] = new NameAndType(
4531592Srgrimes                readName(getChar(index + 1)),
4541592Srgrimes                readType(getChar(index + 3)), types);
4551592Srgrimes            break;
4561592Srgrimes        case CONSTANT_Integer:
4571592Srgrimes            poolObj[i] = getInt(index + 1);
4581592Srgrimes            break;
4591592Srgrimes        case CONSTANT_Float:
4601592Srgrimes            poolObj[i] = Float.valueOf(getFloat(index + 1));
4611592Srgrimes            break;
4621592Srgrimes        case CONSTANT_Long:
4631592Srgrimes            poolObj[i] = Long.valueOf(getLong(index + 1));
4641592Srgrimes            break;
4651592Srgrimes        case CONSTANT_Double:
4661592Srgrimes            poolObj[i] = Double.valueOf(getDouble(index + 1));
4671592Srgrimes            break;
4681592Srgrimes        case CONSTANT_MethodHandle:
4691592Srgrimes            skipBytes(4);
4701592Srgrimes            break;
4711592Srgrimes        case CONSTANT_MethodType:
4721592Srgrimes            skipBytes(3);
4731592Srgrimes            break;
4741592Srgrimes        case CONSTANT_InvokeDynamic:
4751592Srgrimes            skipBytes(5);
4761592Srgrimes            break;
4771592Srgrimes        default:
4781592Srgrimes            throw badClassFile("bad.const.pool.tag", Byte.toString(tag));
4791592Srgrimes        }
4801592Srgrimes        return poolObj[i];
4811592Srgrimes    }
48229917Smarkm
48329917Smarkm    /** Read signature and convert to type.
4841592Srgrimes     */
4851592Srgrimes    Type readType(int i) {
4861592Srgrimes        int index = poolIdx[i];
4871592Srgrimes        return sigToType(buf, index + 3, getChar(index + 1));
4881592Srgrimes    }
4891592Srgrimes
4901592Srgrimes    /** If name is an array type or class signature, return the
4911592Srgrimes     *  corresponding type; otherwise return a ClassSymbol with given name.
4921592Srgrimes     */
4931592Srgrimes    Object readClassOrType(int i) {
4941592Srgrimes        int index =  poolIdx[i];
4951592Srgrimes        int len = getChar(index + 1);
4961592Srgrimes        int start = index + 3;
4971592Srgrimes        Assert.check(buf[start] == '[' || buf[start + len - 1] != ';');
4981592Srgrimes        // by the above assertion, the following test can be
4991592Srgrimes        // simplified to (buf[start] == '[')
5001592Srgrimes        return (buf[start] == '[' || buf[start + len - 1] == ';')
5011592Srgrimes            ? (Object)sigToType(buf, start, len)
5021592Srgrimes            : (Object)enterClass(names.fromUtf(internalize(buf, start,
5031592Srgrimes                                                           len)));
5041592Srgrimes    }
5051592Srgrimes
5061592Srgrimes    /** Read signature and convert to type parameters.
5071592Srgrimes     */
5081592Srgrimes    List<Type> readTypeParams(int i) {
5091592Srgrimes        int index = poolIdx[i];
5101592Srgrimes        return sigToTypeParams(buf, index + 3, getChar(index + 1));
5111592Srgrimes    }
5121592Srgrimes
5131592Srgrimes    /** Read class entry.
5141592Srgrimes     */
5151592Srgrimes    ClassSymbol readClassSymbol(int i) {
5161592Srgrimes        Object obj = readPool(i);
5171592Srgrimes        if (obj != null && !(obj instanceof ClassSymbol))
5181592Srgrimes            throw badClassFile("bad.const.pool.entry",
5191592Srgrimes                               currentClassFile.toString(),
5201592Srgrimes                               "CONSTANT_Class_info", i);
5211592Srgrimes        return (ClassSymbol)obj;
5221592Srgrimes    }
5231592Srgrimes
5241592Srgrimes    Name readClassName(int i) {
5251592Srgrimes        int index = poolIdx[i];
5261592Srgrimes        if (index == 0) return null;
5271592Srgrimes        byte tag = buf[index];
5281592Srgrimes        if (tag != CONSTANT_Class) {
5291592Srgrimes            throw badClassFile("bad.const.pool.entry",
5301592Srgrimes                               currentClassFile.toString(),
5311592Srgrimes                               "CONSTANT_Class_info", i);
5321592Srgrimes        }
53329917Smarkm        int nameIndex =  poolIdx[getChar(index + 1)];
53429917Smarkm        int len = getChar(nameIndex + 1);
5351592Srgrimes        int start = nameIndex + 3;
5361592Srgrimes        if (buf[start] == '[' || buf[start + len - 1] == ';')
5371592Srgrimes            throw badClassFile("wrong class name"); //TODO: proper diagnostics
5381592Srgrimes        return names.fromUtf(internalize(buf, start, len));
5391592Srgrimes    }
5401592Srgrimes
5411592Srgrimes    /** Read name.
5421592Srgrimes     */
5431592Srgrimes    Name readName(int i) {
5441592Srgrimes        Object obj = readPool(i);
5451592Srgrimes        if (obj != null && !(obj instanceof Name))
5461592Srgrimes            throw badClassFile("bad.const.pool.entry",
5471592Srgrimes                               currentClassFile.toString(),
5481592Srgrimes                               "CONSTANT_Utf8_info or CONSTANT_String_info", i);
5491592Srgrimes        return (Name)obj;
5501592Srgrimes    }
5511592Srgrimes
5521592Srgrimes    /** Read name and type.
55329917Smarkm     */
55429917Smarkm    NameAndType readNameAndType(int i) {
5551592Srgrimes        Object obj = readPool(i);
5561592Srgrimes        if (obj != null && !(obj instanceof NameAndType))
5571592Srgrimes            throw badClassFile("bad.const.pool.entry",
5581592Srgrimes                               currentClassFile.toString(),
5591592Srgrimes                               "CONSTANT_NameAndType_info", i);
5601592Srgrimes        return (NameAndType)obj;
5611592Srgrimes    }
5621592Srgrimes
5631592Srgrimes    /** Read the class name of a module-info.class file.
5641592Srgrimes     * The name is stored in a CONSTANT_Class entry, where the
5651592Srgrimes     * class name is of the form module-name.module-info.
5661592Srgrimes     */
5671592Srgrimes    Name readModuleInfoName(int i) {
5681592Srgrimes        int classIndex = poolIdx[i];
56929917Smarkm        if (buf[classIndex] == CONSTANT_Class) {
57029917Smarkm            int utf8Index = poolIdx[getChar(classIndex + 1)];
57129917Smarkm            if (buf[utf8Index] == CONSTANT_Utf8) {
5721592Srgrimes                int len = getChar(utf8Index + 1);
5731592Srgrimes                int start = utf8Index + 3;
5741592Srgrimes                return names.fromUtf(internalize(buf, start, len));
5751592Srgrimes            }
57629917Smarkm        }
57729917Smarkm        throw badClassFile("bad.module-info.name");
57829917Smarkm    }
5791592Srgrimes
5801592Srgrimes    /** Read requires_flags.
5811592Srgrimes     */
5821592Srgrimes    Set<RequiresFlag> readRequiresFlags(int flags) {
5831592Srgrimes        Set<RequiresFlag> set = EnumSet.noneOf(RequiresFlag.class);
5841592Srgrimes        for (RequiresFlag f: RequiresFlag.values()) {
5851592Srgrimes            if ((flags & f.value) != 0)
5861592Srgrimes                set.add(f);
5871592Srgrimes        }
5881592Srgrimes        return set;
5891592Srgrimes    }
5901592Srgrimes
5911592Srgrimes/************************************************************************
5921592Srgrimes * Reading Types
5931592Srgrimes ***********************************************************************/
5941592Srgrimes
5951592Srgrimes    /** The unread portion of the currently read type is
5961592Srgrimes     *  signature[sigp..siglimit-1].
5971592Srgrimes     */
5981592Srgrimes    byte[] signature;
5991592Srgrimes    int sigp;
6001592Srgrimes    int siglimit;
6011592Srgrimes    boolean sigEnterPhase = false;
6021592Srgrimes
6031592Srgrimes    /** Convert signature to type, where signature is a byte array segment.
6041592Srgrimes     */
6051592Srgrimes    Type sigToType(byte[] sig, int offset, int len) {
6061592Srgrimes        signature = sig;
6071592Srgrimes        sigp = offset;
6081592Srgrimes        siglimit = offset + len;
6091592Srgrimes        return sigToType();
6101592Srgrimes    }
6111592Srgrimes
6121592Srgrimes    /** Convert signature to type, where signature is implicit.
6131592Srgrimes     */
6141592Srgrimes    Type sigToType() {
6151592Srgrimes        switch ((char) signature[sigp]) {
6161592Srgrimes        case 'T':
6171592Srgrimes            sigp++;
6181592Srgrimes            int start = sigp;
6191592Srgrimes            while (signature[sigp] != ';') sigp++;
6201592Srgrimes            sigp++;
62125099Sdavidn            return sigEnterPhase
62225099Sdavidn                ? Type.noType
62325099Sdavidn                : findTypeVar(names.fromUtf(signature, start, sigp - 1 - start));
62425099Sdavidn        case '+': {
62525099Sdavidn            sigp++;
62625099Sdavidn            Type t = sigToType();
62725099Sdavidn            return new WildcardType(t, BoundKind.EXTENDS, syms.boundClass);
62825099Sdavidn        }
62925099Sdavidn        case '*':
63025099Sdavidn            sigp++;
63125099Sdavidn            return new WildcardType(syms.objectType, BoundKind.UNBOUND,
6321592Srgrimes                                    syms.boundClass);
6331592Srgrimes        case '-': {
6341592Srgrimes            sigp++;
63545393Sbrian            Type t = sigToType();
6361592Srgrimes            return new WildcardType(t, BoundKind.SUPER, syms.boundClass);
6371592Srgrimes        }
6381592Srgrimes        case 'B':
6391592Srgrimes            sigp++;
6401592Srgrimes            return syms.byteType;
6411592Srgrimes        case 'C':
6421592Srgrimes            sigp++;
6431592Srgrimes            return syms.charType;
6441592Srgrimes        case 'D':
6451592Srgrimes            sigp++;
6461592Srgrimes            return syms.doubleType;
6471592Srgrimes        case 'F':
6481592Srgrimes            sigp++;
6491592Srgrimes            return syms.floatType;
6501592Srgrimes        case 'I':
6511592Srgrimes            sigp++;
6521592Srgrimes            return syms.intType;
6531592Srgrimes        case 'J':
6541592Srgrimes            sigp++;
6551592Srgrimes            return syms.longType;
6561592Srgrimes        case 'L':
6571592Srgrimes            {
6581592Srgrimes                // int oldsigp = sigp;
6591592Srgrimes                Type t = classSigToType();
6601592Srgrimes                if (sigp < siglimit && signature[sigp] == '.')
6611592Srgrimes                    throw badClassFile("deprecated inner class signature syntax " +
6621592Srgrimes                                       "(please recompile from source)");
6631592Srgrimes                /*
6641592Srgrimes                System.err.println(" decoded " +
6651592Srgrimes                                   new String(signature, oldsigp, sigp-oldsigp) +
6661592Srgrimes                                   " => " + t + " outer " + t.outer());
6671592Srgrimes                */
6681592Srgrimes                return t;
6691592Srgrimes            }
6701592Srgrimes        case 'S':
6711592Srgrimes            sigp++;
6721592Srgrimes            return syms.shortType;
6731592Srgrimes        case 'V':
6741592Srgrimes            sigp++;
6751592Srgrimes            return syms.voidType;
6761592Srgrimes        case 'Z':
6771592Srgrimes            sigp++;
6781592Srgrimes            return syms.booleanType;
6791592Srgrimes        case '[':
6801592Srgrimes            sigp++;
6811592Srgrimes            return new ArrayType(sigToType(), syms.arrayClass);
6821592Srgrimes        case '(':
6831592Srgrimes            sigp++;
6841592Srgrimes            List<Type> argtypes = sigToTypes(')');
6851592Srgrimes            Type restype = sigToType();
6861592Srgrimes            List<Type> thrown = List.nil();
6871592Srgrimes            while (signature[sigp] == '^') {
6881592Srgrimes                sigp++;
6891592Srgrimes                thrown = thrown.prepend(sigToType());
6901592Srgrimes            }
6911592Srgrimes            // if there is a typevar in the throws clause we should state it.
6921592Srgrimes            for (List<Type> l = thrown; l.nonEmpty(); l = l.tail) {
6931592Srgrimes                if (l.head.hasTag(TYPEVAR)) {
6941592Srgrimes                    l.head.tsym.flags_field |= THROWS;
6951592Srgrimes                }
6961592Srgrimes            }
6971592Srgrimes            return new MethodType(argtypes,
6981592Srgrimes                                  restype,
6991592Srgrimes                                  thrown.reverse(),
7001592Srgrimes                                  syms.methodClass);
7011592Srgrimes        case '<':
7021592Srgrimes            typevars = typevars.dup(currentOwner);
7031592Srgrimes            Type poly = new ForAll(sigToTypeParams(), sigToType());
7041592Srgrimes            typevars = typevars.leave();
7051592Srgrimes            return poly;
7061592Srgrimes        default:
7071592Srgrimes            throw badClassFile("bad.signature",
7081592Srgrimes                               Convert.utf2string(signature, sigp, 10));
7091592Srgrimes        }
7101592Srgrimes    }
7111592Srgrimes
7121592Srgrimes    byte[] signatureBuffer = new byte[0];
7131592Srgrimes    int sbp = 0;
71445422Sbrian    /** Convert class signature to type, where signature is implicit.
71545422Sbrian     */
7161592Srgrimes    Type classSigToType() {
7171592Srgrimes        if (signature[sigp] != 'L')
7181592Srgrimes            throw badClassFile("bad.class.signature",
7191592Srgrimes                               Convert.utf2string(signature, sigp, 10));
7201592Srgrimes        sigp++;
7211592Srgrimes        Type outer = Type.noType;
7221592Srgrimes        int startSbp = sbp;
7231592Srgrimes
7241592Srgrimes        while (true) {
7251592Srgrimes            final byte c = signature[sigp++];
7261592Srgrimes            switch (c) {
7271592Srgrimes
7281592Srgrimes            case ';': {         // end
7291592Srgrimes                ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
7301592Srgrimes                                                         startSbp,
7311592Srgrimes                                                         sbp - startSbp));
7321592Srgrimes
7331592Srgrimes                try {
7341592Srgrimes                    return (outer == Type.noType) ?
7351592Srgrimes                            t.erasure(types) :
7361592Srgrimes                        new ClassType(outer, List.<Type>nil(), t);
7371592Srgrimes                } finally {
7381592Srgrimes                    sbp = startSbp;
7391592Srgrimes                }
7401592Srgrimes            }
7411592Srgrimes
7421592Srgrimes            case '<':           // generic arguments
7431592Srgrimes                ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
7441592Srgrimes                                                         startSbp,
7451592Srgrimes                                                         sbp - startSbp));
7461592Srgrimes                outer = new ClassType(outer, sigToTypes('>'), t) {
747                        boolean completed = false;
748                        @Override @DefinedBy(Api.LANGUAGE_MODEL)
749                        public Type getEnclosingType() {
750                            if (!completed) {
751                                completed = true;
752                                tsym.complete();
753                                Type enclosingType = tsym.type.getEnclosingType();
754                                if (enclosingType != Type.noType) {
755                                    List<Type> typeArgs =
756                                        super.getEnclosingType().allparams();
757                                    List<Type> typeParams =
758                                        enclosingType.allparams();
759                                    if (typeParams.length() != typeArgs.length()) {
760                                        // no "rare" types
761                                        super.setEnclosingType(types.erasure(enclosingType));
762                                    } else {
763                                        super.setEnclosingType(types.subst(enclosingType,
764                                                                           typeParams,
765                                                                           typeArgs));
766                                    }
767                                } else {
768                                    super.setEnclosingType(Type.noType);
769                                }
770                            }
771                            return super.getEnclosingType();
772                        }
773                        @Override
774                        public void setEnclosingType(Type outer) {
775                            throw new UnsupportedOperationException();
776                        }
777                    };
778                switch (signature[sigp++]) {
779                case ';':
780                    if (sigp < signature.length && signature[sigp] == '.') {
781                        // support old-style GJC signatures
782                        // The signature produced was
783                        // Lfoo/Outer<Lfoo/X;>;.Lfoo/Outer$Inner<Lfoo/Y;>;
784                        // rather than say
785                        // Lfoo/Outer<Lfoo/X;>.Inner<Lfoo/Y;>;
786                        // so we skip past ".Lfoo/Outer$"
787                        sigp += (sbp - startSbp) + // "foo/Outer"
788                            3;  // ".L" and "$"
789                        signatureBuffer[sbp++] = (byte)'$';
790                        break;
791                    } else {
792                        sbp = startSbp;
793                        return outer;
794                    }
795                case '.':
796                    signatureBuffer[sbp++] = (byte)'$';
797                    break;
798                default:
799                    throw new AssertionError(signature[sigp-1]);
800                }
801                continue;
802
803            case '.':
804                //we have seen an enclosing non-generic class
805                if (outer != Type.noType) {
806                    t = enterClass(names.fromUtf(signatureBuffer,
807                                                 startSbp,
808                                                 sbp - startSbp));
809                    outer = new ClassType(outer, List.<Type>nil(), t);
810                }
811                signatureBuffer[sbp++] = (byte)'$';
812                continue;
813            case '/':
814                signatureBuffer[sbp++] = (byte)'.';
815                continue;
816            default:
817                signatureBuffer[sbp++] = c;
818                continue;
819            }
820        }
821    }
822
823    /** Convert (implicit) signature to list of types
824     *  until `terminator' is encountered.
825     */
826    List<Type> sigToTypes(char terminator) {
827        List<Type> head = List.of(null);
828        List<Type> tail = head;
829        while (signature[sigp] != terminator)
830            tail = tail.setTail(List.of(sigToType()));
831        sigp++;
832        return head.tail;
833    }
834
835    /** Convert signature to type parameters, where signature is a byte
836     *  array segment.
837     */
838    List<Type> sigToTypeParams(byte[] sig, int offset, int len) {
839        signature = sig;
840        sigp = offset;
841        siglimit = offset + len;
842        return sigToTypeParams();
843    }
844
845    /** Convert signature to type parameters, where signature is implicit.
846     */
847    List<Type> sigToTypeParams() {
848        List<Type> tvars = List.nil();
849        if (signature[sigp] == '<') {
850            sigp++;
851            int start = sigp;
852            sigEnterPhase = true;
853            while (signature[sigp] != '>')
854                tvars = tvars.prepend(sigToTypeParam());
855            sigEnterPhase = false;
856            sigp = start;
857            while (signature[sigp] != '>')
858                sigToTypeParam();
859            sigp++;
860        }
861        return tvars.reverse();
862    }
863
864    /** Convert (implicit) signature to type parameter.
865     */
866    Type sigToTypeParam() {
867        int start = sigp;
868        while (signature[sigp] != ':') sigp++;
869        Name name = names.fromUtf(signature, start, sigp - start);
870        TypeVar tvar;
871        if (sigEnterPhase) {
872            tvar = new TypeVar(name, currentOwner, syms.botType);
873            typevars.enter(tvar.tsym);
874        } else {
875            tvar = (TypeVar)findTypeVar(name);
876        }
877        List<Type> bounds = List.nil();
878        boolean allInterfaces = false;
879        if (signature[sigp] == ':' && signature[sigp+1] == ':') {
880            sigp++;
881            allInterfaces = true;
882        }
883        while (signature[sigp] == ':') {
884            sigp++;
885            bounds = bounds.prepend(sigToType());
886        }
887        if (!sigEnterPhase) {
888            types.setBounds(tvar, bounds.reverse(), allInterfaces);
889        }
890        return tvar;
891    }
892
893    /** Find type variable with given name in `typevars' scope.
894     */
895    Type findTypeVar(Name name) {
896        Symbol s = typevars.findFirst(name);
897        if (s != null) {
898            return s.type;
899        } else {
900            if (readingClassAttr) {
901                // While reading the class attribute, the supertypes
902                // might refer to a type variable from an enclosing element
903                // (method or class).
904                // If the type variable is defined in the enclosing class,
905                // we can actually find it in
906                // currentOwner.owner.type.getTypeArguments()
907                // However, until we have read the enclosing method attribute
908                // we don't know for sure if this owner is correct.  It could
909                // be a method and there is no way to tell before reading the
910                // enclosing method attribute.
911                TypeVar t = new TypeVar(name, currentOwner, syms.botType);
912                missingTypeVariables = missingTypeVariables.prepend(t);
913                // System.err.println("Missing type var " + name);
914                return t;
915            }
916            throw badClassFile("undecl.type.var", name);
917        }
918    }
919
920/************************************************************************
921 * Reading Attributes
922 ***********************************************************************/
923
924    protected enum AttributeKind { CLASS, MEMBER }
925
926    protected abstract class AttributeReader {
927        protected AttributeReader(Name name, ClassFile.Version version, Set<AttributeKind> kinds) {
928            this.name = name;
929            this.version = version;
930            this.kinds = kinds;
931        }
932
933        protected boolean accepts(AttributeKind kind) {
934            if (kinds.contains(kind)) {
935                if (majorVersion > version.major || (majorVersion == version.major && minorVersion >= version.minor))
936                    return true;
937
938                if (lintClassfile && !warnedAttrs.contains(name)) {
939                    JavaFileObject prev = log.useSource(currentClassFile);
940                    try {
941                        log.warning(LintCategory.CLASSFILE, (DiagnosticPosition) null, "future.attr",
942                                name, version.major, version.minor, majorVersion, minorVersion);
943                    } finally {
944                        log.useSource(prev);
945                    }
946                    warnedAttrs.add(name);
947                }
948            }
949            return false;
950        }
951
952        protected abstract void read(Symbol sym, int attrLen);
953
954        protected final Name name;
955        protected final ClassFile.Version version;
956        protected final Set<AttributeKind> kinds;
957    }
958
959    protected Set<AttributeKind> CLASS_ATTRIBUTE =
960            EnumSet.of(AttributeKind.CLASS);
961    protected Set<AttributeKind> MEMBER_ATTRIBUTE =
962            EnumSet.of(AttributeKind.MEMBER);
963    protected Set<AttributeKind> CLASS_OR_MEMBER_ATTRIBUTE =
964            EnumSet.of(AttributeKind.CLASS, AttributeKind.MEMBER);
965
966    protected Map<Name, AttributeReader> attributeReaders = new HashMap<>();
967
968    private void initAttributeReaders() {
969        AttributeReader[] readers = {
970            // v45.3 attributes
971
972            new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) {
973                protected void read(Symbol sym, int attrLen) {
974                    if (readAllOfClassFile || saveParameterNames)
975                        ((MethodSymbol)sym).code = readCode(sym);
976                    else
977                        bp = bp + attrLen;
978                }
979            },
980
981            new AttributeReader(names.ConstantValue, V45_3, MEMBER_ATTRIBUTE) {
982                protected void read(Symbol sym, int attrLen) {
983                    Object v = readPool(nextChar());
984                    // Ignore ConstantValue attribute if field not final.
985                    if ((sym.flags() & FINAL) != 0)
986                        ((VarSymbol) sym).setData(v);
987                }
988            },
989
990            new AttributeReader(names.Deprecated, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
991                protected void read(Symbol sym, int attrLen) {
992                    sym.flags_field |= DEPRECATED;
993                }
994            },
995
996            new AttributeReader(names.Exceptions, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
997                protected void read(Symbol sym, int attrLen) {
998                    int nexceptions = nextChar();
999                    List<Type> thrown = List.nil();
1000                    for (int j = 0; j < nexceptions; j++)
1001                        thrown = thrown.prepend(readClassSymbol(nextChar()).type);
1002                    if (sym.type.getThrownTypes().isEmpty())
1003                        sym.type.asMethodType().thrown = thrown.reverse();
1004                }
1005            },
1006
1007            new AttributeReader(names.InnerClasses, V45_3, CLASS_ATTRIBUTE) {
1008                protected void read(Symbol sym, int attrLen) {
1009                    ClassSymbol c = (ClassSymbol) sym;
1010                    if (currentModule.module_info == c) {
1011                        //prevent entering the classes too soon:
1012                        skipInnerClasses();
1013                    } else {
1014                        readInnerClasses(c);
1015                    }
1016                }
1017            },
1018
1019            new AttributeReader(names.LocalVariableTable, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
1020                protected void read(Symbol sym, int attrLen) {
1021                    int newbp = bp + attrLen;
1022                    if (saveParameterNames && !sawMethodParameters) {
1023                        // Pick up parameter names from the variable table.
1024                        // Parameter names are not explicitly identified as such,
1025                        // but all parameter name entries in the LocalVariableTable
1026                        // have a start_pc of 0.  Therefore, we record the name
1027                        // indicies of all slots with a start_pc of zero in the
1028                        // parameterNameIndicies array.
1029                        // Note that this implicitly honors the JVMS spec that
1030                        // there may be more than one LocalVariableTable, and that
1031                        // there is no specified ordering for the entries.
1032                        int numEntries = nextChar();
1033                        for (int i = 0; i < numEntries; i++) {
1034                            int start_pc = nextChar();
1035                            int length = nextChar();
1036                            int nameIndex = nextChar();
1037                            int sigIndex = nextChar();
1038                            int register = nextChar();
1039                            if (start_pc == 0) {
1040                                // ensure array large enough
1041                                if (register >= parameterNameIndices.length) {
1042                                    int newSize = Math.max(register, parameterNameIndices.length + 8);
1043                                    parameterNameIndices =
1044                                            Arrays.copyOf(parameterNameIndices, newSize);
1045                                }
1046                                parameterNameIndices[register] = nameIndex;
1047                                haveParameterNameIndices = true;
1048                            }
1049                        }
1050                    }
1051                    bp = newbp;
1052                }
1053            },
1054
1055            new AttributeReader(names.SourceFile, V45_3, CLASS_ATTRIBUTE) {
1056                protected void read(Symbol sym, int attrLen) {
1057                    ClassSymbol c = (ClassSymbol) sym;
1058                    Name n = readName(nextChar());
1059                    c.sourcefile = new SourceFileObject(n, c.flatname);
1060                    // If the class is a toplevel class, originating from a Java source file,
1061                    // but the class name does not match the file name, then it is
1062                    // an auxiliary class.
1063                    String sn = n.toString();
1064                    if (c.owner.kind == PCK &&
1065                        sn.endsWith(".java") &&
1066                        !sn.equals(c.name.toString()+".java")) {
1067                        c.flags_field |= AUXILIARY;
1068                    }
1069                }
1070            },
1071
1072            new AttributeReader(names.Synthetic, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
1073                protected void read(Symbol sym, int attrLen) {
1074                    sym.flags_field |= SYNTHETIC;
1075                }
1076            },
1077
1078            // standard v49 attributes
1079
1080            new AttributeReader(names.EnclosingMethod, V49, CLASS_ATTRIBUTE) {
1081                protected void read(Symbol sym, int attrLen) {
1082                    int newbp = bp + attrLen;
1083                    readEnclosingMethodAttr(sym);
1084                    bp = newbp;
1085                }
1086            },
1087
1088            new AttributeReader(names.Signature, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1089                protected void read(Symbol sym, int attrLen) {
1090                    if (sym.kind == TYP) {
1091                        ClassSymbol c = (ClassSymbol) sym;
1092                        readingClassAttr = true;
1093                        try {
1094                            ClassType ct1 = (ClassType)c.type;
1095                            Assert.check(c == currentOwner);
1096                            ct1.typarams_field = readTypeParams(nextChar());
1097                            ct1.supertype_field = sigToType();
1098                            ListBuffer<Type> is = new ListBuffer<>();
1099                            while (sigp != siglimit) is.append(sigToType());
1100                            ct1.interfaces_field = is.toList();
1101                        } finally {
1102                            readingClassAttr = false;
1103                        }
1104                    } else {
1105                        List<Type> thrown = sym.type.getThrownTypes();
1106                        sym.type = readType(nextChar());
1107                        //- System.err.println(" # " + sym.type);
1108                        if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty())
1109                            sym.type.asMethodType().thrown = thrown;
1110
1111                    }
1112                }
1113            },
1114
1115            // v49 annotation attributes
1116
1117            new AttributeReader(names.AnnotationDefault, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1118                protected void read(Symbol sym, int attrLen) {
1119                    attachAnnotationDefault(sym);
1120                }
1121            },
1122
1123            new AttributeReader(names.RuntimeInvisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1124                protected void read(Symbol sym, int attrLen) {
1125                    attachAnnotations(sym);
1126                }
1127            },
1128
1129            new AttributeReader(names.RuntimeInvisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1130                protected void read(Symbol sym, int attrLen) {
1131                    attachParameterAnnotations(sym);
1132                }
1133            },
1134
1135            new AttributeReader(names.RuntimeVisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1136                protected void read(Symbol sym, int attrLen) {
1137                    attachAnnotations(sym);
1138                }
1139            },
1140
1141            new AttributeReader(names.RuntimeVisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1142                protected void read(Symbol sym, int attrLen) {
1143                    attachParameterAnnotations(sym);
1144                }
1145            },
1146
1147            // additional "legacy" v49 attributes, superceded by flags
1148
1149            new AttributeReader(names.Annotation, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1150                protected void read(Symbol sym, int attrLen) {
1151                    sym.flags_field |= ANNOTATION;
1152                }
1153            },
1154
1155            new AttributeReader(names.Bridge, V49, MEMBER_ATTRIBUTE) {
1156                protected void read(Symbol sym, int attrLen) {
1157                    sym.flags_field |= BRIDGE;
1158                }
1159            },
1160
1161            new AttributeReader(names.Enum, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1162                protected void read(Symbol sym, int attrLen) {
1163                    sym.flags_field |= ENUM;
1164                }
1165            },
1166
1167            new AttributeReader(names.Varargs, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1168                protected void read(Symbol sym, int attrLen) {
1169                    sym.flags_field |= VARARGS;
1170                }
1171            },
1172
1173            new AttributeReader(names.RuntimeVisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) {
1174                protected void read(Symbol sym, int attrLen) {
1175                    attachTypeAnnotations(sym);
1176                }
1177            },
1178
1179            new AttributeReader(names.RuntimeInvisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) {
1180                protected void read(Symbol sym, int attrLen) {
1181                    attachTypeAnnotations(sym);
1182                }
1183            },
1184
1185            // The following attributes for a Code attribute are not currently handled
1186            // StackMapTable
1187            // SourceDebugExtension
1188            // LineNumberTable
1189            // LocalVariableTypeTable
1190
1191            // standard v52 attributes
1192
1193            new AttributeReader(names.MethodParameters, V52, MEMBER_ATTRIBUTE) {
1194                protected void read(Symbol sym, int attrlen) {
1195                    int newbp = bp + attrlen;
1196                    if (saveParameterNames) {
1197                        sawMethodParameters = true;
1198                        int numEntries = nextByte();
1199                        parameterNameIndices = new int[numEntries];
1200                        haveParameterNameIndices = true;
1201                        for (int i = 0; i < numEntries; i++) {
1202                            int nameIndex = nextChar();
1203                            int flags = nextChar();
1204                            parameterNameIndices[i] = nameIndex;
1205                        }
1206                    }
1207                    bp = newbp;
1208                }
1209            },
1210
1211            // standard v53 attributes
1212
1213            new AttributeReader(names.Module, V53, CLASS_ATTRIBUTE) {
1214                @Override
1215                protected boolean accepts(AttributeKind kind) {
1216                    return super.accepts(kind) && allowModules;
1217                }
1218                protected void read(Symbol sym, int attrLen) {
1219                    if (sym.kind == TYP && sym.owner.kind == MDL) {
1220                        ModuleSymbol msym = (ModuleSymbol) sym.owner;
1221                        ListBuffer<Directive> directives = new ListBuffer<>();
1222
1223                        ListBuffer<RequiresDirective> requires = new ListBuffer<>();
1224                        int nrequires = nextChar();
1225                        for (int i = 0; i < nrequires; i++) {
1226                            Name name = readName(nextChar());
1227                            ModuleSymbol rsym = syms.enterModule(name);
1228                            Set<RequiresFlag> flags = readRequiresFlags(nextChar());
1229                            requires.add(new RequiresDirective(rsym, flags));
1230                        }
1231                        msym.requires = requires.toList();
1232                        directives.addAll(msym.requires);
1233
1234                        ListBuffer<ExportsDirective> exports = new ListBuffer<>();
1235                        int nexports = nextChar();
1236                        for (int i = 0; i < nexports; i++) {
1237                            Name n = readName(nextChar());
1238                            PackageSymbol p = syms.enterPackage(currentModule, names.fromUtf(internalize(n)));
1239                            int nto = nextChar();
1240                            List<ModuleSymbol> to;
1241                            if (nto == 0) {
1242                                to = null;
1243                            } else {
1244                                ListBuffer<ModuleSymbol> lb = new ListBuffer<>();
1245                                for (int t = 0; t < nto; t++)
1246                                    lb.append(syms.enterModule(readName(nextChar())));
1247                                to = lb.toList();
1248                            }
1249                            exports.add(new ExportsDirective(p, to));
1250                        }
1251                        msym.exports = exports.toList();
1252                        directives.addAll(msym.exports);
1253
1254                        msym.directives = directives.toList();
1255
1256                        ListBuffer<InterimUsesDirective> uses = new ListBuffer<>();
1257                        int nuses = nextChar();
1258                        for (int i = 0; i < nuses; i++) {
1259                            Name srvc = readClassName(nextChar());
1260                            uses.add(new InterimUsesDirective(srvc));
1261                        }
1262                        interimUses = uses.toList();
1263
1264                        ListBuffer<InterimProvidesDirective> provides = new ListBuffer<>();
1265                        int nprovides = nextChar();
1266                        for (int i = 0; i < nprovides; i++) {
1267                            Name srvc = readClassName(nextChar());
1268                            Name impl = readClassName(nextChar());
1269                            provides.add(new InterimProvidesDirective(srvc, impl));
1270                        }
1271                        interimProvides = provides.toList();
1272                    }
1273                }
1274            },
1275
1276            new AttributeReader(names.Version, V53, CLASS_ATTRIBUTE) {
1277                @Override
1278                protected boolean accepts(AttributeKind kind) {
1279                    return super.accepts(kind) && allowModules;
1280                }
1281                protected void read(Symbol sym, int attrLen) {
1282                    if (sym.kind == TYP && sym.owner.kind == MDL) {
1283                        ModuleSymbol msym = (ModuleSymbol) sym.owner;
1284                        msym.version = readName(nextChar());
1285                    }
1286                }
1287            },
1288        };
1289
1290        for (AttributeReader r: readers)
1291            attributeReaders.put(r.name, r);
1292    }
1293
1294    protected void readEnclosingMethodAttr(Symbol sym) {
1295        // sym is a nested class with an "Enclosing Method" attribute
1296        // remove sym from it's current owners scope and place it in
1297        // the scope specified by the attribute
1298        sym.owner.members().remove(sym);
1299        ClassSymbol self = (ClassSymbol)sym;
1300        ClassSymbol c = readClassSymbol(nextChar());
1301        NameAndType nt = readNameAndType(nextChar());
1302
1303        if (c.members_field == null)
1304            throw badClassFile("bad.enclosing.class", self, c);
1305
1306        MethodSymbol m = findMethod(nt, c.members_field, self.flags());
1307        if (nt != null && m == null)
1308            throw badEnclosingMethod(self);
1309
1310        self.name = simpleBinaryName(self.flatname, c.flatname) ;
1311        self.owner = m != null ? m : c;
1312        if (self.name.isEmpty())
1313            self.fullname = names.empty;
1314        else
1315            self.fullname = ClassSymbol.formFullName(self.name, self.owner);
1316
1317        if (m != null) {
1318            ((ClassType)sym.type).setEnclosingType(m.type);
1319        } else if ((self.flags_field & STATIC) == 0) {
1320            ((ClassType)sym.type).setEnclosingType(c.type);
1321        } else {
1322            ((ClassType)sym.type).setEnclosingType(Type.noType);
1323        }
1324        enterTypevars(self);
1325        if (!missingTypeVariables.isEmpty()) {
1326            ListBuffer<Type> typeVars =  new ListBuffer<>();
1327            for (Type typevar : missingTypeVariables) {
1328                typeVars.append(findTypeVar(typevar.tsym.name));
1329            }
1330            foundTypeVariables = typeVars.toList();
1331        } else {
1332            foundTypeVariables = List.nil();
1333        }
1334    }
1335
1336    // See java.lang.Class
1337    private Name simpleBinaryName(Name self, Name enclosing) {
1338        String simpleBinaryName = self.toString().substring(enclosing.toString().length());
1339        if (simpleBinaryName.length() < 1 || simpleBinaryName.charAt(0) != '$')
1340            throw badClassFile("bad.enclosing.method", self);
1341        int index = 1;
1342        while (index < simpleBinaryName.length() &&
1343               isAsciiDigit(simpleBinaryName.charAt(index)))
1344            index++;
1345        return names.fromString(simpleBinaryName.substring(index));
1346    }
1347
1348    private MethodSymbol findMethod(NameAndType nt, Scope scope, long flags) {
1349        if (nt == null)
1350            return null;
1351
1352        MethodType type = nt.uniqueType.type.asMethodType();
1353
1354        for (Symbol sym : scope.getSymbolsByName(nt.name)) {
1355            if (sym.kind == MTH && isSameBinaryType(sym.type.asMethodType(), type))
1356                return (MethodSymbol)sym;
1357        }
1358
1359        if (nt.name != names.init)
1360            // not a constructor
1361            return null;
1362        if ((flags & INTERFACE) != 0)
1363            // no enclosing instance
1364            return null;
1365        if (nt.uniqueType.type.getParameterTypes().isEmpty())
1366            // no parameters
1367            return null;
1368
1369        // A constructor of an inner class.
1370        // Remove the first argument (the enclosing instance)
1371        nt.setType(new MethodType(nt.uniqueType.type.getParameterTypes().tail,
1372                                 nt.uniqueType.type.getReturnType(),
1373                                 nt.uniqueType.type.getThrownTypes(),
1374                                 syms.methodClass));
1375        // Try searching again
1376        return findMethod(nt, scope, flags);
1377    }
1378
1379    /** Similar to Types.isSameType but avoids completion */
1380    private boolean isSameBinaryType(MethodType mt1, MethodType mt2) {
1381        List<Type> types1 = types.erasure(mt1.getParameterTypes())
1382            .prepend(types.erasure(mt1.getReturnType()));
1383        List<Type> types2 = mt2.getParameterTypes().prepend(mt2.getReturnType());
1384        while (!types1.isEmpty() && !types2.isEmpty()) {
1385            if (types1.head.tsym != types2.head.tsym)
1386                return false;
1387            types1 = types1.tail;
1388            types2 = types2.tail;
1389        }
1390        return types1.isEmpty() && types2.isEmpty();
1391    }
1392
1393    /**
1394     * Character.isDigit answers <tt>true</tt> to some non-ascii
1395     * digits.  This one does not.  <b>copied from java.lang.Class</b>
1396     */
1397    private static boolean isAsciiDigit(char c) {
1398        return '0' <= c && c <= '9';
1399    }
1400
1401    /** Read member attributes.
1402     */
1403    void readMemberAttrs(Symbol sym) {
1404        readAttrs(sym, AttributeKind.MEMBER);
1405    }
1406
1407    void readAttrs(Symbol sym, AttributeKind kind) {
1408        char ac = nextChar();
1409        for (int i = 0; i < ac; i++) {
1410            Name attrName = readName(nextChar());
1411            int attrLen = nextInt();
1412            AttributeReader r = attributeReaders.get(attrName);
1413            if (r != null && r.accepts(kind))
1414                r.read(sym, attrLen);
1415            else  {
1416                bp = bp + attrLen;
1417            }
1418        }
1419    }
1420
1421    private boolean readingClassAttr = false;
1422    private List<Type> missingTypeVariables = List.nil();
1423    private List<Type> foundTypeVariables = List.nil();
1424
1425    /** Read class attributes.
1426     */
1427    void readClassAttrs(ClassSymbol c) {
1428        readAttrs(c, AttributeKind.CLASS);
1429    }
1430
1431    /** Read code block.
1432     */
1433    Code readCode(Symbol owner) {
1434        nextChar(); // max_stack
1435        nextChar(); // max_locals
1436        final int  code_length = nextInt();
1437        bp += code_length;
1438        final char exception_table_length = nextChar();
1439        bp += exception_table_length * 8;
1440        readMemberAttrs(owner);
1441        return null;
1442    }
1443
1444/************************************************************************
1445 * Reading Java-language annotations
1446 ***********************************************************************/
1447
1448    /** Attach annotations.
1449     */
1450    void attachAnnotations(final Symbol sym) {
1451        int numAttributes = nextChar();
1452        if (numAttributes != 0) {
1453            ListBuffer<CompoundAnnotationProxy> proxies = new ListBuffer<>();
1454            for (int i = 0; i<numAttributes; i++) {
1455                CompoundAnnotationProxy proxy = readCompoundAnnotation();
1456
1457                if (proxy.type.tsym == syms.proprietaryType.tsym)
1458                    sym.flags_field |= PROPRIETARY;
1459                else if (proxy.type.tsym == syms.profileType.tsym) {
1460                    if (profile != Profile.DEFAULT) {
1461                        for (Pair<Name,Attribute> v: proxy.values) {
1462                            if (v.fst == names.value && v.snd instanceof Attribute.Constant) {
1463                                Attribute.Constant c = (Attribute.Constant) v.snd;
1464                                if (c.type == syms.intType && ((Integer) c.value) > profile.value) {
1465                                    sym.flags_field |= NOT_IN_PROFILE;
1466                                }
1467                            }
1468                        }
1469                    }
1470                } else {
1471                    if (proxy.type.tsym == syms.annotationTargetType.tsym) {
1472                        target = proxy;
1473                    } else if (proxy.type.tsym == syms.repeatableType.tsym) {
1474                        repeatable = proxy;
1475                    }
1476
1477                    proxies.append(proxy);
1478                }
1479            }
1480            annotate.normal(new AnnotationCompleter(sym, proxies.toList()));
1481        }
1482    }
1483
1484    /** Attach parameter annotations.
1485     */
1486    void attachParameterAnnotations(final Symbol method) {
1487        final MethodSymbol meth = (MethodSymbol)method;
1488        int numParameters = buf[bp++] & 0xFF;
1489        List<VarSymbol> parameters = meth.params();
1490        int pnum = 0;
1491        while (parameters.tail != null) {
1492            attachAnnotations(parameters.head);
1493            parameters = parameters.tail;
1494            pnum++;
1495        }
1496        if (pnum != numParameters) {
1497            throw badClassFile("bad.runtime.invisible.param.annotations", meth);
1498        }
1499    }
1500
1501    void attachTypeAnnotations(final Symbol sym) {
1502        int numAttributes = nextChar();
1503        if (numAttributes != 0) {
1504            ListBuffer<TypeAnnotationProxy> proxies = new ListBuffer<>();
1505            for (int i = 0; i < numAttributes; i++)
1506                proxies.append(readTypeAnnotation());
1507            annotate.normal(new TypeAnnotationCompleter(sym, proxies.toList()));
1508        }
1509    }
1510
1511    /** Attach the default value for an annotation element.
1512     */
1513    void attachAnnotationDefault(final Symbol sym) {
1514        final MethodSymbol meth = (MethodSymbol)sym; // only on methods
1515        final Attribute value = readAttributeValue();
1516
1517        // The default value is set later during annotation. It might
1518        // be the case that the Symbol sym is annotated _after_ the
1519        // repeating instances that depend on this default value,
1520        // because of this we set an interim value that tells us this
1521        // element (most likely) has a default.
1522        //
1523        // Set interim value for now, reset just before we do this
1524        // properly at annotate time.
1525        meth.defaultValue = value;
1526        annotate.normal(new AnnotationDefaultCompleter(meth, value));
1527    }
1528
1529    Type readTypeOrClassSymbol(int i) {
1530        // support preliminary jsr175-format class files
1531        if (buf[poolIdx[i]] == CONSTANT_Class)
1532            return readClassSymbol(i).type;
1533        return readType(i);
1534    }
1535    Type readEnumType(int i) {
1536        // support preliminary jsr175-format class files
1537        int index = poolIdx[i];
1538        int length = getChar(index + 1);
1539        if (buf[index + length + 2] != ';')
1540            return enterClass(readName(i)).type;
1541        return readType(i);
1542    }
1543
1544    CompoundAnnotationProxy readCompoundAnnotation() {
1545        Type t = readTypeOrClassSymbol(nextChar());
1546        int numFields = nextChar();
1547        ListBuffer<Pair<Name,Attribute>> pairs = new ListBuffer<>();
1548        for (int i=0; i<numFields; i++) {
1549            Name name = readName(nextChar());
1550            Attribute value = readAttributeValue();
1551            pairs.append(new Pair<>(name, value));
1552        }
1553        return new CompoundAnnotationProxy(t, pairs.toList());
1554    }
1555
1556    TypeAnnotationProxy readTypeAnnotation() {
1557        TypeAnnotationPosition position = readPosition();
1558        CompoundAnnotationProxy proxy = readCompoundAnnotation();
1559
1560        return new TypeAnnotationProxy(proxy, position);
1561    }
1562
1563    TypeAnnotationPosition readPosition() {
1564        int tag = nextByte(); // TargetType tag is a byte
1565
1566        if (!TargetType.isValidTargetTypeValue(tag))
1567            throw badClassFile("bad.type.annotation.value", String.format("0x%02X", tag));
1568
1569        TargetType type = TargetType.fromTargetTypeValue(tag);
1570
1571        switch (type) {
1572        // instanceof
1573        case INSTANCEOF: {
1574            final int offset = nextChar();
1575            final TypeAnnotationPosition position =
1576                TypeAnnotationPosition.instanceOf(readTypePath());
1577            position.offset = offset;
1578            return position;
1579        }
1580        // new expression
1581        case NEW: {
1582            final int offset = nextChar();
1583            final TypeAnnotationPosition position =
1584                TypeAnnotationPosition.newObj(readTypePath());
1585            position.offset = offset;
1586            return position;
1587        }
1588        // constructor/method reference receiver
1589        case CONSTRUCTOR_REFERENCE: {
1590            final int offset = nextChar();
1591            final TypeAnnotationPosition position =
1592                TypeAnnotationPosition.constructorRef(readTypePath());
1593            position.offset = offset;
1594            return position;
1595        }
1596        case METHOD_REFERENCE: {
1597            final int offset = nextChar();
1598            final TypeAnnotationPosition position =
1599                TypeAnnotationPosition.methodRef(readTypePath());
1600            position.offset = offset;
1601            return position;
1602        }
1603        // local variable
1604        case LOCAL_VARIABLE: {
1605            final int table_length = nextChar();
1606            final int[] newLvarOffset = new int[table_length];
1607            final int[] newLvarLength = new int[table_length];
1608            final int[] newLvarIndex = new int[table_length];
1609
1610            for (int i = 0; i < table_length; ++i) {
1611                newLvarOffset[i] = nextChar();
1612                newLvarLength[i] = nextChar();
1613                newLvarIndex[i] = nextChar();
1614            }
1615
1616            final TypeAnnotationPosition position =
1617                    TypeAnnotationPosition.localVariable(readTypePath());
1618            position.lvarOffset = newLvarOffset;
1619            position.lvarLength = newLvarLength;
1620            position.lvarIndex = newLvarIndex;
1621            return position;
1622        }
1623        // resource variable
1624        case RESOURCE_VARIABLE: {
1625            final int table_length = nextChar();
1626            final int[] newLvarOffset = new int[table_length];
1627            final int[] newLvarLength = new int[table_length];
1628            final int[] newLvarIndex = new int[table_length];
1629
1630            for (int i = 0; i < table_length; ++i) {
1631                newLvarOffset[i] = nextChar();
1632                newLvarLength[i] = nextChar();
1633                newLvarIndex[i] = nextChar();
1634            }
1635
1636            final TypeAnnotationPosition position =
1637                    TypeAnnotationPosition.resourceVariable(readTypePath());
1638            position.lvarOffset = newLvarOffset;
1639            position.lvarLength = newLvarLength;
1640            position.lvarIndex = newLvarIndex;
1641            return position;
1642        }
1643        // exception parameter
1644        case EXCEPTION_PARAMETER: {
1645            final int exception_index = nextChar();
1646            final TypeAnnotationPosition position =
1647                TypeAnnotationPosition.exceptionParameter(readTypePath());
1648            position.setExceptionIndex(exception_index);
1649            return position;
1650        }
1651        // method receiver
1652        case METHOD_RECEIVER:
1653            return TypeAnnotationPosition.methodReceiver(readTypePath());
1654        // type parameter
1655        case CLASS_TYPE_PARAMETER: {
1656            final int parameter_index = nextByte();
1657            return TypeAnnotationPosition
1658                .typeParameter(readTypePath(), parameter_index);
1659        }
1660        case METHOD_TYPE_PARAMETER: {
1661            final int parameter_index = nextByte();
1662            return TypeAnnotationPosition
1663                .methodTypeParameter(readTypePath(), parameter_index);
1664        }
1665        // type parameter bound
1666        case CLASS_TYPE_PARAMETER_BOUND: {
1667            final int parameter_index = nextByte();
1668            final int bound_index = nextByte();
1669            return TypeAnnotationPosition
1670                .typeParameterBound(readTypePath(), parameter_index,
1671                                    bound_index);
1672        }
1673        case METHOD_TYPE_PARAMETER_BOUND: {
1674            final int parameter_index = nextByte();
1675            final int bound_index = nextByte();
1676            return TypeAnnotationPosition
1677                .methodTypeParameterBound(readTypePath(), parameter_index,
1678                                          bound_index);
1679        }
1680        // class extends or implements clause
1681        case CLASS_EXTENDS: {
1682            final int type_index = nextChar();
1683            return TypeAnnotationPosition.classExtends(readTypePath(),
1684                                                       type_index);
1685        }
1686        // throws
1687        case THROWS: {
1688            final int type_index = nextChar();
1689            return TypeAnnotationPosition.methodThrows(readTypePath(),
1690                                                       type_index);
1691        }
1692        // method parameter
1693        case METHOD_FORMAL_PARAMETER: {
1694            final int parameter_index = nextByte();
1695            return TypeAnnotationPosition.methodParameter(readTypePath(),
1696                                                          parameter_index);
1697        }
1698        // type cast
1699        case CAST: {
1700            final int offset = nextChar();
1701            final int type_index = nextByte();
1702            final TypeAnnotationPosition position =
1703                TypeAnnotationPosition.typeCast(readTypePath(), type_index);
1704            position.offset = offset;
1705            return position;
1706        }
1707        // method/constructor/reference type argument
1708        case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: {
1709            final int offset = nextChar();
1710            final int type_index = nextByte();
1711            final TypeAnnotationPosition position = TypeAnnotationPosition
1712                .constructorInvocationTypeArg(readTypePath(), type_index);
1713            position.offset = offset;
1714            return position;
1715        }
1716        case METHOD_INVOCATION_TYPE_ARGUMENT: {
1717            final int offset = nextChar();
1718            final int type_index = nextByte();
1719            final TypeAnnotationPosition position = TypeAnnotationPosition
1720                .methodInvocationTypeArg(readTypePath(), type_index);
1721            position.offset = offset;
1722            return position;
1723        }
1724        case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: {
1725            final int offset = nextChar();
1726            final int type_index = nextByte();
1727            final TypeAnnotationPosition position = TypeAnnotationPosition
1728                .constructorRefTypeArg(readTypePath(), type_index);
1729            position.offset = offset;
1730            return position;
1731        }
1732        case METHOD_REFERENCE_TYPE_ARGUMENT: {
1733            final int offset = nextChar();
1734            final int type_index = nextByte();
1735            final TypeAnnotationPosition position = TypeAnnotationPosition
1736                .methodRefTypeArg(readTypePath(), type_index);
1737            position.offset = offset;
1738            return position;
1739        }
1740        // We don't need to worry about these
1741        case METHOD_RETURN:
1742            return TypeAnnotationPosition.methodReturn(readTypePath());
1743        case FIELD:
1744            return TypeAnnotationPosition.field(readTypePath());
1745        case UNKNOWN:
1746            throw new AssertionError("jvm.ClassReader: UNKNOWN target type should never occur!");
1747        default:
1748            throw new AssertionError("jvm.ClassReader: Unknown target type for position: " + type);
1749        }
1750    }
1751
1752    List<TypeAnnotationPosition.TypePathEntry> readTypePath() {
1753        int len = nextByte();
1754        ListBuffer<Integer> loc = new ListBuffer<>();
1755        for (int i = 0; i < len * TypeAnnotationPosition.TypePathEntry.bytesPerEntry; ++i)
1756            loc = loc.append(nextByte());
1757
1758        return TypeAnnotationPosition.getTypePathFromBinary(loc.toList());
1759
1760    }
1761
1762    Attribute readAttributeValue() {
1763        char c = (char) buf[bp++];
1764        switch (c) {
1765        case 'B':
1766            return new Attribute.Constant(syms.byteType, readPool(nextChar()));
1767        case 'C':
1768            return new Attribute.Constant(syms.charType, readPool(nextChar()));
1769        case 'D':
1770            return new Attribute.Constant(syms.doubleType, readPool(nextChar()));
1771        case 'F':
1772            return new Attribute.Constant(syms.floatType, readPool(nextChar()));
1773        case 'I':
1774            return new Attribute.Constant(syms.intType, readPool(nextChar()));
1775        case 'J':
1776            return new Attribute.Constant(syms.longType, readPool(nextChar()));
1777        case 'S':
1778            return new Attribute.Constant(syms.shortType, readPool(nextChar()));
1779        case 'Z':
1780            return new Attribute.Constant(syms.booleanType, readPool(nextChar()));
1781        case 's':
1782            return new Attribute.Constant(syms.stringType, readPool(nextChar()).toString());
1783        case 'e':
1784            return new EnumAttributeProxy(readEnumType(nextChar()), readName(nextChar()));
1785        case 'c':
1786            return new Attribute.Class(types, readTypeOrClassSymbol(nextChar()));
1787        case '[': {
1788            int n = nextChar();
1789            ListBuffer<Attribute> l = new ListBuffer<>();
1790            for (int i=0; i<n; i++)
1791                l.append(readAttributeValue());
1792            return new ArrayAttributeProxy(l.toList());
1793        }
1794        case '@':
1795            return readCompoundAnnotation();
1796        default:
1797            throw new AssertionError("unknown annotation tag '" + c + "'");
1798        }
1799    }
1800
1801    interface ProxyVisitor extends Attribute.Visitor {
1802        void visitEnumAttributeProxy(EnumAttributeProxy proxy);
1803        void visitArrayAttributeProxy(ArrayAttributeProxy proxy);
1804        void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy);
1805    }
1806
1807    static class EnumAttributeProxy extends Attribute {
1808        Type enumType;
1809        Name enumerator;
1810        public EnumAttributeProxy(Type enumType, Name enumerator) {
1811            super(null);
1812            this.enumType = enumType;
1813            this.enumerator = enumerator;
1814        }
1815        public void accept(Visitor v) { ((ProxyVisitor)v).visitEnumAttributeProxy(this); }
1816        @Override @DefinedBy(Api.LANGUAGE_MODEL)
1817        public String toString() {
1818            return "/*proxy enum*/" + enumType + "." + enumerator;
1819        }
1820    }
1821
1822    static class ArrayAttributeProxy extends Attribute {
1823        List<Attribute> values;
1824        ArrayAttributeProxy(List<Attribute> values) {
1825            super(null);
1826            this.values = values;
1827        }
1828        public void accept(Visitor v) { ((ProxyVisitor)v).visitArrayAttributeProxy(this); }
1829        @Override @DefinedBy(Api.LANGUAGE_MODEL)
1830        public String toString() {
1831            return "{" + values + "}";
1832        }
1833    }
1834
1835    /** A temporary proxy representing a compound attribute.
1836     */
1837    static class CompoundAnnotationProxy extends Attribute {
1838        final List<Pair<Name,Attribute>> values;
1839        public CompoundAnnotationProxy(Type type,
1840                                      List<Pair<Name,Attribute>> values) {
1841            super(type);
1842            this.values = values;
1843        }
1844        public void accept(Visitor v) { ((ProxyVisitor)v).visitCompoundAnnotationProxy(this); }
1845        @Override @DefinedBy(Api.LANGUAGE_MODEL)
1846        public String toString() {
1847            StringBuilder buf = new StringBuilder();
1848            buf.append("@");
1849            buf.append(type.tsym.getQualifiedName());
1850            buf.append("/*proxy*/{");
1851            boolean first = true;
1852            for (List<Pair<Name,Attribute>> v = values;
1853                 v.nonEmpty(); v = v.tail) {
1854                Pair<Name,Attribute> value = v.head;
1855                if (!first) buf.append(",");
1856                first = false;
1857                buf.append(value.fst);
1858                buf.append("=");
1859                buf.append(value.snd);
1860            }
1861            buf.append("}");
1862            return buf.toString();
1863        }
1864    }
1865
1866    /** A temporary proxy representing a type annotation.
1867     */
1868    static class TypeAnnotationProxy {
1869        final CompoundAnnotationProxy compound;
1870        final TypeAnnotationPosition position;
1871        public TypeAnnotationProxy(CompoundAnnotationProxy compound,
1872                TypeAnnotationPosition position) {
1873            this.compound = compound;
1874            this.position = position;
1875        }
1876    }
1877
1878    class AnnotationDeproxy implements ProxyVisitor {
1879        private ClassSymbol requestingOwner;
1880
1881        AnnotationDeproxy(ClassSymbol owner) {
1882            this.requestingOwner = owner;
1883        }
1884
1885        List<Attribute.Compound> deproxyCompoundList(List<CompoundAnnotationProxy> pl) {
1886            // also must fill in types!!!!
1887            ListBuffer<Attribute.Compound> buf = new ListBuffer<>();
1888            for (List<CompoundAnnotationProxy> l = pl; l.nonEmpty(); l=l.tail) {
1889                buf.append(deproxyCompound(l.head));
1890            }
1891            return buf.toList();
1892        }
1893
1894        Attribute.Compound deproxyCompound(CompoundAnnotationProxy a) {
1895            ListBuffer<Pair<Symbol.MethodSymbol,Attribute>> buf = new ListBuffer<>();
1896            for (List<Pair<Name,Attribute>> l = a.values;
1897                 l.nonEmpty();
1898                 l = l.tail) {
1899                MethodSymbol meth = findAccessMethod(a.type, l.head.fst);
1900                buf.append(new Pair<>(meth, deproxy(meth.type.getReturnType(), l.head.snd)));
1901            }
1902            return new Attribute.Compound(a.type, buf.toList());
1903        }
1904
1905        MethodSymbol findAccessMethod(Type container, Name name) {
1906            CompletionFailure failure = null;
1907            try {
1908                for (Symbol sym : container.tsym.members().getSymbolsByName(name)) {
1909                    if (sym.kind == MTH && sym.type.getParameterTypes().length() == 0)
1910                        return (MethodSymbol) sym;
1911                }
1912            } catch (CompletionFailure ex) {
1913                failure = ex;
1914            }
1915            // The method wasn't found: emit a warning and recover
1916            JavaFileObject prevSource = log.useSource(requestingOwner.classfile);
1917            try {
1918                if (lintClassfile) {
1919                    if (failure == null) {
1920                        log.warning("annotation.method.not.found",
1921                                    container,
1922                                    name);
1923                    } else {
1924                        log.warning("annotation.method.not.found.reason",
1925                                    container,
1926                                    name,
1927                                    failure.getDetailValue());//diagnostic, if present
1928                    }
1929                }
1930            } finally {
1931                log.useSource(prevSource);
1932            }
1933            // Construct a new method type and symbol.  Use bottom
1934            // type (typeof null) as return type because this type is
1935            // a subtype of all reference types and can be converted
1936            // to primitive types by unboxing.
1937            MethodType mt = new MethodType(List.<Type>nil(),
1938                                           syms.botType,
1939                                           List.<Type>nil(),
1940                                           syms.methodClass);
1941            return new MethodSymbol(PUBLIC | ABSTRACT, name, mt, container.tsym);
1942        }
1943
1944        Attribute result;
1945        Type type;
1946        Attribute deproxy(Type t, Attribute a) {
1947            Type oldType = type;
1948            try {
1949                type = t;
1950                a.accept(this);
1951                return result;
1952            } finally {
1953                type = oldType;
1954            }
1955        }
1956
1957        // implement Attribute.Visitor below
1958
1959        public void visitConstant(Attribute.Constant value) {
1960            // assert value.type == type;
1961            result = value;
1962        }
1963
1964        public void visitClass(Attribute.Class clazz) {
1965            result = clazz;
1966        }
1967
1968        public void visitEnum(Attribute.Enum e) {
1969            throw new AssertionError(); // shouldn't happen
1970        }
1971
1972        public void visitCompound(Attribute.Compound compound) {
1973            throw new AssertionError(); // shouldn't happen
1974        }
1975
1976        public void visitArray(Attribute.Array array) {
1977            throw new AssertionError(); // shouldn't happen
1978        }
1979
1980        public void visitError(Attribute.Error e) {
1981            throw new AssertionError(); // shouldn't happen
1982        }
1983
1984        public void visitEnumAttributeProxy(EnumAttributeProxy proxy) {
1985            // type.tsym.flatName() should == proxy.enumFlatName
1986            TypeSymbol enumTypeSym = proxy.enumType.tsym;
1987            VarSymbol enumerator = null;
1988            CompletionFailure failure = null;
1989            try {
1990                for (Symbol sym : enumTypeSym.members().getSymbolsByName(proxy.enumerator)) {
1991                    if (sym.kind == VAR) {
1992                        enumerator = (VarSymbol)sym;
1993                        break;
1994                    }
1995                }
1996            }
1997            catch (CompletionFailure ex) {
1998                failure = ex;
1999            }
2000            if (enumerator == null) {
2001                if (failure != null) {
2002                    log.warning("unknown.enum.constant.reason",
2003                              currentClassFile, enumTypeSym, proxy.enumerator,
2004                              failure.getDiagnostic());
2005                } else {
2006                    log.warning("unknown.enum.constant",
2007                              currentClassFile, enumTypeSym, proxy.enumerator);
2008                }
2009                result = new Attribute.Enum(enumTypeSym.type,
2010                        new VarSymbol(0, proxy.enumerator, syms.botType, enumTypeSym));
2011            } else {
2012                result = new Attribute.Enum(enumTypeSym.type, enumerator);
2013            }
2014        }
2015
2016        public void visitArrayAttributeProxy(ArrayAttributeProxy proxy) {
2017            int length = proxy.values.length();
2018            Attribute[] ats = new Attribute[length];
2019            Type elemtype = types.elemtype(type);
2020            int i = 0;
2021            for (List<Attribute> p = proxy.values; p.nonEmpty(); p = p.tail) {
2022                ats[i++] = deproxy(elemtype, p.head);
2023            }
2024            result = new Attribute.Array(type, ats);
2025        }
2026
2027        public void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy) {
2028            result = deproxyCompound(proxy);
2029        }
2030    }
2031
2032    class AnnotationDefaultCompleter extends AnnotationDeproxy implements Runnable {
2033        final MethodSymbol sym;
2034        final Attribute value;
2035        final JavaFileObject classFile = currentClassFile;
2036
2037        AnnotationDefaultCompleter(MethodSymbol sym, Attribute value) {
2038            super(currentOwner.kind == MTH
2039                    ? currentOwner.enclClass() : (ClassSymbol)currentOwner);
2040            this.sym = sym;
2041            this.value = value;
2042        }
2043
2044        @Override
2045        public void run() {
2046            JavaFileObject previousClassFile = currentClassFile;
2047            try {
2048                // Reset the interim value set earlier in
2049                // attachAnnotationDefault().
2050                sym.defaultValue = null;
2051                currentClassFile = classFile;
2052                sym.defaultValue = deproxy(sym.type.getReturnType(), value);
2053            } finally {
2054                currentClassFile = previousClassFile;
2055            }
2056        }
2057
2058        @Override
2059        public String toString() {
2060            return " ClassReader store default for " + sym.owner + "." + sym + " is " + value;
2061        }
2062    }
2063
2064    class AnnotationCompleter extends AnnotationDeproxy implements Runnable {
2065        final Symbol sym;
2066        final List<CompoundAnnotationProxy> l;
2067        final JavaFileObject classFile;
2068
2069        AnnotationCompleter(Symbol sym, List<CompoundAnnotationProxy> l) {
2070            super(currentOwner.kind == MTH
2071                    ? currentOwner.enclClass() : (ClassSymbol)currentOwner);
2072            this.sym = sym;
2073            this.l = l;
2074            this.classFile = currentClassFile;
2075        }
2076
2077        @Override
2078        public void run() {
2079            JavaFileObject previousClassFile = currentClassFile;
2080            try {
2081                currentClassFile = classFile;
2082                List<Attribute.Compound> newList = deproxyCompoundList(l);
2083                if (sym.annotationsPendingCompletion()) {
2084                    sym.setDeclarationAttributes(newList);
2085                } else {
2086                    sym.appendAttributes(newList);
2087                }
2088            } finally {
2089                currentClassFile = previousClassFile;
2090            }
2091        }
2092
2093        @Override
2094        public String toString() {
2095            return " ClassReader annotate " + sym.owner + "." + sym + " with " + l;
2096        }
2097    }
2098
2099    class TypeAnnotationCompleter extends AnnotationCompleter {
2100
2101        List<TypeAnnotationProxy> proxies;
2102
2103        TypeAnnotationCompleter(Symbol sym,
2104                List<TypeAnnotationProxy> proxies) {
2105            super(sym, List.<CompoundAnnotationProxy>nil());
2106            this.proxies = proxies;
2107        }
2108
2109        List<Attribute.TypeCompound> deproxyTypeCompoundList(List<TypeAnnotationProxy> proxies) {
2110            ListBuffer<Attribute.TypeCompound> buf = new ListBuffer<>();
2111            for (TypeAnnotationProxy proxy: proxies) {
2112                Attribute.Compound compound = deproxyCompound(proxy.compound);
2113                Attribute.TypeCompound typeCompound = new Attribute.TypeCompound(compound, proxy.position);
2114                buf.add(typeCompound);
2115            }
2116            return buf.toList();
2117        }
2118
2119        @Override
2120        public void run() {
2121            JavaFileObject previousClassFile = currentClassFile;
2122            try {
2123                currentClassFile = classFile;
2124                List<Attribute.TypeCompound> newList = deproxyTypeCompoundList(proxies);
2125                sym.setTypeAttributes(newList.prependList(sym.getRawTypeAttributes()));
2126            } finally {
2127                currentClassFile = previousClassFile;
2128            }
2129        }
2130    }
2131
2132
2133/************************************************************************
2134 * Reading Symbols
2135 ***********************************************************************/
2136
2137    /** Read a field.
2138     */
2139    VarSymbol readField() {
2140        long flags = adjustFieldFlags(nextChar());
2141        Name name = readName(nextChar());
2142        Type type = readType(nextChar());
2143        VarSymbol v = new VarSymbol(flags, name, type, currentOwner);
2144        readMemberAttrs(v);
2145        return v;
2146    }
2147
2148    /** Read a method.
2149     */
2150    MethodSymbol readMethod() {
2151        long flags = adjustMethodFlags(nextChar());
2152        Name name = readName(nextChar());
2153        Type type = readType(nextChar());
2154        if (currentOwner.isInterface() &&
2155                (flags & ABSTRACT) == 0 && !name.equals(names.clinit)) {
2156            if (majorVersion > Version.V52.major ||
2157                    (majorVersion == Version.V52.major && minorVersion >= Version.V52.minor)) {
2158                if ((flags & STATIC) == 0) {
2159                    currentOwner.flags_field |= DEFAULT;
2160                    flags |= DEFAULT | ABSTRACT;
2161                }
2162            } else {
2163                //protect against ill-formed classfiles
2164                throw badClassFile((flags & STATIC) == 0 ? "invalid.default.interface" : "invalid.static.interface",
2165                                   Integer.toString(majorVersion),
2166                                   Integer.toString(minorVersion));
2167            }
2168        }
2169        if (name == names.init && currentOwner.hasOuterInstance()) {
2170            // Sometimes anonymous classes don't have an outer
2171            // instance, however, there is no reliable way to tell so
2172            // we never strip this$n
2173            if (!currentOwner.name.isEmpty())
2174                type = new MethodType(adjustMethodParams(flags, type.getParameterTypes()),
2175                                      type.getReturnType(),
2176                                      type.getThrownTypes(),
2177                                      syms.methodClass);
2178        }
2179        MethodSymbol m = new MethodSymbol(flags, name, type, currentOwner);
2180        if (types.isSignaturePolymorphic(m)) {
2181            m.flags_field |= SIGNATURE_POLYMORPHIC;
2182        }
2183        if (saveParameterNames)
2184            initParameterNames(m);
2185        Symbol prevOwner = currentOwner;
2186        currentOwner = m;
2187        try {
2188            readMemberAttrs(m);
2189        } finally {
2190            currentOwner = prevOwner;
2191        }
2192        if (saveParameterNames)
2193            setParameterNames(m, type);
2194
2195        if ((flags & VARARGS) != 0) {
2196            final Type last = type.getParameterTypes().last();
2197            if (last == null || !last.hasTag(ARRAY)) {
2198                m.flags_field &= ~VARARGS;
2199                throw badClassFile("malformed.vararg.method", m);
2200            }
2201        }
2202
2203        return m;
2204    }
2205
2206    private List<Type> adjustMethodParams(long flags, List<Type> args) {
2207        boolean isVarargs = (flags & VARARGS) != 0;
2208        if (isVarargs) {
2209            Type varargsElem = args.last();
2210            ListBuffer<Type> adjustedArgs = new ListBuffer<>();
2211            for (Type t : args) {
2212                adjustedArgs.append(t != varargsElem ?
2213                    t :
2214                    ((ArrayType)t).makeVarargs());
2215            }
2216            args = adjustedArgs.toList();
2217        }
2218        return args.tail;
2219    }
2220
2221    /**
2222     * Init the parameter names array.
2223     * Parameter names are currently inferred from the names in the
2224     * LocalVariableTable attributes of a Code attribute.
2225     * (Note: this means parameter names are currently not available for
2226     * methods without a Code attribute.)
2227     * This method initializes an array in which to store the name indexes
2228     * of parameter names found in LocalVariableTable attributes. It is
2229     * slightly supersized to allow for additional slots with a start_pc of 0.
2230     */
2231    void initParameterNames(MethodSymbol sym) {
2232        // make allowance for synthetic parameters.
2233        final int excessSlots = 4;
2234        int expectedParameterSlots =
2235                Code.width(sym.type.getParameterTypes()) + excessSlots;
2236        if (parameterNameIndices == null
2237                || parameterNameIndices.length < expectedParameterSlots) {
2238            parameterNameIndices = new int[expectedParameterSlots];
2239        } else
2240            Arrays.fill(parameterNameIndices, 0);
2241        haveParameterNameIndices = false;
2242        sawMethodParameters = false;
2243    }
2244
2245    /**
2246     * Set the parameter names for a symbol from the name index in the
2247     * parameterNameIndicies array. The type of the symbol may have changed
2248     * while reading the method attributes (see the Signature attribute).
2249     * This may be because of generic information or because anonymous
2250     * synthetic parameters were added.   The original type (as read from
2251     * the method descriptor) is used to help guess the existence of
2252     * anonymous synthetic parameters.
2253     * On completion, sym.savedParameter names will either be null (if
2254     * no parameter names were found in the class file) or will be set to a
2255     * list of names, one per entry in sym.type.getParameterTypes, with
2256     * any missing names represented by the empty name.
2257     */
2258    void setParameterNames(MethodSymbol sym, Type jvmType) {
2259        // if no names were found in the class file, there's nothing more to do
2260        if (!haveParameterNameIndices)
2261            return;
2262        // If we get parameter names from MethodParameters, then we
2263        // don't need to skip.
2264        int firstParam = 0;
2265        if (!sawMethodParameters) {
2266            firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0;
2267            // the code in readMethod may have skipped the first
2268            // parameter when setting up the MethodType. If so, we
2269            // make a corresponding allowance here for the position of
2270            // the first parameter.  Note that this assumes the
2271            // skipped parameter has a width of 1 -- i.e. it is not
2272        // a double width type (long or double.)
2273        if (sym.name == names.init && currentOwner.hasOuterInstance()) {
2274            // Sometimes anonymous classes don't have an outer
2275            // instance, however, there is no reliable way to tell so
2276            // we never strip this$n
2277            if (!currentOwner.name.isEmpty())
2278                firstParam += 1;
2279        }
2280
2281        if (sym.type != jvmType) {
2282                // reading the method attributes has caused the
2283                // symbol's type to be changed. (i.e. the Signature
2284                // attribute.)  This may happen if there are hidden
2285                // (synthetic) parameters in the descriptor, but not
2286                // in the Signature.  The position of these hidden
2287                // parameters is unspecified; for now, assume they are
2288                // at the beginning, and so skip over them. The
2289                // primary case for this is two hidden parameters
2290                // passed into Enum constructors.
2291            int skip = Code.width(jvmType.getParameterTypes())
2292                    - Code.width(sym.type.getParameterTypes());
2293            firstParam += skip;
2294        }
2295        }
2296        List<Name> paramNames = List.nil();
2297        int index = firstParam;
2298        for (Type t: sym.type.getParameterTypes()) {
2299            int nameIdx = (index < parameterNameIndices.length
2300                    ? parameterNameIndices[index] : 0);
2301            Name name = nameIdx == 0 ? names.empty : readName(nameIdx);
2302            paramNames = paramNames.prepend(name);
2303            index += Code.width(t);
2304        }
2305        sym.savedParameterNames = paramNames.reverse();
2306    }
2307
2308    /**
2309     * skip n bytes
2310     */
2311    void skipBytes(int n) {
2312        bp = bp + n;
2313    }
2314
2315    /** Skip a field or method
2316     */
2317    void skipMember() {
2318        bp = bp + 6;
2319        char ac = nextChar();
2320        for (int i = 0; i < ac; i++) {
2321            bp = bp + 2;
2322            int attrLen = nextInt();
2323            bp = bp + attrLen;
2324        }
2325    }
2326
2327    void skipInnerClasses() {
2328        int n = nextChar();
2329        for (int i = 0; i < n; i++) {
2330            nextChar();
2331            nextChar();
2332            nextChar();
2333            nextChar();
2334        }
2335    }
2336
2337    /** Enter type variables of this classtype and all enclosing ones in
2338     *  `typevars'.
2339     */
2340    protected void enterTypevars(Type t) {
2341        if (t.getEnclosingType() != null && t.getEnclosingType().hasTag(CLASS))
2342            enterTypevars(t.getEnclosingType());
2343        for (List<Type> xs = t.getTypeArguments(); xs.nonEmpty(); xs = xs.tail)
2344            typevars.enter(xs.head.tsym);
2345    }
2346
2347    protected void enterTypevars(Symbol sym) {
2348        if (sym.owner.kind == MTH) {
2349            enterTypevars(sym.owner);
2350            enterTypevars(sym.owner.owner);
2351        }
2352        enterTypevars(sym.type);
2353    }
2354
2355    protected ClassSymbol enterClass(Name name) {
2356        return syms.enterClass(currentModule, name);
2357    }
2358
2359    protected ClassSymbol enterClass(Name name, TypeSymbol owner) {
2360        return syms.enterClass(currentModule, name, owner);
2361    }
2362
2363    /** Read contents of a given class symbol `c'. Both external and internal
2364     *  versions of an inner class are read.
2365     */
2366    void readClass(ClassSymbol c) {
2367        ClassType ct = (ClassType)c.type;
2368
2369        // allocate scope for members
2370        c.members_field = WriteableScope.create(c);
2371
2372        // prepare type variable table
2373        typevars = typevars.dup(currentOwner);
2374        if (ct.getEnclosingType().hasTag(CLASS))
2375            enterTypevars(ct.getEnclosingType());
2376
2377        // read flags, or skip if this is an inner class
2378        long f = nextChar();
2379        long flags = adjustClassFlags(f);
2380        if ((flags & MODULE) == 0) {
2381            if (c.owner.kind == PCK) c.flags_field = flags;
2382            // read own class name and check that it matches
2383            currentModule = c.packge().modle;
2384            ClassSymbol self = readClassSymbol(nextChar());
2385            if (c != self) {
2386                throw badClassFile("class.file.wrong.class",
2387                                   self.flatname);
2388            }
2389        } else {
2390            c.flags_field = flags;
2391            Name modInfoName = readModuleInfoName(nextChar());
2392            if (c.owner.name == null) {
2393                syms.enterModule((ModuleSymbol) c.owner, Convert.packagePart(modInfoName));
2394            } else {
2395                // TODO: validate name
2396            }
2397            currentModule = (ModuleSymbol) c.owner;
2398        }
2399
2400        // class attributes must be read before class
2401        // skip ahead to read class attributes
2402        int startbp = bp;
2403        nextChar();
2404        char interfaceCount = nextChar();
2405        bp += interfaceCount * 2;
2406        char fieldCount = nextChar();
2407        for (int i = 0; i < fieldCount; i++) skipMember();
2408        char methodCount = nextChar();
2409        for (int i = 0; i < methodCount; i++) skipMember();
2410        readClassAttrs(c);
2411
2412        if (readAllOfClassFile) {
2413            for (int i = 1; i < poolObj.length; i++) readPool(i);
2414            c.pool = new Pool(poolObj.length, poolObj, types);
2415        }
2416
2417        // reset and read rest of classinfo
2418        bp = startbp;
2419        int n = nextChar();
2420        if (ct.supertype_field == null)
2421            ct.supertype_field = (n == 0)
2422                ? Type.noType
2423                : readClassSymbol(n).erasure(types);
2424        n = nextChar();
2425        List<Type> is = List.nil();
2426        for (int i = 0; i < n; i++) {
2427            Type _inter = readClassSymbol(nextChar()).erasure(types);
2428            is = is.prepend(_inter);
2429        }
2430        if (ct.interfaces_field == null)
2431            ct.interfaces_field = is.reverse();
2432
2433        Assert.check(fieldCount == nextChar());
2434        for (int i = 0; i < fieldCount; i++) enterMember(c, readField());
2435        Assert.check(methodCount == nextChar());
2436        for (int i = 0; i < methodCount; i++) enterMember(c, readMethod());
2437
2438        typevars = typevars.leave();
2439    }
2440
2441    /** Read inner class info. For each inner/outer pair allocate a
2442     *  member class.
2443     */
2444    void readInnerClasses(ClassSymbol c) {
2445        int n = nextChar();
2446        for (int i = 0; i < n; i++) {
2447            nextChar(); // skip inner class symbol
2448            ClassSymbol outer = readClassSymbol(nextChar());
2449            Name name = readName(nextChar());
2450            if (name == null) name = names.empty;
2451            long flags = adjustClassFlags(nextChar());
2452            if (outer != null) { // we have a member class
2453                if (name == names.empty)
2454                    name = names.one;
2455                ClassSymbol member = enterClass(name, outer);
2456                if ((flags & STATIC) == 0) {
2457                    ((ClassType)member.type).setEnclosingType(outer.type);
2458                    if (member.erasure_field != null)
2459                        ((ClassType)member.erasure_field).setEnclosingType(types.erasure(outer.type));
2460                }
2461                if (c == outer) {
2462                    member.flags_field = flags;
2463                    enterMember(c, member);
2464                }
2465            }
2466        }
2467    }
2468
2469    /** Read a class definition from the bytes in buf.
2470     */
2471    private void readClassBuffer(ClassSymbol c) throws IOException {
2472        int magic = nextInt();
2473        if (magic != JAVA_MAGIC)
2474            throw badClassFile("illegal.start.of.class.file");
2475
2476        minorVersion = nextChar();
2477        majorVersion = nextChar();
2478        int maxMajor = Version.MAX().major;
2479        int maxMinor = Version.MAX().minor;
2480        if (majorVersion > maxMajor ||
2481            majorVersion * 1000 + minorVersion <
2482            Version.MIN().major * 1000 + Version.MIN().minor) {
2483            if (majorVersion == (maxMajor + 1))
2484                log.warning("big.major.version",
2485                            currentClassFile,
2486                            majorVersion,
2487                            maxMajor);
2488            else
2489                throw badClassFile("wrong.version",
2490                                   Integer.toString(majorVersion),
2491                                   Integer.toString(minorVersion),
2492                                   Integer.toString(maxMajor),
2493                                   Integer.toString(maxMinor));
2494        }
2495
2496        indexPool();
2497        if (signatureBuffer.length < bp) {
2498            int ns = Integer.highestOneBit(bp) << 1;
2499            signatureBuffer = new byte[ns];
2500        }
2501        readClass(c);
2502    }
2503
2504    public void readClassFile(ClassSymbol c) {
2505        currentOwner = c;
2506        currentClassFile = c.classfile;
2507        warnedAttrs.clear();
2508        filling = true;
2509        target = null;
2510        repeatable = null;
2511        try {
2512            bp = 0;
2513            buf = readInputStream(buf, c.classfile.openInputStream());
2514            readClassBuffer(c);
2515            if (!missingTypeVariables.isEmpty() && !foundTypeVariables.isEmpty()) {
2516                List<Type> missing = missingTypeVariables;
2517                List<Type> found = foundTypeVariables;
2518                missingTypeVariables = List.nil();
2519                foundTypeVariables = List.nil();
2520                filling = false;
2521                ClassType ct = (ClassType)currentOwner.type;
2522                ct.supertype_field =
2523                    types.subst(ct.supertype_field, missing, found);
2524                ct.interfaces_field =
2525                    types.subst(ct.interfaces_field, missing, found);
2526            } else if (missingTypeVariables.isEmpty() !=
2527                       foundTypeVariables.isEmpty()) {
2528                Name name = missingTypeVariables.head.tsym.name;
2529                throw badClassFile("undecl.type.var", name);
2530            }
2531
2532            if ((c.flags_field & Flags.ANNOTATION) != 0) {
2533                c.setAnnotationTypeMetadata(new AnnotationTypeMetadata(c, new CompleterDeproxy(c, target, repeatable)));
2534            } else {
2535                c.setAnnotationTypeMetadata(AnnotationTypeMetadata.notAnAnnotationType());
2536            }
2537
2538            if (c == currentModule.module_info) {
2539                if (interimUses.nonEmpty() || interimProvides.nonEmpty()) {
2540                    Assert.check(currentModule.isCompleted());
2541                    currentModule.usesProvidesCompleter =
2542                            new UsesProvidesCompleter(currentModule, interimUses, interimProvides);
2543                } else {
2544                    currentModule.uses = List.nil();
2545                    currentModule.provides = List.nil();
2546                }
2547            }
2548        } catch (IOException ex) {
2549            throw badClassFile("unable.to.access.file", ex.getMessage());
2550        } catch (ArrayIndexOutOfBoundsException ex) {
2551            throw badClassFile("bad.class.file", c.flatname);
2552        } finally {
2553            interimUses = List.nil();
2554            interimProvides = List.nil();
2555            missingTypeVariables = List.nil();
2556            foundTypeVariables = List.nil();
2557            filling = false;
2558        }
2559    }
2560    // where
2561        private static byte[] readInputStream(byte[] buf, InputStream s) throws IOException {
2562            try {
2563                buf = ensureCapacity(buf, s.available());
2564                int r = s.read(buf);
2565                int bp = 0;
2566                while (r != -1) {
2567                    bp += r;
2568                    buf = ensureCapacity(buf, bp);
2569                    r = s.read(buf, bp, buf.length - bp);
2570                }
2571                return buf;
2572            } finally {
2573                try {
2574                    s.close();
2575                } catch (IOException e) {
2576                    /* Ignore any errors, as this stream may have already
2577                     * thrown a related exception which is the one that
2578                     * should be reported.
2579                     */
2580                }
2581            }
2582        }
2583        /*
2584         * ensureCapacity will increase the buffer as needed, taking note that
2585         * the new buffer will always be greater than the needed and never
2586         * exactly equal to the needed size or bp. If equal then the read (above)
2587         * will infinitely loop as buf.length - bp == 0.
2588         */
2589        private static byte[] ensureCapacity(byte[] buf, int needed) {
2590            if (buf.length <= needed) {
2591                byte[] old = buf;
2592                buf = new byte[Integer.highestOneBit(needed) << 1];
2593                System.arraycopy(old, 0, buf, 0, old.length);
2594            }
2595            return buf;
2596        }
2597
2598    /** We can only read a single class file at a time; this
2599     *  flag keeps track of when we are currently reading a class
2600     *  file.
2601     */
2602    public boolean filling = false;
2603
2604/************************************************************************
2605 * Adjusting flags
2606 ***********************************************************************/
2607
2608    long adjustFieldFlags(long flags) {
2609        return flags;
2610    }
2611
2612    long adjustMethodFlags(long flags) {
2613        if ((flags & ACC_BRIDGE) != 0) {
2614            flags &= ~ACC_BRIDGE;
2615            flags |= BRIDGE;
2616        }
2617        if ((flags & ACC_VARARGS) != 0) {
2618            flags &= ~ACC_VARARGS;
2619            flags |= VARARGS;
2620        }
2621        return flags;
2622    }
2623
2624    long adjustClassFlags(long flags) {
2625        if ((flags & ACC_MODULE) != 0) {
2626            flags &= ~ACC_MODULE;
2627            flags |= MODULE;
2628        }
2629        return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
2630    }
2631
2632    /**
2633     * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
2634     * The attribute is only the last component of the original filename, so is unlikely
2635     * to be valid as is, so operations other than those to access the name throw
2636     * UnsupportedOperationException
2637     */
2638    private static class SourceFileObject implements JavaFileObject {
2639
2640        /** The file's name.
2641         */
2642        private final Name name;
2643        private final Name flatname;
2644
2645        public SourceFileObject(Name name, Name flatname) {
2646            this.name = name;
2647            this.flatname = flatname;
2648        }
2649
2650        @Override @DefinedBy(Api.COMPILER)
2651        public URI toUri() {
2652            try {
2653                return new URI(null, name.toString(), null);
2654            } catch (URISyntaxException e) {
2655                throw new PathFileObject.CannotCreateUriError(name.toString(), e);
2656            }
2657        }
2658
2659        @Override @DefinedBy(Api.COMPILER)
2660        public String getName() {
2661            return name.toString();
2662        }
2663
2664        @Override @DefinedBy(Api.COMPILER)
2665        public JavaFileObject.Kind getKind() {
2666            return BaseFileManager.getKind(getName());
2667        }
2668
2669        @Override @DefinedBy(Api.COMPILER)
2670        public InputStream openInputStream() {
2671            throw new UnsupportedOperationException();
2672        }
2673
2674        @Override @DefinedBy(Api.COMPILER)
2675        public OutputStream openOutputStream() {
2676            throw new UnsupportedOperationException();
2677        }
2678
2679        @Override @DefinedBy(Api.COMPILER)
2680        public CharBuffer getCharContent(boolean ignoreEncodingErrors) {
2681            throw new UnsupportedOperationException();
2682        }
2683
2684        @Override @DefinedBy(Api.COMPILER)
2685        public Reader openReader(boolean ignoreEncodingErrors) {
2686            throw new UnsupportedOperationException();
2687        }
2688
2689        @Override @DefinedBy(Api.COMPILER)
2690        public Writer openWriter() {
2691            throw new UnsupportedOperationException();
2692        }
2693
2694        @Override @DefinedBy(Api.COMPILER)
2695        public long getLastModified() {
2696            throw new UnsupportedOperationException();
2697        }
2698
2699        @Override @DefinedBy(Api.COMPILER)
2700        public boolean delete() {
2701            throw new UnsupportedOperationException();
2702        }
2703
2704        @Override @DefinedBy(Api.COMPILER)
2705        public boolean isNameCompatible(String simpleName, JavaFileObject.Kind kind) {
2706            return true; // fail-safe mode
2707        }
2708
2709        @Override @DefinedBy(Api.COMPILER)
2710        public NestingKind getNestingKind() {
2711            return null;
2712        }
2713
2714        @Override @DefinedBy(Api.COMPILER)
2715        public Modifier getAccessLevel() {
2716            return null;
2717        }
2718
2719        /**
2720         * Check if two file objects are equal.
2721         * SourceFileObjects are just placeholder objects for the value of a
2722         * SourceFile attribute, and do not directly represent specific files.
2723         * Two SourceFileObjects are equal if their names are equal.
2724         */
2725        @Override
2726        public boolean equals(Object other) {
2727            if (this == other)
2728                return true;
2729
2730            if (!(other instanceof SourceFileObject))
2731                return false;
2732
2733            SourceFileObject o = (SourceFileObject) other;
2734            return name.equals(o.name);
2735        }
2736
2737        @Override
2738        public int hashCode() {
2739            return name.hashCode();
2740        }
2741    }
2742
2743    private class CompleterDeproxy implements AnnotationTypeCompleter {
2744        ClassSymbol proxyOn;
2745        CompoundAnnotationProxy target;
2746        CompoundAnnotationProxy repeatable;
2747
2748        public CompleterDeproxy(ClassSymbol c, CompoundAnnotationProxy target,
2749                CompoundAnnotationProxy repeatable)
2750        {
2751            this.proxyOn = c;
2752            this.target = target;
2753            this.repeatable = repeatable;
2754        }
2755
2756        @Override
2757        public void complete(ClassSymbol sym) {
2758            Assert.check(proxyOn == sym);
2759            Attribute.Compound theTarget = null, theRepeatable = null;
2760            AnnotationDeproxy deproxy;
2761
2762            try {
2763                if (target != null) {
2764                    deproxy = new AnnotationDeproxy(proxyOn);
2765                    theTarget = deproxy.deproxyCompound(target);
2766                }
2767
2768                if (repeatable != null) {
2769                    deproxy = new AnnotationDeproxy(proxyOn);
2770                    theRepeatable = deproxy.deproxyCompound(repeatable);
2771                }
2772            } catch (Exception e) {
2773                throw new CompletionFailure(sym, e.getMessage());
2774            }
2775
2776            sym.getAnnotationTypeMetadata().setTarget(theTarget);
2777            sym.getAnnotationTypeMetadata().setRepeatable(theRepeatable);
2778        }
2779    }
2780
2781    private static final class InterimUsesDirective {
2782        public final Name service;
2783
2784        public InterimUsesDirective(Name service) {
2785            this.service = service;
2786        }
2787
2788    }
2789
2790    private static final class InterimProvidesDirective {
2791        public final Name service;
2792        public final Name impl;
2793
2794        public InterimProvidesDirective(Name service, Name impl) {
2795            this.service = service;
2796            this.impl = impl;
2797        }
2798
2799    }
2800
2801    private final class UsesProvidesCompleter implements Completer {
2802        private final ModuleSymbol currentModule;
2803        private final List<InterimUsesDirective> interimUsesCopy;
2804        private final List<InterimProvidesDirective> interimProvidesCopy;
2805
2806        public UsesProvidesCompleter(ModuleSymbol currentModule, List<InterimUsesDirective> interimUsesCopy, List<InterimProvidesDirective> interimProvidesCopy) {
2807            this.currentModule = currentModule;
2808            this.interimUsesCopy = interimUsesCopy;
2809            this.interimProvidesCopy = interimProvidesCopy;
2810        }
2811
2812        @Override
2813        public void complete(Symbol sym) throws CompletionFailure {
2814            ListBuffer<Directive> directives = new ListBuffer<>();
2815            directives.addAll(currentModule.directives);
2816            ListBuffer<UsesDirective> uses = new ListBuffer<>();
2817            for (InterimUsesDirective interim : interimUsesCopy) {
2818                UsesDirective d = new UsesDirective(syms.enterClass(currentModule, interim.service));
2819                uses.add(d);
2820                directives.add(d);
2821            }
2822            currentModule.uses = uses.toList();
2823            ListBuffer<ProvidesDirective> provides = new ListBuffer<>();
2824            for (InterimProvidesDirective interim : interimProvidesCopy) {
2825                ProvidesDirective d = new ProvidesDirective(syms.enterClass(currentModule, interim.service),
2826                                                            syms.enterClass(currentModule, interim.impl));
2827                provides.add(d);
2828                directives.add(d);
2829            }
2830            currentModule.provides = provides.toList();
2831            currentModule.directives = directives.toList();
2832        }
2833    }
2834}
2835