ClassReader.java revision 3850:8e69054abeeb
1/*
2 * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.tools.javac.jvm;
27
28import java.io.*;
29import java.net.URI;
30import java.net.URISyntaxException;
31import java.nio.CharBuffer;
32import java.util.Arrays;
33import java.util.EnumSet;
34import java.util.HashMap;
35import java.util.HashSet;
36import java.util.Map;
37import java.util.Set;
38
39import javax.lang.model.element.Modifier;
40import javax.lang.model.element.NestingKind;
41import javax.tools.JavaFileManager;
42import javax.tools.JavaFileObject;
43
44import com.sun.tools.javac.comp.Annotate;
45import com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter;
46import com.sun.tools.javac.code.*;
47import com.sun.tools.javac.code.Directive.*;
48import com.sun.tools.javac.code.Lint.LintCategory;
49import com.sun.tools.javac.code.Scope.WriteableScope;
50import com.sun.tools.javac.code.Symbol.*;
51import com.sun.tools.javac.code.Symtab;
52import com.sun.tools.javac.code.Type.*;
53import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
54import com.sun.tools.javac.file.BaseFileManager;
55import com.sun.tools.javac.file.PathFileObject;
56import com.sun.tools.javac.jvm.ClassFile.NameAndType;
57import com.sun.tools.javac.jvm.ClassFile.Version;
58import com.sun.tools.javac.main.Option;
59import com.sun.tools.javac.util.*;
60import com.sun.tools.javac.util.DefinedBy.Api;
61import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
62
63import static com.sun.tools.javac.code.Flags.*;
64import static com.sun.tools.javac.code.Kinds.Kind.*;
65
66import com.sun.tools.javac.code.Scope.LookupKind;
67
68import static com.sun.tools.javac.code.TypeTag.ARRAY;
69import static com.sun.tools.javac.code.TypeTag.CLASS;
70import static com.sun.tools.javac.code.TypeTag.TYPEVAR;
71import static com.sun.tools.javac.jvm.ClassFile.*;
72import static com.sun.tools.javac.jvm.ClassFile.Version.*;
73
74import static com.sun.tools.javac.main.Option.PARAMETERS;
75
76/** This class provides operations to read a classfile into an internal
77 *  representation. The internal representation is anchored in a
78 *  ClassSymbol which contains in its scope symbol representations
79 *  for all other definitions in the classfile. Top-level Classes themselves
80 *  appear as members of the scopes of PackageSymbols.
81 *
82 *  <p><b>This is NOT part of any supported API.
83 *  If you write code that depends on this, you do so at your own risk.
84 *  This code and its internal interfaces are subject to change or
85 *  deletion without notice.</b>
86 */
87public class ClassReader {
88    /** The context key for the class reader. */
89    protected static final Context.Key<ClassReader> classReaderKey = new Context.Key<>();
90
91    public static final int INITIAL_BUFFER_SIZE = 0x0fff0;
92
93    private final Annotate annotate;
94
95    /** Switch: verbose output.
96     */
97    boolean verbose;
98
99    /** Switch: read constant pool and code sections. This switch is initially
100     *  set to false but can be turned on from outside.
101     */
102    public boolean readAllOfClassFile = false;
103
104    /** Switch: allow simplified varargs.
105     */
106    boolean allowSimplifiedVarargs;
107
108    /** Switch: allow modules.
109     */
110    boolean allowModules;
111
112   /** Lint option: warn about classfile issues
113     */
114    boolean lintClassfile;
115
116    /** Switch: preserve parameter names from the variable table.
117     */
118    public boolean saveParameterNames;
119
120    /**
121     * The currently selected profile.
122     */
123    public final Profile profile;
124
125    /** The log to use for verbose output
126     */
127    final Log log;
128
129    /** The symbol table. */
130    Symtab syms;
131
132    Types types;
133
134    /** The name table. */
135    final Names names;
136
137    /** Access to files
138     */
139    private final JavaFileManager fileManager;
140
141    /** Factory for diagnostics
142     */
143    JCDiagnostic.Factory diagFactory;
144
145    /** The current scope where type variables are entered.
146     */
147    protected WriteableScope typevars;
148
149    private List<InterimUsesDirective> interimUses = List.nil();
150    private List<InterimProvidesDirective> interimProvides = List.nil();
151
152    /** The path name of the class file currently being read.
153     */
154    protected JavaFileObject currentClassFile = null;
155
156    /** The class or method currently being read.
157     */
158    protected Symbol currentOwner = null;
159
160    /** The module containing the class currently being read.
161     */
162    protected ModuleSymbol currentModule = null;
163
164    /** The buffer containing the currently read class file.
165     */
166    byte[] buf = new byte[INITIAL_BUFFER_SIZE];
167
168    /** The current input pointer.
169     */
170    protected int bp;
171
172    /** The objects of the constant pool.
173     */
174    Object[] poolObj;
175
176    /** For every constant pool entry, an index into buf where the
177     *  defining section of the entry is found.
178     */
179    int[] poolIdx;
180
181    /** The major version number of the class file being read. */
182    int majorVersion;
183    /** The minor version number of the class file being read. */
184    int minorVersion;
185
186    /** A table to hold the constant pool indices for method parameter
187     * names, as given in LocalVariableTable attributes.
188     */
189    int[] parameterNameIndices;
190
191    /**
192     * Whether or not any parameter names have been found.
193     */
194    boolean haveParameterNameIndices;
195
196    /** Set this to false every time we start reading a method
197     * and are saving parameter names.  Set it to true when we see
198     * MethodParameters, if it's set when we see a LocalVariableTable,
199     * then we ignore the parameter names from the LVT.
200     */
201    boolean sawMethodParameters;
202
203    /**
204     * The set of attribute names for which warnings have been generated for the current class
205     */
206    Set<Name> warnedAttrs = new HashSet<>();
207
208    /**
209     * The prototype @Target Attribute.Compound if this class is an annotation annotated with
210     * @Target
211     */
212    CompoundAnnotationProxy target;
213
214    /**
215     * The prototype @Repetable Attribute.Compound if this class is an annotation annotated with
216     * @Repeatable
217     */
218    CompoundAnnotationProxy repeatable;
219
220    /** Get the ClassReader instance for this invocation. */
221    public static ClassReader instance(Context context) {
222        ClassReader instance = context.get(classReaderKey);
223        if (instance == null)
224            instance = new ClassReader(context);
225        return instance;
226    }
227
228    /** Construct a new class reader. */
229    protected ClassReader(Context context) {
230        context.put(classReaderKey, this);
231        annotate = Annotate.instance(context);
232        names = Names.instance(context);
233        syms = Symtab.instance(context);
234        types = Types.instance(context);
235        fileManager = context.get(JavaFileManager.class);
236        if (fileManager == null)
237            throw new AssertionError("FileManager initialization error");
238        diagFactory = JCDiagnostic.Factory.instance(context);
239
240        log = Log.instance(context);
241
242        Options options = Options.instance(context);
243        verbose         = options.isSet(Option.VERBOSE);
244
245        Source source = Source.instance(context);
246        allowSimplifiedVarargs = source.allowSimplifiedVarargs();
247        allowModules     = source.allowModules();
248
249        saveParameterNames = options.isSet(PARAMETERS);
250
251        profile = Profile.instance(context);
252
253        typevars = WriteableScope.create(syms.noSymbol);
254
255        lintClassfile = Lint.instance(context).isEnabled(LintCategory.CLASSFILE);
256
257        initAttributeReaders();
258    }
259
260    /** Add member to class unless it is synthetic.
261     */
262    private void enterMember(ClassSymbol c, Symbol sym) {
263        // Synthetic members are not entered -- reason lost to history (optimization?).
264        // Lambda methods must be entered because they may have inner classes (which reference them)
265        if ((sym.flags_field & (SYNTHETIC|BRIDGE)) != SYNTHETIC || sym.name.startsWith(names.lambda))
266            c.members_field.enter(sym);
267    }
268
269/************************************************************************
270 * Error Diagnoses
271 ***********************************************************************/
272
273    public ClassFinder.BadClassFile badClassFile(String key, Object... args) {
274        return new ClassFinder.BadClassFile (
275            currentOwner.enclClass(),
276            currentClassFile,
277            diagFactory.fragment(key, args),
278            diagFactory);
279    }
280
281    public ClassFinder.BadEnclosingMethodAttr badEnclosingMethod(Object... args) {
282        return new ClassFinder.BadEnclosingMethodAttr (
283            currentOwner.enclClass(),
284            currentClassFile,
285            diagFactory.fragment("bad.enclosing.method", args),
286            diagFactory);
287    }
288
289/************************************************************************
290 * Buffer Access
291 ***********************************************************************/
292
293    /** Read a character.
294     */
295    char nextChar() {
296        return (char)(((buf[bp++] & 0xFF) << 8) + (buf[bp++] & 0xFF));
297    }
298
299    /** Read a byte.
300     */
301    int nextByte() {
302        return buf[bp++] & 0xFF;
303    }
304
305    /** Read an integer.
306     */
307    int nextInt() {
308        return
309            ((buf[bp++] & 0xFF) << 24) +
310            ((buf[bp++] & 0xFF) << 16) +
311            ((buf[bp++] & 0xFF) << 8) +
312            (buf[bp++] & 0xFF);
313    }
314
315    /** Extract a character at position bp from buf.
316     */
317    char getChar(int bp) {
318        return
319            (char)(((buf[bp] & 0xFF) << 8) + (buf[bp+1] & 0xFF));
320    }
321
322    /** Extract an integer at position bp from buf.
323     */
324    int getInt(int bp) {
325        return
326            ((buf[bp] & 0xFF) << 24) +
327            ((buf[bp+1] & 0xFF) << 16) +
328            ((buf[bp+2] & 0xFF) << 8) +
329            (buf[bp+3] & 0xFF);
330    }
331
332
333    /** Extract a long integer at position bp from buf.
334     */
335    long getLong(int bp) {
336        DataInputStream bufin =
337            new DataInputStream(new ByteArrayInputStream(buf, bp, 8));
338        try {
339            return bufin.readLong();
340        } catch (IOException e) {
341            throw new AssertionError(e);
342        }
343    }
344
345    /** Extract a float at position bp from buf.
346     */
347    float getFloat(int bp) {
348        DataInputStream bufin =
349            new DataInputStream(new ByteArrayInputStream(buf, bp, 4));
350        try {
351            return bufin.readFloat();
352        } catch (IOException e) {
353            throw new AssertionError(e);
354        }
355    }
356
357    /** Extract a double at position bp from buf.
358     */
359    double getDouble(int bp) {
360        DataInputStream bufin =
361            new DataInputStream(new ByteArrayInputStream(buf, bp, 8));
362        try {
363            return bufin.readDouble();
364        } catch (IOException e) {
365            throw new AssertionError(e);
366        }
367    }
368
369/************************************************************************
370 * Constant Pool Access
371 ***********************************************************************/
372
373    /** Index all constant pool entries, writing their start addresses into
374     *  poolIdx.
375     */
376    void indexPool() {
377        poolIdx = new int[nextChar()];
378        poolObj = new Object[poolIdx.length];
379        int i = 1;
380        while (i < poolIdx.length) {
381            poolIdx[i++] = bp;
382            byte tag = buf[bp++];
383            switch (tag) {
384            case CONSTANT_Utf8: case CONSTANT_Unicode: {
385                int len = nextChar();
386                bp = bp + len;
387                break;
388            }
389            case CONSTANT_Class:
390            case CONSTANT_String:
391            case CONSTANT_MethodType:
392            case CONSTANT_Module:
393            case CONSTANT_Package:
394                bp = bp + 2;
395                break;
396            case CONSTANT_MethodHandle:
397                bp = bp + 3;
398                break;
399            case CONSTANT_Fieldref:
400            case CONSTANT_Methodref:
401            case CONSTANT_InterfaceMethodref:
402            case CONSTANT_NameandType:
403            case CONSTANT_Integer:
404            case CONSTANT_Float:
405            case CONSTANT_InvokeDynamic:
406                bp = bp + 4;
407                break;
408            case CONSTANT_Long:
409            case CONSTANT_Double:
410                bp = bp + 8;
411                i++;
412                break;
413            default:
414                throw badClassFile("bad.const.pool.tag.at",
415                                   Byte.toString(tag),
416                                   Integer.toString(bp -1));
417            }
418        }
419    }
420
421    /** Read constant pool entry at start address i, use pool as a cache.
422     */
423    Object readPool(int i) {
424        Object result = poolObj[i];
425        if (result != null) return result;
426
427        int index = poolIdx[i];
428        if (index == 0) return null;
429
430        byte tag = buf[index];
431        switch (tag) {
432        case CONSTANT_Utf8:
433            poolObj[i] = names.fromUtf(buf, index + 3, getChar(index + 1));
434            break;
435        case CONSTANT_Unicode:
436            throw badClassFile("unicode.str.not.supported");
437        case CONSTANT_Class:
438            poolObj[i] = readClassOrType(getChar(index + 1));
439            break;
440        case CONSTANT_String:
441            // FIXME: (footprint) do not use toString here
442            poolObj[i] = readName(getChar(index + 1)).toString();
443            break;
444        case CONSTANT_Fieldref: {
445            ClassSymbol owner = readClassSymbol(getChar(index + 1));
446            NameAndType nt = readNameAndType(getChar(index + 3));
447            poolObj[i] = new VarSymbol(0, nt.name, nt.uniqueType.type, owner);
448            break;
449        }
450        case CONSTANT_Methodref:
451        case CONSTANT_InterfaceMethodref: {
452            ClassSymbol owner = readClassSymbol(getChar(index + 1));
453            NameAndType nt = readNameAndType(getChar(index + 3));
454            poolObj[i] = new MethodSymbol(0, nt.name, nt.uniqueType.type, owner);
455            break;
456        }
457        case CONSTANT_NameandType:
458            poolObj[i] = new NameAndType(
459                readName(getChar(index + 1)),
460                readType(getChar(index + 3)), types);
461            break;
462        case CONSTANT_Integer:
463            poolObj[i] = getInt(index + 1);
464            break;
465        case CONSTANT_Float:
466            poolObj[i] = Float.valueOf(getFloat(index + 1));
467            break;
468        case CONSTANT_Long:
469            poolObj[i] = Long.valueOf(getLong(index + 1));
470            break;
471        case CONSTANT_Double:
472            poolObj[i] = Double.valueOf(getDouble(index + 1));
473            break;
474        case CONSTANT_MethodHandle:
475            skipBytes(4);
476            break;
477        case CONSTANT_MethodType:
478            skipBytes(3);
479            break;
480        case CONSTANT_InvokeDynamic:
481            skipBytes(5);
482            break;
483        case CONSTANT_Module:
484        case CONSTANT_Package:
485            // this is temporary for now: treat as a simple reference to the underlying Utf8.
486            poolObj[i] = readName(getChar(index + 1));
487            break;
488        default:
489            throw badClassFile("bad.const.pool.tag", Byte.toString(tag));
490        }
491        return poolObj[i];
492    }
493
494    /** Read signature and convert to type.
495     */
496    Type readType(int i) {
497        int index = poolIdx[i];
498        return sigToType(buf, index + 3, getChar(index + 1));
499    }
500
501    /** If name is an array type or class signature, return the
502     *  corresponding type; otherwise return a ClassSymbol with given name.
503     */
504    Object readClassOrType(int i) {
505        int index =  poolIdx[i];
506        int len = getChar(index + 1);
507        int start = index + 3;
508        Assert.check(buf[start] == '[' || buf[start + len - 1] != ';');
509        // by the above assertion, the following test can be
510        // simplified to (buf[start] == '[')
511        return (buf[start] == '[' || buf[start + len - 1] == ';')
512            ? (Object)sigToType(buf, start, len)
513            : (Object)enterClass(names.fromUtf(internalize(buf, start,
514                                                           len)));
515    }
516
517    /** Read signature and convert to type parameters.
518     */
519    List<Type> readTypeParams(int i) {
520        int index = poolIdx[i];
521        return sigToTypeParams(buf, index + 3, getChar(index + 1));
522    }
523
524    /** Read class entry.
525     */
526    ClassSymbol readClassSymbol(int i) {
527        Object obj = readPool(i);
528        if (obj != null && !(obj instanceof ClassSymbol))
529            throw badClassFile("bad.const.pool.entry",
530                               currentClassFile.toString(),
531                               "CONSTANT_Class_info", i);
532        return (ClassSymbol)obj;
533    }
534
535    Name readClassName(int i) {
536        int index = poolIdx[i];
537        if (index == 0) return null;
538        byte tag = buf[index];
539        if (tag != CONSTANT_Class) {
540            throw badClassFile("bad.const.pool.entry",
541                               currentClassFile.toString(),
542                               "CONSTANT_Class_info", i);
543        }
544        int nameIndex =  poolIdx[getChar(index + 1)];
545        int len = getChar(nameIndex + 1);
546        int start = nameIndex + 3;
547        if (buf[start] == '[' || buf[start + len - 1] == ';')
548            throw badClassFile("wrong class name"); //TODO: proper diagnostics
549        return names.fromUtf(internalize(buf, start, len));
550    }
551
552    /** Read name.
553     */
554    Name readName(int i) {
555        Object obj = readPool(i);
556        if (obj != null && !(obj instanceof Name))
557            throw badClassFile("bad.const.pool.entry",
558                               currentClassFile.toString(),
559                               "CONSTANT_Utf8_info or CONSTANT_String_info", i);
560        return (Name)obj;
561    }
562
563    /** Read name and type.
564     */
565    NameAndType readNameAndType(int i) {
566        Object obj = readPool(i);
567        if (obj != null && !(obj instanceof NameAndType))
568            throw badClassFile("bad.const.pool.entry",
569                               currentClassFile.toString(),
570                               "CONSTANT_NameAndType_info", i);
571        return (NameAndType)obj;
572    }
573
574    /** Read the name of a module.
575     * The name is stored in a CONSTANT_Module entry, in
576     * JVMS 4.2 binary form (using ".", not "/")
577     */
578    Name readModuleName(int i) {
579        return readName(i);
580    }
581
582    /** Read module_flags.
583     */
584    Set<ModuleFlags> readModuleFlags(int flags) {
585        Set<ModuleFlags> set = EnumSet.noneOf(ModuleFlags.class);
586        for (ModuleFlags f : ModuleFlags.values()) {
587            if ((flags & f.value) != 0)
588                set.add(f);
589        }
590        return set;
591    }
592
593    /** Read resolution_flags.
594     */
595    Set<ModuleResolutionFlags> readModuleResolutionFlags(int flags) {
596        Set<ModuleResolutionFlags> set = EnumSet.noneOf(ModuleResolutionFlags.class);
597        for (ModuleResolutionFlags f : ModuleResolutionFlags.values()) {
598            if ((flags & f.value) != 0)
599                set.add(f);
600        }
601        return set;
602    }
603
604    /** Read exports_flags.
605     */
606    Set<ExportsFlag> readExportsFlags(int flags) {
607        Set<ExportsFlag> set = EnumSet.noneOf(ExportsFlag.class);
608        for (ExportsFlag f: ExportsFlag.values()) {
609            if ((flags & f.value) != 0)
610                set.add(f);
611        }
612        return set;
613    }
614
615    /** Read opens_flags.
616     */
617    Set<OpensFlag> readOpensFlags(int flags) {
618        Set<OpensFlag> set = EnumSet.noneOf(OpensFlag.class);
619        for (OpensFlag f: OpensFlag.values()) {
620            if ((flags & f.value) != 0)
621                set.add(f);
622        }
623        return set;
624    }
625
626    /** Read requires_flags.
627     */
628    Set<RequiresFlag> readRequiresFlags(int flags) {
629        Set<RequiresFlag> set = EnumSet.noneOf(RequiresFlag.class);
630        for (RequiresFlag f: RequiresFlag.values()) {
631            if ((flags & f.value) != 0)
632                set.add(f);
633        }
634        return set;
635    }
636
637/************************************************************************
638 * Reading Types
639 ***********************************************************************/
640
641    /** The unread portion of the currently read type is
642     *  signature[sigp..siglimit-1].
643     */
644    byte[] signature;
645    int sigp;
646    int siglimit;
647    boolean sigEnterPhase = false;
648
649    /** Convert signature to type, where signature is a byte array segment.
650     */
651    Type sigToType(byte[] sig, int offset, int len) {
652        signature = sig;
653        sigp = offset;
654        siglimit = offset + len;
655        return sigToType();
656    }
657
658    /** Convert signature to type, where signature is implicit.
659     */
660    Type sigToType() {
661        switch ((char) signature[sigp]) {
662        case 'T':
663            sigp++;
664            int start = sigp;
665            while (signature[sigp] != ';') sigp++;
666            sigp++;
667            return sigEnterPhase
668                ? Type.noType
669                : findTypeVar(names.fromUtf(signature, start, sigp - 1 - start));
670        case '+': {
671            sigp++;
672            Type t = sigToType();
673            return new WildcardType(t, BoundKind.EXTENDS, syms.boundClass);
674        }
675        case '*':
676            sigp++;
677            return new WildcardType(syms.objectType, BoundKind.UNBOUND,
678                                    syms.boundClass);
679        case '-': {
680            sigp++;
681            Type t = sigToType();
682            return new WildcardType(t, BoundKind.SUPER, syms.boundClass);
683        }
684        case 'B':
685            sigp++;
686            return syms.byteType;
687        case 'C':
688            sigp++;
689            return syms.charType;
690        case 'D':
691            sigp++;
692            return syms.doubleType;
693        case 'F':
694            sigp++;
695            return syms.floatType;
696        case 'I':
697            sigp++;
698            return syms.intType;
699        case 'J':
700            sigp++;
701            return syms.longType;
702        case 'L':
703            {
704                // int oldsigp = sigp;
705                Type t = classSigToType();
706                if (sigp < siglimit && signature[sigp] == '.')
707                    throw badClassFile("deprecated inner class signature syntax " +
708                                       "(please recompile from source)");
709                /*
710                System.err.println(" decoded " +
711                                   new String(signature, oldsigp, sigp-oldsigp) +
712                                   " => " + t + " outer " + t.outer());
713                */
714                return t;
715            }
716        case 'S':
717            sigp++;
718            return syms.shortType;
719        case 'V':
720            sigp++;
721            return syms.voidType;
722        case 'Z':
723            sigp++;
724            return syms.booleanType;
725        case '[':
726            sigp++;
727            return new ArrayType(sigToType(), syms.arrayClass);
728        case '(':
729            sigp++;
730            List<Type> argtypes = sigToTypes(')');
731            Type restype = sigToType();
732            List<Type> thrown = List.nil();
733            while (signature[sigp] == '^') {
734                sigp++;
735                thrown = thrown.prepend(sigToType());
736            }
737            // if there is a typevar in the throws clause we should state it.
738            for (List<Type> l = thrown; l.nonEmpty(); l = l.tail) {
739                if (l.head.hasTag(TYPEVAR)) {
740                    l.head.tsym.flags_field |= THROWS;
741                }
742            }
743            return new MethodType(argtypes,
744                                  restype,
745                                  thrown.reverse(),
746                                  syms.methodClass);
747        case '<':
748            typevars = typevars.dup(currentOwner);
749            Type poly = new ForAll(sigToTypeParams(), sigToType());
750            typevars = typevars.leave();
751            return poly;
752        default:
753            throw badClassFile("bad.signature",
754                               Convert.utf2string(signature, sigp, 10));
755        }
756    }
757
758    byte[] signatureBuffer = new byte[0];
759    int sbp = 0;
760    /** Convert class signature to type, where signature is implicit.
761     */
762    Type classSigToType() {
763        if (signature[sigp] != 'L')
764            throw badClassFile("bad.class.signature",
765                               Convert.utf2string(signature, sigp, 10));
766        sigp++;
767        Type outer = Type.noType;
768        int startSbp = sbp;
769
770        while (true) {
771            final byte c = signature[sigp++];
772            switch (c) {
773
774            case ';': {         // end
775                ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
776                                                         startSbp,
777                                                         sbp - startSbp));
778
779                try {
780                    return (outer == Type.noType) ?
781                            t.erasure(types) :
782                        new ClassType(outer, List.nil(), t);
783                } finally {
784                    sbp = startSbp;
785                }
786            }
787
788            case '<':           // generic arguments
789                ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
790                                                         startSbp,
791                                                         sbp - startSbp));
792                outer = new ClassType(outer, sigToTypes('>'), t) {
793                        boolean completed = false;
794                        @Override @DefinedBy(Api.LANGUAGE_MODEL)
795                        public Type getEnclosingType() {
796                            if (!completed) {
797                                completed = true;
798                                tsym.complete();
799                                Type enclosingType = tsym.type.getEnclosingType();
800                                if (enclosingType != Type.noType) {
801                                    List<Type> typeArgs =
802                                        super.getEnclosingType().allparams();
803                                    List<Type> typeParams =
804                                        enclosingType.allparams();
805                                    if (typeParams.length() != typeArgs.length()) {
806                                        // no "rare" types
807                                        super.setEnclosingType(types.erasure(enclosingType));
808                                    } else {
809                                        super.setEnclosingType(types.subst(enclosingType,
810                                                                           typeParams,
811                                                                           typeArgs));
812                                    }
813                                } else {
814                                    super.setEnclosingType(Type.noType);
815                                }
816                            }
817                            return super.getEnclosingType();
818                        }
819                        @Override
820                        public void setEnclosingType(Type outer) {
821                            throw new UnsupportedOperationException();
822                        }
823                    };
824                switch (signature[sigp++]) {
825                case ';':
826                    if (sigp < signature.length && signature[sigp] == '.') {
827                        // support old-style GJC signatures
828                        // The signature produced was
829                        // Lfoo/Outer<Lfoo/X;>;.Lfoo/Outer$Inner<Lfoo/Y;>;
830                        // rather than say
831                        // Lfoo/Outer<Lfoo/X;>.Inner<Lfoo/Y;>;
832                        // so we skip past ".Lfoo/Outer$"
833                        sigp += (sbp - startSbp) + // "foo/Outer"
834                            3;  // ".L" and "$"
835                        signatureBuffer[sbp++] = (byte)'$';
836                        break;
837                    } else {
838                        sbp = startSbp;
839                        return outer;
840                    }
841                case '.':
842                    signatureBuffer[sbp++] = (byte)'$';
843                    break;
844                default:
845                    throw new AssertionError(signature[sigp-1]);
846                }
847                continue;
848
849            case '.':
850                //we have seen an enclosing non-generic class
851                if (outer != Type.noType) {
852                    t = enterClass(names.fromUtf(signatureBuffer,
853                                                 startSbp,
854                                                 sbp - startSbp));
855                    outer = new ClassType(outer, List.nil(), t);
856                }
857                signatureBuffer[sbp++] = (byte)'$';
858                continue;
859            case '/':
860                signatureBuffer[sbp++] = (byte)'.';
861                continue;
862            default:
863                signatureBuffer[sbp++] = c;
864                continue;
865            }
866        }
867    }
868
869    /** Convert (implicit) signature to list of types
870     *  until `terminator' is encountered.
871     */
872    List<Type> sigToTypes(char terminator) {
873        List<Type> head = List.of(null);
874        List<Type> tail = head;
875        while (signature[sigp] != terminator)
876            tail = tail.setTail(List.of(sigToType()));
877        sigp++;
878        return head.tail;
879    }
880
881    /** Convert signature to type parameters, where signature is a byte
882     *  array segment.
883     */
884    List<Type> sigToTypeParams(byte[] sig, int offset, int len) {
885        signature = sig;
886        sigp = offset;
887        siglimit = offset + len;
888        return sigToTypeParams();
889    }
890
891    /** Convert signature to type parameters, where signature is implicit.
892     */
893    List<Type> sigToTypeParams() {
894        List<Type> tvars = List.nil();
895        if (signature[sigp] == '<') {
896            sigp++;
897            int start = sigp;
898            sigEnterPhase = true;
899            while (signature[sigp] != '>')
900                tvars = tvars.prepend(sigToTypeParam());
901            sigEnterPhase = false;
902            sigp = start;
903            while (signature[sigp] != '>')
904                sigToTypeParam();
905            sigp++;
906        }
907        return tvars.reverse();
908    }
909
910    /** Convert (implicit) signature to type parameter.
911     */
912    Type sigToTypeParam() {
913        int start = sigp;
914        while (signature[sigp] != ':') sigp++;
915        Name name = names.fromUtf(signature, start, sigp - start);
916        TypeVar tvar;
917        if (sigEnterPhase) {
918            tvar = new TypeVar(name, currentOwner, syms.botType);
919            typevars.enter(tvar.tsym);
920        } else {
921            tvar = (TypeVar)findTypeVar(name);
922        }
923        List<Type> bounds = List.nil();
924        boolean allInterfaces = false;
925        if (signature[sigp] == ':' && signature[sigp+1] == ':') {
926            sigp++;
927            allInterfaces = true;
928        }
929        while (signature[sigp] == ':') {
930            sigp++;
931            bounds = bounds.prepend(sigToType());
932        }
933        if (!sigEnterPhase) {
934            types.setBounds(tvar, bounds.reverse(), allInterfaces);
935        }
936        return tvar;
937    }
938
939    /** Find type variable with given name in `typevars' scope.
940     */
941    Type findTypeVar(Name name) {
942        Symbol s = typevars.findFirst(name);
943        if (s != null) {
944            return s.type;
945        } else {
946            if (readingClassAttr) {
947                // While reading the class attribute, the supertypes
948                // might refer to a type variable from an enclosing element
949                // (method or class).
950                // If the type variable is defined in the enclosing class,
951                // we can actually find it in
952                // currentOwner.owner.type.getTypeArguments()
953                // However, until we have read the enclosing method attribute
954                // we don't know for sure if this owner is correct.  It could
955                // be a method and there is no way to tell before reading the
956                // enclosing method attribute.
957                TypeVar t = new TypeVar(name, currentOwner, syms.botType);
958                missingTypeVariables = missingTypeVariables.prepend(t);
959                // System.err.println("Missing type var " + name);
960                return t;
961            }
962            throw badClassFile("undecl.type.var", name);
963        }
964    }
965
966/************************************************************************
967 * Reading Attributes
968 ***********************************************************************/
969
970    protected enum AttributeKind { CLASS, MEMBER }
971
972    protected abstract class AttributeReader {
973        protected AttributeReader(Name name, ClassFile.Version version, Set<AttributeKind> kinds) {
974            this.name = name;
975            this.version = version;
976            this.kinds = kinds;
977        }
978
979        protected boolean accepts(AttributeKind kind) {
980            if (kinds.contains(kind)) {
981                if (majorVersion > version.major || (majorVersion == version.major && minorVersion >= version.minor))
982                    return true;
983
984                if (lintClassfile && !warnedAttrs.contains(name)) {
985                    JavaFileObject prev = log.useSource(currentClassFile);
986                    try {
987                        log.warning(LintCategory.CLASSFILE, (DiagnosticPosition) null, "future.attr",
988                                name, version.major, version.minor, majorVersion, minorVersion);
989                    } finally {
990                        log.useSource(prev);
991                    }
992                    warnedAttrs.add(name);
993                }
994            }
995            return false;
996        }
997
998        protected abstract void read(Symbol sym, int attrLen);
999
1000        protected final Name name;
1001        protected final ClassFile.Version version;
1002        protected final Set<AttributeKind> kinds;
1003    }
1004
1005    protected Set<AttributeKind> CLASS_ATTRIBUTE =
1006            EnumSet.of(AttributeKind.CLASS);
1007    protected Set<AttributeKind> MEMBER_ATTRIBUTE =
1008            EnumSet.of(AttributeKind.MEMBER);
1009    protected Set<AttributeKind> CLASS_OR_MEMBER_ATTRIBUTE =
1010            EnumSet.of(AttributeKind.CLASS, AttributeKind.MEMBER);
1011
1012    protected Map<Name, AttributeReader> attributeReaders = new HashMap<>();
1013
1014    private void initAttributeReaders() {
1015        AttributeReader[] readers = {
1016            // v45.3 attributes
1017
1018            new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) {
1019                protected void read(Symbol sym, int attrLen) {
1020                    if (readAllOfClassFile || saveParameterNames)
1021                        ((MethodSymbol)sym).code = readCode(sym);
1022                    else
1023                        bp = bp + attrLen;
1024                }
1025            },
1026
1027            new AttributeReader(names.ConstantValue, V45_3, MEMBER_ATTRIBUTE) {
1028                protected void read(Symbol sym, int attrLen) {
1029                    Object v = readPool(nextChar());
1030                    // Ignore ConstantValue attribute if field not final.
1031                    if ((sym.flags() & FINAL) == 0) {
1032                        return;
1033                    }
1034                    VarSymbol var = (VarSymbol) sym;
1035                    switch (var.type.getTag()) {
1036                       case BOOLEAN:
1037                       case BYTE:
1038                       case CHAR:
1039                       case SHORT:
1040                       case INT:
1041                           checkType(var, Integer.class, v);
1042                           break;
1043                       case LONG:
1044                           checkType(var, Long.class, v);
1045                           break;
1046                       case FLOAT:
1047                           checkType(var, Float.class, v);
1048                           break;
1049                       case DOUBLE:
1050                           checkType(var, Double.class, v);
1051                           break;
1052                       case CLASS:
1053                           Assert.check(var.type.tsym == syms.stringType.tsym);
1054                           checkType(var, String.class, v);
1055                           break;
1056                       default:
1057                           // ignore ConstantValue attribute if type is not primitive or String
1058                           return;
1059                    }
1060                    if (v instanceof Integer && !var.type.getTag().checkRange((Integer) v)) {
1061                        throw badClassFile("bad.constant.range", v, var, var.type);
1062                    }
1063                    var.setData(v);
1064                }
1065
1066                void checkType(Symbol var, Class<?> clazz, Object value) {
1067                    if (!clazz.isInstance(value)) {
1068                        throw badClassFile("bad.constant.value", value, var, clazz.getSimpleName());
1069                    }
1070                }
1071            },
1072
1073            new AttributeReader(names.Deprecated, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
1074                protected void read(Symbol sym, int attrLen) {
1075                    Symbol s = sym.owner.kind == MDL ? sym.owner : sym;
1076
1077                    s.flags_field |= DEPRECATED;
1078                }
1079            },
1080
1081            new AttributeReader(names.Exceptions, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
1082                protected void read(Symbol sym, int attrLen) {
1083                    int nexceptions = nextChar();
1084                    List<Type> thrown = List.nil();
1085                    for (int j = 0; j < nexceptions; j++)
1086                        thrown = thrown.prepend(readClassSymbol(nextChar()).type);
1087                    if (sym.type.getThrownTypes().isEmpty())
1088                        sym.type.asMethodType().thrown = thrown.reverse();
1089                }
1090            },
1091
1092            new AttributeReader(names.InnerClasses, V45_3, CLASS_ATTRIBUTE) {
1093                protected void read(Symbol sym, int attrLen) {
1094                    ClassSymbol c = (ClassSymbol) sym;
1095                    if (currentModule.module_info == c) {
1096                        //prevent entering the classes too soon:
1097                        skipInnerClasses();
1098                    } else {
1099                        readInnerClasses(c);
1100                    }
1101                }
1102            },
1103
1104            new AttributeReader(names.LocalVariableTable, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
1105                protected void read(Symbol sym, int attrLen) {
1106                    int newbp = bp + attrLen;
1107                    if (saveParameterNames && !sawMethodParameters) {
1108                        // Pick up parameter names from the variable table.
1109                        // Parameter names are not explicitly identified as such,
1110                        // but all parameter name entries in the LocalVariableTable
1111                        // have a start_pc of 0.  Therefore, we record the name
1112                        // indicies of all slots with a start_pc of zero in the
1113                        // parameterNameIndicies array.
1114                        // Note that this implicitly honors the JVMS spec that
1115                        // there may be more than one LocalVariableTable, and that
1116                        // there is no specified ordering for the entries.
1117                        int numEntries = nextChar();
1118                        for (int i = 0; i < numEntries; i++) {
1119                            int start_pc = nextChar();
1120                            int length = nextChar();
1121                            int nameIndex = nextChar();
1122                            int sigIndex = nextChar();
1123                            int register = nextChar();
1124                            if (start_pc == 0) {
1125                                // ensure array large enough
1126                                if (register >= parameterNameIndices.length) {
1127                                    int newSize =
1128                                            Math.max(register + 1, parameterNameIndices.length + 8);
1129                                    parameterNameIndices =
1130                                            Arrays.copyOf(parameterNameIndices, newSize);
1131                                }
1132                                parameterNameIndices[register] = nameIndex;
1133                                haveParameterNameIndices = true;
1134                            }
1135                        }
1136                    }
1137                    bp = newbp;
1138                }
1139            },
1140
1141            new AttributeReader(names.SourceFile, V45_3, CLASS_ATTRIBUTE) {
1142                protected void read(Symbol sym, int attrLen) {
1143                    ClassSymbol c = (ClassSymbol) sym;
1144                    Name n = readName(nextChar());
1145                    c.sourcefile = new SourceFileObject(n, c.flatname);
1146                    // If the class is a toplevel class, originating from a Java source file,
1147                    // but the class name does not match the file name, then it is
1148                    // an auxiliary class.
1149                    String sn = n.toString();
1150                    if (c.owner.kind == PCK &&
1151                        sn.endsWith(".java") &&
1152                        !sn.equals(c.name.toString()+".java")) {
1153                        c.flags_field |= AUXILIARY;
1154                    }
1155                }
1156            },
1157
1158            new AttributeReader(names.Synthetic, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
1159                protected void read(Symbol sym, int attrLen) {
1160                    sym.flags_field |= SYNTHETIC;
1161                }
1162            },
1163
1164            // standard v49 attributes
1165
1166            new AttributeReader(names.EnclosingMethod, V49, CLASS_ATTRIBUTE) {
1167                protected void read(Symbol sym, int attrLen) {
1168                    int newbp = bp + attrLen;
1169                    readEnclosingMethodAttr(sym);
1170                    bp = newbp;
1171                }
1172            },
1173
1174            new AttributeReader(names.Signature, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1175                protected void read(Symbol sym, int attrLen) {
1176                    if (sym.kind == TYP) {
1177                        ClassSymbol c = (ClassSymbol) sym;
1178                        readingClassAttr = true;
1179                        try {
1180                            ClassType ct1 = (ClassType)c.type;
1181                            Assert.check(c == currentOwner);
1182                            ct1.typarams_field = readTypeParams(nextChar());
1183                            ct1.supertype_field = sigToType();
1184                            ListBuffer<Type> is = new ListBuffer<>();
1185                            while (sigp != siglimit) is.append(sigToType());
1186                            ct1.interfaces_field = is.toList();
1187                        } finally {
1188                            readingClassAttr = false;
1189                        }
1190                    } else {
1191                        List<Type> thrown = sym.type.getThrownTypes();
1192                        sym.type = readType(nextChar());
1193                        //- System.err.println(" # " + sym.type);
1194                        if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty())
1195                            sym.type.asMethodType().thrown = thrown;
1196
1197                    }
1198                }
1199            },
1200
1201            // v49 annotation attributes
1202
1203            new AttributeReader(names.AnnotationDefault, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1204                protected void read(Symbol sym, int attrLen) {
1205                    attachAnnotationDefault(sym);
1206                }
1207            },
1208
1209            new AttributeReader(names.RuntimeInvisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1210                protected void read(Symbol sym, int attrLen) {
1211                    attachAnnotations(sym);
1212                }
1213            },
1214
1215            new AttributeReader(names.RuntimeInvisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1216                protected void read(Symbol sym, int attrLen) {
1217                    attachParameterAnnotations(sym);
1218                }
1219            },
1220
1221            new AttributeReader(names.RuntimeVisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1222                protected void read(Symbol sym, int attrLen) {
1223                    attachAnnotations(sym);
1224                }
1225            },
1226
1227            new AttributeReader(names.RuntimeVisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1228                protected void read(Symbol sym, int attrLen) {
1229                    attachParameterAnnotations(sym);
1230                }
1231            },
1232
1233            // additional "legacy" v49 attributes, superceded by flags
1234
1235            new AttributeReader(names.Annotation, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1236                protected void read(Symbol sym, int attrLen) {
1237                    sym.flags_field |= ANNOTATION;
1238                }
1239            },
1240
1241            new AttributeReader(names.Bridge, V49, MEMBER_ATTRIBUTE) {
1242                protected void read(Symbol sym, int attrLen) {
1243                    sym.flags_field |= BRIDGE;
1244                }
1245            },
1246
1247            new AttributeReader(names.Enum, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1248                protected void read(Symbol sym, int attrLen) {
1249                    sym.flags_field |= ENUM;
1250                }
1251            },
1252
1253            new AttributeReader(names.Varargs, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1254                protected void read(Symbol sym, int attrLen) {
1255                    sym.flags_field |= VARARGS;
1256                }
1257            },
1258
1259            new AttributeReader(names.RuntimeVisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) {
1260                protected void read(Symbol sym, int attrLen) {
1261                    attachTypeAnnotations(sym);
1262                }
1263            },
1264
1265            new AttributeReader(names.RuntimeInvisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) {
1266                protected void read(Symbol sym, int attrLen) {
1267                    attachTypeAnnotations(sym);
1268                }
1269            },
1270
1271            // The following attributes for a Code attribute are not currently handled
1272            // StackMapTable
1273            // SourceDebugExtension
1274            // LineNumberTable
1275            // LocalVariableTypeTable
1276
1277            // standard v52 attributes
1278
1279            new AttributeReader(names.MethodParameters, V52, MEMBER_ATTRIBUTE) {
1280                protected void read(Symbol sym, int attrlen) {
1281                    int newbp = bp + attrlen;
1282                    if (saveParameterNames) {
1283                        sawMethodParameters = true;
1284                        int numEntries = nextByte();
1285                        parameterNameIndices = new int[numEntries];
1286                        haveParameterNameIndices = true;
1287                        for (int i = 0; i < numEntries; i++) {
1288                            int nameIndex = nextChar();
1289                            int flags = nextChar();
1290                            parameterNameIndices[i] = nameIndex;
1291                        }
1292                    }
1293                    bp = newbp;
1294                }
1295            },
1296
1297            // standard v53 attributes
1298
1299            new AttributeReader(names.Module, V53, CLASS_ATTRIBUTE) {
1300                @Override
1301                protected boolean accepts(AttributeKind kind) {
1302                    return super.accepts(kind) && allowModules;
1303                }
1304                protected void read(Symbol sym, int attrLen) {
1305                    if (sym.kind == TYP && sym.owner.kind == MDL) {
1306                        ModuleSymbol msym = (ModuleSymbol) sym.owner;
1307                        ListBuffer<Directive> directives = new ListBuffer<>();
1308
1309                        Name moduleName = readModuleName(nextChar());
1310                        if (currentModule.name != moduleName) {
1311                            throw badClassFile("module.name.mismatch", moduleName, currentModule.name);
1312                        }
1313
1314                        msym.flags.addAll(readModuleFlags(nextChar()));
1315                        msym.version = readName(nextChar());
1316
1317                        ListBuffer<RequiresDirective> requires = new ListBuffer<>();
1318                        int nrequires = nextChar();
1319                        for (int i = 0; i < nrequires; i++) {
1320                            ModuleSymbol rsym = syms.enterModule(readModuleName(nextChar()));
1321                            Set<RequiresFlag> flags = readRequiresFlags(nextChar());
1322                            nextChar(); // skip compiled version
1323                            requires.add(new RequiresDirective(rsym, flags));
1324                        }
1325                        msym.requires = requires.toList();
1326                        directives.addAll(msym.requires);
1327
1328                        ListBuffer<ExportsDirective> exports = new ListBuffer<>();
1329                        int nexports = nextChar();
1330                        for (int i = 0; i < nexports; i++) {
1331                            Name n = readName(nextChar());
1332                            PackageSymbol p = syms.enterPackage(currentModule, names.fromUtf(internalize(n)));
1333                            Set<ExportsFlag> flags = readExportsFlags(nextChar());
1334                            int nto = nextChar();
1335                            List<ModuleSymbol> to;
1336                            if (nto == 0) {
1337                                to = null;
1338                            } else {
1339                                ListBuffer<ModuleSymbol> lb = new ListBuffer<>();
1340                                for (int t = 0; t < nto; t++)
1341                                    lb.append(syms.enterModule(readModuleName(nextChar())));
1342                                to = lb.toList();
1343                            }
1344                            exports.add(new ExportsDirective(p, to, flags));
1345                        }
1346                        msym.exports = exports.toList();
1347                        directives.addAll(msym.exports);
1348                        ListBuffer<OpensDirective> opens = new ListBuffer<>();
1349                        int nopens = nextChar();
1350                        if (nopens != 0 && msym.flags.contains(ModuleFlags.OPEN)) {
1351                            throw badClassFile("module.non.zero.opens", currentModule.name);
1352                        }
1353                        for (int i = 0; i < nopens; i++) {
1354                            Name n = readName(nextChar());
1355                            PackageSymbol p = syms.enterPackage(currentModule, names.fromUtf(internalize(n)));
1356                            Set<OpensFlag> flags = readOpensFlags(nextChar());
1357                            int nto = nextChar();
1358                            List<ModuleSymbol> to;
1359                            if (nto == 0) {
1360                                to = null;
1361                            } else {
1362                                ListBuffer<ModuleSymbol> lb = new ListBuffer<>();
1363                                for (int t = 0; t < nto; t++)
1364                                    lb.append(syms.enterModule(readModuleName(nextChar())));
1365                                to = lb.toList();
1366                            }
1367                            opens.add(new OpensDirective(p, to, flags));
1368                        }
1369                        msym.opens = opens.toList();
1370                        directives.addAll(msym.opens);
1371
1372                        msym.directives = directives.toList();
1373
1374                        ListBuffer<InterimUsesDirective> uses = new ListBuffer<>();
1375                        int nuses = nextChar();
1376                        for (int i = 0; i < nuses; i++) {
1377                            Name srvc = readClassName(nextChar());
1378                            uses.add(new InterimUsesDirective(srvc));
1379                        }
1380                        interimUses = uses.toList();
1381
1382                        ListBuffer<InterimProvidesDirective> provides = new ListBuffer<>();
1383                        int nprovides = nextChar();
1384                        for (int p = 0; p < nprovides; p++) {
1385                            Name srvc = readClassName(nextChar());
1386                            int nimpls = nextChar();
1387                            ListBuffer<Name> impls = new ListBuffer<>();
1388                            for (int i = 0; i < nimpls; i++) {
1389                                impls.append(readClassName(nextChar()));
1390                            provides.add(new InterimProvidesDirective(srvc, impls.toList()));
1391                            }
1392                        }
1393                        interimProvides = provides.toList();
1394                    }
1395                }
1396            },
1397
1398            new AttributeReader(names.ModuleResolution, V53, CLASS_ATTRIBUTE) {
1399                @Override
1400                protected boolean accepts(AttributeKind kind) {
1401                    return super.accepts(kind) && allowModules;
1402                }
1403                protected void read(Symbol sym, int attrLen) {
1404                    if (sym.kind == TYP && sym.owner.kind == MDL) {
1405                        ModuleSymbol msym = (ModuleSymbol) sym.owner;
1406                        msym.resolutionFlags.addAll(readModuleResolutionFlags(nextChar()));
1407                    }
1408                }
1409            },
1410        };
1411
1412        for (AttributeReader r: readers)
1413            attributeReaders.put(r.name, r);
1414    }
1415
1416    protected void readEnclosingMethodAttr(Symbol sym) {
1417        // sym is a nested class with an "Enclosing Method" attribute
1418        // remove sym from it's current owners scope and place it in
1419        // the scope specified by the attribute
1420        sym.owner.members().remove(sym);
1421        ClassSymbol self = (ClassSymbol)sym;
1422        ClassSymbol c = readClassSymbol(nextChar());
1423        NameAndType nt = readNameAndType(nextChar());
1424
1425        if (c.members_field == null)
1426            throw badClassFile("bad.enclosing.class", self, c);
1427
1428        MethodSymbol m = findMethod(nt, c.members_field, self.flags());
1429        if (nt != null && m == null)
1430            throw badEnclosingMethod(self);
1431
1432        self.name = simpleBinaryName(self.flatname, c.flatname) ;
1433        self.owner = m != null ? m : c;
1434        if (self.name.isEmpty())
1435            self.fullname = names.empty;
1436        else
1437            self.fullname = ClassSymbol.formFullName(self.name, self.owner);
1438
1439        if (m != null) {
1440            ((ClassType)sym.type).setEnclosingType(m.type);
1441        } else if ((self.flags_field & STATIC) == 0) {
1442            ((ClassType)sym.type).setEnclosingType(c.type);
1443        } else {
1444            ((ClassType)sym.type).setEnclosingType(Type.noType);
1445        }
1446        enterTypevars(self, self.type);
1447        if (!missingTypeVariables.isEmpty()) {
1448            ListBuffer<Type> typeVars =  new ListBuffer<>();
1449            for (Type typevar : missingTypeVariables) {
1450                typeVars.append(findTypeVar(typevar.tsym.name));
1451            }
1452            foundTypeVariables = typeVars.toList();
1453        } else {
1454            foundTypeVariables = List.nil();
1455        }
1456    }
1457
1458    // See java.lang.Class
1459    private Name simpleBinaryName(Name self, Name enclosing) {
1460        String simpleBinaryName = self.toString().substring(enclosing.toString().length());
1461        if (simpleBinaryName.length() < 1 || simpleBinaryName.charAt(0) != '$')
1462            throw badClassFile("bad.enclosing.method", self);
1463        int index = 1;
1464        while (index < simpleBinaryName.length() &&
1465               isAsciiDigit(simpleBinaryName.charAt(index)))
1466            index++;
1467        return names.fromString(simpleBinaryName.substring(index));
1468    }
1469
1470    private MethodSymbol findMethod(NameAndType nt, Scope scope, long flags) {
1471        if (nt == null)
1472            return null;
1473
1474        MethodType type = nt.uniqueType.type.asMethodType();
1475
1476        for (Symbol sym : scope.getSymbolsByName(nt.name)) {
1477            if (sym.kind == MTH && isSameBinaryType(sym.type.asMethodType(), type))
1478                return (MethodSymbol)sym;
1479        }
1480
1481        if (nt.name != names.init)
1482            // not a constructor
1483            return null;
1484        if ((flags & INTERFACE) != 0)
1485            // no enclosing instance
1486            return null;
1487        if (nt.uniqueType.type.getParameterTypes().isEmpty())
1488            // no parameters
1489            return null;
1490
1491        // A constructor of an inner class.
1492        // Remove the first argument (the enclosing instance)
1493        nt.setType(new MethodType(nt.uniqueType.type.getParameterTypes().tail,
1494                                 nt.uniqueType.type.getReturnType(),
1495                                 nt.uniqueType.type.getThrownTypes(),
1496                                 syms.methodClass));
1497        // Try searching again
1498        return findMethod(nt, scope, flags);
1499    }
1500
1501    /** Similar to Types.isSameType but avoids completion */
1502    private boolean isSameBinaryType(MethodType mt1, MethodType mt2) {
1503        List<Type> types1 = types.erasure(mt1.getParameterTypes())
1504            .prepend(types.erasure(mt1.getReturnType()));
1505        List<Type> types2 = mt2.getParameterTypes().prepend(mt2.getReturnType());
1506        while (!types1.isEmpty() && !types2.isEmpty()) {
1507            if (types1.head.tsym != types2.head.tsym)
1508                return false;
1509            types1 = types1.tail;
1510            types2 = types2.tail;
1511        }
1512        return types1.isEmpty() && types2.isEmpty();
1513    }
1514
1515    /**
1516     * Character.isDigit answers <tt>true</tt> to some non-ascii
1517     * digits.  This one does not.  <b>copied from java.lang.Class</b>
1518     */
1519    private static boolean isAsciiDigit(char c) {
1520        return '0' <= c && c <= '9';
1521    }
1522
1523    /** Read member attributes.
1524     */
1525    void readMemberAttrs(Symbol sym) {
1526        readAttrs(sym, AttributeKind.MEMBER);
1527    }
1528
1529    void readAttrs(Symbol sym, AttributeKind kind) {
1530        char ac = nextChar();
1531        for (int i = 0; i < ac; i++) {
1532            Name attrName = readName(nextChar());
1533            int attrLen = nextInt();
1534            AttributeReader r = attributeReaders.get(attrName);
1535            if (r != null && r.accepts(kind))
1536                r.read(sym, attrLen);
1537            else  {
1538                bp = bp + attrLen;
1539            }
1540        }
1541    }
1542
1543    private boolean readingClassAttr = false;
1544    private List<Type> missingTypeVariables = List.nil();
1545    private List<Type> foundTypeVariables = List.nil();
1546
1547    /** Read class attributes.
1548     */
1549    void readClassAttrs(ClassSymbol c) {
1550        readAttrs(c, AttributeKind.CLASS);
1551    }
1552
1553    /** Read code block.
1554     */
1555    Code readCode(Symbol owner) {
1556        nextChar(); // max_stack
1557        nextChar(); // max_locals
1558        final int  code_length = nextInt();
1559        bp += code_length;
1560        final char exception_table_length = nextChar();
1561        bp += exception_table_length * 8;
1562        readMemberAttrs(owner);
1563        return null;
1564    }
1565
1566/************************************************************************
1567 * Reading Java-language annotations
1568 ***********************************************************************/
1569
1570    /** Attach annotations.
1571     */
1572    void attachAnnotations(final Symbol sym) {
1573        int numAttributes = nextChar();
1574        if (numAttributes != 0) {
1575            ListBuffer<CompoundAnnotationProxy> proxies = new ListBuffer<>();
1576            for (int i = 0; i<numAttributes; i++) {
1577                CompoundAnnotationProxy proxy = readCompoundAnnotation();
1578                if (proxy.type.tsym == syms.proprietaryType.tsym)
1579                    sym.flags_field |= PROPRIETARY;
1580                else if (proxy.type.tsym == syms.profileType.tsym) {
1581                    if (profile != Profile.DEFAULT) {
1582                        for (Pair<Name,Attribute> v: proxy.values) {
1583                            if (v.fst == names.value && v.snd instanceof Attribute.Constant) {
1584                                Attribute.Constant c = (Attribute.Constant) v.snd;
1585                                if (c.type == syms.intType && ((Integer) c.value) > profile.value) {
1586                                    sym.flags_field |= NOT_IN_PROFILE;
1587                                }
1588                            }
1589                        }
1590                    }
1591                } else {
1592                    if (proxy.type.tsym == syms.annotationTargetType.tsym) {
1593                        target = proxy;
1594                    } else if (proxy.type.tsym == syms.repeatableType.tsym) {
1595                        repeatable = proxy;
1596                    } else if (proxy.type.tsym == syms.deprecatedType.tsym) {
1597                        sym.flags_field |= (DEPRECATED | DEPRECATED_ANNOTATION);
1598                        for (Pair<Name, Attribute> v : proxy.values) {
1599                            if (v.fst == names.forRemoval && v.snd instanceof Attribute.Constant) {
1600                                Attribute.Constant c = (Attribute.Constant) v.snd;
1601                                if (c.type == syms.booleanType && ((Integer) c.value) != 0) {
1602                                    sym.flags_field |= DEPRECATED_REMOVAL;
1603                                }
1604                            }
1605                        }
1606                    }
1607
1608                    proxies.append(proxy);
1609                }
1610            }
1611            annotate.normal(new AnnotationCompleter(sym, proxies.toList()));
1612        }
1613    }
1614
1615    /** Attach parameter annotations.
1616     */
1617    void attachParameterAnnotations(final Symbol method) {
1618        final MethodSymbol meth = (MethodSymbol)method;
1619        int numParameters = buf[bp++] & 0xFF;
1620        List<VarSymbol> parameters = meth.params();
1621        int pnum = 0;
1622        while (parameters.tail != null) {
1623            attachAnnotations(parameters.head);
1624            parameters = parameters.tail;
1625            pnum++;
1626        }
1627        if (pnum != numParameters) {
1628            throw badClassFile("bad.runtime.invisible.param.annotations", meth);
1629        }
1630    }
1631
1632    void attachTypeAnnotations(final Symbol sym) {
1633        int numAttributes = nextChar();
1634        if (numAttributes != 0) {
1635            ListBuffer<TypeAnnotationProxy> proxies = new ListBuffer<>();
1636            for (int i = 0; i < numAttributes; i++)
1637                proxies.append(readTypeAnnotation());
1638            annotate.normal(new TypeAnnotationCompleter(sym, proxies.toList()));
1639        }
1640    }
1641
1642    /** Attach the default value for an annotation element.
1643     */
1644    void attachAnnotationDefault(final Symbol sym) {
1645        final MethodSymbol meth = (MethodSymbol)sym; // only on methods
1646        final Attribute value = readAttributeValue();
1647
1648        // The default value is set later during annotation. It might
1649        // be the case that the Symbol sym is annotated _after_ the
1650        // repeating instances that depend on this default value,
1651        // because of this we set an interim value that tells us this
1652        // element (most likely) has a default.
1653        //
1654        // Set interim value for now, reset just before we do this
1655        // properly at annotate time.
1656        meth.defaultValue = value;
1657        annotate.normal(new AnnotationDefaultCompleter(meth, value));
1658    }
1659
1660    Type readTypeOrClassSymbol(int i) {
1661        // support preliminary jsr175-format class files
1662        if (buf[poolIdx[i]] == CONSTANT_Class)
1663            return readClassSymbol(i).type;
1664        return readTypeToProxy(i);
1665    }
1666    Type readEnumType(int i) {
1667        // support preliminary jsr175-format class files
1668        int index = poolIdx[i];
1669        int length = getChar(index + 1);
1670        if (buf[index + length + 2] != ';')
1671            return enterClass(readName(i)).type;
1672        return readTypeToProxy(i);
1673    }
1674    Type readTypeToProxy(int i) {
1675        if (currentModule.module_info == currentOwner) {
1676            int index = poolIdx[i];
1677            return new ProxyType(Arrays.copyOfRange(buf, index + 3, index + 3 + getChar(index + 1)));
1678        } else {
1679            return readType(i);
1680        }
1681    }
1682
1683    CompoundAnnotationProxy readCompoundAnnotation() {
1684        Type t;
1685        if (currentModule.module_info == currentOwner) {
1686            int index = poolIdx[nextChar()];
1687            t = new ProxyType(Arrays.copyOfRange(buf, index + 3, index + 3 + getChar(index + 1)));
1688        } else {
1689            t = readTypeOrClassSymbol(nextChar());
1690        }
1691        int numFields = nextChar();
1692        ListBuffer<Pair<Name,Attribute>> pairs = new ListBuffer<>();
1693        for (int i=0; i<numFields; i++) {
1694            Name name = readName(nextChar());
1695            Attribute value = readAttributeValue();
1696            pairs.append(new Pair<>(name, value));
1697        }
1698        return new CompoundAnnotationProxy(t, pairs.toList());
1699    }
1700
1701    TypeAnnotationProxy readTypeAnnotation() {
1702        TypeAnnotationPosition position = readPosition();
1703        CompoundAnnotationProxy proxy = readCompoundAnnotation();
1704
1705        return new TypeAnnotationProxy(proxy, position);
1706    }
1707
1708    TypeAnnotationPosition readPosition() {
1709        int tag = nextByte(); // TargetType tag is a byte
1710
1711        if (!TargetType.isValidTargetTypeValue(tag))
1712            throw badClassFile("bad.type.annotation.value", String.format("0x%02X", tag));
1713
1714        TargetType type = TargetType.fromTargetTypeValue(tag);
1715
1716        switch (type) {
1717        // instanceof
1718        case INSTANCEOF: {
1719            final int offset = nextChar();
1720            final TypeAnnotationPosition position =
1721                TypeAnnotationPosition.instanceOf(readTypePath());
1722            position.offset = offset;
1723            return position;
1724        }
1725        // new expression
1726        case NEW: {
1727            final int offset = nextChar();
1728            final TypeAnnotationPosition position =
1729                TypeAnnotationPosition.newObj(readTypePath());
1730            position.offset = offset;
1731            return position;
1732        }
1733        // constructor/method reference receiver
1734        case CONSTRUCTOR_REFERENCE: {
1735            final int offset = nextChar();
1736            final TypeAnnotationPosition position =
1737                TypeAnnotationPosition.constructorRef(readTypePath());
1738            position.offset = offset;
1739            return position;
1740        }
1741        case METHOD_REFERENCE: {
1742            final int offset = nextChar();
1743            final TypeAnnotationPosition position =
1744                TypeAnnotationPosition.methodRef(readTypePath());
1745            position.offset = offset;
1746            return position;
1747        }
1748        // local variable
1749        case LOCAL_VARIABLE: {
1750            final int table_length = nextChar();
1751            final int[] newLvarOffset = new int[table_length];
1752            final int[] newLvarLength = new int[table_length];
1753            final int[] newLvarIndex = new int[table_length];
1754
1755            for (int i = 0; i < table_length; ++i) {
1756                newLvarOffset[i] = nextChar();
1757                newLvarLength[i] = nextChar();
1758                newLvarIndex[i] = nextChar();
1759            }
1760
1761            final TypeAnnotationPosition position =
1762                    TypeAnnotationPosition.localVariable(readTypePath());
1763            position.lvarOffset = newLvarOffset;
1764            position.lvarLength = newLvarLength;
1765            position.lvarIndex = newLvarIndex;
1766            return position;
1767        }
1768        // resource variable
1769        case RESOURCE_VARIABLE: {
1770            final int table_length = nextChar();
1771            final int[] newLvarOffset = new int[table_length];
1772            final int[] newLvarLength = new int[table_length];
1773            final int[] newLvarIndex = new int[table_length];
1774
1775            for (int i = 0; i < table_length; ++i) {
1776                newLvarOffset[i] = nextChar();
1777                newLvarLength[i] = nextChar();
1778                newLvarIndex[i] = nextChar();
1779            }
1780
1781            final TypeAnnotationPosition position =
1782                    TypeAnnotationPosition.resourceVariable(readTypePath());
1783            position.lvarOffset = newLvarOffset;
1784            position.lvarLength = newLvarLength;
1785            position.lvarIndex = newLvarIndex;
1786            return position;
1787        }
1788        // exception parameter
1789        case EXCEPTION_PARAMETER: {
1790            final int exception_index = nextChar();
1791            final TypeAnnotationPosition position =
1792                TypeAnnotationPosition.exceptionParameter(readTypePath());
1793            position.setExceptionIndex(exception_index);
1794            return position;
1795        }
1796        // method receiver
1797        case METHOD_RECEIVER:
1798            return TypeAnnotationPosition.methodReceiver(readTypePath());
1799        // type parameter
1800        case CLASS_TYPE_PARAMETER: {
1801            final int parameter_index = nextByte();
1802            return TypeAnnotationPosition
1803                .typeParameter(readTypePath(), parameter_index);
1804        }
1805        case METHOD_TYPE_PARAMETER: {
1806            final int parameter_index = nextByte();
1807            return TypeAnnotationPosition
1808                .methodTypeParameter(readTypePath(), parameter_index);
1809        }
1810        // type parameter bound
1811        case CLASS_TYPE_PARAMETER_BOUND: {
1812            final int parameter_index = nextByte();
1813            final int bound_index = nextByte();
1814            return TypeAnnotationPosition
1815                .typeParameterBound(readTypePath(), parameter_index,
1816                                    bound_index);
1817        }
1818        case METHOD_TYPE_PARAMETER_BOUND: {
1819            final int parameter_index = nextByte();
1820            final int bound_index = nextByte();
1821            return TypeAnnotationPosition
1822                .methodTypeParameterBound(readTypePath(), parameter_index,
1823                                          bound_index);
1824        }
1825        // class extends or implements clause
1826        case CLASS_EXTENDS: {
1827            final int type_index = nextChar();
1828            return TypeAnnotationPosition.classExtends(readTypePath(),
1829                                                       type_index);
1830        }
1831        // throws
1832        case THROWS: {
1833            final int type_index = nextChar();
1834            return TypeAnnotationPosition.methodThrows(readTypePath(),
1835                                                       type_index);
1836        }
1837        // method parameter
1838        case METHOD_FORMAL_PARAMETER: {
1839            final int parameter_index = nextByte();
1840            return TypeAnnotationPosition.methodParameter(readTypePath(),
1841                                                          parameter_index);
1842        }
1843        // type cast
1844        case CAST: {
1845            final int offset = nextChar();
1846            final int type_index = nextByte();
1847            final TypeAnnotationPosition position =
1848                TypeAnnotationPosition.typeCast(readTypePath(), type_index);
1849            position.offset = offset;
1850            return position;
1851        }
1852        // method/constructor/reference type argument
1853        case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: {
1854            final int offset = nextChar();
1855            final int type_index = nextByte();
1856            final TypeAnnotationPosition position = TypeAnnotationPosition
1857                .constructorInvocationTypeArg(readTypePath(), type_index);
1858            position.offset = offset;
1859            return position;
1860        }
1861        case METHOD_INVOCATION_TYPE_ARGUMENT: {
1862            final int offset = nextChar();
1863            final int type_index = nextByte();
1864            final TypeAnnotationPosition position = TypeAnnotationPosition
1865                .methodInvocationTypeArg(readTypePath(), type_index);
1866            position.offset = offset;
1867            return position;
1868        }
1869        case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: {
1870            final int offset = nextChar();
1871            final int type_index = nextByte();
1872            final TypeAnnotationPosition position = TypeAnnotationPosition
1873                .constructorRefTypeArg(readTypePath(), type_index);
1874            position.offset = offset;
1875            return position;
1876        }
1877        case METHOD_REFERENCE_TYPE_ARGUMENT: {
1878            final int offset = nextChar();
1879            final int type_index = nextByte();
1880            final TypeAnnotationPosition position = TypeAnnotationPosition
1881                .methodRefTypeArg(readTypePath(), type_index);
1882            position.offset = offset;
1883            return position;
1884        }
1885        // We don't need to worry about these
1886        case METHOD_RETURN:
1887            return TypeAnnotationPosition.methodReturn(readTypePath());
1888        case FIELD:
1889            return TypeAnnotationPosition.field(readTypePath());
1890        case UNKNOWN:
1891            throw new AssertionError("jvm.ClassReader: UNKNOWN target type should never occur!");
1892        default:
1893            throw new AssertionError("jvm.ClassReader: Unknown target type for position: " + type);
1894        }
1895    }
1896
1897    List<TypeAnnotationPosition.TypePathEntry> readTypePath() {
1898        int len = nextByte();
1899        ListBuffer<Integer> loc = new ListBuffer<>();
1900        for (int i = 0; i < len * TypeAnnotationPosition.TypePathEntry.bytesPerEntry; ++i)
1901            loc = loc.append(nextByte());
1902
1903        return TypeAnnotationPosition.getTypePathFromBinary(loc.toList());
1904
1905    }
1906
1907    Attribute readAttributeValue() {
1908        char c = (char) buf[bp++];
1909        switch (c) {
1910        case 'B':
1911            return new Attribute.Constant(syms.byteType, readPool(nextChar()));
1912        case 'C':
1913            return new Attribute.Constant(syms.charType, readPool(nextChar()));
1914        case 'D':
1915            return new Attribute.Constant(syms.doubleType, readPool(nextChar()));
1916        case 'F':
1917            return new Attribute.Constant(syms.floatType, readPool(nextChar()));
1918        case 'I':
1919            return new Attribute.Constant(syms.intType, readPool(nextChar()));
1920        case 'J':
1921            return new Attribute.Constant(syms.longType, readPool(nextChar()));
1922        case 'S':
1923            return new Attribute.Constant(syms.shortType, readPool(nextChar()));
1924        case 'Z':
1925            return new Attribute.Constant(syms.booleanType, readPool(nextChar()));
1926        case 's':
1927            return new Attribute.Constant(syms.stringType, readPool(nextChar()).toString());
1928        case 'e':
1929            return new EnumAttributeProxy(readEnumType(nextChar()), readName(nextChar()));
1930        case 'c':
1931            return new ClassAttributeProxy(readTypeOrClassSymbol(nextChar()));
1932        case '[': {
1933            int n = nextChar();
1934            ListBuffer<Attribute> l = new ListBuffer<>();
1935            for (int i=0; i<n; i++)
1936                l.append(readAttributeValue());
1937            return new ArrayAttributeProxy(l.toList());
1938        }
1939        case '@':
1940            return readCompoundAnnotation();
1941        default:
1942            throw new AssertionError("unknown annotation tag '" + c + "'");
1943        }
1944    }
1945
1946    interface ProxyVisitor extends Attribute.Visitor {
1947        void visitEnumAttributeProxy(EnumAttributeProxy proxy);
1948        void visitClassAttributeProxy(ClassAttributeProxy proxy);
1949        void visitArrayAttributeProxy(ArrayAttributeProxy proxy);
1950        void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy);
1951    }
1952
1953    static class EnumAttributeProxy extends Attribute {
1954        Type enumType;
1955        Name enumerator;
1956        public EnumAttributeProxy(Type enumType, Name enumerator) {
1957            super(null);
1958            this.enumType = enumType;
1959            this.enumerator = enumerator;
1960        }
1961        public void accept(Visitor v) { ((ProxyVisitor)v).visitEnumAttributeProxy(this); }
1962        @Override @DefinedBy(Api.LANGUAGE_MODEL)
1963        public String toString() {
1964            return "/*proxy enum*/" + enumType + "." + enumerator;
1965        }
1966    }
1967
1968    static class ClassAttributeProxy extends Attribute {
1969        Type classType;
1970        public ClassAttributeProxy(Type classType) {
1971            super(null);
1972            this.classType = classType;
1973        }
1974        public void accept(Visitor v) { ((ProxyVisitor)v).visitClassAttributeProxy(this); }
1975        @Override @DefinedBy(Api.LANGUAGE_MODEL)
1976        public String toString() {
1977            return "/*proxy class*/" + classType + ".class";
1978        }
1979    }
1980
1981    static class ArrayAttributeProxy extends Attribute {
1982        List<Attribute> values;
1983        ArrayAttributeProxy(List<Attribute> values) {
1984            super(null);
1985            this.values = values;
1986        }
1987        public void accept(Visitor v) { ((ProxyVisitor)v).visitArrayAttributeProxy(this); }
1988        @Override @DefinedBy(Api.LANGUAGE_MODEL)
1989        public String toString() {
1990            return "{" + values + "}";
1991        }
1992    }
1993
1994    /** A temporary proxy representing a compound attribute.
1995     */
1996    static class CompoundAnnotationProxy extends Attribute {
1997        final List<Pair<Name,Attribute>> values;
1998        public CompoundAnnotationProxy(Type type,
1999                                      List<Pair<Name,Attribute>> values) {
2000            super(type);
2001            this.values = values;
2002        }
2003        public void accept(Visitor v) { ((ProxyVisitor)v).visitCompoundAnnotationProxy(this); }
2004        @Override @DefinedBy(Api.LANGUAGE_MODEL)
2005        public String toString() {
2006            StringBuilder buf = new StringBuilder();
2007            buf.append("@");
2008            buf.append(type.tsym.getQualifiedName());
2009            buf.append("/*proxy*/{");
2010            boolean first = true;
2011            for (List<Pair<Name,Attribute>> v = values;
2012                 v.nonEmpty(); v = v.tail) {
2013                Pair<Name,Attribute> value = v.head;
2014                if (!first) buf.append(",");
2015                first = false;
2016                buf.append(value.fst);
2017                buf.append("=");
2018                buf.append(value.snd);
2019            }
2020            buf.append("}");
2021            return buf.toString();
2022        }
2023    }
2024
2025    /** A temporary proxy representing a type annotation.
2026     */
2027    static class TypeAnnotationProxy {
2028        final CompoundAnnotationProxy compound;
2029        final TypeAnnotationPosition position;
2030        public TypeAnnotationProxy(CompoundAnnotationProxy compound,
2031                TypeAnnotationPosition position) {
2032            this.compound = compound;
2033            this.position = position;
2034        }
2035    }
2036
2037    class AnnotationDeproxy implements ProxyVisitor {
2038        private ClassSymbol requestingOwner;
2039
2040        AnnotationDeproxy(ClassSymbol owner) {
2041            this.requestingOwner = owner;
2042        }
2043
2044        List<Attribute.Compound> deproxyCompoundList(List<CompoundAnnotationProxy> pl) {
2045            // also must fill in types!!!!
2046            ListBuffer<Attribute.Compound> buf = new ListBuffer<>();
2047            for (List<CompoundAnnotationProxy> l = pl; l.nonEmpty(); l=l.tail) {
2048                buf.append(deproxyCompound(l.head));
2049            }
2050            return buf.toList();
2051        }
2052
2053        Attribute.Compound deproxyCompound(CompoundAnnotationProxy a) {
2054            Type annotationType = resolvePossibleProxyType(a.type);
2055            ListBuffer<Pair<Symbol.MethodSymbol,Attribute>> buf = new ListBuffer<>();
2056            for (List<Pair<Name,Attribute>> l = a.values;
2057                 l.nonEmpty();
2058                 l = l.tail) {
2059                MethodSymbol meth = findAccessMethod(annotationType, l.head.fst);
2060                buf.append(new Pair<>(meth, deproxy(meth.type.getReturnType(), l.head.snd)));
2061            }
2062            return new Attribute.Compound(annotationType, buf.toList());
2063        }
2064
2065        MethodSymbol findAccessMethod(Type container, Name name) {
2066            CompletionFailure failure = null;
2067            try {
2068                for (Symbol sym : container.tsym.members().getSymbolsByName(name)) {
2069                    if (sym.kind == MTH && sym.type.getParameterTypes().length() == 0)
2070                        return (MethodSymbol) sym;
2071                }
2072            } catch (CompletionFailure ex) {
2073                failure = ex;
2074            }
2075            // The method wasn't found: emit a warning and recover
2076            JavaFileObject prevSource = log.useSource(requestingOwner.classfile);
2077            try {
2078                if (lintClassfile) {
2079                    if (failure == null) {
2080                        log.warning("annotation.method.not.found",
2081                                    container,
2082                                    name);
2083                    } else {
2084                        log.warning("annotation.method.not.found.reason",
2085                                    container,
2086                                    name,
2087                                    failure.getDetailValue());//diagnostic, if present
2088                    }
2089                }
2090            } finally {
2091                log.useSource(prevSource);
2092            }
2093            // Construct a new method type and symbol.  Use bottom
2094            // type (typeof null) as return type because this type is
2095            // a subtype of all reference types and can be converted
2096            // to primitive types by unboxing.
2097            MethodType mt = new MethodType(List.nil(),
2098                                           syms.botType,
2099                                           List.nil(),
2100                                           syms.methodClass);
2101            return new MethodSymbol(PUBLIC | ABSTRACT, name, mt, container.tsym);
2102        }
2103
2104        Attribute result;
2105        Type type;
2106        Attribute deproxy(Type t, Attribute a) {
2107            Type oldType = type;
2108            try {
2109                type = t;
2110                a.accept(this);
2111                return result;
2112            } finally {
2113                type = oldType;
2114            }
2115        }
2116
2117        // implement Attribute.Visitor below
2118
2119        public void visitConstant(Attribute.Constant value) {
2120            // assert value.type == type;
2121            result = value;
2122        }
2123
2124        public void visitClass(Attribute.Class clazz) {
2125            result = clazz;
2126        }
2127
2128        public void visitEnum(Attribute.Enum e) {
2129            throw new AssertionError(); // shouldn't happen
2130        }
2131
2132        public void visitCompound(Attribute.Compound compound) {
2133            throw new AssertionError(); // shouldn't happen
2134        }
2135
2136        public void visitArray(Attribute.Array array) {
2137            throw new AssertionError(); // shouldn't happen
2138        }
2139
2140        public void visitError(Attribute.Error e) {
2141            throw new AssertionError(); // shouldn't happen
2142        }
2143
2144        public void visitEnumAttributeProxy(EnumAttributeProxy proxy) {
2145            // type.tsym.flatName() should == proxy.enumFlatName
2146            Type enumType = resolvePossibleProxyType(proxy.enumType);
2147            TypeSymbol enumTypeSym = enumType.tsym;
2148            VarSymbol enumerator = null;
2149            CompletionFailure failure = null;
2150            try {
2151                for (Symbol sym : enumTypeSym.members().getSymbolsByName(proxy.enumerator)) {
2152                    if (sym.kind == VAR) {
2153                        enumerator = (VarSymbol)sym;
2154                        break;
2155                    }
2156                }
2157            }
2158            catch (CompletionFailure ex) {
2159                failure = ex;
2160            }
2161            if (enumerator == null) {
2162                if (failure != null) {
2163                    log.warning("unknown.enum.constant.reason",
2164                              currentClassFile, enumTypeSym, proxy.enumerator,
2165                              failure.getDiagnostic());
2166                } else {
2167                    log.warning("unknown.enum.constant",
2168                              currentClassFile, enumTypeSym, proxy.enumerator);
2169                }
2170                result = new Attribute.Enum(enumTypeSym.type,
2171                        new VarSymbol(0, proxy.enumerator, syms.botType, enumTypeSym));
2172            } else {
2173                result = new Attribute.Enum(enumTypeSym.type, enumerator);
2174            }
2175        }
2176
2177        @Override
2178        public void visitClassAttributeProxy(ClassAttributeProxy proxy) {
2179            Type classType = resolvePossibleProxyType(proxy.classType);
2180            result = new Attribute.Class(types, classType);
2181        }
2182
2183        public void visitArrayAttributeProxy(ArrayAttributeProxy proxy) {
2184            int length = proxy.values.length();
2185            Attribute[] ats = new Attribute[length];
2186            Type elemtype = types.elemtype(type);
2187            int i = 0;
2188            for (List<Attribute> p = proxy.values; p.nonEmpty(); p = p.tail) {
2189                ats[i++] = deproxy(elemtype, p.head);
2190            }
2191            result = new Attribute.Array(type, ats);
2192        }
2193
2194        public void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy) {
2195            result = deproxyCompound(proxy);
2196        }
2197
2198        Type resolvePossibleProxyType(Type t) {
2199            if (t instanceof ProxyType) {
2200                Assert.check(requestingOwner.owner.kind == MDL);
2201                ModuleSymbol prevCurrentModule = currentModule;
2202                currentModule = (ModuleSymbol) requestingOwner.owner;
2203                try {
2204                    return ((ProxyType) t).resolve();
2205                } finally {
2206                    currentModule = prevCurrentModule;
2207                }
2208            } else {
2209                return t;
2210            }
2211        }
2212    }
2213
2214    class AnnotationDefaultCompleter extends AnnotationDeproxy implements Runnable {
2215        final MethodSymbol sym;
2216        final Attribute value;
2217        final JavaFileObject classFile = currentClassFile;
2218
2219        AnnotationDefaultCompleter(MethodSymbol sym, Attribute value) {
2220            super(currentOwner.kind == MTH
2221                    ? currentOwner.enclClass() : (ClassSymbol)currentOwner);
2222            this.sym = sym;
2223            this.value = value;
2224        }
2225
2226        @Override
2227        public void run() {
2228            JavaFileObject previousClassFile = currentClassFile;
2229            try {
2230                // Reset the interim value set earlier in
2231                // attachAnnotationDefault().
2232                sym.defaultValue = null;
2233                currentClassFile = classFile;
2234                sym.defaultValue = deproxy(sym.type.getReturnType(), value);
2235            } finally {
2236                currentClassFile = previousClassFile;
2237            }
2238        }
2239
2240        @Override
2241        public String toString() {
2242            return " ClassReader store default for " + sym.owner + "." + sym + " is " + value;
2243        }
2244    }
2245
2246    class AnnotationCompleter extends AnnotationDeproxy implements Runnable {
2247        final Symbol sym;
2248        final List<CompoundAnnotationProxy> l;
2249        final JavaFileObject classFile;
2250
2251        AnnotationCompleter(Symbol sym, List<CompoundAnnotationProxy> l) {
2252            super(currentOwner.kind == MTH
2253                    ? currentOwner.enclClass() : (ClassSymbol)currentOwner);
2254            if (sym.kind == TYP && sym.owner.kind == MDL) {
2255                this.sym = sym.owner;
2256            } else {
2257                this.sym = sym;
2258            }
2259            this.l = l;
2260            this.classFile = currentClassFile;
2261        }
2262
2263        @Override
2264        public void run() {
2265            JavaFileObject previousClassFile = currentClassFile;
2266            try {
2267                currentClassFile = classFile;
2268                List<Attribute.Compound> newList = deproxyCompoundList(l);
2269                for (Attribute.Compound attr : newList) {
2270                    if (attr.type.tsym == syms.deprecatedType.tsym) {
2271                        sym.flags_field |= (DEPRECATED | DEPRECATED_ANNOTATION);
2272                        Attribute forRemoval = attr.member(names.forRemoval);
2273                        if (forRemoval instanceof Attribute.Constant) {
2274                            Attribute.Constant c = (Attribute.Constant) forRemoval;
2275                            if (c.type == syms.booleanType && ((Integer) c.value) != 0) {
2276                                sym.flags_field |= DEPRECATED_REMOVAL;
2277                            }
2278                        }
2279                    }
2280                }
2281                if (sym.annotationsPendingCompletion()) {
2282                    sym.setDeclarationAttributes(newList);
2283                } else {
2284                    sym.appendAttributes(newList);
2285                }
2286            } finally {
2287                currentClassFile = previousClassFile;
2288            }
2289        }
2290
2291        @Override
2292        public String toString() {
2293            return " ClassReader annotate " + sym.owner + "." + sym + " with " + l;
2294        }
2295    }
2296
2297    class TypeAnnotationCompleter extends AnnotationCompleter {
2298
2299        List<TypeAnnotationProxy> proxies;
2300
2301        TypeAnnotationCompleter(Symbol sym,
2302                List<TypeAnnotationProxy> proxies) {
2303            super(sym, List.nil());
2304            this.proxies = proxies;
2305        }
2306
2307        List<Attribute.TypeCompound> deproxyTypeCompoundList(List<TypeAnnotationProxy> proxies) {
2308            ListBuffer<Attribute.TypeCompound> buf = new ListBuffer<>();
2309            for (TypeAnnotationProxy proxy: proxies) {
2310                Attribute.Compound compound = deproxyCompound(proxy.compound);
2311                Attribute.TypeCompound typeCompound = new Attribute.TypeCompound(compound, proxy.position);
2312                buf.add(typeCompound);
2313            }
2314            return buf.toList();
2315        }
2316
2317        @Override
2318        public void run() {
2319            JavaFileObject previousClassFile = currentClassFile;
2320            try {
2321                currentClassFile = classFile;
2322                List<Attribute.TypeCompound> newList = deproxyTypeCompoundList(proxies);
2323                sym.setTypeAttributes(newList.prependList(sym.getRawTypeAttributes()));
2324            } finally {
2325                currentClassFile = previousClassFile;
2326            }
2327        }
2328    }
2329
2330
2331/************************************************************************
2332 * Reading Symbols
2333 ***********************************************************************/
2334
2335    /** Read a field.
2336     */
2337    VarSymbol readField() {
2338        long flags = adjustFieldFlags(nextChar());
2339        Name name = readName(nextChar());
2340        Type type = readType(nextChar());
2341        VarSymbol v = new VarSymbol(flags, name, type, currentOwner);
2342        readMemberAttrs(v);
2343        return v;
2344    }
2345
2346    /** Read a method.
2347     */
2348    MethodSymbol readMethod() {
2349        long flags = adjustMethodFlags(nextChar());
2350        Name name = readName(nextChar());
2351        Type type = readType(nextChar());
2352        if (currentOwner.isInterface() &&
2353                (flags & ABSTRACT) == 0 && !name.equals(names.clinit)) {
2354            if (majorVersion > Version.V52.major ||
2355                    (majorVersion == Version.V52.major && minorVersion >= Version.V52.minor)) {
2356                if ((flags & STATIC) == 0) {
2357                    currentOwner.flags_field |= DEFAULT;
2358                    flags |= DEFAULT | ABSTRACT;
2359                }
2360            } else {
2361                //protect against ill-formed classfiles
2362                throw badClassFile((flags & STATIC) == 0 ? "invalid.default.interface" : "invalid.static.interface",
2363                                   Integer.toString(majorVersion),
2364                                   Integer.toString(minorVersion));
2365            }
2366        }
2367        if (name == names.init && currentOwner.hasOuterInstance()) {
2368            // Sometimes anonymous classes don't have an outer
2369            // instance, however, there is no reliable way to tell so
2370            // we never strip this$n
2371            // ditto for local classes. Local classes that have an enclosing method set
2372            // won't pass the "hasOuterInstance" check above, but those that don't have an
2373            // enclosing method (i.e. from initializers) will pass that check.
2374            boolean local = !currentOwner.owner.members().includes(currentOwner, LookupKind.NON_RECURSIVE);
2375            if (!currentOwner.name.isEmpty() && !local)
2376                type = new MethodType(adjustMethodParams(flags, type.getParameterTypes()),
2377                                      type.getReturnType(),
2378                                      type.getThrownTypes(),
2379                                      syms.methodClass);
2380        }
2381        MethodSymbol m = new MethodSymbol(flags, name, type, currentOwner);
2382        if (types.isSignaturePolymorphic(m)) {
2383            m.flags_field |= SIGNATURE_POLYMORPHIC;
2384        }
2385        if (saveParameterNames)
2386            initParameterNames(m);
2387        Symbol prevOwner = currentOwner;
2388        currentOwner = m;
2389        try {
2390            readMemberAttrs(m);
2391        } finally {
2392            currentOwner = prevOwner;
2393        }
2394        if (saveParameterNames)
2395            setParameterNames(m, type);
2396
2397        if ((flags & VARARGS) != 0) {
2398            final Type last = type.getParameterTypes().last();
2399            if (last == null || !last.hasTag(ARRAY)) {
2400                m.flags_field &= ~VARARGS;
2401                throw badClassFile("malformed.vararg.method", m);
2402            }
2403        }
2404
2405        return m;
2406    }
2407
2408    private List<Type> adjustMethodParams(long flags, List<Type> args) {
2409        boolean isVarargs = (flags & VARARGS) != 0;
2410        if (isVarargs) {
2411            Type varargsElem = args.last();
2412            ListBuffer<Type> adjustedArgs = new ListBuffer<>();
2413            for (Type t : args) {
2414                adjustedArgs.append(t != varargsElem ?
2415                    t :
2416                    ((ArrayType)t).makeVarargs());
2417            }
2418            args = adjustedArgs.toList();
2419        }
2420        return args.tail;
2421    }
2422
2423    /**
2424     * Init the parameter names array.
2425     * Parameter names are currently inferred from the names in the
2426     * LocalVariableTable attributes of a Code attribute.
2427     * (Note: this means parameter names are currently not available for
2428     * methods without a Code attribute.)
2429     * This method initializes an array in which to store the name indexes
2430     * of parameter names found in LocalVariableTable attributes. It is
2431     * slightly supersized to allow for additional slots with a start_pc of 0.
2432     */
2433    void initParameterNames(MethodSymbol sym) {
2434        // make allowance for synthetic parameters.
2435        final int excessSlots = 4;
2436        int expectedParameterSlots =
2437                Code.width(sym.type.getParameterTypes()) + excessSlots;
2438        if (parameterNameIndices == null
2439                || parameterNameIndices.length < expectedParameterSlots) {
2440            parameterNameIndices = new int[expectedParameterSlots];
2441        } else
2442            Arrays.fill(parameterNameIndices, 0);
2443        haveParameterNameIndices = false;
2444        sawMethodParameters = false;
2445    }
2446
2447    /**
2448     * Set the parameter names for a symbol from the name index in the
2449     * parameterNameIndicies array. The type of the symbol may have changed
2450     * while reading the method attributes (see the Signature attribute).
2451     * This may be because of generic information or because anonymous
2452     * synthetic parameters were added.   The original type (as read from
2453     * the method descriptor) is used to help guess the existence of
2454     * anonymous synthetic parameters.
2455     * On completion, sym.savedParameter names will either be null (if
2456     * no parameter names were found in the class file) or will be set to a
2457     * list of names, one per entry in sym.type.getParameterTypes, with
2458     * any missing names represented by the empty name.
2459     */
2460    void setParameterNames(MethodSymbol sym, Type jvmType) {
2461        // if no names were found in the class file, there's nothing more to do
2462        if (!haveParameterNameIndices)
2463            return;
2464        // If we get parameter names from MethodParameters, then we
2465        // don't need to skip.
2466        int firstParam = 0;
2467        if (!sawMethodParameters) {
2468            firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0;
2469            // the code in readMethod may have skipped the first
2470            // parameter when setting up the MethodType. If so, we
2471            // make a corresponding allowance here for the position of
2472            // the first parameter.  Note that this assumes the
2473            // skipped parameter has a width of 1 -- i.e. it is not
2474        // a double width type (long or double.)
2475        if (sym.name == names.init && currentOwner.hasOuterInstance()) {
2476            // Sometimes anonymous classes don't have an outer
2477            // instance, however, there is no reliable way to tell so
2478            // we never strip this$n
2479            if (!currentOwner.name.isEmpty())
2480                firstParam += 1;
2481        }
2482
2483        if (sym.type != jvmType) {
2484                // reading the method attributes has caused the
2485                // symbol's type to be changed. (i.e. the Signature
2486                // attribute.)  This may happen if there are hidden
2487                // (synthetic) parameters in the descriptor, but not
2488                // in the Signature.  The position of these hidden
2489                // parameters is unspecified; for now, assume they are
2490                // at the beginning, and so skip over them. The
2491                // primary case for this is two hidden parameters
2492                // passed into Enum constructors.
2493            int skip = Code.width(jvmType.getParameterTypes())
2494                    - Code.width(sym.type.getParameterTypes());
2495            firstParam += skip;
2496        }
2497        }
2498        List<Name> paramNames = List.nil();
2499        int index = firstParam;
2500        for (Type t: sym.type.getParameterTypes()) {
2501            int nameIdx = (index < parameterNameIndices.length
2502                    ? parameterNameIndices[index] : 0);
2503            Name name = nameIdx == 0 ? names.empty : readName(nameIdx);
2504            paramNames = paramNames.prepend(name);
2505            index += sawMethodParameters ? 1 : Code.width(t);
2506        }
2507        sym.savedParameterNames = paramNames.reverse();
2508    }
2509
2510    /**
2511     * skip n bytes
2512     */
2513    void skipBytes(int n) {
2514        bp = bp + n;
2515    }
2516
2517    /** Skip a field or method
2518     */
2519    void skipMember() {
2520        bp = bp + 6;
2521        char ac = nextChar();
2522        for (int i = 0; i < ac; i++) {
2523            bp = bp + 2;
2524            int attrLen = nextInt();
2525            bp = bp + attrLen;
2526        }
2527    }
2528
2529    void skipInnerClasses() {
2530        int n = nextChar();
2531        for (int i = 0; i < n; i++) {
2532            nextChar();
2533            nextChar();
2534            nextChar();
2535            nextChar();
2536        }
2537    }
2538
2539    /** Enter type variables of this classtype and all enclosing ones in
2540     *  `typevars'.
2541     */
2542    protected void enterTypevars(Symbol sym, Type t) {
2543        if (t.getEnclosingType() != null) {
2544            if (!t.getEnclosingType().hasTag(TypeTag.NONE)) {
2545                enterTypevars(sym.owner, t.getEnclosingType());
2546            }
2547        } else if (sym.kind == MTH && !sym.isStatic()) {
2548            enterTypevars(sym.owner, sym.owner.type);
2549        }
2550        for (List<Type> xs = t.getTypeArguments(); xs.nonEmpty(); xs = xs.tail) {
2551            typevars.enter(xs.head.tsym);
2552        }
2553    }
2554
2555    protected ClassSymbol enterClass(Name name) {
2556        return syms.enterClass(currentModule, name);
2557    }
2558
2559    protected ClassSymbol enterClass(Name name, TypeSymbol owner) {
2560        return syms.enterClass(currentModule, name, owner);
2561    }
2562
2563    /** Read contents of a given class symbol `c'. Both external and internal
2564     *  versions of an inner class are read.
2565     */
2566    void readClass(ClassSymbol c) {
2567        ClassType ct = (ClassType)c.type;
2568
2569        // allocate scope for members
2570        c.members_field = WriteableScope.create(c);
2571
2572        // prepare type variable table
2573        typevars = typevars.dup(currentOwner);
2574        if (ct.getEnclosingType().hasTag(CLASS))
2575            enterTypevars(c.owner, ct.getEnclosingType());
2576
2577        // read flags, or skip if this is an inner class
2578        long f = nextChar();
2579        long flags = adjustClassFlags(f);
2580        if ((flags & MODULE) == 0) {
2581            if (c.owner.kind == PCK) c.flags_field = flags;
2582            // read own class name and check that it matches
2583            currentModule = c.packge().modle;
2584            ClassSymbol self = readClassSymbol(nextChar());
2585            if (c != self) {
2586                throw badClassFile("class.file.wrong.class",
2587                                   self.flatname);
2588            }
2589        } else {
2590            if (majorVersion < Version.V53.major) {
2591                throw badClassFile("anachronistic.module.info",
2592                        Integer.toString(majorVersion),
2593                        Integer.toString(minorVersion));
2594            }
2595            c.flags_field = flags;
2596            currentModule = (ModuleSymbol) c.owner;
2597            int this_class = nextChar();
2598            // temp, no check on this_class
2599        }
2600
2601        // class attributes must be read before class
2602        // skip ahead to read class attributes
2603        int startbp = bp;
2604        nextChar();
2605        char interfaceCount = nextChar();
2606        bp += interfaceCount * 2;
2607        char fieldCount = nextChar();
2608        for (int i = 0; i < fieldCount; i++) skipMember();
2609        char methodCount = nextChar();
2610        for (int i = 0; i < methodCount; i++) skipMember();
2611        readClassAttrs(c);
2612
2613        if (readAllOfClassFile) {
2614            for (int i = 1; i < poolObj.length; i++) readPool(i);
2615            c.pool = new Pool(poolObj.length, poolObj, types);
2616        }
2617
2618        // reset and read rest of classinfo
2619        bp = startbp;
2620        int n = nextChar();
2621        if ((flags & MODULE) != 0 && n > 0) {
2622            throw badClassFile("module.info.invalid.super.class");
2623        }
2624        if (ct.supertype_field == null)
2625            ct.supertype_field = (n == 0)
2626                ? Type.noType
2627                : readClassSymbol(n).erasure(types);
2628        n = nextChar();
2629        List<Type> is = List.nil();
2630        for (int i = 0; i < n; i++) {
2631            Type _inter = readClassSymbol(nextChar()).erasure(types);
2632            is = is.prepend(_inter);
2633        }
2634        if (ct.interfaces_field == null)
2635            ct.interfaces_field = is.reverse();
2636
2637        Assert.check(fieldCount == nextChar());
2638        for (int i = 0; i < fieldCount; i++) enterMember(c, readField());
2639        Assert.check(methodCount == nextChar());
2640        for (int i = 0; i < methodCount; i++) enterMember(c, readMethod());
2641
2642        typevars = typevars.leave();
2643    }
2644
2645    /** Read inner class info. For each inner/outer pair allocate a
2646     *  member class.
2647     */
2648    void readInnerClasses(ClassSymbol c) {
2649        int n = nextChar();
2650        for (int i = 0; i < n; i++) {
2651            nextChar(); // skip inner class symbol
2652            ClassSymbol outer = readClassSymbol(nextChar());
2653            Name name = readName(nextChar());
2654            if (name == null) name = names.empty;
2655            long flags = adjustClassFlags(nextChar());
2656            if (outer != null) { // we have a member class
2657                if (name == names.empty)
2658                    name = names.one;
2659                ClassSymbol member = enterClass(name, outer);
2660                if ((flags & STATIC) == 0) {
2661                    ((ClassType)member.type).setEnclosingType(outer.type);
2662                    if (member.erasure_field != null)
2663                        ((ClassType)member.erasure_field).setEnclosingType(types.erasure(outer.type));
2664                }
2665                if (c == outer) {
2666                    member.flags_field = flags;
2667                    enterMember(c, member);
2668                }
2669            }
2670        }
2671    }
2672
2673    /** Read a class definition from the bytes in buf.
2674     */
2675    private void readClassBuffer(ClassSymbol c) throws IOException {
2676        int magic = nextInt();
2677        if (magic != JAVA_MAGIC)
2678            throw badClassFile("illegal.start.of.class.file");
2679
2680        minorVersion = nextChar();
2681        majorVersion = nextChar();
2682        int maxMajor = 53; // Version.MAX().major;  //******* TEMPORARY *******
2683        int maxMinor = Version.MAX().minor;
2684        if (majorVersion > maxMajor ||
2685            majorVersion * 1000 + minorVersion <
2686            Version.MIN().major * 1000 + Version.MIN().minor) {
2687            if (majorVersion == (maxMajor + 1))
2688                log.warning("big.major.version",
2689                            currentClassFile,
2690                            majorVersion,
2691                            maxMajor);
2692            else
2693                throw badClassFile("wrong.version",
2694                                   Integer.toString(majorVersion),
2695                                   Integer.toString(minorVersion),
2696                                   Integer.toString(maxMajor),
2697                                   Integer.toString(maxMinor));
2698        }
2699
2700        indexPool();
2701        if (signatureBuffer.length < bp) {
2702            int ns = Integer.highestOneBit(bp) << 1;
2703            signatureBuffer = new byte[ns];
2704        }
2705        readClass(c);
2706    }
2707
2708    public void readClassFile(ClassSymbol c) {
2709        currentOwner = c;
2710        currentClassFile = c.classfile;
2711        warnedAttrs.clear();
2712        filling = true;
2713        target = null;
2714        repeatable = null;
2715        try {
2716            bp = 0;
2717            buf = readInputStream(buf, c.classfile.openInputStream());
2718            readClassBuffer(c);
2719            if (!missingTypeVariables.isEmpty() && !foundTypeVariables.isEmpty()) {
2720                List<Type> missing = missingTypeVariables;
2721                List<Type> found = foundTypeVariables;
2722                missingTypeVariables = List.nil();
2723                foundTypeVariables = List.nil();
2724                interimUses = List.nil();
2725                interimProvides = List.nil();
2726                filling = false;
2727                ClassType ct = (ClassType)currentOwner.type;
2728                ct.supertype_field =
2729                    types.subst(ct.supertype_field, missing, found);
2730                ct.interfaces_field =
2731                    types.subst(ct.interfaces_field, missing, found);
2732                ct.typarams_field =
2733                    types.substBounds(ct.typarams_field, missing, found);
2734                for (List<Type> types = ct.typarams_field; types.nonEmpty(); types = types.tail) {
2735                    types.head.tsym.type = types.head;
2736                }
2737            } else if (missingTypeVariables.isEmpty() !=
2738                       foundTypeVariables.isEmpty()) {
2739                Name name = missingTypeVariables.head.tsym.name;
2740                throw badClassFile("undecl.type.var", name);
2741            }
2742
2743            if ((c.flags_field & Flags.ANNOTATION) != 0) {
2744                c.setAnnotationTypeMetadata(new AnnotationTypeMetadata(c, new CompleterDeproxy(c, target, repeatable)));
2745            } else {
2746                c.setAnnotationTypeMetadata(AnnotationTypeMetadata.notAnAnnotationType());
2747            }
2748
2749            if (c == currentModule.module_info) {
2750                if (interimUses.nonEmpty() || interimProvides.nonEmpty()) {
2751                    Assert.check(currentModule.isCompleted());
2752                    currentModule.usesProvidesCompleter =
2753                            new UsesProvidesCompleter(currentModule, interimUses, interimProvides);
2754                } else {
2755                    currentModule.uses = List.nil();
2756                    currentModule.provides = List.nil();
2757                }
2758            }
2759        } catch (IOException ex) {
2760            throw badClassFile("unable.to.access.file", ex.getMessage());
2761        } catch (ArrayIndexOutOfBoundsException ex) {
2762            throw badClassFile("bad.class.file", c.flatname);
2763        } finally {
2764            interimUses = List.nil();
2765            interimProvides = List.nil();
2766            missingTypeVariables = List.nil();
2767            foundTypeVariables = List.nil();
2768            filling = false;
2769        }
2770    }
2771    // where
2772        private static byte[] readInputStream(byte[] buf, InputStream s) throws IOException {
2773            try {
2774                buf = ensureCapacity(buf, s.available());
2775                int r = s.read(buf);
2776                int bp = 0;
2777                while (r != -1) {
2778                    bp += r;
2779                    buf = ensureCapacity(buf, bp);
2780                    r = s.read(buf, bp, buf.length - bp);
2781                }
2782                return buf;
2783            } finally {
2784                try {
2785                    s.close();
2786                } catch (IOException e) {
2787                    /* Ignore any errors, as this stream may have already
2788                     * thrown a related exception which is the one that
2789                     * should be reported.
2790                     */
2791                }
2792            }
2793        }
2794        /*
2795         * ensureCapacity will increase the buffer as needed, taking note that
2796         * the new buffer will always be greater than the needed and never
2797         * exactly equal to the needed size or bp. If equal then the read (above)
2798         * will infinitely loop as buf.length - bp == 0.
2799         */
2800        private static byte[] ensureCapacity(byte[] buf, int needed) {
2801            if (buf.length <= needed) {
2802                byte[] old = buf;
2803                buf = new byte[Integer.highestOneBit(needed) << 1];
2804                System.arraycopy(old, 0, buf, 0, old.length);
2805            }
2806            return buf;
2807        }
2808
2809    /** We can only read a single class file at a time; this
2810     *  flag keeps track of when we are currently reading a class
2811     *  file.
2812     */
2813    public boolean filling = false;
2814
2815/************************************************************************
2816 * Adjusting flags
2817 ***********************************************************************/
2818
2819    long adjustFieldFlags(long flags) {
2820        return flags;
2821    }
2822
2823    long adjustMethodFlags(long flags) {
2824        if ((flags & ACC_BRIDGE) != 0) {
2825            flags &= ~ACC_BRIDGE;
2826            flags |= BRIDGE;
2827        }
2828        if ((flags & ACC_VARARGS) != 0) {
2829            flags &= ~ACC_VARARGS;
2830            flags |= VARARGS;
2831        }
2832        return flags;
2833    }
2834
2835    long adjustClassFlags(long flags) {
2836        if ((flags & ACC_MODULE) != 0) {
2837            flags &= ~ACC_MODULE;
2838            flags |= MODULE;
2839        }
2840        return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
2841    }
2842
2843    /**
2844     * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
2845     * The attribute is only the last component of the original filename, so is unlikely
2846     * to be valid as is, so operations other than those to access the name throw
2847     * UnsupportedOperationException
2848     */
2849    private static class SourceFileObject implements JavaFileObject {
2850
2851        /** The file's name.
2852         */
2853        private final Name name;
2854        private final Name flatname;
2855
2856        public SourceFileObject(Name name, Name flatname) {
2857            this.name = name;
2858            this.flatname = flatname;
2859        }
2860
2861        @Override @DefinedBy(Api.COMPILER)
2862        public URI toUri() {
2863            try {
2864                return new URI(null, name.toString(), null);
2865            } catch (URISyntaxException e) {
2866                throw new PathFileObject.CannotCreateUriError(name.toString(), e);
2867            }
2868        }
2869
2870        @Override @DefinedBy(Api.COMPILER)
2871        public String getName() {
2872            return name.toString();
2873        }
2874
2875        @Override @DefinedBy(Api.COMPILER)
2876        public JavaFileObject.Kind getKind() {
2877            return BaseFileManager.getKind(getName());
2878        }
2879
2880        @Override @DefinedBy(Api.COMPILER)
2881        public InputStream openInputStream() {
2882            throw new UnsupportedOperationException();
2883        }
2884
2885        @Override @DefinedBy(Api.COMPILER)
2886        public OutputStream openOutputStream() {
2887            throw new UnsupportedOperationException();
2888        }
2889
2890        @Override @DefinedBy(Api.COMPILER)
2891        public CharBuffer getCharContent(boolean ignoreEncodingErrors) {
2892            throw new UnsupportedOperationException();
2893        }
2894
2895        @Override @DefinedBy(Api.COMPILER)
2896        public Reader openReader(boolean ignoreEncodingErrors) {
2897            throw new UnsupportedOperationException();
2898        }
2899
2900        @Override @DefinedBy(Api.COMPILER)
2901        public Writer openWriter() {
2902            throw new UnsupportedOperationException();
2903        }
2904
2905        @Override @DefinedBy(Api.COMPILER)
2906        public long getLastModified() {
2907            throw new UnsupportedOperationException();
2908        }
2909
2910        @Override @DefinedBy(Api.COMPILER)
2911        public boolean delete() {
2912            throw new UnsupportedOperationException();
2913        }
2914
2915        @Override @DefinedBy(Api.COMPILER)
2916        public boolean isNameCompatible(String simpleName, JavaFileObject.Kind kind) {
2917            return true; // fail-safe mode
2918        }
2919
2920        @Override @DefinedBy(Api.COMPILER)
2921        public NestingKind getNestingKind() {
2922            return null;
2923        }
2924
2925        @Override @DefinedBy(Api.COMPILER)
2926        public Modifier getAccessLevel() {
2927            return null;
2928        }
2929
2930        /**
2931         * Check if two file objects are equal.
2932         * SourceFileObjects are just placeholder objects for the value of a
2933         * SourceFile attribute, and do not directly represent specific files.
2934         * Two SourceFileObjects are equal if their names are equal.
2935         */
2936        @Override
2937        public boolean equals(Object other) {
2938            if (this == other)
2939                return true;
2940
2941            if (!(other instanceof SourceFileObject))
2942                return false;
2943
2944            SourceFileObject o = (SourceFileObject) other;
2945            return name.equals(o.name);
2946        }
2947
2948        @Override
2949        public int hashCode() {
2950            return name.hashCode();
2951        }
2952    }
2953
2954    private class CompleterDeproxy implements AnnotationTypeCompleter {
2955        ClassSymbol proxyOn;
2956        CompoundAnnotationProxy target;
2957        CompoundAnnotationProxy repeatable;
2958
2959        public CompleterDeproxy(ClassSymbol c, CompoundAnnotationProxy target,
2960                CompoundAnnotationProxy repeatable)
2961        {
2962            this.proxyOn = c;
2963            this.target = target;
2964            this.repeatable = repeatable;
2965        }
2966
2967        @Override
2968        public void complete(ClassSymbol sym) {
2969            Assert.check(proxyOn == sym);
2970            Attribute.Compound theTarget = null, theRepeatable = null;
2971            AnnotationDeproxy deproxy;
2972
2973            try {
2974                if (target != null) {
2975                    deproxy = new AnnotationDeproxy(proxyOn);
2976                    theTarget = deproxy.deproxyCompound(target);
2977                }
2978
2979                if (repeatable != null) {
2980                    deproxy = new AnnotationDeproxy(proxyOn);
2981                    theRepeatable = deproxy.deproxyCompound(repeatable);
2982                }
2983            } catch (Exception e) {
2984                throw new CompletionFailure(sym, e.getMessage());
2985            }
2986
2987            sym.getAnnotationTypeMetadata().setTarget(theTarget);
2988            sym.getAnnotationTypeMetadata().setRepeatable(theRepeatable);
2989        }
2990    }
2991
2992    private class ProxyType extends Type {
2993
2994        private final byte[] content;
2995
2996        public ProxyType(byte[] content) {
2997            super(syms.noSymbol, TypeMetadata.EMPTY);
2998            this.content = content;
2999        }
3000
3001        @Override
3002        public TypeTag getTag() {
3003            return TypeTag.NONE;
3004        }
3005
3006        @Override
3007        public Type cloneWithMetadata(TypeMetadata metadata) {
3008            throw new UnsupportedOperationException();
3009        }
3010
3011        public Type resolve() {
3012            return sigToType(content, 0, content.length);
3013        }
3014
3015        @Override @DefinedBy(Api.LANGUAGE_MODEL)
3016        public String toString() {
3017            return "<ProxyType>";
3018        }
3019
3020    }
3021
3022    private static final class InterimUsesDirective {
3023        public final Name service;
3024
3025        public InterimUsesDirective(Name service) {
3026            this.service = service;
3027        }
3028
3029    }
3030
3031    private static final class InterimProvidesDirective {
3032        public final Name service;
3033        public final List<Name> impls;
3034
3035        public InterimProvidesDirective(Name service, List<Name> impls) {
3036            this.service = service;
3037            this.impls = impls;
3038        }
3039
3040    }
3041
3042    private final class UsesProvidesCompleter implements Completer {
3043        private final ModuleSymbol currentModule;
3044        private final List<InterimUsesDirective> interimUsesCopy;
3045        private final List<InterimProvidesDirective> interimProvidesCopy;
3046
3047        public UsesProvidesCompleter(ModuleSymbol currentModule, List<InterimUsesDirective> interimUsesCopy, List<InterimProvidesDirective> interimProvidesCopy) {
3048            this.currentModule = currentModule;
3049            this.interimUsesCopy = interimUsesCopy;
3050            this.interimProvidesCopy = interimProvidesCopy;
3051        }
3052
3053        @Override
3054        public void complete(Symbol sym) throws CompletionFailure {
3055            ListBuffer<Directive> directives = new ListBuffer<>();
3056            directives.addAll(currentModule.directives);
3057            ListBuffer<UsesDirective> uses = new ListBuffer<>();
3058            for (InterimUsesDirective interim : interimUsesCopy) {
3059                UsesDirective d = new UsesDirective(syms.enterClass(currentModule, interim.service));
3060                uses.add(d);
3061                directives.add(d);
3062            }
3063            currentModule.uses = uses.toList();
3064            ListBuffer<ProvidesDirective> provides = new ListBuffer<>();
3065            for (InterimProvidesDirective interim : interimProvidesCopy) {
3066                ListBuffer<ClassSymbol> impls = new ListBuffer<>();
3067                for (Name impl : interim.impls) {
3068                    impls.append(syms.enterClass(currentModule, impl));
3069                }
3070                ProvidesDirective d = new ProvidesDirective(syms.enterClass(currentModule, interim.service),
3071                                                            impls.toList());
3072                provides.add(d);
3073                directives.add(d);
3074            }
3075            currentModule.provides = provides.toList();
3076            currentModule.directives = directives.toList();
3077        }
3078    }
3079}
3080