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