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