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