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