ClassReader.java revision 2628:8df25ec8c930
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        case UNKNOWN:
1592            throw new AssertionError("jvm.ClassReader: UNKNOWN target type should never occur!");
1593        default:
1594            throw new AssertionError("jvm.ClassReader: Unknown target type for position: " + type);
1595        }
1596    }
1597
1598    List<TypeAnnotationPosition.TypePathEntry> readTypePath() {
1599        int len = nextByte();
1600        ListBuffer<Integer> loc = new ListBuffer<>();
1601        for (int i = 0; i < len * TypeAnnotationPosition.TypePathEntry.bytesPerEntry; ++i)
1602            loc = loc.append(nextByte());
1603
1604        return TypeAnnotationPosition.getTypePathFromBinary(loc.toList());
1605
1606    }
1607
1608    Attribute readAttributeValue() {
1609        char c = (char) buf[bp++];
1610        switch (c) {
1611        case 'B':
1612            return new Attribute.Constant(syms.byteType, readPool(nextChar()));
1613        case 'C':
1614            return new Attribute.Constant(syms.charType, readPool(nextChar()));
1615        case 'D':
1616            return new Attribute.Constant(syms.doubleType, readPool(nextChar()));
1617        case 'F':
1618            return new Attribute.Constant(syms.floatType, readPool(nextChar()));
1619        case 'I':
1620            return new Attribute.Constant(syms.intType, readPool(nextChar()));
1621        case 'J':
1622            return new Attribute.Constant(syms.longType, readPool(nextChar()));
1623        case 'S':
1624            return new Attribute.Constant(syms.shortType, readPool(nextChar()));
1625        case 'Z':
1626            return new Attribute.Constant(syms.booleanType, readPool(nextChar()));
1627        case 's':
1628            return new Attribute.Constant(syms.stringType, readPool(nextChar()).toString());
1629        case 'e':
1630            return new EnumAttributeProxy(readEnumType(nextChar()), readName(nextChar()));
1631        case 'c':
1632            return new Attribute.Class(types, readTypeOrClassSymbol(nextChar()));
1633        case '[': {
1634            int n = nextChar();
1635            ListBuffer<Attribute> l = new ListBuffer<>();
1636            for (int i=0; i<n; i++)
1637                l.append(readAttributeValue());
1638            return new ArrayAttributeProxy(l.toList());
1639        }
1640        case '@':
1641            return readCompoundAnnotation();
1642        default:
1643            throw new AssertionError("unknown annotation tag '" + c + "'");
1644        }
1645    }
1646
1647    interface ProxyVisitor extends Attribute.Visitor {
1648        void visitEnumAttributeProxy(EnumAttributeProxy proxy);
1649        void visitArrayAttributeProxy(ArrayAttributeProxy proxy);
1650        void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy);
1651    }
1652
1653    static class EnumAttributeProxy extends Attribute {
1654        Type enumType;
1655        Name enumerator;
1656        public EnumAttributeProxy(Type enumType, Name enumerator) {
1657            super(null);
1658            this.enumType = enumType;
1659            this.enumerator = enumerator;
1660        }
1661        public void accept(Visitor v) { ((ProxyVisitor)v).visitEnumAttributeProxy(this); }
1662        @Override @DefinedBy(Api.LANGUAGE_MODEL)
1663        public String toString() {
1664            return "/*proxy enum*/" + enumType + "." + enumerator;
1665        }
1666    }
1667
1668    static class ArrayAttributeProxy extends Attribute {
1669        List<Attribute> values;
1670        ArrayAttributeProxy(List<Attribute> values) {
1671            super(null);
1672            this.values = values;
1673        }
1674        public void accept(Visitor v) { ((ProxyVisitor)v).visitArrayAttributeProxy(this); }
1675        @Override @DefinedBy(Api.LANGUAGE_MODEL)
1676        public String toString() {
1677            return "{" + values + "}";
1678        }
1679    }
1680
1681    /** A temporary proxy representing a compound attribute.
1682     */
1683    static class CompoundAnnotationProxy extends Attribute {
1684        final List<Pair<Name,Attribute>> values;
1685        public CompoundAnnotationProxy(Type type,
1686                                      List<Pair<Name,Attribute>> values) {
1687            super(type);
1688            this.values = values;
1689        }
1690        public void accept(Visitor v) { ((ProxyVisitor)v).visitCompoundAnnotationProxy(this); }
1691        @Override @DefinedBy(Api.LANGUAGE_MODEL)
1692        public String toString() {
1693            StringBuilder buf = new StringBuilder();
1694            buf.append("@");
1695            buf.append(type.tsym.getQualifiedName());
1696            buf.append("/*proxy*/{");
1697            boolean first = true;
1698            for (List<Pair<Name,Attribute>> v = values;
1699                 v.nonEmpty(); v = v.tail) {
1700                Pair<Name,Attribute> value = v.head;
1701                if (!first) buf.append(",");
1702                first = false;
1703                buf.append(value.fst);
1704                buf.append("=");
1705                buf.append(value.snd);
1706            }
1707            buf.append("}");
1708            return buf.toString();
1709        }
1710    }
1711
1712    /** A temporary proxy representing a type annotation.
1713     */
1714    static class TypeAnnotationProxy {
1715        final CompoundAnnotationProxy compound;
1716        final TypeAnnotationPosition position;
1717        public TypeAnnotationProxy(CompoundAnnotationProxy compound,
1718                TypeAnnotationPosition position) {
1719            this.compound = compound;
1720            this.position = position;
1721        }
1722    }
1723
1724    class AnnotationDeproxy implements ProxyVisitor {
1725        private ClassSymbol requestingOwner = currentOwner.kind == MTH
1726            ? currentOwner.enclClass() : (ClassSymbol)currentOwner;
1727
1728        List<Attribute.Compound> deproxyCompoundList(List<CompoundAnnotationProxy> pl) {
1729            // also must fill in types!!!!
1730            ListBuffer<Attribute.Compound> buf = new ListBuffer<>();
1731            for (List<CompoundAnnotationProxy> l = pl; l.nonEmpty(); l=l.tail) {
1732                buf.append(deproxyCompound(l.head));
1733            }
1734            return buf.toList();
1735        }
1736
1737        Attribute.Compound deproxyCompound(CompoundAnnotationProxy a) {
1738            ListBuffer<Pair<Symbol.MethodSymbol,Attribute>> buf = new ListBuffer<>();
1739            for (List<Pair<Name,Attribute>> l = a.values;
1740                 l.nonEmpty();
1741                 l = l.tail) {
1742                MethodSymbol meth = findAccessMethod(a.type, l.head.fst);
1743                buf.append(new Pair<>(meth, deproxy(meth.type.getReturnType(), l.head.snd)));
1744            }
1745            return new Attribute.Compound(a.type, buf.toList());
1746        }
1747
1748        MethodSymbol findAccessMethod(Type container, Name name) {
1749            CompletionFailure failure = null;
1750            try {
1751                for (Symbol sym : container.tsym.members().getSymbolsByName(name)) {
1752                    if (sym.kind == MTH && sym.type.getParameterTypes().length() == 0)
1753                        return (MethodSymbol) sym;
1754                }
1755            } catch (CompletionFailure ex) {
1756                failure = ex;
1757            }
1758            // The method wasn't found: emit a warning and recover
1759            JavaFileObject prevSource = log.useSource(requestingOwner.classfile);
1760            try {
1761                if (failure == null) {
1762                    log.warning("annotation.method.not.found",
1763                                container,
1764                                name);
1765                } else {
1766                    log.warning("annotation.method.not.found.reason",
1767                                container,
1768                                name,
1769                                failure.getDetailValue());//diagnostic, if present
1770                }
1771            } finally {
1772                log.useSource(prevSource);
1773            }
1774            // Construct a new method type and symbol.  Use bottom
1775            // type (typeof null) as return type because this type is
1776            // a subtype of all reference types and can be converted
1777            // to primitive types by unboxing.
1778            MethodType mt = new MethodType(List.<Type>nil(),
1779                                           syms.botType,
1780                                           List.<Type>nil(),
1781                                           syms.methodClass);
1782            return new MethodSymbol(PUBLIC | ABSTRACT, name, mt, container.tsym);
1783        }
1784
1785        Attribute result;
1786        Type type;
1787        Attribute deproxy(Type t, Attribute a) {
1788            Type oldType = type;
1789            try {
1790                type = t;
1791                a.accept(this);
1792                return result;
1793            } finally {
1794                type = oldType;
1795            }
1796        }
1797
1798        // implement Attribute.Visitor below
1799
1800        public void visitConstant(Attribute.Constant value) {
1801            // assert value.type == type;
1802            result = value;
1803        }
1804
1805        public void visitClass(Attribute.Class clazz) {
1806            result = clazz;
1807        }
1808
1809        public void visitEnum(Attribute.Enum e) {
1810            throw new AssertionError(); // shouldn't happen
1811        }
1812
1813        public void visitCompound(Attribute.Compound compound) {
1814            throw new AssertionError(); // shouldn't happen
1815        }
1816
1817        public void visitArray(Attribute.Array array) {
1818            throw new AssertionError(); // shouldn't happen
1819        }
1820
1821        public void visitError(Attribute.Error e) {
1822            throw new AssertionError(); // shouldn't happen
1823        }
1824
1825        public void visitEnumAttributeProxy(EnumAttributeProxy proxy) {
1826            // type.tsym.flatName() should == proxy.enumFlatName
1827            TypeSymbol enumTypeSym = proxy.enumType.tsym;
1828            VarSymbol enumerator = null;
1829            CompletionFailure failure = null;
1830            try {
1831                for (Symbol sym : enumTypeSym.members().getSymbolsByName(proxy.enumerator)) {
1832                    if (sym.kind == VAR) {
1833                        enumerator = (VarSymbol)sym;
1834                        break;
1835                    }
1836                }
1837            }
1838            catch (CompletionFailure ex) {
1839                failure = ex;
1840            }
1841            if (enumerator == null) {
1842                if (failure != null) {
1843                    log.warning("unknown.enum.constant.reason",
1844                              currentClassFile, enumTypeSym, proxy.enumerator,
1845                              failure.getDiagnostic());
1846                } else {
1847                    log.warning("unknown.enum.constant",
1848                              currentClassFile, enumTypeSym, proxy.enumerator);
1849                }
1850                result = new Attribute.Enum(enumTypeSym.type,
1851                        new VarSymbol(0, proxy.enumerator, syms.botType, enumTypeSym));
1852            } else {
1853                result = new Attribute.Enum(enumTypeSym.type, enumerator);
1854            }
1855        }
1856
1857        public void visitArrayAttributeProxy(ArrayAttributeProxy proxy) {
1858            int length = proxy.values.length();
1859            Attribute[] ats = new Attribute[length];
1860            Type elemtype = types.elemtype(type);
1861            int i = 0;
1862            for (List<Attribute> p = proxy.values; p.nonEmpty(); p = p.tail) {
1863                ats[i++] = deproxy(elemtype, p.head);
1864            }
1865            result = new Attribute.Array(type, ats);
1866        }
1867
1868        public void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy) {
1869            result = deproxyCompound(proxy);
1870        }
1871    }
1872
1873    class AnnotationDefaultCompleter extends AnnotationDeproxy implements Annotate.Worker {
1874        final MethodSymbol sym;
1875        final Attribute value;
1876        final JavaFileObject classFile = currentClassFile;
1877        @Override
1878        public String toString() {
1879            return " ClassReader store default for " + sym.owner + "." + sym + " is " + value;
1880        }
1881        AnnotationDefaultCompleter(MethodSymbol sym, Attribute value) {
1882            this.sym = sym;
1883            this.value = value;
1884        }
1885        // implement Annotate.Worker.run()
1886        public void run() {
1887            JavaFileObject previousClassFile = currentClassFile;
1888            try {
1889                // Reset the interim value set earlier in
1890                // attachAnnotationDefault().
1891                sym.defaultValue = null;
1892                currentClassFile = classFile;
1893                sym.defaultValue = deproxy(sym.type.getReturnType(), value);
1894            } finally {
1895                currentClassFile = previousClassFile;
1896            }
1897        }
1898    }
1899
1900    class AnnotationCompleter extends AnnotationDeproxy implements Annotate.Worker {
1901        final Symbol sym;
1902        final List<CompoundAnnotationProxy> l;
1903        final JavaFileObject classFile;
1904        @Override
1905        public String toString() {
1906            return " ClassReader annotate " + sym.owner + "." + sym + " with " + l;
1907        }
1908        AnnotationCompleter(Symbol sym, List<CompoundAnnotationProxy> l) {
1909            this.sym = sym;
1910            this.l = l;
1911            this.classFile = currentClassFile;
1912        }
1913        // implement Annotate.Worker.run()
1914        public void run() {
1915            JavaFileObject previousClassFile = currentClassFile;
1916            try {
1917                currentClassFile = classFile;
1918                List<Attribute.Compound> newList = deproxyCompoundList(l);
1919                if (sym.annotationsPendingCompletion()) {
1920                    sym.setDeclarationAttributes(newList);
1921                } else {
1922                    sym.appendAttributes(newList);
1923                }
1924            } finally {
1925                currentClassFile = previousClassFile;
1926            }
1927        }
1928    }
1929
1930    class TypeAnnotationCompleter extends AnnotationCompleter {
1931
1932        List<TypeAnnotationProxy> proxies;
1933
1934        TypeAnnotationCompleter(Symbol sym,
1935                List<TypeAnnotationProxy> proxies) {
1936            super(sym, List.<CompoundAnnotationProxy>nil());
1937            this.proxies = proxies;
1938        }
1939
1940        List<Attribute.TypeCompound> deproxyTypeCompoundList(List<TypeAnnotationProxy> proxies) {
1941            ListBuffer<Attribute.TypeCompound> buf = new ListBuffer<>();
1942            for (TypeAnnotationProxy proxy: proxies) {
1943                Attribute.Compound compound = deproxyCompound(proxy.compound);
1944                Attribute.TypeCompound typeCompound = new Attribute.TypeCompound(compound, proxy.position);
1945                buf.add(typeCompound);
1946            }
1947            return buf.toList();
1948        }
1949
1950        @Override
1951        public void run() {
1952            JavaFileObject previousClassFile = currentClassFile;
1953            try {
1954                currentClassFile = classFile;
1955                List<Attribute.TypeCompound> newList = deproxyTypeCompoundList(proxies);
1956                sym.setTypeAttributes(newList.prependList(sym.getRawTypeAttributes()));
1957            } finally {
1958                currentClassFile = previousClassFile;
1959            }
1960        }
1961    }
1962
1963
1964/************************************************************************
1965 * Reading Symbols
1966 ***********************************************************************/
1967
1968    /** Read a field.
1969     */
1970    VarSymbol readField() {
1971        long flags = adjustFieldFlags(nextChar());
1972        Name name = readName(nextChar());
1973        Type type = readType(nextChar());
1974        VarSymbol v = new VarSymbol(flags, name, type, currentOwner);
1975        readMemberAttrs(v);
1976        return v;
1977    }
1978
1979    /** Read a method.
1980     */
1981    MethodSymbol readMethod() {
1982        long flags = adjustMethodFlags(nextChar());
1983        Name name = readName(nextChar());
1984        Type type = readType(nextChar());
1985        if (currentOwner.isInterface() &&
1986                (flags & ABSTRACT) == 0 && !name.equals(names.clinit)) {
1987            if (majorVersion > Version.V52.major ||
1988                    (majorVersion == Version.V52.major && minorVersion >= Version.V52.minor)) {
1989                if ((flags & STATIC) == 0) {
1990                    currentOwner.flags_field |= DEFAULT;
1991                    flags |= DEFAULT | ABSTRACT;
1992                }
1993            } else {
1994                //protect against ill-formed classfiles
1995                throw badClassFile((flags & STATIC) == 0 ? "invalid.default.interface" : "invalid.static.interface",
1996                                   Integer.toString(majorVersion),
1997                                   Integer.toString(minorVersion));
1998            }
1999        }
2000        if (name == names.init && currentOwner.hasOuterInstance()) {
2001            // Sometimes anonymous classes don't have an outer
2002            // instance, however, there is no reliable way to tell so
2003            // we never strip this$n
2004            if (!currentOwner.name.isEmpty())
2005                type = new MethodType(adjustMethodParams(flags, type.getParameterTypes()),
2006                                      type.getReturnType(),
2007                                      type.getThrownTypes(),
2008                                      syms.methodClass);
2009        }
2010        MethodSymbol m = new MethodSymbol(flags, name, type, currentOwner);
2011        if (types.isSignaturePolymorphic(m)) {
2012            m.flags_field |= SIGNATURE_POLYMORPHIC;
2013        }
2014        if (saveParameterNames)
2015            initParameterNames(m);
2016        Symbol prevOwner = currentOwner;
2017        currentOwner = m;
2018        try {
2019            readMemberAttrs(m);
2020        } finally {
2021            currentOwner = prevOwner;
2022        }
2023        if (saveParameterNames)
2024            setParameterNames(m, type);
2025        return m;
2026    }
2027
2028    private List<Type> adjustMethodParams(long flags, List<Type> args) {
2029        boolean isVarargs = (flags & VARARGS) != 0;
2030        if (isVarargs) {
2031            Type varargsElem = args.last();
2032            ListBuffer<Type> adjustedArgs = new ListBuffer<>();
2033            for (Type t : args) {
2034                adjustedArgs.append(t != varargsElem ?
2035                    t :
2036                    ((ArrayType)t).makeVarargs());
2037            }
2038            args = adjustedArgs.toList();
2039        }
2040        return args.tail;
2041    }
2042
2043    /**
2044     * Init the parameter names array.
2045     * Parameter names are currently inferred from the names in the
2046     * LocalVariableTable attributes of a Code attribute.
2047     * (Note: this means parameter names are currently not available for
2048     * methods without a Code attribute.)
2049     * This method initializes an array in which to store the name indexes
2050     * of parameter names found in LocalVariableTable attributes. It is
2051     * slightly supersized to allow for additional slots with a start_pc of 0.
2052     */
2053    void initParameterNames(MethodSymbol sym) {
2054        // make allowance for synthetic parameters.
2055        final int excessSlots = 4;
2056        int expectedParameterSlots =
2057                Code.width(sym.type.getParameterTypes()) + excessSlots;
2058        if (parameterNameIndices == null
2059                || parameterNameIndices.length < expectedParameterSlots) {
2060            parameterNameIndices = new int[expectedParameterSlots];
2061        } else
2062            Arrays.fill(parameterNameIndices, 0);
2063        haveParameterNameIndices = false;
2064        sawMethodParameters = false;
2065    }
2066
2067    /**
2068     * Set the parameter names for a symbol from the name index in the
2069     * parameterNameIndicies array. The type of the symbol may have changed
2070     * while reading the method attributes (see the Signature attribute).
2071     * This may be because of generic information or because anonymous
2072     * synthetic parameters were added.   The original type (as read from
2073     * the method descriptor) is used to help guess the existence of
2074     * anonymous synthetic parameters.
2075     * On completion, sym.savedParameter names will either be null (if
2076     * no parameter names were found in the class file) or will be set to a
2077     * list of names, one per entry in sym.type.getParameterTypes, with
2078     * any missing names represented by the empty name.
2079     */
2080    void setParameterNames(MethodSymbol sym, Type jvmType) {
2081        // if no names were found in the class file, there's nothing more to do
2082        if (!haveParameterNameIndices)
2083            return;
2084        // If we get parameter names from MethodParameters, then we
2085        // don't need to skip.
2086        int firstParam = 0;
2087        if (!sawMethodParameters) {
2088            firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0;
2089            // the code in readMethod may have skipped the first
2090            // parameter when setting up the MethodType. If so, we
2091            // make a corresponding allowance here for the position of
2092            // the first parameter.  Note that this assumes the
2093            // skipped parameter has a width of 1 -- i.e. it is not
2094        // a double width type (long or double.)
2095        if (sym.name == names.init && currentOwner.hasOuterInstance()) {
2096            // Sometimes anonymous classes don't have an outer
2097            // instance, however, there is no reliable way to tell so
2098            // we never strip this$n
2099            if (!currentOwner.name.isEmpty())
2100                firstParam += 1;
2101        }
2102
2103        if (sym.type != jvmType) {
2104                // reading the method attributes has caused the
2105                // symbol's type to be changed. (i.e. the Signature
2106                // attribute.)  This may happen if there are hidden
2107                // (synthetic) parameters in the descriptor, but not
2108                // in the Signature.  The position of these hidden
2109                // parameters is unspecified; for now, assume they are
2110                // at the beginning, and so skip over them. The
2111                // primary case for this is two hidden parameters
2112                // passed into Enum constructors.
2113            int skip = Code.width(jvmType.getParameterTypes())
2114                    - Code.width(sym.type.getParameterTypes());
2115            firstParam += skip;
2116        }
2117        }
2118        List<Name> paramNames = List.nil();
2119        int index = firstParam;
2120        for (Type t: sym.type.getParameterTypes()) {
2121            int nameIdx = (index < parameterNameIndices.length
2122                    ? parameterNameIndices[index] : 0);
2123            Name name = nameIdx == 0 ? names.empty : readName(nameIdx);
2124            paramNames = paramNames.prepend(name);
2125            index += Code.width(t);
2126        }
2127        sym.savedParameterNames = paramNames.reverse();
2128    }
2129
2130    /**
2131     * skip n bytes
2132     */
2133    void skipBytes(int n) {
2134        bp = bp + n;
2135    }
2136
2137    /** Skip a field or method
2138     */
2139    void skipMember() {
2140        bp = bp + 6;
2141        char ac = nextChar();
2142        for (int i = 0; i < ac; i++) {
2143            bp = bp + 2;
2144            int attrLen = nextInt();
2145            bp = bp + attrLen;
2146        }
2147    }
2148
2149    /** Enter type variables of this classtype and all enclosing ones in
2150     *  `typevars'.
2151     */
2152    protected void enterTypevars(Type t) {
2153        if (t.getEnclosingType() != null && t.getEnclosingType().hasTag(CLASS))
2154            enterTypevars(t.getEnclosingType());
2155        for (List<Type> xs = t.getTypeArguments(); xs.nonEmpty(); xs = xs.tail)
2156            typevars.enter(xs.head.tsym);
2157    }
2158
2159    protected void enterTypevars(Symbol sym) {
2160        if (sym.owner.kind == MTH) {
2161            enterTypevars(sym.owner);
2162            enterTypevars(sym.owner.owner);
2163        }
2164        enterTypevars(sym.type);
2165    }
2166
2167    /** Read contents of a given class symbol `c'. Both external and internal
2168     *  versions of an inner class are read.
2169     */
2170    void readClass(ClassSymbol c) {
2171        ClassType ct = (ClassType)c.type;
2172
2173        // allocate scope for members
2174        c.members_field = WriteableScope.create(c);
2175
2176        // prepare type variable table
2177        typevars = typevars.dup(currentOwner);
2178        if (ct.getEnclosingType().hasTag(CLASS))
2179            enterTypevars(ct.getEnclosingType());
2180
2181        // read flags, or skip if this is an inner class
2182        long flags = adjustClassFlags(nextChar());
2183        if (c.owner.kind == PCK) c.flags_field = flags;
2184
2185        // read own class name and check that it matches
2186        ClassSymbol self = readClassSymbol(nextChar());
2187        if (c != self)
2188            throw badClassFile("class.file.wrong.class",
2189                               self.flatname);
2190
2191        // class attributes must be read before class
2192        // skip ahead to read class attributes
2193        int startbp = bp;
2194        nextChar();
2195        char interfaceCount = nextChar();
2196        bp += interfaceCount * 2;
2197        char fieldCount = nextChar();
2198        for (int i = 0; i < fieldCount; i++) skipMember();
2199        char methodCount = nextChar();
2200        for (int i = 0; i < methodCount; i++) skipMember();
2201        readClassAttrs(c);
2202
2203        if (readAllOfClassFile) {
2204            for (int i = 1; i < poolObj.length; i++) readPool(i);
2205            c.pool = new Pool(poolObj.length, poolObj, types);
2206        }
2207
2208        // reset and read rest of classinfo
2209        bp = startbp;
2210        int n = nextChar();
2211        if (ct.supertype_field == null)
2212            ct.supertype_field = (n == 0)
2213                ? Type.noType
2214                : readClassSymbol(n).erasure(types);
2215        n = nextChar();
2216        List<Type> is = List.nil();
2217        for (int i = 0; i < n; i++) {
2218            Type _inter = readClassSymbol(nextChar()).erasure(types);
2219            is = is.prepend(_inter);
2220        }
2221        if (ct.interfaces_field == null)
2222            ct.interfaces_field = is.reverse();
2223
2224        Assert.check(fieldCount == nextChar());
2225        for (int i = 0; i < fieldCount; i++) enterMember(c, readField());
2226        Assert.check(methodCount == nextChar());
2227        for (int i = 0; i < methodCount; i++) enterMember(c, readMethod());
2228
2229        typevars = typevars.leave();
2230    }
2231
2232    /** Read inner class info. For each inner/outer pair allocate a
2233     *  member class.
2234     */
2235    void readInnerClasses(ClassSymbol c) {
2236        int n = nextChar();
2237        for (int i = 0; i < n; i++) {
2238            nextChar(); // skip inner class symbol
2239            ClassSymbol outer = readClassSymbol(nextChar());
2240            Name name = readName(nextChar());
2241            if (name == null) name = names.empty;
2242            long flags = adjustClassFlags(nextChar());
2243            if (outer != null) { // we have a member class
2244                if (name == names.empty)
2245                    name = names.one;
2246                ClassSymbol member = syms.enterClass(name, outer);
2247                if ((flags & STATIC) == 0) {
2248                    ((ClassType)member.type).setEnclosingType(outer.type);
2249                    if (member.erasure_field != null)
2250                        ((ClassType)member.erasure_field).setEnclosingType(types.erasure(outer.type));
2251                }
2252                if (c == outer) {
2253                    member.flags_field = flags;
2254                    enterMember(c, member);
2255                }
2256            }
2257        }
2258    }
2259
2260    /** Read a class definition from the bytes in buf.
2261     */
2262    private void readClassBuffer(ClassSymbol c) throws IOException {
2263        int magic = nextInt();
2264        if (magic != JAVA_MAGIC)
2265            throw badClassFile("illegal.start.of.class.file");
2266
2267        minorVersion = nextChar();
2268        majorVersion = nextChar();
2269        int maxMajor = Version.MAX().major;
2270        int maxMinor = Version.MAX().minor;
2271        if (majorVersion > maxMajor ||
2272            majorVersion * 1000 + minorVersion <
2273            Version.MIN().major * 1000 + Version.MIN().minor)
2274        {
2275            if (majorVersion == (maxMajor + 1))
2276                log.warning("big.major.version",
2277                            currentClassFile,
2278                            majorVersion,
2279                            maxMajor);
2280            else
2281                throw badClassFile("wrong.version",
2282                                   Integer.toString(majorVersion),
2283                                   Integer.toString(minorVersion),
2284                                   Integer.toString(maxMajor),
2285                                   Integer.toString(maxMinor));
2286        }
2287        else if (checkClassFile &&
2288                 majorVersion == maxMajor &&
2289                 minorVersion > maxMinor)
2290        {
2291            printCCF("found.later.version",
2292                     Integer.toString(minorVersion));
2293        }
2294        indexPool();
2295        if (signatureBuffer.length < bp) {
2296            int ns = Integer.highestOneBit(bp) << 1;
2297            signatureBuffer = new byte[ns];
2298        }
2299        readClass(c);
2300    }
2301
2302    public void readClassFile(ClassSymbol c) {
2303        currentOwner = c;
2304        currentClassFile = c.classfile;
2305        warnedAttrs.clear();
2306        filling = true;
2307        try {
2308            bp = 0;
2309            buf = readInputStream(buf, c.classfile.openInputStream());
2310            readClassBuffer(c);
2311            if (!missingTypeVariables.isEmpty() && !foundTypeVariables.isEmpty()) {
2312                List<Type> missing = missingTypeVariables;
2313                List<Type> found = foundTypeVariables;
2314                missingTypeVariables = List.nil();
2315                foundTypeVariables = List.nil();
2316                filling = false;
2317                ClassType ct = (ClassType)currentOwner.type;
2318                ct.supertype_field =
2319                    types.subst(ct.supertype_field, missing, found);
2320                ct.interfaces_field =
2321                    types.subst(ct.interfaces_field, missing, found);
2322            } else if (missingTypeVariables.isEmpty() !=
2323                       foundTypeVariables.isEmpty()) {
2324                Name name = missingTypeVariables.head.tsym.name;
2325                throw badClassFile("undecl.type.var", name);
2326            }
2327        } catch (IOException ex) {
2328            throw badClassFile("unable.to.access.file", ex.getMessage());
2329        } catch (ArrayIndexOutOfBoundsException ex) {
2330            throw badClassFile("bad.class.file", c.flatname);
2331        } finally {
2332            missingTypeVariables = List.nil();
2333            foundTypeVariables = List.nil();
2334            filling = false;
2335        }
2336    }
2337    // where
2338        private static byte[] readInputStream(byte[] buf, InputStream s) throws IOException {
2339            try {
2340                buf = ensureCapacity(buf, s.available());
2341                int r = s.read(buf);
2342                int bp = 0;
2343                while (r != -1) {
2344                    bp += r;
2345                    buf = ensureCapacity(buf, bp);
2346                    r = s.read(buf, bp, buf.length - bp);
2347                }
2348                return buf;
2349            } finally {
2350                try {
2351                    s.close();
2352                } catch (IOException e) {
2353                    /* Ignore any errors, as this stream may have already
2354                     * thrown a related exception which is the one that
2355                     * should be reported.
2356                     */
2357                }
2358            }
2359        }
2360        /*
2361         * ensureCapacity will increase the buffer as needed, taking note that
2362         * the new buffer will always be greater than the needed and never
2363         * exactly equal to the needed size or bp. If equal then the read (above)
2364         * will infinitely loop as buf.length - bp == 0.
2365         */
2366        private static byte[] ensureCapacity(byte[] buf, int needed) {
2367            if (buf.length <= needed) {
2368                byte[] old = buf;
2369                buf = new byte[Integer.highestOneBit(needed) << 1];
2370                System.arraycopy(old, 0, buf, 0, old.length);
2371            }
2372            return buf;
2373        }
2374
2375    /** We can only read a single class file at a time; this
2376     *  flag keeps track of when we are currently reading a class
2377     *  file.
2378     */
2379    public boolean filling = false;
2380
2381/************************************************************************
2382 * Adjusting flags
2383 ***********************************************************************/
2384
2385    long adjustFieldFlags(long flags) {
2386        return flags;
2387    }
2388
2389    long adjustMethodFlags(long flags) {
2390        if ((flags & ACC_BRIDGE) != 0) {
2391            flags &= ~ACC_BRIDGE;
2392            flags |= BRIDGE;
2393        }
2394        if ((flags & ACC_VARARGS) != 0) {
2395            flags &= ~ACC_VARARGS;
2396            flags |= VARARGS;
2397        }
2398        return flags;
2399    }
2400
2401    long adjustClassFlags(long flags) {
2402        return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
2403    }
2404
2405    /** Output for "-checkclassfile" option.
2406     *  @param key The key to look up the correct internationalized string.
2407     *  @param arg An argument for substitution into the output string.
2408     */
2409    private void printCCF(String key, Object arg) {
2410        log.printLines(key, arg);
2411    }
2412
2413    /**
2414     * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
2415     * The attribute is only the last component of the original filename, so is unlikely
2416     * to be valid as is, so operations other than those to access the name throw
2417     * UnsupportedOperationException
2418     */
2419    private static class SourceFileObject extends BaseFileObject {
2420
2421        /** The file's name.
2422         */
2423        private Name name;
2424        private Name flatname;
2425
2426        public SourceFileObject(Name name, Name flatname) {
2427            super(null); // no file manager; never referenced for this file object
2428            this.name = name;
2429            this.flatname = flatname;
2430        }
2431
2432        @Override @DefinedBy(Api.COMPILER)
2433        public URI toUri() {
2434            try {
2435                return new URI(null, name.toString(), null);
2436            } catch (URISyntaxException e) {
2437                throw new CannotCreateUriError(name.toString(), e);
2438            }
2439        }
2440
2441        @Override @DefinedBy(Api.COMPILER)
2442        public String getName() {
2443            return name.toString();
2444        }
2445
2446        @Override
2447        public String getShortName() {
2448            return getName();
2449        }
2450
2451        @Override @DefinedBy(Api.COMPILER)
2452        public JavaFileObject.Kind getKind() {
2453            return getKind(getName());
2454        }
2455
2456        @Override @DefinedBy(Api.COMPILER)
2457        public InputStream openInputStream() {
2458            throw new UnsupportedOperationException();
2459        }
2460
2461        @Override @DefinedBy(Api.COMPILER)
2462        public OutputStream openOutputStream() {
2463            throw new UnsupportedOperationException();
2464        }
2465
2466        @Override @DefinedBy(Api.COMPILER)
2467        public CharBuffer getCharContent(boolean ignoreEncodingErrors) {
2468            throw new UnsupportedOperationException();
2469        }
2470
2471        @Override @DefinedBy(Api.COMPILER)
2472        public Reader openReader(boolean ignoreEncodingErrors) {
2473            throw new UnsupportedOperationException();
2474        }
2475
2476        @Override @DefinedBy(Api.COMPILER)
2477        public Writer openWriter() {
2478            throw new UnsupportedOperationException();
2479        }
2480
2481        @Override @DefinedBy(Api.COMPILER)
2482        public long getLastModified() {
2483            throw new UnsupportedOperationException();
2484        }
2485
2486        @Override @DefinedBy(Api.COMPILER)
2487        public boolean delete() {
2488            throw new UnsupportedOperationException();
2489        }
2490
2491        @Override
2492        protected String inferBinaryName(Iterable<? extends File> path) {
2493            return flatname.toString();
2494        }
2495
2496        @Override @DefinedBy(Api.COMPILER)
2497        public boolean isNameCompatible(String simpleName, JavaFileObject.Kind kind) {
2498            return true; // fail-safe mode
2499        }
2500
2501        /**
2502         * Check if two file objects are equal.
2503         * SourceFileObjects are just placeholder objects for the value of a
2504         * SourceFile attribute, and do not directly represent specific files.
2505         * Two SourceFileObjects are equal if their names are equal.
2506         */
2507        @Override
2508        public boolean equals(Object other) {
2509            if (this == other)
2510                return true;
2511
2512            if (!(other instanceof SourceFileObject))
2513                return false;
2514
2515            SourceFileObject o = (SourceFileObject) other;
2516            return name.equals(o.name);
2517        }
2518
2519        @Override
2520        public int hashCode() {
2521            return name.hashCode();
2522        }
2523    }
2524}
2525