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