ClassReader.java revision 2646:ff1998c1ecab
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        }
548        case '*':
549            sigp++;
550            return new WildcardType(syms.objectType, BoundKind.UNBOUND,
551                                    syms.boundClass);
552        case '-': {
553            sigp++;
554            Type t = sigToType();
555            return new WildcardType(t, BoundKind.SUPER, syms.boundClass);
556        }
557        case 'B':
558            sigp++;
559            return syms.byteType;
560        case 'C':
561            sigp++;
562            return syms.charType;
563        case 'D':
564            sigp++;
565            return syms.doubleType;
566        case 'F':
567            sigp++;
568            return syms.floatType;
569        case 'I':
570            sigp++;
571            return syms.intType;
572        case 'J':
573            sigp++;
574            return syms.longType;
575        case 'L':
576            {
577                // int oldsigp = sigp;
578                Type t = classSigToType();
579                if (sigp < siglimit && signature[sigp] == '.')
580                    throw badClassFile("deprecated inner class signature syntax " +
581                                       "(please recompile from source)");
582                /*
583                System.err.println(" decoded " +
584                                   new String(signature, oldsigp, sigp-oldsigp) +
585                                   " => " + t + " outer " + t.outer());
586                */
587                return t;
588            }
589        case 'S':
590            sigp++;
591            return syms.shortType;
592        case 'V':
593            sigp++;
594            return syms.voidType;
595        case 'Z':
596            sigp++;
597            return syms.booleanType;
598        case '[':
599            sigp++;
600            return new ArrayType(sigToType(), syms.arrayClass);
601        case '(':
602            sigp++;
603            List<Type> argtypes = sigToTypes(')');
604            Type restype = sigToType();
605            List<Type> thrown = List.nil();
606            while (signature[sigp] == '^') {
607                sigp++;
608                thrown = thrown.prepend(sigToType());
609            }
610            // if there is a typevar in the throws clause we should state it.
611            for (List<Type> l = thrown; l.nonEmpty(); l = l.tail) {
612                if (l.head.hasTag(TYPEVAR)) {
613                    l.head.tsym.flags_field |= THROWS;
614                }
615            }
616            return new MethodType(argtypes,
617                                  restype,
618                                  thrown.reverse(),
619                                  syms.methodClass);
620        case '<':
621            typevars = typevars.dup(currentOwner);
622            Type poly = new ForAll(sigToTypeParams(), sigToType());
623            typevars = typevars.leave();
624            return poly;
625        default:
626            throw badClassFile("bad.signature",
627                               Convert.utf2string(signature, sigp, 10));
628        }
629    }
630
631    byte[] signatureBuffer = new byte[0];
632    int sbp = 0;
633    /** Convert class signature to type, where signature is implicit.
634     */
635    Type classSigToType() {
636        if (signature[sigp] != 'L')
637            throw badClassFile("bad.class.signature",
638                               Convert.utf2string(signature, sigp, 10));
639        sigp++;
640        Type outer = Type.noType;
641        int startSbp = sbp;
642
643        while (true) {
644            final byte c = signature[sigp++];
645            switch (c) {
646
647            case ';': {         // end
648                ClassSymbol t = syms.enterClass(names.fromUtf(signatureBuffer,
649                                                         startSbp,
650                                                         sbp - startSbp));
651
652                try {
653                    return (outer == Type.noType) ?
654                            t.erasure(types) :
655                        new ClassType(outer, List.<Type>nil(), t);
656                } finally {
657                    sbp = startSbp;
658                }
659            }
660
661            case '<':           // generic arguments
662                ClassSymbol t = syms.enterClass(names.fromUtf(signatureBuffer,
663                                                         startSbp,
664                                                         sbp - startSbp));
665                outer = new ClassType(outer, sigToTypes('>'), t) {
666                        boolean completed = false;
667                        @Override @DefinedBy(Api.LANGUAGE_MODEL)
668                        public Type getEnclosingType() {
669                            if (!completed) {
670                                completed = true;
671                                tsym.complete();
672                                Type enclosingType = tsym.type.getEnclosingType();
673                                if (enclosingType != Type.noType) {
674                                    List<Type> typeArgs =
675                                        super.getEnclosingType().allparams();
676                                    List<Type> typeParams =
677                                        enclosingType.allparams();
678                                    if (typeParams.length() != typeArgs.length()) {
679                                        // no "rare" types
680                                        super.setEnclosingType(types.erasure(enclosingType));
681                                    } else {
682                                        super.setEnclosingType(types.subst(enclosingType,
683                                                                           typeParams,
684                                                                           typeArgs));
685                                    }
686                                } else {
687                                    super.setEnclosingType(Type.noType);
688                                }
689                            }
690                            return super.getEnclosingType();
691                        }
692                        @Override
693                        public void setEnclosingType(Type outer) {
694                            throw new UnsupportedOperationException();
695                        }
696                    };
697                switch (signature[sigp++]) {
698                case ';':
699                    if (sigp < signature.length && signature[sigp] == '.') {
700                        // support old-style GJC signatures
701                        // The signature produced was
702                        // Lfoo/Outer<Lfoo/X;>;.Lfoo/Outer$Inner<Lfoo/Y;>;
703                        // rather than say
704                        // Lfoo/Outer<Lfoo/X;>.Inner<Lfoo/Y;>;
705                        // so we skip past ".Lfoo/Outer$"
706                        sigp += (sbp - startSbp) + // "foo/Outer"
707                            3;  // ".L" and "$"
708                        signatureBuffer[sbp++] = (byte)'$';
709                        break;
710                    } else {
711                        sbp = startSbp;
712                        return outer;
713                    }
714                case '.':
715                    signatureBuffer[sbp++] = (byte)'$';
716                    break;
717                default:
718                    throw new AssertionError(signature[sigp-1]);
719                }
720                continue;
721
722            case '.':
723                //we have seen an enclosing non-generic class
724                if (outer != Type.noType) {
725                    t = syms.enterClass(names.fromUtf(signatureBuffer,
726                                                 startSbp,
727                                                 sbp - startSbp));
728                    outer = new ClassType(outer, List.<Type>nil(), t);
729                }
730                signatureBuffer[sbp++] = (byte)'$';
731                continue;
732            case '/':
733                signatureBuffer[sbp++] = (byte)'.';
734                continue;
735            default:
736                signatureBuffer[sbp++] = c;
737                continue;
738            }
739        }
740    }
741
742    /** Convert (implicit) signature to list of types
743     *  until `terminator' is encountered.
744     */
745    List<Type> sigToTypes(char terminator) {
746        List<Type> head = List.of(null);
747        List<Type> tail = head;
748        while (signature[sigp] != terminator)
749            tail = tail.setTail(List.of(sigToType()));
750        sigp++;
751        return head.tail;
752    }
753
754    /** Convert signature to type parameters, where signature is a byte
755     *  array segment.
756     */
757    List<Type> sigToTypeParams(byte[] sig, int offset, int len) {
758        signature = sig;
759        sigp = offset;
760        siglimit = offset + len;
761        return sigToTypeParams();
762    }
763
764    /** Convert signature to type parameters, where signature is implicit.
765     */
766    List<Type> sigToTypeParams() {
767        List<Type> tvars = List.nil();
768        if (signature[sigp] == '<') {
769            sigp++;
770            int start = sigp;
771            sigEnterPhase = true;
772            while (signature[sigp] != '>')
773                tvars = tvars.prepend(sigToTypeParam());
774            sigEnterPhase = false;
775            sigp = start;
776            while (signature[sigp] != '>')
777                sigToTypeParam();
778            sigp++;
779        }
780        return tvars.reverse();
781    }
782
783    /** Convert (implicit) signature to type parameter.
784     */
785    Type sigToTypeParam() {
786        int start = sigp;
787        while (signature[sigp] != ':') sigp++;
788        Name name = names.fromUtf(signature, start, sigp - start);
789        TypeVar tvar;
790        if (sigEnterPhase) {
791            tvar = new TypeVar(name, currentOwner, syms.botType);
792            typevars.enter(tvar.tsym);
793        } else {
794            tvar = (TypeVar)findTypeVar(name);
795        }
796        List<Type> bounds = List.nil();
797        boolean allInterfaces = false;
798        if (signature[sigp] == ':' && signature[sigp+1] == ':') {
799            sigp++;
800            allInterfaces = true;
801        }
802        while (signature[sigp] == ':') {
803            sigp++;
804            bounds = bounds.prepend(sigToType());
805        }
806        if (!sigEnterPhase) {
807            types.setBounds(tvar, bounds.reverse(), allInterfaces);
808        }
809        return tvar;
810    }
811
812    /** Find type variable with given name in `typevars' scope.
813     */
814    Type findTypeVar(Name name) {
815        Symbol s = typevars.findFirst(name);
816        if (s != null) {
817            return s.type;
818        } else {
819            if (readingClassAttr) {
820                // While reading the class attribute, the supertypes
821                // might refer to a type variable from an enclosing element
822                // (method or class).
823                // If the type variable is defined in the enclosing class,
824                // we can actually find it in
825                // currentOwner.owner.type.getTypeArguments()
826                // However, until we have read the enclosing method attribute
827                // we don't know for sure if this owner is correct.  It could
828                // be a method and there is no way to tell before reading the
829                // enclosing method attribute.
830                TypeVar t = new TypeVar(name, currentOwner, syms.botType);
831                missingTypeVariables = missingTypeVariables.prepend(t);
832                // System.err.println("Missing type var " + name);
833                return t;
834            }
835            throw badClassFile("undecl.type.var", name);
836        }
837    }
838
839/************************************************************************
840 * Reading Attributes
841 ***********************************************************************/
842
843    protected enum AttributeKind { CLASS, MEMBER }
844
845    protected abstract class AttributeReader {
846        protected AttributeReader(Name name, ClassFile.Version version, Set<AttributeKind> kinds) {
847            this.name = name;
848            this.version = version;
849            this.kinds = kinds;
850        }
851
852        protected boolean accepts(AttributeKind kind) {
853            if (kinds.contains(kind)) {
854                if (majorVersion > version.major || (majorVersion == version.major && minorVersion >= version.minor))
855                    return true;
856
857                if (lintClassfile && !warnedAttrs.contains(name)) {
858                    JavaFileObject prev = log.useSource(currentClassFile);
859                    try {
860                        log.warning(LintCategory.CLASSFILE, (DiagnosticPosition) null, "future.attr",
861                                name, version.major, version.minor, majorVersion, minorVersion);
862                    } finally {
863                        log.useSource(prev);
864                    }
865                    warnedAttrs.add(name);
866                }
867            }
868            return false;
869        }
870
871        protected abstract void read(Symbol sym, int attrLen);
872
873        protected final Name name;
874        protected final ClassFile.Version version;
875        protected final Set<AttributeKind> kinds;
876    }
877
878    protected Set<AttributeKind> CLASS_ATTRIBUTE =
879            EnumSet.of(AttributeKind.CLASS);
880    protected Set<AttributeKind> MEMBER_ATTRIBUTE =
881            EnumSet.of(AttributeKind.MEMBER);
882    protected Set<AttributeKind> CLASS_OR_MEMBER_ATTRIBUTE =
883            EnumSet.of(AttributeKind.CLASS, AttributeKind.MEMBER);
884
885    protected Map<Name, AttributeReader> attributeReaders = new HashMap<>();
886
887    private void initAttributeReaders() {
888        AttributeReader[] readers = {
889            // v45.3 attributes
890
891            new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) {
892                protected void read(Symbol sym, int attrLen) {
893                    if (readAllOfClassFile || saveParameterNames)
894                        ((MethodSymbol)sym).code = readCode(sym);
895                    else
896                        bp = bp + attrLen;
897                }
898            },
899
900            new AttributeReader(names.ConstantValue, V45_3, MEMBER_ATTRIBUTE) {
901                protected void read(Symbol sym, int attrLen) {
902                    Object v = readPool(nextChar());
903                    // Ignore ConstantValue attribute if field not final.
904                    if ((sym.flags() & FINAL) != 0)
905                        ((VarSymbol) sym).setData(v);
906                }
907            },
908
909            new AttributeReader(names.Deprecated, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
910                protected void read(Symbol sym, int attrLen) {
911                    sym.flags_field |= DEPRECATED;
912                }
913            },
914
915            new AttributeReader(names.Exceptions, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
916                protected void read(Symbol sym, int attrLen) {
917                    int nexceptions = nextChar();
918                    List<Type> thrown = List.nil();
919                    for (int j = 0; j < nexceptions; j++)
920                        thrown = thrown.prepend(readClassSymbol(nextChar()).type);
921                    if (sym.type.getThrownTypes().isEmpty())
922                        sym.type.asMethodType().thrown = thrown.reverse();
923                }
924            },
925
926            new AttributeReader(names.InnerClasses, V45_3, CLASS_ATTRIBUTE) {
927                protected void read(Symbol sym, int attrLen) {
928                    ClassSymbol c = (ClassSymbol) sym;
929                    readInnerClasses(c);
930                }
931            },
932
933            new AttributeReader(names.LocalVariableTable, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
934                protected void read(Symbol sym, int attrLen) {
935                    int newbp = bp + attrLen;
936                    if (saveParameterNames && !sawMethodParameters) {
937                        // Pick up parameter names from the variable table.
938                        // Parameter names are not explicitly identified as such,
939                        // but all parameter name entries in the LocalVariableTable
940                        // have a start_pc of 0.  Therefore, we record the name
941                        // indicies of all slots with a start_pc of zero in the
942                        // parameterNameIndicies array.
943                        // Note that this implicitly honors the JVMS spec that
944                        // there may be more than one LocalVariableTable, and that
945                        // there is no specified ordering for the entries.
946                        int numEntries = nextChar();
947                        for (int i = 0; i < numEntries; i++) {
948                            int start_pc = nextChar();
949                            int length = nextChar();
950                            int nameIndex = nextChar();
951                            int sigIndex = nextChar();
952                            int register = nextChar();
953                            if (start_pc == 0) {
954                                // ensure array large enough
955                                if (register >= parameterNameIndices.length) {
956                                    int newSize = Math.max(register, parameterNameIndices.length + 8);
957                                    parameterNameIndices =
958                                            Arrays.copyOf(parameterNameIndices, newSize);
959                                }
960                                parameterNameIndices[register] = nameIndex;
961                                haveParameterNameIndices = true;
962                            }
963                        }
964                    }
965                    bp = newbp;
966                }
967            },
968
969            new AttributeReader(names.MethodParameters, V52, MEMBER_ATTRIBUTE) {
970                protected void read(Symbol sym, int attrlen) {
971                    int newbp = bp + attrlen;
972                    if (saveParameterNames) {
973                        sawMethodParameters = true;
974                        int numEntries = nextByte();
975                        parameterNameIndices = new int[numEntries];
976                        haveParameterNameIndices = true;
977                        for (int i = 0; i < numEntries; i++) {
978                            int nameIndex = nextChar();
979                            int flags = nextChar();
980                            parameterNameIndices[i] = nameIndex;
981                        }
982                    }
983                    bp = newbp;
984                }
985            },
986
987
988            new AttributeReader(names.SourceFile, V45_3, CLASS_ATTRIBUTE) {
989                protected void read(Symbol sym, int attrLen) {
990                    ClassSymbol c = (ClassSymbol) sym;
991                    Name n = readName(nextChar());
992                    c.sourcefile = new SourceFileObject(n, c.flatname);
993                    // If the class is a toplevel class, originating from a Java source file,
994                    // but the class name does not match the file name, then it is
995                    // an auxiliary class.
996                    String sn = n.toString();
997                    if (c.owner.kind == Kinds.PCK &&
998                        sn.endsWith(".java") &&
999                        !sn.equals(c.name.toString()+".java")) {
1000                        c.flags_field |= AUXILIARY;
1001                    }
1002                }
1003            },
1004
1005            new AttributeReader(names.Synthetic, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
1006                protected void read(Symbol sym, int attrLen) {
1007                    sym.flags_field |= SYNTHETIC;
1008                }
1009            },
1010
1011            // standard v49 attributes
1012
1013            new AttributeReader(names.EnclosingMethod, V49, CLASS_ATTRIBUTE) {
1014                protected void read(Symbol sym, int attrLen) {
1015                    int newbp = bp + attrLen;
1016                    readEnclosingMethodAttr(sym);
1017                    bp = newbp;
1018                }
1019            },
1020
1021            new AttributeReader(names.Signature, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1022                protected void read(Symbol sym, int attrLen) {
1023                    if (sym.kind == TYP) {
1024                        ClassSymbol c = (ClassSymbol) sym;
1025                        readingClassAttr = true;
1026                        try {
1027                            ClassType ct1 = (ClassType)c.type;
1028                            Assert.check(c == currentOwner);
1029                            ct1.typarams_field = readTypeParams(nextChar());
1030                            ct1.supertype_field = sigToType();
1031                            ListBuffer<Type> is = new ListBuffer<>();
1032                            while (sigp != siglimit) is.append(sigToType());
1033                            ct1.interfaces_field = is.toList();
1034                        } finally {
1035                            readingClassAttr = false;
1036                        }
1037                    } else {
1038                        List<Type> thrown = sym.type.getThrownTypes();
1039                        sym.type = readType(nextChar());
1040                        //- System.err.println(" # " + sym.type);
1041                        if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty())
1042                            sym.type.asMethodType().thrown = thrown;
1043
1044                    }
1045                }
1046            },
1047
1048            // v49 annotation attributes
1049
1050            new AttributeReader(names.AnnotationDefault, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1051                protected void read(Symbol sym, int attrLen) {
1052                    attachAnnotationDefault(sym);
1053                }
1054            },
1055
1056            new AttributeReader(names.RuntimeInvisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1057                protected void read(Symbol sym, int attrLen) {
1058                    attachAnnotations(sym);
1059                }
1060            },
1061
1062            new AttributeReader(names.RuntimeInvisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1063                protected void read(Symbol sym, int attrLen) {
1064                    attachParameterAnnotations(sym);
1065                }
1066            },
1067
1068            new AttributeReader(names.RuntimeVisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1069                protected void read(Symbol sym, int attrLen) {
1070                    attachAnnotations(sym);
1071                }
1072            },
1073
1074            new AttributeReader(names.RuntimeVisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1075                protected void read(Symbol sym, int attrLen) {
1076                    attachParameterAnnotations(sym);
1077                }
1078            },
1079
1080            // additional "legacy" v49 attributes, superceded by flags
1081
1082            new AttributeReader(names.Annotation, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1083                protected void read(Symbol sym, int attrLen) {
1084                    sym.flags_field |= ANNOTATION;
1085                }
1086            },
1087
1088            new AttributeReader(names.Bridge, V49, MEMBER_ATTRIBUTE) {
1089                protected void read(Symbol sym, int attrLen) {
1090                    sym.flags_field |= BRIDGE;
1091                }
1092            },
1093
1094            new AttributeReader(names.Enum, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1095                protected void read(Symbol sym, int attrLen) {
1096                    sym.flags_field |= ENUM;
1097                }
1098            },
1099
1100            new AttributeReader(names.Varargs, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1101                protected void read(Symbol sym, int attrLen) {
1102                    sym.flags_field |= VARARGS;
1103                }
1104            },
1105
1106            new AttributeReader(names.RuntimeVisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) {
1107                protected void read(Symbol sym, int attrLen) {
1108                    attachTypeAnnotations(sym);
1109                }
1110            },
1111
1112            new AttributeReader(names.RuntimeInvisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) {
1113                protected void read(Symbol sym, int attrLen) {
1114                    attachTypeAnnotations(sym);
1115                }
1116            },
1117
1118
1119            // The following attributes for a Code attribute are not currently handled
1120            // StackMapTable
1121            // SourceDebugExtension
1122            // LineNumberTable
1123            // LocalVariableTypeTable
1124        };
1125
1126        for (AttributeReader r: readers)
1127            attributeReaders.put(r.name, r);
1128    }
1129
1130    /** Report unrecognized attribute.
1131     */
1132    void unrecognized(Name attrName) {
1133        if (checkClassFile)
1134            printCCF("ccf.unrecognized.attribute", attrName);
1135    }
1136
1137
1138
1139    protected void readEnclosingMethodAttr(Symbol sym) {
1140        // sym is a nested class with an "Enclosing Method" attribute
1141        // remove sym from it's current owners scope and place it in
1142        // the scope specified by the attribute
1143        sym.owner.members().remove(sym);
1144        ClassSymbol self = (ClassSymbol)sym;
1145        ClassSymbol c = readClassSymbol(nextChar());
1146        NameAndType nt = readNameAndType(nextChar());
1147
1148        if (c.members_field == null)
1149            throw badClassFile("bad.enclosing.class", self, c);
1150
1151        MethodSymbol m = findMethod(nt, c.members_field, self.flags());
1152        if (nt != null && m == null)
1153            throw badClassFile("bad.enclosing.method", self);
1154
1155        self.name = simpleBinaryName(self.flatname, c.flatname) ;
1156        self.owner = m != null ? m : c;
1157        if (self.name.isEmpty())
1158            self.fullname = names.empty;
1159        else
1160            self.fullname = ClassSymbol.formFullName(self.name, self.owner);
1161
1162        if (m != null) {
1163            ((ClassType)sym.type).setEnclosingType(m.type);
1164        } else if ((self.flags_field & STATIC) == 0) {
1165            ((ClassType)sym.type).setEnclosingType(c.type);
1166        } else {
1167            ((ClassType)sym.type).setEnclosingType(Type.noType);
1168        }
1169        enterTypevars(self);
1170        if (!missingTypeVariables.isEmpty()) {
1171            ListBuffer<Type> typeVars =  new ListBuffer<>();
1172            for (Type typevar : missingTypeVariables) {
1173                typeVars.append(findTypeVar(typevar.tsym.name));
1174            }
1175            foundTypeVariables = typeVars.toList();
1176        } else {
1177            foundTypeVariables = List.nil();
1178        }
1179    }
1180
1181    // See java.lang.Class
1182    private Name simpleBinaryName(Name self, Name enclosing) {
1183        String simpleBinaryName = self.toString().substring(enclosing.toString().length());
1184        if (simpleBinaryName.length() < 1 || simpleBinaryName.charAt(0) != '$')
1185            throw badClassFile("bad.enclosing.method", self);
1186        int index = 1;
1187        while (index < simpleBinaryName.length() &&
1188               isAsciiDigit(simpleBinaryName.charAt(index)))
1189            index++;
1190        return names.fromString(simpleBinaryName.substring(index));
1191    }
1192
1193    private MethodSymbol findMethod(NameAndType nt, Scope scope, long flags) {
1194        if (nt == null)
1195            return null;
1196
1197        MethodType type = nt.uniqueType.type.asMethodType();
1198
1199        for (Symbol sym : scope.getSymbolsByName(nt.name)) {
1200            if (sym.kind == MTH && isSameBinaryType(sym.type.asMethodType(), type))
1201                return (MethodSymbol)sym;
1202        }
1203
1204        if (nt.name != names.init)
1205            // not a constructor
1206            return null;
1207        if ((flags & INTERFACE) != 0)
1208            // no enclosing instance
1209            return null;
1210        if (nt.uniqueType.type.getParameterTypes().isEmpty())
1211            // no parameters
1212            return null;
1213
1214        // A constructor of an inner class.
1215        // Remove the first argument (the enclosing instance)
1216        nt.setType(new MethodType(nt.uniqueType.type.getParameterTypes().tail,
1217                                 nt.uniqueType.type.getReturnType(),
1218                                 nt.uniqueType.type.getThrownTypes(),
1219                                 syms.methodClass));
1220        // Try searching again
1221        return findMethod(nt, scope, flags);
1222    }
1223
1224    /** Similar to Types.isSameType but avoids completion */
1225    private boolean isSameBinaryType(MethodType mt1, MethodType mt2) {
1226        List<Type> types1 = types.erasure(mt1.getParameterTypes())
1227            .prepend(types.erasure(mt1.getReturnType()));
1228        List<Type> types2 = mt2.getParameterTypes().prepend(mt2.getReturnType());
1229        while (!types1.isEmpty() && !types2.isEmpty()) {
1230            if (types1.head.tsym != types2.head.tsym)
1231                return false;
1232            types1 = types1.tail;
1233            types2 = types2.tail;
1234        }
1235        return types1.isEmpty() && types2.isEmpty();
1236    }
1237
1238    /**
1239     * Character.isDigit answers <tt>true</tt> to some non-ascii
1240     * digits.  This one does not.  <b>copied from java.lang.Class</b>
1241     */
1242    private static boolean isAsciiDigit(char c) {
1243        return '0' <= c && c <= '9';
1244    }
1245
1246    /** Read member attributes.
1247     */
1248    void readMemberAttrs(Symbol sym) {
1249        readAttrs(sym, AttributeKind.MEMBER);
1250    }
1251
1252    void readAttrs(Symbol sym, AttributeKind kind) {
1253        char ac = nextChar();
1254        for (int i = 0; i < ac; i++) {
1255            Name attrName = readName(nextChar());
1256            int attrLen = nextInt();
1257            AttributeReader r = attributeReaders.get(attrName);
1258            if (r != null && r.accepts(kind))
1259                r.read(sym, attrLen);
1260            else  {
1261                unrecognized(attrName);
1262                bp = bp + attrLen;
1263            }
1264        }
1265    }
1266
1267    private boolean readingClassAttr = false;
1268    private List<Type> missingTypeVariables = List.nil();
1269    private List<Type> foundTypeVariables = List.nil();
1270
1271    /** Read class attributes.
1272     */
1273    void readClassAttrs(ClassSymbol c) {
1274        readAttrs(c, AttributeKind.CLASS);
1275    }
1276
1277    /** Read code block.
1278     */
1279    Code readCode(Symbol owner) {
1280        nextChar(); // max_stack
1281        nextChar(); // max_locals
1282        final int  code_length = nextInt();
1283        bp += code_length;
1284        final char exception_table_length = nextChar();
1285        bp += exception_table_length * 8;
1286        readMemberAttrs(owner);
1287        return null;
1288    }
1289
1290/************************************************************************
1291 * Reading Java-language annotations
1292 ***********************************************************************/
1293
1294    /** Attach annotations.
1295     */
1296    void attachAnnotations(final Symbol sym) {
1297        int numAttributes = nextChar();
1298        if (numAttributes != 0) {
1299            ListBuffer<CompoundAnnotationProxy> proxies = new ListBuffer<>();
1300            for (int i = 0; i<numAttributes; i++) {
1301                CompoundAnnotationProxy proxy = readCompoundAnnotation();
1302                if (proxy.type.tsym == syms.proprietaryType.tsym)
1303                    sym.flags_field |= PROPRIETARY;
1304                else if (proxy.type.tsym == syms.profileType.tsym) {
1305                    if (profile != Profile.DEFAULT) {
1306                        for (Pair<Name,Attribute> v: proxy.values) {
1307                            if (v.fst == names.value && v.snd instanceof Attribute.Constant) {
1308                                Attribute.Constant c = (Attribute.Constant) v.snd;
1309                                if (c.type == syms.intType && ((Integer) c.value) > profile.value) {
1310                                    sym.flags_field |= NOT_IN_PROFILE;
1311                                }
1312                            }
1313                        }
1314                    }
1315                } else
1316                    proxies.append(proxy);
1317            }
1318            annotate.normal(new AnnotationCompleter(sym, proxies.toList()));
1319        }
1320    }
1321
1322    /** Attach parameter annotations.
1323     */
1324    void attachParameterAnnotations(final Symbol method) {
1325        final MethodSymbol meth = (MethodSymbol)method;
1326        int numParameters = buf[bp++] & 0xFF;
1327        List<VarSymbol> parameters = meth.params();
1328        int pnum = 0;
1329        while (parameters.tail != null) {
1330            attachAnnotations(parameters.head);
1331            parameters = parameters.tail;
1332            pnum++;
1333        }
1334        if (pnum != numParameters) {
1335            throw badClassFile("bad.runtime.invisible.param.annotations", meth);
1336        }
1337    }
1338
1339    void attachTypeAnnotations(final Symbol sym) {
1340        int numAttributes = nextChar();
1341        if (numAttributes != 0) {
1342            ListBuffer<TypeAnnotationProxy> proxies = new ListBuffer<>();
1343            for (int i = 0; i < numAttributes; i++)
1344                proxies.append(readTypeAnnotation());
1345            annotate.normal(new TypeAnnotationCompleter(sym, proxies.toList()));
1346        }
1347    }
1348
1349    /** Attach the default value for an annotation element.
1350     */
1351    void attachAnnotationDefault(final Symbol sym) {
1352        final MethodSymbol meth = (MethodSymbol)sym; // only on methods
1353        final Attribute value = readAttributeValue();
1354
1355        // The default value is set later during annotation. It might
1356        // be the case that the Symbol sym is annotated _after_ the
1357        // repeating instances that depend on this default value,
1358        // because of this we set an interim value that tells us this
1359        // element (most likely) has a default.
1360        //
1361        // Set interim value for now, reset just before we do this
1362        // properly at annotate time.
1363        meth.defaultValue = value;
1364        annotate.normal(new AnnotationDefaultCompleter(meth, value));
1365    }
1366
1367    Type readTypeOrClassSymbol(int i) {
1368        // support preliminary jsr175-format class files
1369        if (buf[poolIdx[i]] == CONSTANT_Class)
1370            return readClassSymbol(i).type;
1371        return readType(i);
1372    }
1373    Type readEnumType(int i) {
1374        // support preliminary jsr175-format class files
1375        int index = poolIdx[i];
1376        int length = getChar(index + 1);
1377        if (buf[index + length + 2] != ';')
1378            return syms.enterClass(readName(i)).type;
1379        return readType(i);
1380    }
1381
1382    CompoundAnnotationProxy readCompoundAnnotation() {
1383        Type t = readTypeOrClassSymbol(nextChar());
1384        int numFields = nextChar();
1385        ListBuffer<Pair<Name,Attribute>> pairs = new ListBuffer<>();
1386        for (int i=0; i<numFields; i++) {
1387            Name name = readName(nextChar());
1388            Attribute value = readAttributeValue();
1389            pairs.append(new Pair<>(name, value));
1390        }
1391        return new CompoundAnnotationProxy(t, pairs.toList());
1392    }
1393
1394    TypeAnnotationProxy readTypeAnnotation() {
1395        TypeAnnotationPosition position = readPosition();
1396        CompoundAnnotationProxy proxy = readCompoundAnnotation();
1397
1398        return new TypeAnnotationProxy(proxy, position);
1399    }
1400
1401    TypeAnnotationPosition readPosition() {
1402        int tag = nextByte(); // TargetType tag is a byte
1403
1404        if (!TargetType.isValidTargetTypeValue(tag))
1405            throw badClassFile("bad.type.annotation.value", String.format("0x%02X", tag));
1406
1407        TargetType type = TargetType.fromTargetTypeValue(tag);
1408
1409        switch (type) {
1410        // instanceof
1411        case INSTANCEOF: {
1412            final int offset = nextChar();
1413            final TypeAnnotationPosition position =
1414                TypeAnnotationPosition.instanceOf(readTypePath());
1415            position.offset = offset;
1416            return position;
1417        }
1418        // new expression
1419        case NEW: {
1420            final int offset = nextChar();
1421            final TypeAnnotationPosition position =
1422                TypeAnnotationPosition.newObj(readTypePath());
1423            position.offset = offset;
1424            return position;
1425        }
1426        // constructor/method reference receiver
1427        case CONSTRUCTOR_REFERENCE: {
1428            final int offset = nextChar();
1429            final TypeAnnotationPosition position =
1430                TypeAnnotationPosition.constructorRef(readTypePath());
1431            position.offset = offset;
1432            return position;
1433        }
1434        case METHOD_REFERENCE: {
1435            final int offset = nextChar();
1436            final TypeAnnotationPosition position =
1437                TypeAnnotationPosition.methodRef(readTypePath());
1438            position.offset = offset;
1439            return position;
1440        }
1441        // local variable
1442        case LOCAL_VARIABLE: {
1443            final int table_length = nextChar();
1444            final int[] newLvarOffset = new int[table_length];
1445            final int[] newLvarLength = new int[table_length];
1446            final int[] newLvarIndex = new int[table_length];
1447
1448            for (int i = 0; i < table_length; ++i) {
1449                newLvarOffset[i] = nextChar();
1450                newLvarLength[i] = nextChar();
1451                newLvarIndex[i] = nextChar();
1452            }
1453
1454            final TypeAnnotationPosition position =
1455                    TypeAnnotationPosition.localVariable(readTypePath());
1456            position.lvarOffset = newLvarOffset;
1457            position.lvarLength = newLvarLength;
1458            position.lvarIndex = newLvarIndex;
1459            return position;
1460        }
1461        // resource variable
1462        case RESOURCE_VARIABLE: {
1463            final int table_length = nextChar();
1464            final int[] newLvarOffset = new int[table_length];
1465            final int[] newLvarLength = new int[table_length];
1466            final int[] newLvarIndex = new int[table_length];
1467
1468            for (int i = 0; i < table_length; ++i) {
1469                newLvarOffset[i] = nextChar();
1470                newLvarLength[i] = nextChar();
1471                newLvarIndex[i] = nextChar();
1472            }
1473
1474            final TypeAnnotationPosition position =
1475                    TypeAnnotationPosition.resourceVariable(readTypePath());
1476            position.lvarOffset = newLvarOffset;
1477            position.lvarLength = newLvarLength;
1478            position.lvarIndex = newLvarIndex;
1479            return position;
1480        }
1481        // exception parameter
1482        case EXCEPTION_PARAMETER: {
1483            final int exception_index = nextChar();
1484            final TypeAnnotationPosition position =
1485                TypeAnnotationPosition.exceptionParameter(readTypePath());
1486            position.setExceptionIndex(exception_index);
1487            return position;
1488        }
1489        // method receiver
1490        case METHOD_RECEIVER:
1491            return TypeAnnotationPosition.methodReceiver(readTypePath());
1492        // type parameter
1493        case CLASS_TYPE_PARAMETER: {
1494            final int parameter_index = nextByte();
1495            return TypeAnnotationPosition
1496                .typeParameter(readTypePath(), parameter_index);
1497        }
1498        case METHOD_TYPE_PARAMETER: {
1499            final int parameter_index = nextByte();
1500            return TypeAnnotationPosition
1501                .methodTypeParameter(readTypePath(), parameter_index);
1502        }
1503        // type parameter bound
1504        case CLASS_TYPE_PARAMETER_BOUND: {
1505            final int parameter_index = nextByte();
1506            final int bound_index = nextByte();
1507            return TypeAnnotationPosition
1508                .typeParameterBound(readTypePath(), parameter_index,
1509                                    bound_index);
1510        }
1511        case METHOD_TYPE_PARAMETER_BOUND: {
1512            final int parameter_index = nextByte();
1513            final int bound_index = nextByte();
1514            return TypeAnnotationPosition
1515                .methodTypeParameterBound(readTypePath(), parameter_index,
1516                                          bound_index);
1517        }
1518        // class extends or implements clause
1519        case CLASS_EXTENDS: {
1520            final int type_index = nextChar();
1521            return TypeAnnotationPosition.classExtends(readTypePath(),
1522                                                       type_index);
1523        }
1524        // throws
1525        case THROWS: {
1526            final int type_index = nextChar();
1527            return TypeAnnotationPosition.methodThrows(readTypePath(),
1528                                                       type_index);
1529        }
1530        // method parameter
1531        case METHOD_FORMAL_PARAMETER: {
1532            final int parameter_index = nextByte();
1533            return TypeAnnotationPosition.methodParameter(readTypePath(),
1534                                                          parameter_index);
1535        }
1536        // type cast
1537        case CAST: {
1538            final int offset = nextChar();
1539            final int type_index = nextByte();
1540            final TypeAnnotationPosition position =
1541                TypeAnnotationPosition.typeCast(readTypePath(), type_index);
1542            position.offset = offset;
1543            return position;
1544        }
1545        // method/constructor/reference type argument
1546        case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: {
1547            final int offset = nextChar();
1548            final int type_index = nextByte();
1549            final TypeAnnotationPosition position = TypeAnnotationPosition
1550                .constructorInvocationTypeArg(readTypePath(), type_index);
1551            position.offset = offset;
1552            return position;
1553        }
1554        case METHOD_INVOCATION_TYPE_ARGUMENT: {
1555            final int offset = nextChar();
1556            final int type_index = nextByte();
1557            final TypeAnnotationPosition position = TypeAnnotationPosition
1558                .methodInvocationTypeArg(readTypePath(), type_index);
1559            position.offset = offset;
1560            return position;
1561        }
1562        case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: {
1563            final int offset = nextChar();
1564            final int type_index = nextByte();
1565            final TypeAnnotationPosition position = TypeAnnotationPosition
1566                .constructorRefTypeArg(readTypePath(), type_index);
1567            position.offset = offset;
1568            return position;
1569        }
1570        case METHOD_REFERENCE_TYPE_ARGUMENT: {
1571            final int offset = nextChar();
1572            final int type_index = nextByte();
1573            final TypeAnnotationPosition position = TypeAnnotationPosition
1574                .methodRefTypeArg(readTypePath(), type_index);
1575            position.offset = offset;
1576            return position;
1577        }
1578        // We don't need to worry about these
1579        case METHOD_RETURN:
1580            return TypeAnnotationPosition.methodReturn(readTypePath());
1581        case FIELD:
1582            return TypeAnnotationPosition.field(readTypePath());
1583        case UNKNOWN:
1584            throw new AssertionError("jvm.ClassReader: UNKNOWN target type should never occur!");
1585        default:
1586            throw new AssertionError("jvm.ClassReader: Unknown target type for position: " + type);
1587        }
1588    }
1589
1590    List<TypeAnnotationPosition.TypePathEntry> readTypePath() {
1591        int len = nextByte();
1592        ListBuffer<Integer> loc = new ListBuffer<>();
1593        for (int i = 0; i < len * TypeAnnotationPosition.TypePathEntry.bytesPerEntry; ++i)
1594            loc = loc.append(nextByte());
1595
1596        return TypeAnnotationPosition.getTypePathFromBinary(loc.toList());
1597
1598    }
1599
1600    Attribute readAttributeValue() {
1601        char c = (char) buf[bp++];
1602        switch (c) {
1603        case 'B':
1604            return new Attribute.Constant(syms.byteType, readPool(nextChar()));
1605        case 'C':
1606            return new Attribute.Constant(syms.charType, readPool(nextChar()));
1607        case 'D':
1608            return new Attribute.Constant(syms.doubleType, readPool(nextChar()));
1609        case 'F':
1610            return new Attribute.Constant(syms.floatType, readPool(nextChar()));
1611        case 'I':
1612            return new Attribute.Constant(syms.intType, readPool(nextChar()));
1613        case 'J':
1614            return new Attribute.Constant(syms.longType, readPool(nextChar()));
1615        case 'S':
1616            return new Attribute.Constant(syms.shortType, readPool(nextChar()));
1617        case 'Z':
1618            return new Attribute.Constant(syms.booleanType, readPool(nextChar()));
1619        case 's':
1620            return new Attribute.Constant(syms.stringType, readPool(nextChar()).toString());
1621        case 'e':
1622            return new EnumAttributeProxy(readEnumType(nextChar()), readName(nextChar()));
1623        case 'c':
1624            return new Attribute.Class(types, readTypeOrClassSymbol(nextChar()));
1625        case '[': {
1626            int n = nextChar();
1627            ListBuffer<Attribute> l = new ListBuffer<>();
1628            for (int i=0; i<n; i++)
1629                l.append(readAttributeValue());
1630            return new ArrayAttributeProxy(l.toList());
1631        }
1632        case '@':
1633            return readCompoundAnnotation();
1634        default:
1635            throw new AssertionError("unknown annotation tag '" + c + "'");
1636        }
1637    }
1638
1639    interface ProxyVisitor extends Attribute.Visitor {
1640        void visitEnumAttributeProxy(EnumAttributeProxy proxy);
1641        void visitArrayAttributeProxy(ArrayAttributeProxy proxy);
1642        void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy);
1643    }
1644
1645    static class EnumAttributeProxy extends Attribute {
1646        Type enumType;
1647        Name enumerator;
1648        public EnumAttributeProxy(Type enumType, Name enumerator) {
1649            super(null);
1650            this.enumType = enumType;
1651            this.enumerator = enumerator;
1652        }
1653        public void accept(Visitor v) { ((ProxyVisitor)v).visitEnumAttributeProxy(this); }
1654        @Override @DefinedBy(Api.LANGUAGE_MODEL)
1655        public String toString() {
1656            return "/*proxy enum*/" + enumType + "." + enumerator;
1657        }
1658    }
1659
1660    static class ArrayAttributeProxy extends Attribute {
1661        List<Attribute> values;
1662        ArrayAttributeProxy(List<Attribute> values) {
1663            super(null);
1664            this.values = values;
1665        }
1666        public void accept(Visitor v) { ((ProxyVisitor)v).visitArrayAttributeProxy(this); }
1667        @Override @DefinedBy(Api.LANGUAGE_MODEL)
1668        public String toString() {
1669            return "{" + values + "}";
1670        }
1671    }
1672
1673    /** A temporary proxy representing a compound attribute.
1674     */
1675    static class CompoundAnnotationProxy extends Attribute {
1676        final List<Pair<Name,Attribute>> values;
1677        public CompoundAnnotationProxy(Type type,
1678                                      List<Pair<Name,Attribute>> values) {
1679            super(type);
1680            this.values = values;
1681        }
1682        public void accept(Visitor v) { ((ProxyVisitor)v).visitCompoundAnnotationProxy(this); }
1683        @Override @DefinedBy(Api.LANGUAGE_MODEL)
1684        public String toString() {
1685            StringBuilder buf = new StringBuilder();
1686            buf.append("@");
1687            buf.append(type.tsym.getQualifiedName());
1688            buf.append("/*proxy*/{");
1689            boolean first = true;
1690            for (List<Pair<Name,Attribute>> v = values;
1691                 v.nonEmpty(); v = v.tail) {
1692                Pair<Name,Attribute> value = v.head;
1693                if (!first) buf.append(",");
1694                first = false;
1695                buf.append(value.fst);
1696                buf.append("=");
1697                buf.append(value.snd);
1698            }
1699            buf.append("}");
1700            return buf.toString();
1701        }
1702    }
1703
1704    /** A temporary proxy representing a type annotation.
1705     */
1706    static class TypeAnnotationProxy {
1707        final CompoundAnnotationProxy compound;
1708        final TypeAnnotationPosition position;
1709        public TypeAnnotationProxy(CompoundAnnotationProxy compound,
1710                TypeAnnotationPosition position) {
1711            this.compound = compound;
1712            this.position = position;
1713        }
1714    }
1715
1716    class AnnotationDeproxy implements ProxyVisitor {
1717        private ClassSymbol requestingOwner = currentOwner.kind == MTH
1718            ? currentOwner.enclClass() : (ClassSymbol)currentOwner;
1719
1720        List<Attribute.Compound> deproxyCompoundList(List<CompoundAnnotationProxy> pl) {
1721            // also must fill in types!!!!
1722            ListBuffer<Attribute.Compound> buf = new ListBuffer<>();
1723            for (List<CompoundAnnotationProxy> l = pl; l.nonEmpty(); l=l.tail) {
1724                buf.append(deproxyCompound(l.head));
1725            }
1726            return buf.toList();
1727        }
1728
1729        Attribute.Compound deproxyCompound(CompoundAnnotationProxy a) {
1730            ListBuffer<Pair<Symbol.MethodSymbol,Attribute>> buf = new ListBuffer<>();
1731            for (List<Pair<Name,Attribute>> l = a.values;
1732                 l.nonEmpty();
1733                 l = l.tail) {
1734                MethodSymbol meth = findAccessMethod(a.type, l.head.fst);
1735                buf.append(new Pair<>(meth, deproxy(meth.type.getReturnType(), l.head.snd)));
1736            }
1737            return new Attribute.Compound(a.type, buf.toList());
1738        }
1739
1740        MethodSymbol findAccessMethod(Type container, Name name) {
1741            CompletionFailure failure = null;
1742            try {
1743                for (Symbol sym : container.tsym.members().getSymbolsByName(name)) {
1744                    if (sym.kind == MTH && sym.type.getParameterTypes().length() == 0)
1745                        return (MethodSymbol) sym;
1746                }
1747            } catch (CompletionFailure ex) {
1748                failure = ex;
1749            }
1750            // The method wasn't found: emit a warning and recover
1751            JavaFileObject prevSource = log.useSource(requestingOwner.classfile);
1752            try {
1753                if (failure == null) {
1754                    log.warning("annotation.method.not.found",
1755                                container,
1756                                name);
1757                } else {
1758                    log.warning("annotation.method.not.found.reason",
1759                                container,
1760                                name,
1761                                failure.getDetailValue());//diagnostic, if present
1762                }
1763            } finally {
1764                log.useSource(prevSource);
1765            }
1766            // Construct a new method type and symbol.  Use bottom
1767            // type (typeof null) as return type because this type is
1768            // a subtype of all reference types and can be converted
1769            // to primitive types by unboxing.
1770            MethodType mt = new MethodType(List.<Type>nil(),
1771                                           syms.botType,
1772                                           List.<Type>nil(),
1773                                           syms.methodClass);
1774            return new MethodSymbol(PUBLIC | ABSTRACT, name, mt, container.tsym);
1775        }
1776
1777        Attribute result;
1778        Type type;
1779        Attribute deproxy(Type t, Attribute a) {
1780            Type oldType = type;
1781            try {
1782                type = t;
1783                a.accept(this);
1784                return result;
1785            } finally {
1786                type = oldType;
1787            }
1788        }
1789
1790        // implement Attribute.Visitor below
1791
1792        public void visitConstant(Attribute.Constant value) {
1793            // assert value.type == type;
1794            result = value;
1795        }
1796
1797        public void visitClass(Attribute.Class clazz) {
1798            result = clazz;
1799        }
1800
1801        public void visitEnum(Attribute.Enum e) {
1802            throw new AssertionError(); // shouldn't happen
1803        }
1804
1805        public void visitCompound(Attribute.Compound compound) {
1806            throw new AssertionError(); // shouldn't happen
1807        }
1808
1809        public void visitArray(Attribute.Array array) {
1810            throw new AssertionError(); // shouldn't happen
1811        }
1812
1813        public void visitError(Attribute.Error e) {
1814            throw new AssertionError(); // shouldn't happen
1815        }
1816
1817        public void visitEnumAttributeProxy(EnumAttributeProxy proxy) {
1818            // type.tsym.flatName() should == proxy.enumFlatName
1819            TypeSymbol enumTypeSym = proxy.enumType.tsym;
1820            VarSymbol enumerator = null;
1821            CompletionFailure failure = null;
1822            try {
1823                for (Symbol sym : enumTypeSym.members().getSymbolsByName(proxy.enumerator)) {
1824                    if (sym.kind == VAR) {
1825                        enumerator = (VarSymbol)sym;
1826                        break;
1827                    }
1828                }
1829            }
1830            catch (CompletionFailure ex) {
1831                failure = ex;
1832            }
1833            if (enumerator == null) {
1834                if (failure != null) {
1835                    log.warning("unknown.enum.constant.reason",
1836                              currentClassFile, enumTypeSym, proxy.enumerator,
1837                              failure.getDiagnostic());
1838                } else {
1839                    log.warning("unknown.enum.constant",
1840                              currentClassFile, enumTypeSym, proxy.enumerator);
1841                }
1842                result = new Attribute.Enum(enumTypeSym.type,
1843                        new VarSymbol(0, proxy.enumerator, syms.botType, enumTypeSym));
1844            } else {
1845                result = new Attribute.Enum(enumTypeSym.type, enumerator);
1846            }
1847        }
1848
1849        public void visitArrayAttributeProxy(ArrayAttributeProxy proxy) {
1850            int length = proxy.values.length();
1851            Attribute[] ats = new Attribute[length];
1852            Type elemtype = types.elemtype(type);
1853            int i = 0;
1854            for (List<Attribute> p = proxy.values; p.nonEmpty(); p = p.tail) {
1855                ats[i++] = deproxy(elemtype, p.head);
1856            }
1857            result = new Attribute.Array(type, ats);
1858        }
1859
1860        public void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy) {
1861            result = deproxyCompound(proxy);
1862        }
1863    }
1864
1865    class AnnotationDefaultCompleter extends AnnotationDeproxy implements Annotate.Worker {
1866        final MethodSymbol sym;
1867        final Attribute value;
1868        final JavaFileObject classFile = currentClassFile;
1869        @Override
1870        public String toString() {
1871            return " ClassReader store default for " + sym.owner + "." + sym + " is " + value;
1872        }
1873        AnnotationDefaultCompleter(MethodSymbol sym, Attribute value) {
1874            this.sym = sym;
1875            this.value = value;
1876        }
1877        // implement Annotate.Worker.run()
1878        public void run() {
1879            JavaFileObject previousClassFile = currentClassFile;
1880            try {
1881                // Reset the interim value set earlier in
1882                // attachAnnotationDefault().
1883                sym.defaultValue = null;
1884                currentClassFile = classFile;
1885                sym.defaultValue = deproxy(sym.type.getReturnType(), value);
1886            } finally {
1887                currentClassFile = previousClassFile;
1888            }
1889        }
1890    }
1891
1892    class AnnotationCompleter extends AnnotationDeproxy implements Annotate.Worker {
1893        final Symbol sym;
1894        final List<CompoundAnnotationProxy> l;
1895        final JavaFileObject classFile;
1896        @Override
1897        public String toString() {
1898            return " ClassReader annotate " + sym.owner + "." + sym + " with " + l;
1899        }
1900        AnnotationCompleter(Symbol sym, List<CompoundAnnotationProxy> l) {
1901            this.sym = sym;
1902            this.l = l;
1903            this.classFile = currentClassFile;
1904        }
1905        // implement Annotate.Worker.run()
1906        public void run() {
1907            JavaFileObject previousClassFile = currentClassFile;
1908            try {
1909                currentClassFile = classFile;
1910                List<Attribute.Compound> newList = deproxyCompoundList(l);
1911                if (sym.annotationsPendingCompletion()) {
1912                    sym.setDeclarationAttributes(newList);
1913                } else {
1914                    sym.appendAttributes(newList);
1915                }
1916            } finally {
1917                currentClassFile = previousClassFile;
1918            }
1919        }
1920    }
1921
1922    class TypeAnnotationCompleter extends AnnotationCompleter {
1923
1924        List<TypeAnnotationProxy> proxies;
1925
1926        TypeAnnotationCompleter(Symbol sym,
1927                List<TypeAnnotationProxy> proxies) {
1928            super(sym, List.<CompoundAnnotationProxy>nil());
1929            this.proxies = proxies;
1930        }
1931
1932        List<Attribute.TypeCompound> deproxyTypeCompoundList(List<TypeAnnotationProxy> proxies) {
1933            ListBuffer<Attribute.TypeCompound> buf = new ListBuffer<>();
1934            for (TypeAnnotationProxy proxy: proxies) {
1935                Attribute.Compound compound = deproxyCompound(proxy.compound);
1936                Attribute.TypeCompound typeCompound = new Attribute.TypeCompound(compound, proxy.position);
1937                buf.add(typeCompound);
1938            }
1939            return buf.toList();
1940        }
1941
1942        @Override
1943        public void run() {
1944            JavaFileObject previousClassFile = currentClassFile;
1945            try {
1946                currentClassFile = classFile;
1947                List<Attribute.TypeCompound> newList = deproxyTypeCompoundList(proxies);
1948                sym.setTypeAttributes(newList.prependList(sym.getRawTypeAttributes()));
1949            } finally {
1950                currentClassFile = previousClassFile;
1951            }
1952        }
1953    }
1954
1955
1956/************************************************************************
1957 * Reading Symbols
1958 ***********************************************************************/
1959
1960    /** Read a field.
1961     */
1962    VarSymbol readField() {
1963        long flags = adjustFieldFlags(nextChar());
1964        Name name = readName(nextChar());
1965        Type type = readType(nextChar());
1966        VarSymbol v = new VarSymbol(flags, name, type, currentOwner);
1967        readMemberAttrs(v);
1968        return v;
1969    }
1970
1971    /** Read a method.
1972     */
1973    MethodSymbol readMethod() {
1974        long flags = adjustMethodFlags(nextChar());
1975        Name name = readName(nextChar());
1976        Type type = readType(nextChar());
1977        if (currentOwner.isInterface() &&
1978                (flags & ABSTRACT) == 0 && !name.equals(names.clinit)) {
1979            if (majorVersion > Version.V52.major ||
1980                    (majorVersion == Version.V52.major && minorVersion >= Version.V52.minor)) {
1981                if ((flags & STATIC) == 0) {
1982                    currentOwner.flags_field |= DEFAULT;
1983                    flags |= DEFAULT | ABSTRACT;
1984                }
1985            } else {
1986                //protect against ill-formed classfiles
1987                throw badClassFile((flags & STATIC) == 0 ? "invalid.default.interface" : "invalid.static.interface",
1988                                   Integer.toString(majorVersion),
1989                                   Integer.toString(minorVersion));
1990            }
1991        }
1992        if (name == names.init && currentOwner.hasOuterInstance()) {
1993            // Sometimes anonymous classes don't have an outer
1994            // instance, however, there is no reliable way to tell so
1995            // we never strip this$n
1996            if (!currentOwner.name.isEmpty())
1997                type = new MethodType(adjustMethodParams(flags, type.getParameterTypes()),
1998                                      type.getReturnType(),
1999                                      type.getThrownTypes(),
2000                                      syms.methodClass);
2001        }
2002        MethodSymbol m = new MethodSymbol(flags, name, type, currentOwner);
2003        if (types.isSignaturePolymorphic(m)) {
2004            m.flags_field |= SIGNATURE_POLYMORPHIC;
2005        }
2006        if (saveParameterNames)
2007            initParameterNames(m);
2008        Symbol prevOwner = currentOwner;
2009        currentOwner = m;
2010        try {
2011            readMemberAttrs(m);
2012        } finally {
2013            currentOwner = prevOwner;
2014        }
2015        if (saveParameterNames)
2016            setParameterNames(m, type);
2017        return m;
2018    }
2019
2020    private List<Type> adjustMethodParams(long flags, List<Type> args) {
2021        boolean isVarargs = (flags & VARARGS) != 0;
2022        if (isVarargs) {
2023            Type varargsElem = args.last();
2024            ListBuffer<Type> adjustedArgs = new ListBuffer<>();
2025            for (Type t : args) {
2026                adjustedArgs.append(t != varargsElem ?
2027                    t :
2028                    ((ArrayType)t).makeVarargs());
2029            }
2030            args = adjustedArgs.toList();
2031        }
2032        return args.tail;
2033    }
2034
2035    /**
2036     * Init the parameter names array.
2037     * Parameter names are currently inferred from the names in the
2038     * LocalVariableTable attributes of a Code attribute.
2039     * (Note: this means parameter names are currently not available for
2040     * methods without a Code attribute.)
2041     * This method initializes an array in which to store the name indexes
2042     * of parameter names found in LocalVariableTable attributes. It is
2043     * slightly supersized to allow for additional slots with a start_pc of 0.
2044     */
2045    void initParameterNames(MethodSymbol sym) {
2046        // make allowance for synthetic parameters.
2047        final int excessSlots = 4;
2048        int expectedParameterSlots =
2049                Code.width(sym.type.getParameterTypes()) + excessSlots;
2050        if (parameterNameIndices == null
2051                || parameterNameIndices.length < expectedParameterSlots) {
2052            parameterNameIndices = new int[expectedParameterSlots];
2053        } else
2054            Arrays.fill(parameterNameIndices, 0);
2055        haveParameterNameIndices = false;
2056        sawMethodParameters = false;
2057    }
2058
2059    /**
2060     * Set the parameter names for a symbol from the name index in the
2061     * parameterNameIndicies array. The type of the symbol may have changed
2062     * while reading the method attributes (see the Signature attribute).
2063     * This may be because of generic information or because anonymous
2064     * synthetic parameters were added.   The original type (as read from
2065     * the method descriptor) is used to help guess the existence of
2066     * anonymous synthetic parameters.
2067     * On completion, sym.savedParameter names will either be null (if
2068     * no parameter names were found in the class file) or will be set to a
2069     * list of names, one per entry in sym.type.getParameterTypes, with
2070     * any missing names represented by the empty name.
2071     */
2072    void setParameterNames(MethodSymbol sym, Type jvmType) {
2073        // if no names were found in the class file, there's nothing more to do
2074        if (!haveParameterNameIndices)
2075            return;
2076        // If we get parameter names from MethodParameters, then we
2077        // don't need to skip.
2078        int firstParam = 0;
2079        if (!sawMethodParameters) {
2080            firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0;
2081            // the code in readMethod may have skipped the first
2082            // parameter when setting up the MethodType. If so, we
2083            // make a corresponding allowance here for the position of
2084            // the first parameter.  Note that this assumes the
2085            // skipped parameter has a width of 1 -- i.e. it is not
2086        // a double width type (long or double.)
2087        if (sym.name == names.init && currentOwner.hasOuterInstance()) {
2088            // Sometimes anonymous classes don't have an outer
2089            // instance, however, there is no reliable way to tell so
2090            // we never strip this$n
2091            if (!currentOwner.name.isEmpty())
2092                firstParam += 1;
2093        }
2094
2095        if (sym.type != jvmType) {
2096                // reading the method attributes has caused the
2097                // symbol's type to be changed. (i.e. the Signature
2098                // attribute.)  This may happen if there are hidden
2099                // (synthetic) parameters in the descriptor, but not
2100                // in the Signature.  The position of these hidden
2101                // parameters is unspecified; for now, assume they are
2102                // at the beginning, and so skip over them. The
2103                // primary case for this is two hidden parameters
2104                // passed into Enum constructors.
2105            int skip = Code.width(jvmType.getParameterTypes())
2106                    - Code.width(sym.type.getParameterTypes());
2107            firstParam += skip;
2108        }
2109        }
2110        List<Name> paramNames = List.nil();
2111        int index = firstParam;
2112        for (Type t: sym.type.getParameterTypes()) {
2113            int nameIdx = (index < parameterNameIndices.length
2114                    ? parameterNameIndices[index] : 0);
2115            Name name = nameIdx == 0 ? names.empty : readName(nameIdx);
2116            paramNames = paramNames.prepend(name);
2117            index += Code.width(t);
2118        }
2119        sym.savedParameterNames = paramNames.reverse();
2120    }
2121
2122    /**
2123     * skip n bytes
2124     */
2125    void skipBytes(int n) {
2126        bp = bp + n;
2127    }
2128
2129    /** Skip a field or method
2130     */
2131    void skipMember() {
2132        bp = bp + 6;
2133        char ac = nextChar();
2134        for (int i = 0; i < ac; i++) {
2135            bp = bp + 2;
2136            int attrLen = nextInt();
2137            bp = bp + attrLen;
2138        }
2139    }
2140
2141    /** Enter type variables of this classtype and all enclosing ones in
2142     *  `typevars'.
2143     */
2144    protected void enterTypevars(Type t) {
2145        if (t.getEnclosingType() != null && t.getEnclosingType().hasTag(CLASS))
2146            enterTypevars(t.getEnclosingType());
2147        for (List<Type> xs = t.getTypeArguments(); xs.nonEmpty(); xs = xs.tail)
2148            typevars.enter(xs.head.tsym);
2149    }
2150
2151    protected void enterTypevars(Symbol sym) {
2152        if (sym.owner.kind == MTH) {
2153            enterTypevars(sym.owner);
2154            enterTypevars(sym.owner.owner);
2155        }
2156        enterTypevars(sym.type);
2157    }
2158
2159    /** Read contents of a given class symbol `c'. Both external and internal
2160     *  versions of an inner class are read.
2161     */
2162    void readClass(ClassSymbol c) {
2163        ClassType ct = (ClassType)c.type;
2164
2165        // allocate scope for members
2166        c.members_field = WriteableScope.create(c);
2167
2168        // prepare type variable table
2169        typevars = typevars.dup(currentOwner);
2170        if (ct.getEnclosingType().hasTag(CLASS))
2171            enterTypevars(ct.getEnclosingType());
2172
2173        // read flags, or skip if this is an inner class
2174        long flags = adjustClassFlags(nextChar());
2175        if (c.owner.kind == PCK) c.flags_field = flags;
2176
2177        // read own class name and check that it matches
2178        ClassSymbol self = readClassSymbol(nextChar());
2179        if (c != self)
2180            throw badClassFile("class.file.wrong.class",
2181                               self.flatname);
2182
2183        // class attributes must be read before class
2184        // skip ahead to read class attributes
2185        int startbp = bp;
2186        nextChar();
2187        char interfaceCount = nextChar();
2188        bp += interfaceCount * 2;
2189        char fieldCount = nextChar();
2190        for (int i = 0; i < fieldCount; i++) skipMember();
2191        char methodCount = nextChar();
2192        for (int i = 0; i < methodCount; i++) skipMember();
2193        readClassAttrs(c);
2194
2195        if (readAllOfClassFile) {
2196            for (int i = 1; i < poolObj.length; i++) readPool(i);
2197            c.pool = new Pool(poolObj.length, poolObj, types);
2198        }
2199
2200        // reset and read rest of classinfo
2201        bp = startbp;
2202        int n = nextChar();
2203        if (ct.supertype_field == null)
2204            ct.supertype_field = (n == 0)
2205                ? Type.noType
2206                : readClassSymbol(n).erasure(types);
2207        n = nextChar();
2208        List<Type> is = List.nil();
2209        for (int i = 0; i < n; i++) {
2210            Type _inter = readClassSymbol(nextChar()).erasure(types);
2211            is = is.prepend(_inter);
2212        }
2213        if (ct.interfaces_field == null)
2214            ct.interfaces_field = is.reverse();
2215
2216        Assert.check(fieldCount == nextChar());
2217        for (int i = 0; i < fieldCount; i++) enterMember(c, readField());
2218        Assert.check(methodCount == nextChar());
2219        for (int i = 0; i < methodCount; i++) enterMember(c, readMethod());
2220
2221        typevars = typevars.leave();
2222    }
2223
2224    /** Read inner class info. For each inner/outer pair allocate a
2225     *  member class.
2226     */
2227    void readInnerClasses(ClassSymbol c) {
2228        int n = nextChar();
2229        for (int i = 0; i < n; i++) {
2230            nextChar(); // skip inner class symbol
2231            ClassSymbol outer = readClassSymbol(nextChar());
2232            Name name = readName(nextChar());
2233            if (name == null) name = names.empty;
2234            long flags = adjustClassFlags(nextChar());
2235            if (outer != null) { // we have a member class
2236                if (name == names.empty)
2237                    name = names.one;
2238                ClassSymbol member = syms.enterClass(name, outer);
2239                if ((flags & STATIC) == 0) {
2240                    ((ClassType)member.type).setEnclosingType(outer.type);
2241                    if (member.erasure_field != null)
2242                        ((ClassType)member.erasure_field).setEnclosingType(types.erasure(outer.type));
2243                }
2244                if (c == outer) {
2245                    member.flags_field = flags;
2246                    enterMember(c, member);
2247                }
2248            }
2249        }
2250    }
2251
2252    /** Read a class definition from the bytes in buf.
2253     */
2254    private void readClassBuffer(ClassSymbol c) throws IOException {
2255        int magic = nextInt();
2256        if (magic != JAVA_MAGIC)
2257            throw badClassFile("illegal.start.of.class.file");
2258
2259        minorVersion = nextChar();
2260        majorVersion = nextChar();
2261        int maxMajor = Version.MAX().major;
2262        int maxMinor = Version.MAX().minor;
2263        if (majorVersion > maxMajor ||
2264            majorVersion * 1000 + minorVersion <
2265            Version.MIN().major * 1000 + Version.MIN().minor)
2266        {
2267            if (majorVersion == (maxMajor + 1))
2268                log.warning("big.major.version",
2269                            currentClassFile,
2270                            majorVersion,
2271                            maxMajor);
2272            else
2273                throw badClassFile("wrong.version",
2274                                   Integer.toString(majorVersion),
2275                                   Integer.toString(minorVersion),
2276                                   Integer.toString(maxMajor),
2277                                   Integer.toString(maxMinor));
2278        }
2279        else if (checkClassFile &&
2280                 majorVersion == maxMajor &&
2281                 minorVersion > maxMinor)
2282        {
2283            printCCF("found.later.version",
2284                     Integer.toString(minorVersion));
2285        }
2286        indexPool();
2287        if (signatureBuffer.length < bp) {
2288            int ns = Integer.highestOneBit(bp) << 1;
2289            signatureBuffer = new byte[ns];
2290        }
2291        readClass(c);
2292    }
2293
2294    public void readClassFile(ClassSymbol c) {
2295        currentOwner = c;
2296        currentClassFile = c.classfile;
2297        warnedAttrs.clear();
2298        filling = true;
2299        try {
2300            bp = 0;
2301            buf = readInputStream(buf, c.classfile.openInputStream());
2302            readClassBuffer(c);
2303            if (!missingTypeVariables.isEmpty() && !foundTypeVariables.isEmpty()) {
2304                List<Type> missing = missingTypeVariables;
2305                List<Type> found = foundTypeVariables;
2306                missingTypeVariables = List.nil();
2307                foundTypeVariables = List.nil();
2308                filling = false;
2309                ClassType ct = (ClassType)currentOwner.type;
2310                ct.supertype_field =
2311                    types.subst(ct.supertype_field, missing, found);
2312                ct.interfaces_field =
2313                    types.subst(ct.interfaces_field, missing, found);
2314            } else if (missingTypeVariables.isEmpty() !=
2315                       foundTypeVariables.isEmpty()) {
2316                Name name = missingTypeVariables.head.tsym.name;
2317                throw badClassFile("undecl.type.var", name);
2318            }
2319        } catch (IOException ex) {
2320            throw badClassFile("unable.to.access.file", ex.getMessage());
2321        } catch (ArrayIndexOutOfBoundsException ex) {
2322            throw badClassFile("bad.class.file", c.flatname);
2323        } finally {
2324            missingTypeVariables = List.nil();
2325            foundTypeVariables = List.nil();
2326            filling = false;
2327        }
2328    }
2329    // where
2330        private static byte[] readInputStream(byte[] buf, InputStream s) throws IOException {
2331            try {
2332                buf = ensureCapacity(buf, s.available());
2333                int r = s.read(buf);
2334                int bp = 0;
2335                while (r != -1) {
2336                    bp += r;
2337                    buf = ensureCapacity(buf, bp);
2338                    r = s.read(buf, bp, buf.length - bp);
2339                }
2340                return buf;
2341            } finally {
2342                try {
2343                    s.close();
2344                } catch (IOException e) {
2345                    /* Ignore any errors, as this stream may have already
2346                     * thrown a related exception which is the one that
2347                     * should be reported.
2348                     */
2349                }
2350            }
2351        }
2352        /*
2353         * ensureCapacity will increase the buffer as needed, taking note that
2354         * the new buffer will always be greater than the needed and never
2355         * exactly equal to the needed size or bp. If equal then the read (above)
2356         * will infinitely loop as buf.length - bp == 0.
2357         */
2358        private static byte[] ensureCapacity(byte[] buf, int needed) {
2359            if (buf.length <= needed) {
2360                byte[] old = buf;
2361                buf = new byte[Integer.highestOneBit(needed) << 1];
2362                System.arraycopy(old, 0, buf, 0, old.length);
2363            }
2364            return buf;
2365        }
2366
2367    /** We can only read a single class file at a time; this
2368     *  flag keeps track of when we are currently reading a class
2369     *  file.
2370     */
2371    public boolean filling = false;
2372
2373/************************************************************************
2374 * Adjusting flags
2375 ***********************************************************************/
2376
2377    long adjustFieldFlags(long flags) {
2378        return flags;
2379    }
2380
2381    long adjustMethodFlags(long flags) {
2382        if ((flags & ACC_BRIDGE) != 0) {
2383            flags &= ~ACC_BRIDGE;
2384            flags |= BRIDGE;
2385        }
2386        if ((flags & ACC_VARARGS) != 0) {
2387            flags &= ~ACC_VARARGS;
2388            flags |= VARARGS;
2389        }
2390        return flags;
2391    }
2392
2393    long adjustClassFlags(long flags) {
2394        return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
2395    }
2396
2397    /** Output for "-checkclassfile" option.
2398     *  @param key The key to look up the correct internationalized string.
2399     *  @param arg An argument for substitution into the output string.
2400     */
2401    private void printCCF(String key, Object arg) {
2402        log.printLines(key, arg);
2403    }
2404
2405    /**
2406     * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
2407     * The attribute is only the last component of the original filename, so is unlikely
2408     * to be valid as is, so operations other than those to access the name throw
2409     * UnsupportedOperationException
2410     */
2411    private static class SourceFileObject extends BaseFileObject {
2412
2413        /** The file's name.
2414         */
2415        private Name name;
2416        private Name flatname;
2417
2418        public SourceFileObject(Name name, Name flatname) {
2419            super(null); // no file manager; never referenced for this file object
2420            this.name = name;
2421            this.flatname = flatname;
2422        }
2423
2424        @Override @DefinedBy(Api.COMPILER)
2425        public URI toUri() {
2426            try {
2427                return new URI(null, name.toString(), null);
2428            } catch (URISyntaxException e) {
2429                throw new CannotCreateUriError(name.toString(), e);
2430            }
2431        }
2432
2433        @Override @DefinedBy(Api.COMPILER)
2434        public String getName() {
2435            return name.toString();
2436        }
2437
2438        @Override
2439        public String getShortName() {
2440            return getName();
2441        }
2442
2443        @Override @DefinedBy(Api.COMPILER)
2444        public JavaFileObject.Kind getKind() {
2445            return getKind(getName());
2446        }
2447
2448        @Override @DefinedBy(Api.COMPILER)
2449        public InputStream openInputStream() {
2450            throw new UnsupportedOperationException();
2451        }
2452
2453        @Override @DefinedBy(Api.COMPILER)
2454        public OutputStream openOutputStream() {
2455            throw new UnsupportedOperationException();
2456        }
2457
2458        @Override @DefinedBy(Api.COMPILER)
2459        public CharBuffer getCharContent(boolean ignoreEncodingErrors) {
2460            throw new UnsupportedOperationException();
2461        }
2462
2463        @Override @DefinedBy(Api.COMPILER)
2464        public Reader openReader(boolean ignoreEncodingErrors) {
2465            throw new UnsupportedOperationException();
2466        }
2467
2468        @Override @DefinedBy(Api.COMPILER)
2469        public Writer openWriter() {
2470            throw new UnsupportedOperationException();
2471        }
2472
2473        @Override @DefinedBy(Api.COMPILER)
2474        public long getLastModified() {
2475            throw new UnsupportedOperationException();
2476        }
2477
2478        @Override @DefinedBy(Api.COMPILER)
2479        public boolean delete() {
2480            throw new UnsupportedOperationException();
2481        }
2482
2483        @Override
2484        protected String inferBinaryName(Iterable<? extends File> path) {
2485            return flatname.toString();
2486        }
2487
2488        @Override @DefinedBy(Api.COMPILER)
2489        public boolean isNameCompatible(String simpleName, JavaFileObject.Kind kind) {
2490            return true; // fail-safe mode
2491        }
2492
2493        /**
2494         * Check if two file objects are equal.
2495         * SourceFileObjects are just placeholder objects for the value of a
2496         * SourceFile attribute, and do not directly represent specific files.
2497         * Two SourceFileObjects are equal if their names are equal.
2498         */
2499        @Override
2500        public boolean equals(Object other) {
2501            if (this == other)
2502                return true;
2503
2504            if (!(other instanceof SourceFileObject))
2505                return false;
2506
2507            SourceFileObject o = (SourceFileObject) other;
2508            return name.equals(o.name);
2509        }
2510
2511        @Override
2512        public int hashCode() {
2513            return name.hashCode();
2514        }
2515    }
2516}
2517