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