ClassReader.java revision 2721:f7ce2cfa4cdb
1172009Simp/*
2172009Simp * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
3172009Simp * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4172009Simp *
5172009Simp * This code is free software; you can redistribute it and/or modify it
6172009Simp * under the terms of the GNU General Public License version 2 only, as
7172009Simp * published by the Free Software Foundation.  Oracle designates this
8172009Simp * particular file as subject to the "Classpath" exception as provided
9172009Simp * by Oracle in the LICENSE file that accompanied this code.
10172009Simp *
11172009Simp * This code is distributed in the hope that it will be useful, but WITHOUT
12172009Simp * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13172009Simp * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14172009Simp * version 2 for more details (a copy is included in the LICENSE file that
15172009Simp * accompanied this code).
16172009Simp *
17172009Simp * You should have received a copy of the GNU General Public License version
18172009Simp * 2 along with this work; if not, write to the Free Software Foundation,
19172009Simp * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20172009Simp *
21172009Simp * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22172009Simp * or visit www.oracle.com if you need additional information or have any
23172009Simp * questions.
24172009Simp */
25172009Simp
26172009Simppackage com.sun.tools.javac.jvm;
27172009Simp
28172009Simpimport java.io.*;
29172009Simpimport java.net.URI;
30172009Simpimport java.net.URISyntaxException;
31172009Simpimport java.nio.CharBuffer;
32172009Simpimport java.util.Arrays;
33172009Simpimport java.util.EnumSet;
34172009Simpimport java.util.HashMap;
35247915Sgavinimport java.util.HashSet;
36172009Simpimport java.util.Map;
37172009Simpimport java.util.Set;
38172009Simpimport javax.tools.JavaFileObject;
39172009Simpimport javax.tools.JavaFileManager;
40172009Simp
41172009Simpimport com.sun.tools.javac.comp.Annotate;
42172068Sbruefferimport com.sun.tools.javac.code.*;
43172068Sbruefferimport com.sun.tools.javac.code.Lint.LintCategory;
44172068Sbruefferimport com.sun.tools.javac.code.Type.*;
45172068Sbruefferimport com.sun.tools.javac.code.Scope.WriteableScope;
46172068Sbruefferimport com.sun.tools.javac.code.Symbol.*;
47172068Sbruefferimport com.sun.tools.javac.code.Symtab;
48172068Sbruefferimport com.sun.tools.javac.file.BaseFileObject;
49172068Sbruefferimport com.sun.tools.javac.util.*;
50172068Sbruefferimport com.sun.tools.javac.util.DefinedBy.Api;
51172068Sbruefferimport com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
52172068Sbrueffer
53172068Sbruefferimport static com.sun.tools.javac.code.Flags.*;
54172068Sbruefferimport static com.sun.tools.javac.code.Kinds.Kind.*;
55172068Sbruefferimport static com.sun.tools.javac.code.TypeTag.CLASS;
56172068Sbruefferimport static com.sun.tools.javac.code.TypeTag.TYPEVAR;
57172068Sbruefferimport static com.sun.tools.javac.jvm.ClassFile.*;
58172068Sbruefferimport static com.sun.tools.javac.jvm.ClassFile.Version.*;
59172068Sbrueffer
60172068Sbruefferimport static com.sun.tools.javac.main.Option.*;
61172009Simp
62172009Simp/** This class provides operations to read a classfile into an internal
63172009Simp *  representation. The internal representation is anchored in a
64172009Simp *  ClassSymbol which contains in its scope symbol representations
65172009Simp *  for all other definitions in the classfile. Top-level Classes themselves
66172009Simp *  appear as members of the scopes of PackageSymbols.
67172009Simp *
68178354Ssam *  <p><b>This is NOT part of any supported API.
69180419Sweongyo *  If you write code that depends on this, you do so at your own risk.
70178354Ssam *  This code and its internal interfaces are subject to change or
71178354Ssam *  deletion without notice.</b>
72178354Ssam */
73178354Ssampublic class ClassReader {
74178354Ssam    /** The context key for the class reader. */
75178354Ssam    protected static final Context.Key<ClassReader> classReaderKey = new Context.Key<>();
76172009Simp
77172009Simp    public static final int INITIAL_BUFFER_SIZE = 0x0fff0;
78172009Simp
79172009Simp    Annotate annotate;
80172009Simp
81172009Simp    /** Switch: verbose output.
82172009Simp     */
83172009Simp    boolean verbose;
84172009Simp
85172009Simp    /** Switch: check class file for correct minor version, unrecognized
86172009Simp     *  attributes.
87184523Sbrueffer     */
88172009Simp    boolean checkClassFile;
89172009Simp
90172009Simp    /** Switch: read constant pool and code sections. This switch is initially
91172009Simp     *  set to false but can be turned on from outside.
92172009Simp     */
93172009Simp    public boolean readAllOfClassFile = false;
94172009Simp
95172009Simp    /** Switch: allow simplified varargs.
96172009Simp     */
97172009Simp    boolean allowSimplifiedVarargs;
98172009Simp
99172009Simp   /** Lint option: warn about classfile issues
100172009Simp     */
101184523Sbrueffer    boolean lintClassfile;
102172009Simp
103172009Simp    /** Switch: preserve parameter names from the variable table.
104172009Simp     */
105172009Simp    public boolean saveParameterNames;
106172009Simp
107172009Simp    /**
108172009Simp     * The currently selected profile.
109172009Simp     */
110172009Simp    public final Profile profile;
111172009Simp
112172009Simp    /** The log to use for verbose output
113172009Simp     */
114172009Simp    final Log log;
115172009Simp
116197724Sweongyo    /** The symbol table. */
117172009Simp    Symtab syms;
118172009Simp
119172009Simp    Types types;
120172009Simp
121172009Simp    /** The name table. */
122172009Simp    final Names names;
123172009Simp
124247915Sgavin    /** Access to files
125172009Simp     */
126172009Simp    private final JavaFileManager fileManager;
127172009Simp
128172009Simp    /** Factory for diagnostics
129184523Sbrueffer     */
130172009Simp    JCDiagnostic.Factory diagFactory;
131172009Simp
132172009Simp    /** The current scope where type variables are entered.
133178354Ssam     */
134178354Ssam    protected WriteableScope typevars;
135178354Ssam
136172009Simp    /** The path name of the class file currently being read.
137172009Simp     */
138172009Simp    protected JavaFileObject currentClassFile = null;
139172009Simp
140172009Simp    /** The class or method currently being read.
141178354Ssam     */
142178354Ssam    protected Symbol currentOwner = null;
143172009Simp
144172009Simp    /** The buffer containing the currently read class file.
145172009Simp     */
146172009Simp    byte[] buf = new byte[INITIAL_BUFFER_SIZE];
147172009Simp
148172009Simp    /** The current input pointer.
149172009Simp     */
150172009Simp    protected int bp;
151172009Simp
152172009Simp    /** The objects of the constant pool.
153172009Simp     */
154172009Simp    Object[] poolObj;
155172009Simp
156172009Simp    /** For every constant pool entry, an index into buf where the
157172009Simp     *  defining section of the entry is found.
158172009Simp     */
159172009Simp    int[] poolIdx;
160172009Simp
161172009Simp    /** The major version number of the class file being read. */
162172009Simp    int majorVersion;
163172009Simp    /** The minor version number of the class file being read. */
164172009Simp    int minorVersion;
165172009Simp
166172009Simp    /** A table to hold the constant pool indices for method parameter
167172009Simp     * names, as given in LocalVariableTable attributes.
168178354Ssam     */
169178354Ssam    int[] parameterNameIndices;
170178354Ssam
171178354Ssam    /**
172184523Sbrueffer     * Whether or not any parameter names have been found.
173172009Simp     */
174172009Simp    boolean haveParameterNameIndices;
175178354Ssam
176172009Simp    /** Set this to false every time we start reading a method
177172009Simp     * and are saving parameter names.  Set it to true when we see
178172009Simp     * MethodParameters, if it's set when we see a LocalVariableTable,
179172009Simp     * then we ignore the parameter names from the LVT.
180172009Simp     */
181172009Simp    boolean sawMethodParameters;
182172009Simp
183172009Simp    /**
184172009Simp     * The set of attribute names for which warnings have been generated for the current class
185172009Simp     */
186172009Simp    Set<Name> warnedAttrs = new HashSet<>();
187172009Simp
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 == 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                proxies.append(proxy);
1303            }
1304            annotate.normal(new AnnotationCompleter(sym, proxies.toList()));
1305        }
1306    }
1307
1308    /** Attach parameter annotations.
1309     */
1310    void attachParameterAnnotations(final Symbol method) {
1311        final MethodSymbol meth = (MethodSymbol)method;
1312        int numParameters = buf[bp++] & 0xFF;
1313        List<VarSymbol> parameters = meth.params();
1314        int pnum = 0;
1315        while (parameters.tail != null) {
1316            attachAnnotations(parameters.head);
1317            parameters = parameters.tail;
1318            pnum++;
1319        }
1320        if (pnum != numParameters) {
1321            throw badClassFile("bad.runtime.invisible.param.annotations", meth);
1322        }
1323    }
1324
1325    void attachTypeAnnotations(final Symbol sym) {
1326        int numAttributes = nextChar();
1327        if (numAttributes != 0) {
1328            ListBuffer<TypeAnnotationProxy> proxies = new ListBuffer<>();
1329            for (int i = 0; i < numAttributes; i++)
1330                proxies.append(readTypeAnnotation());
1331            annotate.normal(new TypeAnnotationCompleter(sym, proxies.toList()));
1332        }
1333    }
1334
1335    /** Attach the default value for an annotation element.
1336     */
1337    void attachAnnotationDefault(final Symbol sym) {
1338        final MethodSymbol meth = (MethodSymbol)sym; // only on methods
1339        final Attribute value = readAttributeValue();
1340
1341        // The default value is set later during annotation. It might
1342        // be the case that the Symbol sym is annotated _after_ the
1343        // repeating instances that depend on this default value,
1344        // because of this we set an interim value that tells us this
1345        // element (most likely) has a default.
1346        //
1347        // Set interim value for now, reset just before we do this
1348        // properly at annotate time.
1349        meth.defaultValue = value;
1350        annotate.normal(new AnnotationDefaultCompleter(meth, value));
1351    }
1352
1353    Type readTypeOrClassSymbol(int i) {
1354        // support preliminary jsr175-format class files
1355        if (buf[poolIdx[i]] == CONSTANT_Class)
1356            return readClassSymbol(i).type;
1357        return readType(i);
1358    }
1359    Type readEnumType(int i) {
1360        // support preliminary jsr175-format class files
1361        int index = poolIdx[i];
1362        int length = getChar(index + 1);
1363        if (buf[index + length + 2] != ';')
1364            return syms.enterClass(readName(i)).type;
1365        return readType(i);
1366    }
1367
1368    CompoundAnnotationProxy readCompoundAnnotation() {
1369        Type t = readTypeOrClassSymbol(nextChar());
1370        int numFields = nextChar();
1371        ListBuffer<Pair<Name,Attribute>> pairs = new ListBuffer<>();
1372        for (int i=0; i<numFields; i++) {
1373            Name name = readName(nextChar());
1374            Attribute value = readAttributeValue();
1375            pairs.append(new Pair<>(name, value));
1376        }
1377        return new CompoundAnnotationProxy(t, pairs.toList());
1378    }
1379
1380    TypeAnnotationProxy readTypeAnnotation() {
1381        TypeAnnotationPosition position = readPosition();
1382        CompoundAnnotationProxy proxy = readCompoundAnnotation();
1383
1384        return new TypeAnnotationProxy(proxy, position);
1385    }
1386
1387    TypeAnnotationPosition readPosition() {
1388        int tag = nextByte(); // TargetType tag is a byte
1389
1390        if (!TargetType.isValidTargetTypeValue(tag))
1391            throw badClassFile("bad.type.annotation.value", String.format("0x%02X", tag));
1392
1393        TargetType type = TargetType.fromTargetTypeValue(tag);
1394
1395        switch (type) {
1396        // instanceof
1397        case INSTANCEOF: {
1398            final int offset = nextChar();
1399            final TypeAnnotationPosition position =
1400                TypeAnnotationPosition.instanceOf(readTypePath());
1401            position.offset = offset;
1402            return position;
1403        }
1404        // new expression
1405        case NEW: {
1406            final int offset = nextChar();
1407            final TypeAnnotationPosition position =
1408                TypeAnnotationPosition.newObj(readTypePath());
1409            position.offset = offset;
1410            return position;
1411        }
1412        // constructor/method reference receiver
1413        case CONSTRUCTOR_REFERENCE: {
1414            final int offset = nextChar();
1415            final TypeAnnotationPosition position =
1416                TypeAnnotationPosition.constructorRef(readTypePath());
1417            position.offset = offset;
1418            return position;
1419        }
1420        case METHOD_REFERENCE: {
1421            final int offset = nextChar();
1422            final TypeAnnotationPosition position =
1423                TypeAnnotationPosition.methodRef(readTypePath());
1424            position.offset = offset;
1425            return position;
1426        }
1427        // local variable
1428        case LOCAL_VARIABLE: {
1429            final int table_length = nextChar();
1430            final int[] newLvarOffset = new int[table_length];
1431            final int[] newLvarLength = new int[table_length];
1432            final int[] newLvarIndex = new int[table_length];
1433
1434            for (int i = 0; i < table_length; ++i) {
1435                newLvarOffset[i] = nextChar();
1436                newLvarLength[i] = nextChar();
1437                newLvarIndex[i] = nextChar();
1438            }
1439
1440            final TypeAnnotationPosition position =
1441                    TypeAnnotationPosition.localVariable(readTypePath());
1442            position.lvarOffset = newLvarOffset;
1443            position.lvarLength = newLvarLength;
1444            position.lvarIndex = newLvarIndex;
1445            return position;
1446        }
1447        // resource variable
1448        case RESOURCE_VARIABLE: {
1449            final int table_length = nextChar();
1450            final int[] newLvarOffset = new int[table_length];
1451            final int[] newLvarLength = new int[table_length];
1452            final int[] newLvarIndex = new int[table_length];
1453
1454            for (int i = 0; i < table_length; ++i) {
1455                newLvarOffset[i] = nextChar();
1456                newLvarLength[i] = nextChar();
1457                newLvarIndex[i] = nextChar();
1458            }
1459
1460            final TypeAnnotationPosition position =
1461                    TypeAnnotationPosition.resourceVariable(readTypePath());
1462            position.lvarOffset = newLvarOffset;
1463            position.lvarLength = newLvarLength;
1464            position.lvarIndex = newLvarIndex;
1465            return position;
1466        }
1467        // exception parameter
1468        case EXCEPTION_PARAMETER: {
1469            final int exception_index = nextChar();
1470            final TypeAnnotationPosition position =
1471                TypeAnnotationPosition.exceptionParameter(readTypePath());
1472            position.setExceptionIndex(exception_index);
1473            return position;
1474        }
1475        // method receiver
1476        case METHOD_RECEIVER:
1477            return TypeAnnotationPosition.methodReceiver(readTypePath());
1478        // type parameter
1479        case CLASS_TYPE_PARAMETER: {
1480            final int parameter_index = nextByte();
1481            return TypeAnnotationPosition
1482                .typeParameter(readTypePath(), parameter_index);
1483        }
1484        case METHOD_TYPE_PARAMETER: {
1485            final int parameter_index = nextByte();
1486            return TypeAnnotationPosition
1487                .methodTypeParameter(readTypePath(), parameter_index);
1488        }
1489        // type parameter bound
1490        case CLASS_TYPE_PARAMETER_BOUND: {
1491            final int parameter_index = nextByte();
1492            final int bound_index = nextByte();
1493            return TypeAnnotationPosition
1494                .typeParameterBound(readTypePath(), parameter_index,
1495                                    bound_index);
1496        }
1497        case METHOD_TYPE_PARAMETER_BOUND: {
1498            final int parameter_index = nextByte();
1499            final int bound_index = nextByte();
1500            return TypeAnnotationPosition
1501                .methodTypeParameterBound(readTypePath(), parameter_index,
1502                                          bound_index);
1503        }
1504        // class extends or implements clause
1505        case CLASS_EXTENDS: {
1506            final int type_index = nextChar();
1507            return TypeAnnotationPosition.classExtends(readTypePath(),
1508                                                       type_index);
1509        }
1510        // throws
1511        case THROWS: {
1512            final int type_index = nextChar();
1513            return TypeAnnotationPosition.methodThrows(readTypePath(),
1514                                                       type_index);
1515        }
1516        // method parameter
1517        case METHOD_FORMAL_PARAMETER: {
1518            final int parameter_index = nextByte();
1519            return TypeAnnotationPosition.methodParameter(readTypePath(),
1520                                                          parameter_index);
1521        }
1522        // type cast
1523        case CAST: {
1524            final int offset = nextChar();
1525            final int type_index = nextByte();
1526            final TypeAnnotationPosition position =
1527                TypeAnnotationPosition.typeCast(readTypePath(), type_index);
1528            position.offset = offset;
1529            return position;
1530        }
1531        // method/constructor/reference type argument
1532        case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: {
1533            final int offset = nextChar();
1534            final int type_index = nextByte();
1535            final TypeAnnotationPosition position = TypeAnnotationPosition
1536                .constructorInvocationTypeArg(readTypePath(), type_index);
1537            position.offset = offset;
1538            return position;
1539        }
1540        case METHOD_INVOCATION_TYPE_ARGUMENT: {
1541            final int offset = nextChar();
1542            final int type_index = nextByte();
1543            final TypeAnnotationPosition position = TypeAnnotationPosition
1544                .methodInvocationTypeArg(readTypePath(), type_index);
1545            position.offset = offset;
1546            return position;
1547        }
1548        case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: {
1549            final int offset = nextChar();
1550            final int type_index = nextByte();
1551            final TypeAnnotationPosition position = TypeAnnotationPosition
1552                .constructorRefTypeArg(readTypePath(), type_index);
1553            position.offset = offset;
1554            return position;
1555        }
1556        case METHOD_REFERENCE_TYPE_ARGUMENT: {
1557            final int offset = nextChar();
1558            final int type_index = nextByte();
1559            final TypeAnnotationPosition position = TypeAnnotationPosition
1560                .methodRefTypeArg(readTypePath(), type_index);
1561            position.offset = offset;
1562            return position;
1563        }
1564        // We don't need to worry about these
1565        case METHOD_RETURN:
1566            return TypeAnnotationPosition.methodReturn(readTypePath());
1567        case FIELD:
1568            return TypeAnnotationPosition.field(readTypePath());
1569        case UNKNOWN:
1570            throw new AssertionError("jvm.ClassReader: UNKNOWN target type should never occur!");
1571        default:
1572            throw new AssertionError("jvm.ClassReader: Unknown target type for position: " + type);
1573        }
1574    }
1575
1576    List<TypeAnnotationPosition.TypePathEntry> readTypePath() {
1577        int len = nextByte();
1578        ListBuffer<Integer> loc = new ListBuffer<>();
1579        for (int i = 0; i < len * TypeAnnotationPosition.TypePathEntry.bytesPerEntry; ++i)
1580            loc = loc.append(nextByte());
1581
1582        return TypeAnnotationPosition.getTypePathFromBinary(loc.toList());
1583
1584    }
1585
1586    Attribute readAttributeValue() {
1587        char c = (char) buf[bp++];
1588        switch (c) {
1589        case 'B':
1590            return new Attribute.Constant(syms.byteType, readPool(nextChar()));
1591        case 'C':
1592            return new Attribute.Constant(syms.charType, readPool(nextChar()));
1593        case 'D':
1594            return new Attribute.Constant(syms.doubleType, readPool(nextChar()));
1595        case 'F':
1596            return new Attribute.Constant(syms.floatType, readPool(nextChar()));
1597        case 'I':
1598            return new Attribute.Constant(syms.intType, readPool(nextChar()));
1599        case 'J':
1600            return new Attribute.Constant(syms.longType, readPool(nextChar()));
1601        case 'S':
1602            return new Attribute.Constant(syms.shortType, readPool(nextChar()));
1603        case 'Z':
1604            return new Attribute.Constant(syms.booleanType, readPool(nextChar()));
1605        case 's':
1606            return new Attribute.Constant(syms.stringType, readPool(nextChar()).toString());
1607        case 'e':
1608            return new EnumAttributeProxy(readEnumType(nextChar()), readName(nextChar()));
1609        case 'c':
1610            return new Attribute.Class(types, readTypeOrClassSymbol(nextChar()));
1611        case '[': {
1612            int n = nextChar();
1613            ListBuffer<Attribute> l = new ListBuffer<>();
1614            for (int i=0; i<n; i++)
1615                l.append(readAttributeValue());
1616            return new ArrayAttributeProxy(l.toList());
1617        }
1618        case '@':
1619            return readCompoundAnnotation();
1620        default:
1621            throw new AssertionError("unknown annotation tag '" + c + "'");
1622        }
1623    }
1624
1625    interface ProxyVisitor extends Attribute.Visitor {
1626        void visitEnumAttributeProxy(EnumAttributeProxy proxy);
1627        void visitArrayAttributeProxy(ArrayAttributeProxy proxy);
1628        void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy);
1629    }
1630
1631    static class EnumAttributeProxy extends Attribute {
1632        Type enumType;
1633        Name enumerator;
1634        public EnumAttributeProxy(Type enumType, Name enumerator) {
1635            super(null);
1636            this.enumType = enumType;
1637            this.enumerator = enumerator;
1638        }
1639        public void accept(Visitor v) { ((ProxyVisitor)v).visitEnumAttributeProxy(this); }
1640        @Override @DefinedBy(Api.LANGUAGE_MODEL)
1641        public String toString() {
1642            return "/*proxy enum*/" + enumType + "." + enumerator;
1643        }
1644    }
1645
1646    static class ArrayAttributeProxy extends Attribute {
1647        List<Attribute> values;
1648        ArrayAttributeProxy(List<Attribute> values) {
1649            super(null);
1650            this.values = values;
1651        }
1652        public void accept(Visitor v) { ((ProxyVisitor)v).visitArrayAttributeProxy(this); }
1653        @Override @DefinedBy(Api.LANGUAGE_MODEL)
1654        public String toString() {
1655            return "{" + values + "}";
1656        }
1657    }
1658
1659    /** A temporary proxy representing a compound attribute.
1660     */
1661    static class CompoundAnnotationProxy extends Attribute {
1662        final List<Pair<Name,Attribute>> values;
1663        public CompoundAnnotationProxy(Type type,
1664                                      List<Pair<Name,Attribute>> values) {
1665            super(type);
1666            this.values = values;
1667        }
1668        public void accept(Visitor v) { ((ProxyVisitor)v).visitCompoundAnnotationProxy(this); }
1669        @Override @DefinedBy(Api.LANGUAGE_MODEL)
1670        public String toString() {
1671            StringBuilder buf = new StringBuilder();
1672            buf.append("@");
1673            buf.append(type.tsym.getQualifiedName());
1674            buf.append("/*proxy*/{");
1675            boolean first = true;
1676            for (List<Pair<Name,Attribute>> v = values;
1677                 v.nonEmpty(); v = v.tail) {
1678                Pair<Name,Attribute> value = v.head;
1679                if (!first) buf.append(",");
1680                first = false;
1681                buf.append(value.fst);
1682                buf.append("=");
1683                buf.append(value.snd);
1684            }
1685            buf.append("}");
1686            return buf.toString();
1687        }
1688    }
1689
1690    /** A temporary proxy representing a type annotation.
1691     */
1692    static class TypeAnnotationProxy {
1693        final CompoundAnnotationProxy compound;
1694        final TypeAnnotationPosition position;
1695        public TypeAnnotationProxy(CompoundAnnotationProxy compound,
1696                TypeAnnotationPosition position) {
1697            this.compound = compound;
1698            this.position = position;
1699        }
1700    }
1701
1702    class AnnotationDeproxy implements ProxyVisitor {
1703        private ClassSymbol requestingOwner = currentOwner.kind == MTH
1704            ? currentOwner.enclClass() : (ClassSymbol)currentOwner;
1705
1706        List<Attribute.Compound> deproxyCompoundList(List<CompoundAnnotationProxy> pl) {
1707            // also must fill in types!!!!
1708            ListBuffer<Attribute.Compound> buf = new ListBuffer<>();
1709            for (List<CompoundAnnotationProxy> l = pl; l.nonEmpty(); l=l.tail) {
1710                buf.append(deproxyCompound(l.head));
1711            }
1712            return buf.toList();
1713        }
1714
1715        Attribute.Compound deproxyCompound(CompoundAnnotationProxy a) {
1716            ListBuffer<Pair<Symbol.MethodSymbol,Attribute>> buf = new ListBuffer<>();
1717            for (List<Pair<Name,Attribute>> l = a.values;
1718                 l.nonEmpty();
1719                 l = l.tail) {
1720                MethodSymbol meth = findAccessMethod(a.type, l.head.fst);
1721                buf.append(new Pair<>(meth, deproxy(meth.type.getReturnType(), l.head.snd)));
1722            }
1723            return new Attribute.Compound(a.type, buf.toList());
1724        }
1725
1726        MethodSymbol findAccessMethod(Type container, Name name) {
1727            CompletionFailure failure = null;
1728            try {
1729                for (Symbol sym : container.tsym.members().getSymbolsByName(name)) {
1730                    if (sym.kind == MTH && sym.type.getParameterTypes().length() == 0)
1731                        return (MethodSymbol) sym;
1732                }
1733            } catch (CompletionFailure ex) {
1734                failure = ex;
1735            }
1736            // The method wasn't found: emit a warning and recover
1737            JavaFileObject prevSource = log.useSource(requestingOwner.classfile);
1738            try {
1739                if (failure == null) {
1740                    log.warning("annotation.method.not.found",
1741                                container,
1742                                name);
1743                } else {
1744                    log.warning("annotation.method.not.found.reason",
1745                                container,
1746                                name,
1747                                failure.getDetailValue());//diagnostic, if present
1748                }
1749            } finally {
1750                log.useSource(prevSource);
1751            }
1752            // Construct a new method type and symbol.  Use bottom
1753            // type (typeof null) as return type because this type is
1754            // a subtype of all reference types and can be converted
1755            // to primitive types by unboxing.
1756            MethodType mt = new MethodType(List.<Type>nil(),
1757                                           syms.botType,
1758                                           List.<Type>nil(),
1759                                           syms.methodClass);
1760            return new MethodSymbol(PUBLIC | ABSTRACT, name, mt, container.tsym);
1761        }
1762
1763        Attribute result;
1764        Type type;
1765        Attribute deproxy(Type t, Attribute a) {
1766            Type oldType = type;
1767            try {
1768                type = t;
1769                a.accept(this);
1770                return result;
1771            } finally {
1772                type = oldType;
1773            }
1774        }
1775
1776        // implement Attribute.Visitor below
1777
1778        public void visitConstant(Attribute.Constant value) {
1779            // assert value.type == type;
1780            result = value;
1781        }
1782
1783        public void visitClass(Attribute.Class clazz) {
1784            result = clazz;
1785        }
1786
1787        public void visitEnum(Attribute.Enum e) {
1788            throw new AssertionError(); // shouldn't happen
1789        }
1790
1791        public void visitCompound(Attribute.Compound compound) {
1792            throw new AssertionError(); // shouldn't happen
1793        }
1794
1795        public void visitArray(Attribute.Array array) {
1796            throw new AssertionError(); // shouldn't happen
1797        }
1798
1799        public void visitError(Attribute.Error e) {
1800            throw new AssertionError(); // shouldn't happen
1801        }
1802
1803        public void visitEnumAttributeProxy(EnumAttributeProxy proxy) {
1804            // type.tsym.flatName() should == proxy.enumFlatName
1805            TypeSymbol enumTypeSym = proxy.enumType.tsym;
1806            VarSymbol enumerator = null;
1807            CompletionFailure failure = null;
1808            try {
1809                for (Symbol sym : enumTypeSym.members().getSymbolsByName(proxy.enumerator)) {
1810                    if (sym.kind == VAR) {
1811                        enumerator = (VarSymbol)sym;
1812                        break;
1813                    }
1814                }
1815            }
1816            catch (CompletionFailure ex) {
1817                failure = ex;
1818            }
1819            if (enumerator == null) {
1820                if (failure != null) {
1821                    log.warning("unknown.enum.constant.reason",
1822                              currentClassFile, enumTypeSym, proxy.enumerator,
1823                              failure.getDiagnostic());
1824                } else {
1825                    log.warning("unknown.enum.constant",
1826                              currentClassFile, enumTypeSym, proxy.enumerator);
1827                }
1828                result = new Attribute.Enum(enumTypeSym.type,
1829                        new VarSymbol(0, proxy.enumerator, syms.botType, enumTypeSym));
1830            } else {
1831                result = new Attribute.Enum(enumTypeSym.type, enumerator);
1832            }
1833        }
1834
1835        public void visitArrayAttributeProxy(ArrayAttributeProxy proxy) {
1836            int length = proxy.values.length();
1837            Attribute[] ats = new Attribute[length];
1838            Type elemtype = types.elemtype(type);
1839            int i = 0;
1840            for (List<Attribute> p = proxy.values; p.nonEmpty(); p = p.tail) {
1841                ats[i++] = deproxy(elemtype, p.head);
1842            }
1843            result = new Attribute.Array(type, ats);
1844        }
1845
1846        public void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy) {
1847            result = deproxyCompound(proxy);
1848        }
1849    }
1850
1851    class AnnotationDefaultCompleter extends AnnotationDeproxy implements Annotate.Worker {
1852        final MethodSymbol sym;
1853        final Attribute value;
1854        final JavaFileObject classFile = currentClassFile;
1855        @Override
1856        public String toString() {
1857            return " ClassReader store default for " + sym.owner + "." + sym + " is " + value;
1858        }
1859        AnnotationDefaultCompleter(MethodSymbol sym, Attribute value) {
1860            this.sym = sym;
1861            this.value = value;
1862        }
1863        // implement Annotate.Worker.run()
1864        public void run() {
1865            JavaFileObject previousClassFile = currentClassFile;
1866            try {
1867                // Reset the interim value set earlier in
1868                // attachAnnotationDefault().
1869                sym.defaultValue = null;
1870                currentClassFile = classFile;
1871                sym.defaultValue = deproxy(sym.type.getReturnType(), value);
1872            } finally {
1873                currentClassFile = previousClassFile;
1874            }
1875        }
1876    }
1877
1878    class AnnotationCompleter extends AnnotationDeproxy implements Annotate.Worker {
1879        final Symbol sym;
1880        final List<CompoundAnnotationProxy> l;
1881        final JavaFileObject classFile;
1882        @Override
1883        public String toString() {
1884            return " ClassReader annotate " + sym.owner + "." + sym + " with " + l;
1885        }
1886        AnnotationCompleter(Symbol sym, List<CompoundAnnotationProxy> l) {
1887            this.sym = sym;
1888            this.l = l;
1889            this.classFile = currentClassFile;
1890        }
1891        // implement Annotate.Worker.run()
1892        public void run() {
1893            JavaFileObject previousClassFile = currentClassFile;
1894            try {
1895                currentClassFile = classFile;
1896                List<Attribute.Compound> newList = deproxyCompoundList(l);
1897                if (sym.annotationsPendingCompletion()) {
1898                    sym.setDeclarationAttributes(newList);
1899                } else {
1900                    sym.appendAttributes(newList);
1901                }
1902            } finally {
1903                currentClassFile = previousClassFile;
1904            }
1905        }
1906    }
1907
1908    class TypeAnnotationCompleter extends AnnotationCompleter {
1909
1910        List<TypeAnnotationProxy> proxies;
1911
1912        TypeAnnotationCompleter(Symbol sym,
1913                List<TypeAnnotationProxy> proxies) {
1914            super(sym, List.<CompoundAnnotationProxy>nil());
1915            this.proxies = proxies;
1916        }
1917
1918        List<Attribute.TypeCompound> deproxyTypeCompoundList(List<TypeAnnotationProxy> proxies) {
1919            ListBuffer<Attribute.TypeCompound> buf = new ListBuffer<>();
1920            for (TypeAnnotationProxy proxy: proxies) {
1921                Attribute.Compound compound = deproxyCompound(proxy.compound);
1922                Attribute.TypeCompound typeCompound = new Attribute.TypeCompound(compound, proxy.position);
1923                buf.add(typeCompound);
1924            }
1925            return buf.toList();
1926        }
1927
1928        @Override
1929        public void run() {
1930            JavaFileObject previousClassFile = currentClassFile;
1931            try {
1932                currentClassFile = classFile;
1933                List<Attribute.TypeCompound> newList = deproxyTypeCompoundList(proxies);
1934                sym.setTypeAttributes(newList.prependList(sym.getRawTypeAttributes()));
1935            } finally {
1936                currentClassFile = previousClassFile;
1937            }
1938        }
1939    }
1940
1941
1942/************************************************************************
1943 * Reading Symbols
1944 ***********************************************************************/
1945
1946    /** Read a field.
1947     */
1948    VarSymbol readField() {
1949        long flags = adjustFieldFlags(nextChar());
1950        Name name = readName(nextChar());
1951        Type type = readType(nextChar());
1952        VarSymbol v = new VarSymbol(flags, name, type, currentOwner);
1953        readMemberAttrs(v);
1954        return v;
1955    }
1956
1957    /** Read a method.
1958     */
1959    MethodSymbol readMethod() {
1960        long flags = adjustMethodFlags(nextChar());
1961        Name name = readName(nextChar());
1962        Type type = readType(nextChar());
1963        if (currentOwner.isInterface() &&
1964                (flags & ABSTRACT) == 0 && !name.equals(names.clinit)) {
1965            if (majorVersion > Version.V52.major ||
1966                    (majorVersion == Version.V52.major && minorVersion >= Version.V52.minor)) {
1967                if ((flags & STATIC) == 0) {
1968                    currentOwner.flags_field |= DEFAULT;
1969                    flags |= DEFAULT | ABSTRACT;
1970                }
1971            } else {
1972                //protect against ill-formed classfiles
1973                throw badClassFile((flags & STATIC) == 0 ? "invalid.default.interface" : "invalid.static.interface",
1974                                   Integer.toString(majorVersion),
1975                                   Integer.toString(minorVersion));
1976            }
1977        }
1978        if (name == names.init && currentOwner.hasOuterInstance()) {
1979            // Sometimes anonymous classes don't have an outer
1980            // instance, however, there is no reliable way to tell so
1981            // we never strip this$n
1982            if (!currentOwner.name.isEmpty())
1983                type = new MethodType(adjustMethodParams(flags, type.getParameterTypes()),
1984                                      type.getReturnType(),
1985                                      type.getThrownTypes(),
1986                                      syms.methodClass);
1987        }
1988        MethodSymbol m = new MethodSymbol(flags, name, type, currentOwner);
1989        if (types.isSignaturePolymorphic(m)) {
1990            m.flags_field |= SIGNATURE_POLYMORPHIC;
1991        }
1992        if (saveParameterNames)
1993            initParameterNames(m);
1994        Symbol prevOwner = currentOwner;
1995        currentOwner = m;
1996        try {
1997            readMemberAttrs(m);
1998        } finally {
1999            currentOwner = prevOwner;
2000        }
2001        if (saveParameterNames)
2002            setParameterNames(m, type);
2003        return m;
2004    }
2005
2006    private List<Type> adjustMethodParams(long flags, List<Type> args) {
2007        boolean isVarargs = (flags & VARARGS) != 0;
2008        if (isVarargs) {
2009            Type varargsElem = args.last();
2010            ListBuffer<Type> adjustedArgs = new ListBuffer<>();
2011            for (Type t : args) {
2012                adjustedArgs.append(t != varargsElem ?
2013                    t :
2014                    ((ArrayType)t).makeVarargs());
2015            }
2016            args = adjustedArgs.toList();
2017        }
2018        return args.tail;
2019    }
2020
2021    /**
2022     * Init the parameter names array.
2023     * Parameter names are currently inferred from the names in the
2024     * LocalVariableTable attributes of a Code attribute.
2025     * (Note: this means parameter names are currently not available for
2026     * methods without a Code attribute.)
2027     * This method initializes an array in which to store the name indexes
2028     * of parameter names found in LocalVariableTable attributes. It is
2029     * slightly supersized to allow for additional slots with a start_pc of 0.
2030     */
2031    void initParameterNames(MethodSymbol sym) {
2032        // make allowance for synthetic parameters.
2033        final int excessSlots = 4;
2034        int expectedParameterSlots =
2035                Code.width(sym.type.getParameterTypes()) + excessSlots;
2036        if (parameterNameIndices == null
2037                || parameterNameIndices.length < expectedParameterSlots) {
2038            parameterNameIndices = new int[expectedParameterSlots];
2039        } else
2040            Arrays.fill(parameterNameIndices, 0);
2041        haveParameterNameIndices = false;
2042        sawMethodParameters = false;
2043    }
2044
2045    /**
2046     * Set the parameter names for a symbol from the name index in the
2047     * parameterNameIndicies array. The type of the symbol may have changed
2048     * while reading the method attributes (see the Signature attribute).
2049     * This may be because of generic information or because anonymous
2050     * synthetic parameters were added.   The original type (as read from
2051     * the method descriptor) is used to help guess the existence of
2052     * anonymous synthetic parameters.
2053     * On completion, sym.savedParameter names will either be null (if
2054     * no parameter names were found in the class file) or will be set to a
2055     * list of names, one per entry in sym.type.getParameterTypes, with
2056     * any missing names represented by the empty name.
2057     */
2058    void setParameterNames(MethodSymbol sym, Type jvmType) {
2059        // if no names were found in the class file, there's nothing more to do
2060        if (!haveParameterNameIndices)
2061            return;
2062        // If we get parameter names from MethodParameters, then we
2063        // don't need to skip.
2064        int firstParam = 0;
2065        if (!sawMethodParameters) {
2066            firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0;
2067            // the code in readMethod may have skipped the first
2068            // parameter when setting up the MethodType. If so, we
2069            // make a corresponding allowance here for the position of
2070            // the first parameter.  Note that this assumes the
2071            // skipped parameter has a width of 1 -- i.e. it is not
2072        // a double width type (long or double.)
2073        if (sym.name == names.init && currentOwner.hasOuterInstance()) {
2074            // Sometimes anonymous classes don't have an outer
2075            // instance, however, there is no reliable way to tell so
2076            // we never strip this$n
2077            if (!currentOwner.name.isEmpty())
2078                firstParam += 1;
2079        }
2080
2081        if (sym.type != jvmType) {
2082                // reading the method attributes has caused the
2083                // symbol's type to be changed. (i.e. the Signature
2084                // attribute.)  This may happen if there are hidden
2085                // (synthetic) parameters in the descriptor, but not
2086                // in the Signature.  The position of these hidden
2087                // parameters is unspecified; for now, assume they are
2088                // at the beginning, and so skip over them. The
2089                // primary case for this is two hidden parameters
2090                // passed into Enum constructors.
2091            int skip = Code.width(jvmType.getParameterTypes())
2092                    - Code.width(sym.type.getParameterTypes());
2093            firstParam += skip;
2094        }
2095        }
2096        List<Name> paramNames = List.nil();
2097        int index = firstParam;
2098        for (Type t: sym.type.getParameterTypes()) {
2099            int nameIdx = (index < parameterNameIndices.length
2100                    ? parameterNameIndices[index] : 0);
2101            Name name = nameIdx == 0 ? names.empty : readName(nameIdx);
2102            paramNames = paramNames.prepend(name);
2103            index += Code.width(t);
2104        }
2105        sym.savedParameterNames = paramNames.reverse();
2106    }
2107
2108    /**
2109     * skip n bytes
2110     */
2111    void skipBytes(int n) {
2112        bp = bp + n;
2113    }
2114
2115    /** Skip a field or method
2116     */
2117    void skipMember() {
2118        bp = bp + 6;
2119        char ac = nextChar();
2120        for (int i = 0; i < ac; i++) {
2121            bp = bp + 2;
2122            int attrLen = nextInt();
2123            bp = bp + attrLen;
2124        }
2125    }
2126
2127    /** Enter type variables of this classtype and all enclosing ones in
2128     *  `typevars'.
2129     */
2130    protected void enterTypevars(Type t) {
2131        if (t.getEnclosingType() != null && t.getEnclosingType().hasTag(CLASS))
2132            enterTypevars(t.getEnclosingType());
2133        for (List<Type> xs = t.getTypeArguments(); xs.nonEmpty(); xs = xs.tail)
2134            typevars.enter(xs.head.tsym);
2135    }
2136
2137    protected void enterTypevars(Symbol sym) {
2138        if (sym.owner.kind == MTH) {
2139            enterTypevars(sym.owner);
2140            enterTypevars(sym.owner.owner);
2141        }
2142        enterTypevars(sym.type);
2143    }
2144
2145    /** Read contents of a given class symbol `c'. Both external and internal
2146     *  versions of an inner class are read.
2147     */
2148    void readClass(ClassSymbol c) {
2149        ClassType ct = (ClassType)c.type;
2150
2151        // allocate scope for members
2152        c.members_field = WriteableScope.create(c);
2153
2154        // prepare type variable table
2155        typevars = typevars.dup(currentOwner);
2156        if (ct.getEnclosingType().hasTag(CLASS))
2157            enterTypevars(ct.getEnclosingType());
2158
2159        // read flags, or skip if this is an inner class
2160        long flags = adjustClassFlags(nextChar());
2161        if (c.owner.kind == PCK) c.flags_field = flags;
2162
2163        // read own class name and check that it matches
2164        ClassSymbol self = readClassSymbol(nextChar());
2165        if (c != self)
2166            throw badClassFile("class.file.wrong.class",
2167                               self.flatname);
2168
2169        // class attributes must be read before class
2170        // skip ahead to read class attributes
2171        int startbp = bp;
2172        nextChar();
2173        char interfaceCount = nextChar();
2174        bp += interfaceCount * 2;
2175        char fieldCount = nextChar();
2176        for (int i = 0; i < fieldCount; i++) skipMember();
2177        char methodCount = nextChar();
2178        for (int i = 0; i < methodCount; i++) skipMember();
2179        readClassAttrs(c);
2180
2181        if (readAllOfClassFile) {
2182            for (int i = 1; i < poolObj.length; i++) readPool(i);
2183            c.pool = new Pool(poolObj.length, poolObj, types);
2184        }
2185
2186        // reset and read rest of classinfo
2187        bp = startbp;
2188        int n = nextChar();
2189        if (ct.supertype_field == null)
2190            ct.supertype_field = (n == 0)
2191                ? Type.noType
2192                : readClassSymbol(n).erasure(types);
2193        n = nextChar();
2194        List<Type> is = List.nil();
2195        for (int i = 0; i < n; i++) {
2196            Type _inter = readClassSymbol(nextChar()).erasure(types);
2197            is = is.prepend(_inter);
2198        }
2199        if (ct.interfaces_field == null)
2200            ct.interfaces_field = is.reverse();
2201
2202        Assert.check(fieldCount == nextChar());
2203        for (int i = 0; i < fieldCount; i++) enterMember(c, readField());
2204        Assert.check(methodCount == nextChar());
2205        for (int i = 0; i < methodCount; i++) enterMember(c, readMethod());
2206
2207        typevars = typevars.leave();
2208    }
2209
2210    /** Read inner class info. For each inner/outer pair allocate a
2211     *  member class.
2212     */
2213    void readInnerClasses(ClassSymbol c) {
2214        int n = nextChar();
2215        for (int i = 0; i < n; i++) {
2216            nextChar(); // skip inner class symbol
2217            ClassSymbol outer = readClassSymbol(nextChar());
2218            Name name = readName(nextChar());
2219            if (name == null) name = names.empty;
2220            long flags = adjustClassFlags(nextChar());
2221            if (outer != null) { // we have a member class
2222                if (name == names.empty)
2223                    name = names.one;
2224                ClassSymbol member = syms.enterClass(name, outer);
2225                if ((flags & STATIC) == 0) {
2226                    ((ClassType)member.type).setEnclosingType(outer.type);
2227                    if (member.erasure_field != null)
2228                        ((ClassType)member.erasure_field).setEnclosingType(types.erasure(outer.type));
2229                }
2230                if (c == outer) {
2231                    member.flags_field = flags;
2232                    enterMember(c, member);
2233                }
2234            }
2235        }
2236    }
2237
2238    /** Read a class definition from the bytes in buf.
2239     */
2240    private void readClassBuffer(ClassSymbol c) throws IOException {
2241        int magic = nextInt();
2242        if (magic != JAVA_MAGIC)
2243            throw badClassFile("illegal.start.of.class.file");
2244
2245        minorVersion = nextChar();
2246        majorVersion = nextChar();
2247        int maxMajor = Version.MAX().major;
2248        int maxMinor = Version.MAX().minor;
2249        if (majorVersion > maxMajor ||
2250            majorVersion * 1000 + minorVersion <
2251            Version.MIN().major * 1000 + Version.MIN().minor)
2252        {
2253            if (majorVersion == (maxMajor + 1))
2254                log.warning("big.major.version",
2255                            currentClassFile,
2256                            majorVersion,
2257                            maxMajor);
2258            else
2259                throw badClassFile("wrong.version",
2260                                   Integer.toString(majorVersion),
2261                                   Integer.toString(minorVersion),
2262                                   Integer.toString(maxMajor),
2263                                   Integer.toString(maxMinor));
2264        }
2265        else if (checkClassFile &&
2266                 majorVersion == maxMajor &&
2267                 minorVersion > maxMinor)
2268        {
2269            printCCF("found.later.version",
2270                     Integer.toString(minorVersion));
2271        }
2272        indexPool();
2273        if (signatureBuffer.length < bp) {
2274            int ns = Integer.highestOneBit(bp) << 1;
2275            signatureBuffer = new byte[ns];
2276        }
2277        readClass(c);
2278    }
2279
2280    public void readClassFile(ClassSymbol c) {
2281        currentOwner = c;
2282        currentClassFile = c.classfile;
2283        warnedAttrs.clear();
2284        filling = true;
2285        try {
2286            bp = 0;
2287            buf = readInputStream(buf, c.classfile.openInputStream());
2288            readClassBuffer(c);
2289            if (!missingTypeVariables.isEmpty() && !foundTypeVariables.isEmpty()) {
2290                List<Type> missing = missingTypeVariables;
2291                List<Type> found = foundTypeVariables;
2292                missingTypeVariables = List.nil();
2293                foundTypeVariables = List.nil();
2294                filling = false;
2295                ClassType ct = (ClassType)currentOwner.type;
2296                ct.supertype_field =
2297                    types.subst(ct.supertype_field, missing, found);
2298                ct.interfaces_field =
2299                    types.subst(ct.interfaces_field, missing, found);
2300            } else if (missingTypeVariables.isEmpty() !=
2301                       foundTypeVariables.isEmpty()) {
2302                Name name = missingTypeVariables.head.tsym.name;
2303                throw badClassFile("undecl.type.var", name);
2304            }
2305        } catch (IOException ex) {
2306            throw badClassFile("unable.to.access.file", ex.getMessage());
2307        } catch (ArrayIndexOutOfBoundsException ex) {
2308            throw badClassFile("bad.class.file", c.flatname);
2309        } finally {
2310            missingTypeVariables = List.nil();
2311            foundTypeVariables = List.nil();
2312            filling = false;
2313        }
2314    }
2315    // where
2316        private static byte[] readInputStream(byte[] buf, InputStream s) throws IOException {
2317            try {
2318                buf = ensureCapacity(buf, s.available());
2319                int r = s.read(buf);
2320                int bp = 0;
2321                while (r != -1) {
2322                    bp += r;
2323                    buf = ensureCapacity(buf, bp);
2324                    r = s.read(buf, bp, buf.length - bp);
2325                }
2326                return buf;
2327            } finally {
2328                try {
2329                    s.close();
2330                } catch (IOException e) {
2331                    /* Ignore any errors, as this stream may have already
2332                     * thrown a related exception which is the one that
2333                     * should be reported.
2334                     */
2335                }
2336            }
2337        }
2338        /*
2339         * ensureCapacity will increase the buffer as needed, taking note that
2340         * the new buffer will always be greater than the needed and never
2341         * exactly equal to the needed size or bp. If equal then the read (above)
2342         * will infinitely loop as buf.length - bp == 0.
2343         */
2344        private static byte[] ensureCapacity(byte[] buf, int needed) {
2345            if (buf.length <= needed) {
2346                byte[] old = buf;
2347                buf = new byte[Integer.highestOneBit(needed) << 1];
2348                System.arraycopy(old, 0, buf, 0, old.length);
2349            }
2350            return buf;
2351        }
2352
2353    /** We can only read a single class file at a time; this
2354     *  flag keeps track of when we are currently reading a class
2355     *  file.
2356     */
2357    public boolean filling = false;
2358
2359/************************************************************************
2360 * Adjusting flags
2361 ***********************************************************************/
2362
2363    long adjustFieldFlags(long flags) {
2364        return flags;
2365    }
2366
2367    long adjustMethodFlags(long flags) {
2368        if ((flags & ACC_BRIDGE) != 0) {
2369            flags &= ~ACC_BRIDGE;
2370            flags |= BRIDGE;
2371        }
2372        if ((flags & ACC_VARARGS) != 0) {
2373            flags &= ~ACC_VARARGS;
2374            flags |= VARARGS;
2375        }
2376        return flags;
2377    }
2378
2379    long adjustClassFlags(long flags) {
2380        return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
2381    }
2382
2383    /** Output for "-checkclassfile" option.
2384     *  @param key The key to look up the correct internationalized string.
2385     *  @param arg An argument for substitution into the output string.
2386     */
2387    private void printCCF(String key, Object arg) {
2388        log.printLines(key, arg);
2389    }
2390
2391    /**
2392     * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
2393     * The attribute is only the last component of the original filename, so is unlikely
2394     * to be valid as is, so operations other than those to access the name throw
2395     * UnsupportedOperationException
2396     */
2397    private static class SourceFileObject extends BaseFileObject {
2398
2399        /** The file's name.
2400         */
2401        private Name name;
2402        private Name flatname;
2403
2404        public SourceFileObject(Name name, Name flatname) {
2405            super(null); // no file manager; never referenced for this file object
2406            this.name = name;
2407            this.flatname = flatname;
2408        }
2409
2410        @Override @DefinedBy(Api.COMPILER)
2411        public URI toUri() {
2412            try {
2413                return new URI(null, name.toString(), null);
2414            } catch (URISyntaxException e) {
2415                throw new CannotCreateUriError(name.toString(), e);
2416            }
2417        }
2418
2419        @Override @DefinedBy(Api.COMPILER)
2420        public String getName() {
2421            return name.toString();
2422        }
2423
2424        @Override
2425        public String getShortName() {
2426            return getName();
2427        }
2428
2429        @Override @DefinedBy(Api.COMPILER)
2430        public JavaFileObject.Kind getKind() {
2431            return getKind(getName());
2432        }
2433
2434        @Override @DefinedBy(Api.COMPILER)
2435        public InputStream openInputStream() {
2436            throw new UnsupportedOperationException();
2437        }
2438
2439        @Override @DefinedBy(Api.COMPILER)
2440        public OutputStream openOutputStream() {
2441            throw new UnsupportedOperationException();
2442        }
2443
2444        @Override @DefinedBy(Api.COMPILER)
2445        public CharBuffer getCharContent(boolean ignoreEncodingErrors) {
2446            throw new UnsupportedOperationException();
2447        }
2448
2449        @Override @DefinedBy(Api.COMPILER)
2450        public Reader openReader(boolean ignoreEncodingErrors) {
2451            throw new UnsupportedOperationException();
2452        }
2453
2454        @Override @DefinedBy(Api.COMPILER)
2455        public Writer openWriter() {
2456            throw new UnsupportedOperationException();
2457        }
2458
2459        @Override @DefinedBy(Api.COMPILER)
2460        public long getLastModified() {
2461            throw new UnsupportedOperationException();
2462        }
2463
2464        @Override @DefinedBy(Api.COMPILER)
2465        public boolean delete() {
2466            throw new UnsupportedOperationException();
2467        }
2468
2469        @Override
2470        protected String inferBinaryName(Iterable<? extends File> path) {
2471            return flatname.toString();
2472        }
2473
2474        @Override @DefinedBy(Api.COMPILER)
2475        public boolean isNameCompatible(String simpleName, JavaFileObject.Kind kind) {
2476            return true; // fail-safe mode
2477        }
2478
2479        /**
2480         * Check if two file objects are equal.
2481         * SourceFileObjects are just placeholder objects for the value of a
2482         * SourceFile attribute, and do not directly represent specific files.
2483         * Two SourceFileObjects are equal if their names are equal.
2484         */
2485        @Override
2486        public boolean equals(Object other) {
2487            if (this == other)
2488                return true;
2489
2490            if (!(other instanceof SourceFileObject))
2491                return false;
2492
2493            SourceFileObject o = (SourceFileObject) other;
2494            return name.equals(o.name);
2495        }
2496
2497        @Override
2498        public int hashCode() {
2499            return name.hashCode();
2500        }
2501    }
2502}
2503