1 /*
   2  * Copyright (c) 1999, 2024, 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.nio.file.ClosedFileSystemException;
  33 import java.util.Arrays;
  34 import java.util.EnumSet;
  35 import java.util.HashMap;
  36 import java.util.HashSet;
  37 import java.util.Map;
  38 import java.util.Set;
  39 import java.util.function.IntFunction;
  40 import java.util.function.Predicate;
  41 import java.util.stream.IntStream;
  42 
  43 import javax.lang.model.element.Modifier;
  44 import javax.lang.model.element.NestingKind;
  45 import javax.tools.JavaFileManager;
  46 import javax.tools.JavaFileObject;
  47 
  48 import com.sun.tools.javac.code.Source;
  49 import com.sun.tools.javac.code.Source.Feature;
  50 import com.sun.tools.javac.comp.Annotate;
  51 import com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter;
  52 import com.sun.tools.javac.code.*;
  53 import com.sun.tools.javac.code.Directive.*;
  54 import com.sun.tools.javac.code.Lint.LintCategory;
  55 import com.sun.tools.javac.code.Scope.WriteableScope;
  56 import com.sun.tools.javac.code.Symbol.*;
  57 import com.sun.tools.javac.code.Symtab;
  58 import com.sun.tools.javac.code.Type.*;
  59 import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
  60 import com.sun.tools.javac.file.BaseFileManager;
  61 import com.sun.tools.javac.file.PathFileObject;
  62 import com.sun.tools.javac.jvm.ClassFile.Version;
  63 import com.sun.tools.javac.jvm.PoolConstant.NameAndType;
  64 import com.sun.tools.javac.main.Option;
  65 import com.sun.tools.javac.resources.CompilerProperties;
  66 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  67 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  68 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
  69 import com.sun.tools.javac.tree.JCTree;
  70 import com.sun.tools.javac.util.*;
  71 import com.sun.tools.javac.util.ByteBuffer.UnderflowException;
  72 import com.sun.tools.javac.util.DefinedBy.Api;
  73 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
  74 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
  75 
  76 import static com.sun.tools.javac.code.Flags.*;
  77 import static com.sun.tools.javac.code.Kinds.Kind.*;
  78 
  79 import com.sun.tools.javac.code.Scope.LookupKind;
  80 
  81 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
  82 import static com.sun.tools.javac.code.TypeTag.ARRAY;
  83 import static com.sun.tools.javac.code.TypeTag.CLASS;
  84 import static com.sun.tools.javac.code.TypeTag.TYPEVAR;
  85 import static com.sun.tools.javac.jvm.ClassFile.*;
  86 import static com.sun.tools.javac.jvm.ClassFile.Version.*;
  87 
  88 import static com.sun.tools.javac.main.Option.PARAMETERS;
  89 
  90 /** This class provides operations to read a classfile into an internal
  91  *  representation. The internal representation is anchored in a
  92  *  ClassSymbol which contains in its scope symbol representations
  93  *  for all other definitions in the classfile. Top-level Classes themselves
  94  *  appear as members of the scopes of PackageSymbols.
  95  *
  96  *  <p><b>This is NOT part of any supported API.
  97  *  If you write code that depends on this, you do so at your own risk.
  98  *  This code and its internal interfaces are subject to change or
  99  *  deletion without notice.</b>
 100  */
 101 public class ClassReader {
 102     /** The context key for the class reader. */
 103     protected static final Context.Key<ClassReader> classReaderKey = new Context.Key<>();
 104 
 105     public static final int INITIAL_BUFFER_SIZE = 0x0fff0;
 106 
 107     private final Annotate annotate;
 108 
 109     /** Switch: verbose output.
 110      */
 111     boolean verbose;
 112 
 113     /** Switch: allow modules.
 114      */
 115     boolean allowModules;
 116 
 117     /** Switch: allow value classes.
 118      */
 119     boolean allowValueClasses;
 120 
 121     /** Switch: allow sealed
 122      */
 123     boolean allowSealedTypes;
 124 
 125     /** Switch: allow records
 126      */
 127     boolean allowRecords;
 128 
 129    /** Lint option: warn about classfile issues
 130      */
 131     boolean lintClassfile;
 132 
 133     /** Switch: warn (instead of error) on illegal UTF-8
 134      */
 135     boolean warnOnIllegalUtf8;
 136 
 137     /** Switch: preserve parameter names from the variable table.
 138      */
 139     public boolean saveParameterNames;
 140 
 141     /**
 142      * The currently selected profile.
 143      */
 144     public final Profile profile;
 145 
 146     /** The log to use for verbose output
 147      */
 148     final Log log;
 149 
 150     /** The symbol table. */
 151     Symtab syms;
 152 
 153     Types types;
 154 
 155     /** The name table. */
 156     final Names names;
 157 
 158     /** Access to files
 159      */
 160     private final JavaFileManager fileManager;
 161 
 162     /** Factory for diagnostics
 163      */
 164     JCDiagnostic.Factory diagFactory;
 165 
 166     DeferredCompletionFailureHandler dcfh;
 167 
 168     /**
 169      * Support for preview language features.
 170      */
 171     Preview preview;
 172 
 173     /** The current scope where type variables are entered.
 174      */
 175     protected WriteableScope typevars;
 176 
 177     private List<InterimUsesDirective> interimUses = List.nil();
 178     private List<InterimProvidesDirective> interimProvides = List.nil();
 179 
 180     /** The path name of the class file currently being read.
 181      */
 182     protected JavaFileObject currentClassFile = null;
 183 
 184     /** The class or method currently being read.
 185      */
 186     protected Symbol currentOwner = null;
 187 
 188     /** The module containing the class currently being read.
 189      */
 190     protected ModuleSymbol currentModule = null;
 191 
 192     /** The buffer containing the currently read class file.
 193      */
 194     ByteBuffer buf = new ByteBuffer(INITIAL_BUFFER_SIZE);
 195 
 196     /** The current input pointer.
 197      */
 198     protected int bp;
 199 
 200     /** The pool reader.
 201      */
 202     PoolReader poolReader;
 203 
 204     /** The major version number of the class file being read. */
 205     int majorVersion;
 206     /** The minor version number of the class file being read. */
 207     int minorVersion;
 208 
 209     /** UTF-8 validation level */
 210     Convert.Validation utf8validation;
 211 
 212     /** A table to hold the constant pool indices for method parameter
 213      * names, as given in LocalVariableTable attributes.
 214      */
 215     int[] parameterNameIndicesLvt;
 216 
 217     /**
 218      * A table to hold the constant pool indices for method parameter
 219      * names, as given in the MethodParameters attribute.
 220      */
 221     int[] parameterNameIndicesMp;
 222 
 223     /**
 224      * A table to hold the access flags of the method parameters.
 225      */
 226     int[] parameterAccessFlags;
 227 
 228     /**
 229      * A table to hold the access flags of the method parameters,
 230      * for all parameters including synthetic and mandated ones.
 231      */
 232     int[] allParameterAccessFlags;
 233 
 234     /**
 235      * A table to hold annotations for method parameters.
 236      */
 237     ParameterAnnotations[] parameterAnnotations;
 238 
 239     /**
 240      * A holder for parameter annotations.
 241      */
 242     static class ParameterAnnotations {
 243         List<CompoundAnnotationProxy> proxies;
 244 
 245         void add(List<CompoundAnnotationProxy> newAnnotations) {
 246             if (proxies == null) {
 247                 proxies = newAnnotations;
 248             } else {
 249                 proxies = proxies.prependList(newAnnotations);
 250             }
 251         }
 252     }
 253 
 254     /**
 255      * The set of attribute names for which warnings have been generated for the current class
 256      */
 257     Set<Name> warnedAttrs = new HashSet<>();
 258 
 259     /**
 260      * The prototype @Target Attribute.Compound if this class is an annotation annotated with
 261      * {@code @Target}
 262      */
 263     CompoundAnnotationProxy target;
 264 
 265     /**
 266      * The prototype @Repeatable Attribute.Compound if this class is an annotation annotated with
 267      * {@code @Repeatable}
 268      */
 269     CompoundAnnotationProxy repeatable;
 270 
 271     /** Get the ClassReader instance for this invocation. */
 272     public static ClassReader instance(Context context) {
 273         ClassReader instance = context.get(classReaderKey);
 274         if (instance == null)
 275             instance = new ClassReader(context);
 276         return instance;
 277     }
 278 
 279     /** Construct a new class reader. */
 280     @SuppressWarnings("this-escape")
 281     protected ClassReader(Context context) {
 282         context.put(classReaderKey, this);
 283         annotate = Annotate.instance(context);
 284         names = Names.instance(context);
 285         syms = Symtab.instance(context);
 286         types = Types.instance(context);
 287         fileManager = context.get(JavaFileManager.class);
 288         if (fileManager == null)
 289             throw new AssertionError("FileManager initialization error");
 290         diagFactory = JCDiagnostic.Factory.instance(context);
 291         dcfh = DeferredCompletionFailureHandler.instance(context);
 292 
 293         log = Log.instance(context);
 294 
 295         Options options = Options.instance(context);
 296         verbose         = options.isSet(Option.VERBOSE);
 297 
 298         Source source = Source.instance(context);
 299         preview = Preview.instance(context);
 300         allowModules     = Feature.MODULES.allowedInSource(source);
 301         allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
 302                 Feature.VALUE_CLASSES.allowedInSource(source);
 303         allowRecords = Feature.RECORDS.allowedInSource(source);
 304         allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
 305         warnOnIllegalUtf8 = Feature.WARN_ON_ILLEGAL_UTF8.allowedInSource(source);
 306 
 307         saveParameterNames = options.isSet(PARAMETERS);
 308 
 309         profile = Profile.instance(context);
 310 
 311         typevars = WriteableScope.create(syms.noSymbol);
 312 
 313         lintClassfile = Lint.instance(context).isEnabled(LintCategory.CLASSFILE);
 314 
 315         initAttributeReaders();
 316     }
 317 
 318     /** Add member to class unless it is synthetic.
 319      */
 320     private void enterMember(ClassSymbol c, Symbol sym) {
 321         // Synthetic members are not entered -- reason lost to history (optimization?).
 322         // Lambda methods must be entered because they may have inner classes (which reference them)
 323         if ((sym.flags_field & (SYNTHETIC|BRIDGE)) != SYNTHETIC || sym.name.startsWith(names.lambda))
 324             c.members_field.enter(sym);
 325     }
 326 
 327 /* **********************************************************************
 328  * Error Diagnoses
 329  ***********************************************************************/
 330 
 331     public ClassFinder.BadClassFile badClassFile(String key, Object... args) {
 332         return badClassFile(diagFactory.fragment(key, args));
 333     }
 334 
 335     public ClassFinder.BadClassFile badClassFile(Fragment fragment) {
 336         return badClassFile(diagFactory.fragment(fragment));
 337     }
 338 
 339     public ClassFinder.BadClassFile badClassFile(JCDiagnostic diagnostic) {
 340         return new ClassFinder.BadClassFile (
 341             currentOwner.enclClass(),
 342             currentClassFile,
 343             diagnostic,
 344             diagFactory,
 345             dcfh);
 346     }
 347 
 348     public ClassFinder.BadEnclosingMethodAttr badEnclosingMethod(Symbol sym) {
 349         return new ClassFinder.BadEnclosingMethodAttr (
 350             currentOwner.enclClass(),
 351             currentClassFile,
 352             diagFactory.fragment(Fragments.BadEnclosingMethod(sym)),
 353             diagFactory,
 354             dcfh);
 355     }
 356 
 357 /* **********************************************************************
 358  * Buffer Access
 359  ***********************************************************************/
 360 
 361     /** Read a character.
 362      */
 363     char nextChar() {
 364         char res;
 365         try {
 366             res = buf.getChar(bp);
 367         } catch (UnderflowException e) {
 368             throw badClassFile(Fragments.BadClassTruncatedAtOffset(e.getLength()));
 369         }
 370         bp += 2;
 371         return res;
 372     }
 373 
 374     /** Read a byte.
 375      */
 376     int nextByte() {
 377         try {
 378             return buf.getByte(bp++) & 0xFF;
 379         } catch (UnderflowException e) {
 380             throw badClassFile(Fragments.BadClassTruncatedAtOffset(e.getLength()));
 381         }
 382     }
 383 
 384     /** Read an integer.
 385      */
 386     int nextInt() {
 387         int res;
 388         try {
 389             res = buf.getInt(bp);
 390         } catch (UnderflowException e) {
 391             throw badClassFile(Fragments.BadClassTruncatedAtOffset(e.getLength()));
 392         }
 393         bp += 4;
 394         return res;
 395     }
 396 
 397 /* **********************************************************************
 398  * Constant Pool Access
 399  ***********************************************************************/
 400 
 401     /** Read module_flags.
 402      */
 403     Set<ModuleFlags> readModuleFlags(int flags) {
 404         Set<ModuleFlags> set = EnumSet.noneOf(ModuleFlags.class);
 405         for (ModuleFlags f : ModuleFlags.values()) {
 406             if ((flags & f.value) != 0)
 407                 set.add(f);
 408         }
 409         return set;
 410     }
 411 
 412     /** Read resolution_flags.
 413      */
 414     Set<ModuleResolutionFlags> readModuleResolutionFlags(int flags) {
 415         Set<ModuleResolutionFlags> set = EnumSet.noneOf(ModuleResolutionFlags.class);
 416         for (ModuleResolutionFlags f : ModuleResolutionFlags.values()) {
 417             if ((flags & f.value) != 0)
 418                 set.add(f);
 419         }
 420         return set;
 421     }
 422 
 423     /** Read exports_flags.
 424      */
 425     Set<ExportsFlag> readExportsFlags(int flags) {
 426         Set<ExportsFlag> set = EnumSet.noneOf(ExportsFlag.class);
 427         for (ExportsFlag f: ExportsFlag.values()) {
 428             if ((flags & f.value) != 0)
 429                 set.add(f);
 430         }
 431         return set;
 432     }
 433 
 434     /** Read opens_flags.
 435      */
 436     Set<OpensFlag> readOpensFlags(int flags) {
 437         Set<OpensFlag> set = EnumSet.noneOf(OpensFlag.class);
 438         for (OpensFlag f: OpensFlag.values()) {
 439             if ((flags & f.value) != 0)
 440                 set.add(f);
 441         }
 442         return set;
 443     }
 444 
 445     /** Read requires_flags.
 446      */
 447     Set<RequiresFlag> readRequiresFlags(int flags) {
 448         Set<RequiresFlag> set = EnumSet.noneOf(RequiresFlag.class);
 449         for (RequiresFlag f: RequiresFlag.values()) {
 450             if ((flags & f.value) != 0)
 451                 set.add(f);
 452         }
 453         return set;
 454     }
 455 
 456 /* **********************************************************************
 457  * Reading Types
 458  ***********************************************************************/
 459 
 460     /** The unread portion of the currently read type is
 461      *  signature[sigp..siglimit-1].
 462      */
 463     byte[] signature;
 464     int sigp;
 465     int siglimit;
 466     boolean sigEnterPhase = false;
 467 
 468     /** Convert signature to type, where signature is a byte array segment.
 469      */
 470     Type sigToType(byte[] sig, int offset, int len) {
 471         signature = sig;
 472         sigp = offset;
 473         siglimit = offset + len;
 474         return sigToType();
 475     }
 476 
 477     /** Convert signature to type, where signature is implicit.
 478      */
 479     Type sigToType() {
 480         switch ((char) signature[sigp]) {
 481         case 'T':
 482             sigp++;
 483             int start = sigp;
 484             while (signature[sigp] != ';') sigp++;
 485             sigp++;
 486             return sigEnterPhase
 487                 ? Type.noType
 488                 : findTypeVar(readName(signature, start, sigp - 1 - start));
 489         case '+': {
 490             sigp++;
 491             Type t = sigToType();
 492             return new WildcardType(t, BoundKind.EXTENDS, syms.boundClass);
 493         }
 494         case '*':
 495             sigp++;
 496             return new WildcardType(syms.objectType, BoundKind.UNBOUND,
 497                                     syms.boundClass);
 498         case '-': {
 499             sigp++;
 500             Type t = sigToType();
 501             return new WildcardType(t, BoundKind.SUPER, syms.boundClass);
 502         }
 503         case 'B':
 504             sigp++;
 505             return syms.byteType;
 506         case 'C':
 507             sigp++;
 508             return syms.charType;
 509         case 'D':
 510             sigp++;
 511             return syms.doubleType;
 512         case 'F':
 513             sigp++;
 514             return syms.floatType;
 515         case 'I':
 516             sigp++;
 517             return syms.intType;
 518         case 'J':
 519             sigp++;
 520             return syms.longType;
 521         case 'L':
 522             {
 523                 // int oldsigp = sigp;
 524                 Type t = classSigToType();
 525                 if (sigp < siglimit && signature[sigp] == '.')
 526                     throw badClassFile("deprecated inner class signature syntax " +
 527                                        "(please recompile from source)");
 528                 /*
 529                 System.err.println(" decoded " +
 530                                    new String(signature, oldsigp, sigp-oldsigp) +
 531                                    " => " + t + " outer " + t.outer());
 532                 */
 533                 return t;
 534             }
 535         case 'S':
 536             sigp++;
 537             return syms.shortType;
 538         case 'V':
 539             sigp++;
 540             return syms.voidType;
 541         case 'Z':
 542             sigp++;
 543             return syms.booleanType;
 544         case '[':
 545             sigp++;
 546             return new ArrayType(sigToType(), syms.arrayClass);
 547         case '(':
 548             sigp++;
 549             List<Type> argtypes = sigToTypes(')');
 550             Type restype = sigToType();
 551             List<Type> thrown = List.nil();
 552             while (sigp < siglimit && signature[sigp] == '^') {
 553                 sigp++;
 554                 thrown = thrown.prepend(sigToType());
 555             }
 556             // if there is a typevar in the throws clause we should state it.
 557             for (List<Type> l = thrown; l.nonEmpty(); l = l.tail) {
 558                 if (l.head.hasTag(TYPEVAR)) {
 559                     l.head.tsym.flags_field |= THROWS;
 560                 }
 561             }
 562             return new MethodType(argtypes,
 563                                   restype,
 564                                   thrown.reverse(),
 565                                   syms.methodClass);
 566         case '<':
 567             typevars = typevars.dup(currentOwner);
 568             Type poly = new ForAll(sigToTypeParams(), sigToType());
 569             typevars = typevars.leave();
 570             return poly;
 571         default:
 572             throw badClassFile("bad.signature", quoteBadSignature());
 573         }
 574     }
 575 
 576     byte[] signatureBuffer = new byte[0];
 577     int sbp = 0;
 578     /** Convert class signature to type, where signature is implicit.
 579      */
 580     Type classSigToType() {
 581         if (signature[sigp] != 'L')
 582             throw badClassFile("bad.class.signature", quoteBadSignature());
 583         sigp++;
 584         Type outer = Type.noType;
 585         int startSbp = sbp;
 586 
 587         while (true) {
 588             final byte c = signature[sigp++];
 589             switch (c) {
 590 
 591             case ';': {         // end
 592                 ClassSymbol t = enterClass(readName(signatureBuffer,
 593                                                          startSbp,
 594                                                          sbp - startSbp));
 595 
 596                 try {
 597                     if (outer == Type.noType) {
 598                         ClassType et = (ClassType) t.erasure(types);
 599                         return new ClassType(et.getEnclosingType(), List.nil(), et.tsym, et.getMetadata());
 600                     }
 601                     return new ClassType(outer, List.nil(), t, List.nil());
 602                 } finally {
 603                     sbp = startSbp;
 604                 }
 605             }
 606 
 607             case '<':           // generic arguments
 608                 ClassSymbol t = enterClass(readName(signatureBuffer,
 609                                                          startSbp,
 610                                                          sbp - startSbp));
 611                 List<Type> actuals = sigToTypes('>');
 612                 List<Type> formals = ((ClassType)t.type.tsym.type).typarams_field;
 613                 if (formals != null) {
 614                     if (actuals.isEmpty())
 615                         actuals = formals;
 616                 }
 617                 /* actualsCp is final as it will be captured by the inner class below. We could avoid defining
 618                  * this additional local variable and depend on field ClassType::typarams_field which `actuals` is
 619                  * assigned to but then we would have a dependendy on the internal representation of ClassType which
 620                  * could change in the future
 621                  */
 622                 final List<Type> actualsCp = actuals;
 623                 outer = new ClassType(outer, actuals, t, List.nil()) {
 624                         boolean completed = false;
 625                         boolean typeArgsSet = false;
 626                         @Override @DefinedBy(Api.LANGUAGE_MODEL)
 627                         public Type getEnclosingType() {
 628                             if (!completed) {
 629                                 completed = true;
 630                                 tsym.apiComplete();
 631                                 Type enclosingType = tsym.type.getEnclosingType();
 632                                 if (enclosingType != Type.noType) {
 633                                     List<Type> typeArgs =
 634                                         super.getEnclosingType().allparams();
 635                                     List<Type> typeParams =
 636                                         enclosingType.allparams();
 637                                     if (typeParams.length() != typeArgs.length()) {
 638                                         // no "rare" types
 639                                         super.setEnclosingType(types.erasure(enclosingType));
 640                                     } else {
 641                                         super.setEnclosingType(types.subst(enclosingType,
 642                                                                            typeParams,
 643                                                                            typeArgs));
 644                                     }
 645                                 } else {
 646                                     super.setEnclosingType(Type.noType);
 647                                 }
 648                             }
 649                             return super.getEnclosingType();
 650                         }
 651                         @Override
 652                         public void setEnclosingType(Type outer) {
 653                             throw new UnsupportedOperationException();
 654                         }
 655 
 656                         @Override
 657                         public List<Type> getTypeArguments() {
 658                             if (!typeArgsSet) {
 659                                 typeArgsSet = true;
 660                                 List<Type> formalsCp = ((ClassType)t.type.tsym.type).typarams_field;
 661                                 if (formalsCp != null && !formalsCp.isEmpty()) {
 662                                     if (actualsCp.length() == formalsCp.length()) {
 663                                         List<Type> a = actualsCp;
 664                                         List<Type> f = formalsCp;
 665                                         while (a.nonEmpty()) {
 666                                             a.head = a.head.withTypeVar(f.head);
 667                                             a = a.tail;
 668                                             f = f.tail;
 669                                         }
 670                                     }
 671                                 }
 672                             }
 673                             return super.getTypeArguments();
 674                         }
 675                 };
 676                 switch (signature[sigp++]) {
 677                 case ';':
 678                     if (sigp < siglimit && signature[sigp] == '.') {
 679                         // support old-style GJC signatures
 680                         // The signature produced was
 681                         // Lfoo/Outer<Lfoo/X;>;.Lfoo/Outer$Inner<Lfoo/Y;>;
 682                         // rather than say
 683                         // Lfoo/Outer<Lfoo/X;>.Inner<Lfoo/Y;>;
 684                         // so we skip past ".Lfoo/Outer$"
 685                         sigp += (sbp - startSbp) + // "foo/Outer"
 686                             3;  // ".L" and "$"
 687                         signatureBuffer[sbp++] = (byte)'$';
 688                         break;
 689                     } else {
 690                         sbp = startSbp;
 691                         return outer;
 692                     }
 693                 case '.':
 694                     signatureBuffer[sbp++] = (byte)'$';
 695                     break;
 696                 default:
 697                     throw new AssertionError(signature[sigp-1]);
 698                 }
 699                 continue;
 700 
 701             case '.':
 702                 //we have seen an enclosing non-generic class
 703                 if (outer != Type.noType) {
 704                     t = enterClass(readName(signatureBuffer,
 705                                                  startSbp,
 706                                                  sbp - startSbp));
 707                     outer = new ClassType(outer, List.nil(), t, List.nil());
 708                 }
 709                 signatureBuffer[sbp++] = (byte)'$';
 710                 continue;
 711             case '/':
 712                 signatureBuffer[sbp++] = (byte)'.';
 713                 continue;
 714             default:
 715                 signatureBuffer[sbp++] = c;
 716                 continue;
 717             }
 718         }
 719     }
 720 
 721     /** Quote a bogus signature for display inside an error message.
 722      */
 723     String quoteBadSignature() {
 724         String sigString;
 725         try {
 726             sigString = Convert.utf2string(signature, sigp, siglimit - sigp, Convert.Validation.NONE);
 727         } catch (InvalidUtfException e) {
 728             throw new AssertionError(e);
 729         }
 730         if (sigString.length() > 32)
 731             sigString = sigString.substring(0, 32) + "...";
 732         return "\"" + sigString + "\"";
 733     }
 734 
 735     /** Convert (implicit) signature to list of types
 736      *  until `terminator' is encountered.
 737      */
 738     List<Type> sigToTypes(char terminator) {
 739         List<Type> head = List.of(null);
 740         List<Type> tail = head;
 741         while (signature[sigp] != terminator)
 742             tail = tail.setTail(List.of(sigToType()));
 743         sigp++;
 744         return head.tail;
 745     }
 746 
 747     /** Convert signature to type parameters, where signature is a byte
 748      *  array segment.
 749      */
 750     List<Type> sigToTypeParams(byte[] sig, int offset, int len) {
 751         signature = sig;
 752         sigp = offset;
 753         siglimit = offset + len;
 754         return sigToTypeParams();
 755     }
 756 
 757     /** Convert signature to type parameters, where signature is implicit.
 758      */
 759     List<Type> sigToTypeParams() {
 760         List<Type> tvars = List.nil();
 761         if (signature[sigp] == '<') {
 762             sigp++;
 763             int start = sigp;
 764             sigEnterPhase = true;
 765             while (signature[sigp] != '>')
 766                 tvars = tvars.prepend(sigToTypeParam());
 767             sigEnterPhase = false;
 768             sigp = start;
 769             while (signature[sigp] != '>')
 770                 sigToTypeParam();
 771             sigp++;
 772         }
 773         return tvars.reverse();
 774     }
 775 
 776     /** Convert (implicit) signature to type parameter.
 777      */
 778     Type sigToTypeParam() {
 779         int start = sigp;
 780         while (signature[sigp] != ':') sigp++;
 781         Name name = readName(signature, start, sigp - start);
 782         TypeVar tvar;
 783         if (sigEnterPhase) {
 784             tvar = new TypeVar(name, currentOwner, syms.botType);
 785             typevars.enter(tvar.tsym);
 786         } else {
 787             tvar = (TypeVar)findTypeVar(name);
 788         }
 789         List<Type> bounds = List.nil();
 790         boolean allInterfaces = false;
 791         if (signature[sigp] == ':' && signature[sigp+1] == ':') {
 792             sigp++;
 793             allInterfaces = true;
 794         }
 795         while (signature[sigp] == ':') {
 796             sigp++;
 797             bounds = bounds.prepend(sigToType());
 798         }
 799         if (!sigEnterPhase) {
 800             types.setBounds(tvar, bounds.reverse(), allInterfaces);
 801         }
 802         return tvar;
 803     }
 804 
 805     /** Find type variable with given name in `typevars' scope.
 806      */
 807     Type findTypeVar(Name name) {
 808         Symbol s = typevars.findFirst(name);
 809         if (s != null) {
 810             return s.type;
 811         } else {
 812             if (readingClassAttr) {
 813                 // While reading the class attribute, the supertypes
 814                 // might refer to a type variable from an enclosing element
 815                 // (method or class).
 816                 // If the type variable is defined in the enclosing class,
 817                 // we can actually find it in
 818                 // currentOwner.owner.type.getTypeArguments()
 819                 // However, until we have read the enclosing method attribute
 820                 // we don't know for sure if this owner is correct.  It could
 821                 // be a method and there is no way to tell before reading the
 822                 // enclosing method attribute.
 823                 TypeVar t = new TypeVar(name, currentOwner, syms.botType);
 824                 missingTypeVariables = missingTypeVariables.prepend(t);
 825                 // System.err.println("Missing type var " + name);
 826                 return t;
 827             }
 828             throw badClassFile("undecl.type.var", name);
 829         }
 830     }
 831 
 832     private Name readName(byte[] buf, int off, int len) {
 833         try {
 834             return names.fromUtf(buf, off, len, utf8validation);
 835         } catch (InvalidUtfException e) {
 836             if (warnOnIllegalUtf8) {
 837                 log.warning(Warnings.InvalidUtf8InClassfile(currentClassFile,
 838                     Fragments.BadUtf8ByteSequenceAt(sigp)));
 839                 return names.fromUtfLax(buf, off, len);
 840             }
 841             throw badClassFile(Fragments.BadUtf8ByteSequenceAt(sigp));
 842         }
 843     }
 844 
 845 /* **********************************************************************
 846  * Reading Attributes
 847  ***********************************************************************/
 848 
 849     protected enum AttributeKind { CLASS, MEMBER }
 850 
 851     protected abstract class AttributeReader {
 852         protected AttributeReader(Name name, ClassFile.Version version, Set<AttributeKind> kinds) {
 853             this.name = name;
 854             this.version = version;
 855             this.kinds = kinds;
 856         }
 857 
 858         protected boolean accepts(AttributeKind kind) {
 859             if (kinds.contains(kind)) {
 860                 if (majorVersion > version.major || (majorVersion == version.major && minorVersion >= version.minor))
 861                     return true;
 862 
 863                 if (lintClassfile && !warnedAttrs.contains(name)) {
 864                     JavaFileObject prev = log.useSource(currentClassFile);
 865                     try {
 866                         log.warning(LintCategory.CLASSFILE, (DiagnosticPosition) null,
 867                                     Warnings.FutureAttr(name, version.major, version.minor, majorVersion, minorVersion));
 868                     } finally {
 869                         log.useSource(prev);
 870                     }
 871                     warnedAttrs.add(name);
 872                 }
 873             }
 874             return false;
 875         }
 876 
 877         protected abstract void read(Symbol sym, int attrLen);
 878 
 879         protected final Name name;
 880         protected final ClassFile.Version version;
 881         protected final Set<AttributeKind> kinds;
 882     }
 883 
 884     protected Set<AttributeKind> CLASS_ATTRIBUTE =
 885             EnumSet.of(AttributeKind.CLASS);
 886     protected Set<AttributeKind> MEMBER_ATTRIBUTE =
 887             EnumSet.of(AttributeKind.MEMBER);
 888     protected Set<AttributeKind> CLASS_OR_MEMBER_ATTRIBUTE =
 889             EnumSet.of(AttributeKind.CLASS, AttributeKind.MEMBER);
 890 
 891     protected Map<Name, AttributeReader> attributeReaders = new HashMap<>();
 892 
 893     private void initAttributeReaders() {
 894         AttributeReader[] readers = {
 895             // v45.3 attributes
 896 
 897             new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) {
 898                 protected void read(Symbol sym, int attrLen) {
 899                     if (saveParameterNames)
 900                         ((MethodSymbol)sym).code = readCode(sym);
 901                     else
 902                         bp = bp + attrLen;
 903                 }
 904             },
 905 
 906             new AttributeReader(names.ConstantValue, V45_3, MEMBER_ATTRIBUTE) {
 907                 protected void read(Symbol sym, int attrLen) {
 908                     Object v = poolReader.getConstant(nextChar());
 909                     // Ignore ConstantValue attribute if field not final.
 910                     if ((sym.flags() & FINAL) == 0) {
 911                         return;
 912                     }
 913                     VarSymbol var = (VarSymbol) sym;
 914                     switch (var.type.getTag()) {
 915                        case BOOLEAN:
 916                        case BYTE:
 917                        case CHAR:
 918                        case SHORT:
 919                        case INT:
 920                            checkType(var, Integer.class, v);
 921                            break;
 922                        case LONG:
 923                            checkType(var, Long.class, v);
 924                            break;
 925                        case FLOAT:
 926                            checkType(var, Float.class, v);
 927                            break;
 928                        case DOUBLE:
 929                            checkType(var, Double.class, v);
 930                            break;
 931                        case CLASS:
 932                            if (var.type.tsym == syms.stringType.tsym) {
 933                                checkType(var, String.class, v);
 934                            } else {
 935                                throw badClassFile("bad.constant.value.type", var.type);
 936                            }
 937                            break;
 938                        default:
 939                            // ignore ConstantValue attribute if type is not primitive or String
 940                            return;
 941                     }
 942                     if (v instanceof Integer intVal && !var.type.getTag().checkRange(intVal)) {
 943                         throw badClassFile("bad.constant.range", v, var, var.type);
 944                     }
 945                     var.setData(v);
 946                 }
 947 
 948                 void checkType(Symbol var, Class<?> clazz, Object value) {
 949                     if (!clazz.isInstance(value)) {
 950                         throw badClassFile("bad.constant.value", value, var, clazz.getSimpleName());
 951                     }
 952                 }
 953             },
 954 
 955             new AttributeReader(names.Deprecated, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
 956                 protected void read(Symbol sym, int attrLen) {
 957                     Symbol s = sym.owner.kind == MDL ? sym.owner : sym;
 958 
 959                     s.flags_field |= DEPRECATED;
 960                 }
 961             },
 962 
 963             new AttributeReader(names.Exceptions, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
 964                 protected void read(Symbol sym, int attrLen) {
 965                     int nexceptions = nextChar();
 966                     List<Type> thrown = List.nil();
 967                     for (int j = 0; j < nexceptions; j++)
 968                         thrown = thrown.prepend(poolReader.getClass(nextChar()).type);
 969                     if (sym.type.getThrownTypes().isEmpty())
 970                         sym.type.asMethodType().thrown = thrown.reverse();
 971                 }
 972             },
 973 
 974             new AttributeReader(names.InnerClasses, V45_3, CLASS_ATTRIBUTE) {
 975                 protected void read(Symbol sym, int attrLen) {
 976                     ClassSymbol c = (ClassSymbol) sym;
 977                     if (currentModule.module_info == c) {
 978                         //prevent entering the classes too soon:
 979                         skipInnerClasses();
 980                     } else {
 981                         readInnerClasses(c);
 982                     }
 983                 }
 984             },
 985 
 986             new AttributeReader(names.LocalVariableTable, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
 987                 protected void read(Symbol sym, int attrLen) {
 988                     int newbp = bp + attrLen;
 989                     if (saveParameterNames) {
 990                         // Pick up parameter names from the variable table.
 991                         // Parameter names are not explicitly identified as such,
 992                         // but all parameter name entries in the LocalVariableTable
 993                         // have a start_pc of 0.  Therefore, we record the name
 994                         // indices of all slots with a start_pc of zero in the
 995                         // parameterNameIndices array.
 996                         // Note that this implicitly honors the JVMS spec that
 997                         // there may be more than one LocalVariableTable, and that
 998                         // there is no specified ordering for the entries.
 999                         int numEntries = nextChar();
1000                         for (int i = 0; i < numEntries; i++) {
1001                             int start_pc = nextChar();
1002                             int length = nextChar();
1003                             int nameIndex = nextChar();
1004                             int sigIndex = nextChar();
1005                             int register = nextChar();
1006                             if (start_pc == 0) {
1007                                 // ensure array large enough
1008                                 if (register >= parameterNameIndicesLvt.length) {
1009                                     int newSize =
1010                                             Math.max(register + 1, parameterNameIndicesLvt.length + 8);
1011                                     parameterNameIndicesLvt =
1012                                             Arrays.copyOf(parameterNameIndicesLvt, newSize);
1013                                 }
1014                                 parameterNameIndicesLvt[register] = nameIndex;
1015                             }
1016                         }
1017                     }
1018                     bp = newbp;
1019                 }
1020             },
1021 
1022             new AttributeReader(names.SourceFile, V45_3, CLASS_ATTRIBUTE) {
1023                 protected void read(Symbol sym, int attrLen) {
1024                     ClassSymbol c = (ClassSymbol) sym;
1025                     Name n = poolReader.getName(nextChar());
1026                     c.sourcefile = new SourceFileObject(n);
1027                     // If the class is a toplevel class, originating from a Java source file,
1028                     // but the class name does not match the file name, then it is
1029                     // an auxiliary class.
1030                     String sn = n.toString();
1031                     if (c.owner.kind == PCK &&
1032                         sn.endsWith(".java") &&
1033                         !sn.equals(c.name.toString()+".java")) {
1034                         c.flags_field |= AUXILIARY;
1035                     }
1036                 }
1037             },
1038 
1039             new AttributeReader(names.Synthetic, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
1040                 protected void read(Symbol sym, int attrLen) {
1041                     sym.flags_field |= SYNTHETIC;
1042                 }
1043             },
1044 
1045             // standard v49 attributes
1046 
1047             new AttributeReader(names.EnclosingMethod, V49, CLASS_ATTRIBUTE) {
1048                 protected void read(Symbol sym, int attrLen) {
1049                     int newbp = bp + attrLen;
1050                     readEnclosingMethodAttr(sym);
1051                     bp = newbp;
1052                 }
1053             },
1054 
1055             new AttributeReader(names.Signature, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1056                 protected void read(Symbol sym, int attrLen) {
1057                     if (sym.kind == TYP) {
1058                         ClassSymbol c = (ClassSymbol) sym;
1059                         readingClassAttr = true;
1060                         try {
1061                             ClassType ct1 = (ClassType)c.type;
1062                             Assert.check(c == currentOwner);
1063                             ct1.typarams_field = poolReader.getName(nextChar())
1064                                     .map(ClassReader.this::sigToTypeParams);
1065                             ct1.supertype_field = sigToType();
1066                             ListBuffer<Type> is = new ListBuffer<>();
1067                             while (sigp != siglimit) is.append(sigToType());
1068                             ct1.interfaces_field = is.toList();
1069                         } finally {
1070                             readingClassAttr = false;
1071                         }
1072                     } else {
1073                         List<Type> thrown = sym.type.getThrownTypes();
1074                         sym.type = poolReader.getType(nextChar());
1075                         //- System.err.println(" # " + sym.type);
1076                         if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty())
1077                             sym.type.asMethodType().thrown = thrown;
1078 
1079                     }
1080                 }
1081             },
1082 
1083             // v49 annotation attributes
1084 
1085             new AttributeReader(names.AnnotationDefault, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1086                 protected void read(Symbol sym, int attrLen) {
1087                     attachAnnotationDefault(sym);
1088                 }
1089             },
1090 
1091             new AttributeReader(names.RuntimeInvisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1092                 protected void read(Symbol sym, int attrLen) {
1093                     attachAnnotations(sym);
1094                 }
1095             },
1096 
1097             new AttributeReader(names.RuntimeInvisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1098                 protected void read(Symbol sym, int attrLen) {
1099                     readParameterAnnotations(sym);
1100                 }
1101             },
1102 
1103             new AttributeReader(names.RuntimeVisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1104                 protected void read(Symbol sym, int attrLen) {
1105                     attachAnnotations(sym);
1106                 }
1107             },
1108 
1109             new AttributeReader(names.RuntimeVisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1110                 protected void read(Symbol sym, int attrLen) {
1111                     readParameterAnnotations(sym);
1112                 }
1113             },
1114 
1115             // additional "legacy" v49 attributes, superseded by flags
1116 
1117             new AttributeReader(names.Annotation, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1118                 protected void read(Symbol sym, int attrLen) {
1119                     sym.flags_field |= ANNOTATION;
1120                 }
1121             },
1122 
1123             new AttributeReader(names.Bridge, V49, MEMBER_ATTRIBUTE) {
1124                 protected void read(Symbol sym, int attrLen) {
1125                     sym.flags_field |= BRIDGE;
1126                 }
1127             },
1128 
1129             new AttributeReader(names.Enum, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1130                 protected void read(Symbol sym, int attrLen) {
1131                     sym.flags_field |= ENUM;
1132                 }
1133             },
1134 
1135             new AttributeReader(names.Varargs, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1136                 protected void read(Symbol sym, int attrLen) {
1137                     sym.flags_field |= VARARGS;
1138                 }
1139             },
1140 
1141             new AttributeReader(names.RuntimeVisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) {
1142                 protected void read(Symbol sym, int attrLen) {
1143                     attachTypeAnnotations(sym);
1144                 }
1145             },
1146 
1147             new AttributeReader(names.RuntimeInvisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) {
1148                 protected void read(Symbol sym, int attrLen) {
1149                     attachTypeAnnotations(sym);
1150                 }
1151             },
1152 
1153             // The following attributes for a Code attribute are not currently handled
1154             // StackMapTable
1155             // SourceDebugExtension
1156             // LineNumberTable
1157             // LocalVariableTypeTable
1158 
1159             // standard v52 attributes
1160 
1161             new AttributeReader(names.MethodParameters, V52, MEMBER_ATTRIBUTE) {
1162                 protected void read(Symbol sym, int attrlen) {
1163                     int newbp = bp + attrlen;
1164                     if (saveParameterNames) {
1165                         int numEntries = nextByte();
1166                         allParameterAccessFlags = new int[numEntries];
1167                         parameterNameIndicesMp = new int[numEntries];
1168                         parameterAccessFlags = new int[numEntries];
1169                         int allParamIndex = 0;
1170                         int index = 0;
1171                         for (int i = 0; i < numEntries; i++) {
1172                             int nameIndex = nextChar();
1173                             int flags = nextChar();
1174                             allParameterAccessFlags[allParamIndex++] = flags;
1175                             if ((flags & (Flags.MANDATED | Flags.SYNTHETIC)) != 0) {
1176                                 continue;
1177                             }
1178                             parameterNameIndicesMp[index] = nameIndex;
1179                             parameterAccessFlags[index] = flags;
1180                             index++;
1181                         }
1182                     }
1183                     bp = newbp;
1184                 }
1185             },
1186 
1187             // standard v53 attributes
1188 
1189             new AttributeReader(names.Module, V53, CLASS_ATTRIBUTE) {
1190                 @Override
1191                 protected boolean accepts(AttributeKind kind) {
1192                     return super.accepts(kind) && allowModules;
1193                 }
1194                 protected void read(Symbol sym, int attrLen) {
1195                     if (sym.kind == TYP && sym.owner.kind == MDL) {
1196                         ModuleSymbol msym = (ModuleSymbol) sym.owner;
1197                         ListBuffer<Directive> directives = new ListBuffer<>();
1198 
1199                         Name moduleName = poolReader.peekModuleName(nextChar(), ClassReader.this::readName);
1200                         if (currentModule.name != moduleName) {
1201                             throw badClassFile("module.name.mismatch", moduleName, currentModule.name);
1202                         }
1203 
1204                         Set<ModuleFlags> moduleFlags = readModuleFlags(nextChar());
1205                         msym.flags.addAll(moduleFlags);
1206                         msym.version = optPoolEntry(nextChar(), poolReader::getName, null);
1207 
1208                         ListBuffer<RequiresDirective> requires = new ListBuffer<>();
1209                         int nrequires = nextChar();
1210                         for (int i = 0; i < nrequires; i++) {
1211                             ModuleSymbol rsym = poolReader.getModule(nextChar());
1212                             Set<RequiresFlag> flags = readRequiresFlags(nextChar());
1213                             if (rsym == syms.java_base && majorVersion >= V54.major) {
1214                                 if (flags.contains(RequiresFlag.TRANSITIVE)) {
1215                                     throw badClassFile("bad.requires.flag", RequiresFlag.TRANSITIVE);
1216                                 }
1217                                 if (flags.contains(RequiresFlag.STATIC_PHASE)) {
1218                                     throw badClassFile("bad.requires.flag", RequiresFlag.STATIC_PHASE);
1219                                 }
1220                             }
1221                             nextChar(); // skip compiled version
1222                             requires.add(new RequiresDirective(rsym, flags));
1223                         }
1224                         msym.requires = requires.toList();
1225                         directives.addAll(msym.requires);
1226 
1227                         ListBuffer<ExportsDirective> exports = new ListBuffer<>();
1228                         int nexports = nextChar();
1229                         for (int i = 0; i < nexports; i++) {
1230                             PackageSymbol p = poolReader.getPackage(nextChar());
1231                             Set<ExportsFlag> flags = readExportsFlags(nextChar());
1232                             int nto = nextChar();
1233                             List<ModuleSymbol> to;
1234                             if (nto == 0) {
1235                                 to = null;
1236                             } else {
1237                                 ListBuffer<ModuleSymbol> lb = new ListBuffer<>();
1238                                 for (int t = 0; t < nto; t++)
1239                                     lb.append(poolReader.getModule(nextChar()));
1240                                 to = lb.toList();
1241                             }
1242                             exports.add(new ExportsDirective(p, to, flags));
1243                         }
1244                         msym.exports = exports.toList();
1245                         directives.addAll(msym.exports);
1246                         ListBuffer<OpensDirective> opens = new ListBuffer<>();
1247                         int nopens = nextChar();
1248                         if (nopens != 0 && msym.flags.contains(ModuleFlags.OPEN)) {
1249                             throw badClassFile("module.non.zero.opens", currentModule.name);
1250                         }
1251                         for (int i = 0; i < nopens; i++) {
1252                             PackageSymbol p = poolReader.getPackage(nextChar());
1253                             Set<OpensFlag> flags = readOpensFlags(nextChar());
1254                             int nto = nextChar();
1255                             List<ModuleSymbol> to;
1256                             if (nto == 0) {
1257                                 to = null;
1258                             } else {
1259                                 ListBuffer<ModuleSymbol> lb = new ListBuffer<>();
1260                                 for (int t = 0; t < nto; t++)
1261                                     lb.append(poolReader.getModule(nextChar()));
1262                                 to = lb.toList();
1263                             }
1264                             opens.add(new OpensDirective(p, to, flags));
1265                         }
1266                         msym.opens = opens.toList();
1267                         directives.addAll(msym.opens);
1268 
1269                         msym.directives = directives.toList();
1270 
1271                         ListBuffer<InterimUsesDirective> uses = new ListBuffer<>();
1272                         int nuses = nextChar();
1273                         for (int i = 0; i < nuses; i++) {
1274                             Name srvc = poolReader.peekClassName(nextChar(), this::classNameMapper);
1275                             uses.add(new InterimUsesDirective(srvc));
1276                         }
1277                         interimUses = uses.toList();
1278 
1279                         ListBuffer<InterimProvidesDirective> provides = new ListBuffer<>();
1280                         int nprovides = nextChar();
1281                         for (int p = 0; p < nprovides; p++) {
1282                             Name srvc = poolReader.peekClassName(nextChar(), this::classNameMapper);
1283                             int nimpls = nextChar();
1284                             ListBuffer<Name> impls = new ListBuffer<>();
1285                             for (int i = 0; i < nimpls; i++) {
1286                                 impls.append(poolReader.peekClassName(nextChar(), this::classNameMapper));
1287                             provides.add(new InterimProvidesDirective(srvc, impls.toList()));
1288                             }
1289                         }
1290                         interimProvides = provides.toList();
1291                     }
1292                 }
1293 
1294                 private Name classNameMapper(byte[] arr, int offset, int length) throws InvalidUtfException {
1295                     byte[] buf = ClassFile.internalize(arr, offset, length);
1296                     try {
1297                         return names.fromUtf(buf, 0, buf.length, utf8validation);
1298                     } catch (InvalidUtfException e) {
1299                         if (warnOnIllegalUtf8) {
1300                             log.warning(Warnings.InvalidUtf8InClassfile(currentClassFile,
1301                                 Fragments.BadUtf8ByteSequenceAt(e.getOffset())));
1302                             return names.fromUtfLax(buf, 0, buf.length);
1303                         }
1304                         throw e;
1305                     }
1306                 }
1307             },
1308 
1309             new AttributeReader(names.ModuleResolution, V53, CLASS_ATTRIBUTE) {
1310                 @Override
1311                 protected boolean accepts(AttributeKind kind) {
1312                     return super.accepts(kind) && allowModules;
1313                 }
1314                 protected void read(Symbol sym, int attrLen) {
1315                     if (sym.kind == TYP && sym.owner.kind == MDL) {
1316                         ModuleSymbol msym = (ModuleSymbol) sym.owner;
1317                         msym.resolutionFlags.addAll(readModuleResolutionFlags(nextChar()));
1318                     }
1319                 }
1320             },
1321 
1322             new AttributeReader(names.Record, V58, CLASS_ATTRIBUTE) {
1323                 @Override
1324                 protected boolean accepts(AttributeKind kind) {
1325                     return super.accepts(kind) && allowRecords;
1326                 }
1327                 protected void read(Symbol sym, int attrLen) {
1328                     if (sym.kind == TYP) {
1329                         sym.flags_field |= RECORD;
1330                     }
1331                     int componentCount = nextChar();
1332                     ListBuffer<RecordComponent> components = new ListBuffer<>();
1333                     for (int i = 0; i < componentCount; i++) {
1334                         Name name = poolReader.getName(nextChar());
1335                         Type type = poolReader.getType(nextChar());
1336                         RecordComponent c = new RecordComponent(name, type, sym);
1337                         readAttrs(c, AttributeKind.MEMBER);
1338                         components.add(c);
1339                     }
1340                     ((ClassSymbol) sym).setRecordComponents(components.toList());
1341                 }
1342             },
1343             new AttributeReader(names.PermittedSubclasses, V59, CLASS_ATTRIBUTE) {
1344                 @Override
1345                 protected boolean accepts(AttributeKind kind) {
1346                     return super.accepts(kind) && allowSealedTypes;
1347                 }
1348                 protected void read(Symbol sym, int attrLen) {
1349                     if (sym.kind == TYP) {
1350                         ListBuffer<Symbol> subtypes = new ListBuffer<>();
1351                         int numberOfPermittedSubtypes = nextChar();
1352                         for (int i = 0; i < numberOfPermittedSubtypes; i++) {
1353                             subtypes.add(poolReader.getClass(nextChar()));
1354                         }
1355                         ((ClassSymbol)sym).setPermittedSubclasses(subtypes.toList());
1356                     }
1357                 }
1358             },
1359         };
1360 
1361         for (AttributeReader r: readers)
1362             attributeReaders.put(r.name, r);
1363     }
1364 
1365     protected void readEnclosingMethodAttr(Symbol sym) {
1366         // sym is a nested class with an "Enclosing Method" attribute
1367         // remove sym from it's current owners scope and place it in
1368         // the scope specified by the attribute
1369         sym.owner.members().remove(sym);
1370         ClassSymbol self = (ClassSymbol)sym;
1371         ClassSymbol c = poolReader.getClass(nextChar());
1372         NameAndType nt = optPoolEntry(nextChar(), poolReader::getNameAndType, null);
1373 
1374         if (c.members_field == null || c.kind != TYP)
1375             throw badClassFile("bad.enclosing.class", self, c);
1376 
1377         MethodSymbol m = findMethod(nt, c.members_field, self.flags());
1378         if (nt != null && m == null)
1379             throw badEnclosingMethod(self);
1380 
1381         self.name = simpleBinaryName(self.flatname, c.flatname) ;
1382         self.owner = m != null ? m : c;
1383         if (self.name.isEmpty())
1384             self.fullname = names.empty;
1385         else
1386             self.fullname = ClassSymbol.formFullName(self.name, self.owner);
1387 
1388         if (m != null) {
1389             ((ClassType)sym.type).setEnclosingType(m.type);
1390         } else if ((self.flags_field & STATIC) == 0) {
1391             ((ClassType)sym.type).setEnclosingType(c.type);
1392         } else {
1393             ((ClassType)sym.type).setEnclosingType(Type.noType);
1394         }
1395         enterTypevars(self, self.type);
1396         if (!missingTypeVariables.isEmpty()) {
1397             ListBuffer<Type> typeVars =  new ListBuffer<>();
1398             for (Type typevar : missingTypeVariables) {
1399                 typeVars.append(findTypeVar(typevar.tsym.name));
1400             }
1401             foundTypeVariables = typeVars.toList();
1402         } else {
1403             foundTypeVariables = List.nil();
1404         }
1405     }
1406 
1407     // See java.lang.Class
1408     private Name simpleBinaryName(Name self, Name enclosing) {
1409         if (!self.startsWith(enclosing)) {
1410             throw badClassFile("bad.enclosing.method", self);
1411         }
1412 
1413         String simpleBinaryName = self.toString().substring(enclosing.toString().length());
1414         if (simpleBinaryName.length() < 1 || simpleBinaryName.charAt(0) != '$')
1415             throw badClassFile("bad.enclosing.method", self);
1416         int index = 1;
1417         while (index < simpleBinaryName.length() &&
1418                isAsciiDigit(simpleBinaryName.charAt(index)))
1419             index++;
1420         return names.fromString(simpleBinaryName.substring(index));
1421     }
1422 
1423     private MethodSymbol findMethod(NameAndType nt, Scope scope, long flags) {
1424         if (nt == null)
1425             return null;
1426 
1427         MethodType type = nt.type.asMethodType();
1428 
1429         for (Symbol sym : scope.getSymbolsByName(nt.name)) {
1430             if (sym.kind == MTH && isSameBinaryType(sym.type.asMethodType(), type))
1431                 return (MethodSymbol)sym;
1432         }
1433 
1434         if (nt.name != names.init)
1435             // not a constructor
1436             return null;
1437         if ((flags & INTERFACE) != 0)
1438             // no enclosing instance
1439             return null;
1440         if (nt.type.getParameterTypes().isEmpty())
1441             // no parameters
1442             return null;
1443 
1444         // A constructor of an inner class.
1445         // Remove the first argument (the enclosing instance)
1446         nt = new NameAndType(nt.name, new MethodType(nt.type.getParameterTypes().tail,
1447                                  nt.type.getReturnType(),
1448                                  nt.type.getThrownTypes(),
1449                                  syms.methodClass));
1450         // Try searching again
1451         return findMethod(nt, scope, flags);
1452     }
1453 
1454     /** Similar to Types.isSameType but avoids completion */
1455     private boolean isSameBinaryType(MethodType mt1, MethodType mt2) {
1456         List<Type> types1 = types.erasure(mt1.getParameterTypes())
1457             .prepend(types.erasure(mt1.getReturnType()));
1458         List<Type> types2 = mt2.getParameterTypes().prepend(mt2.getReturnType());
1459         while (!types1.isEmpty() && !types2.isEmpty()) {
1460             if (types1.head.tsym != types2.head.tsym)
1461                 return false;
1462             types1 = types1.tail;
1463             types2 = types2.tail;
1464         }
1465         return types1.isEmpty() && types2.isEmpty();
1466     }
1467 
1468     /**
1469      * Character.isDigit answers <tt>true</tt> to some non-ascii
1470      * digits.  This one does not.  <b>copied from java.lang.Class</b>
1471      */
1472     private static boolean isAsciiDigit(char c) {
1473         return '0' <= c && c <= '9';
1474     }
1475 
1476     /** Read member attributes.
1477      */
1478     void readMemberAttrs(Symbol sym) {
1479         readAttrs(sym, AttributeKind.MEMBER);
1480     }
1481 
1482     void readAttrs(Symbol sym, AttributeKind kind) {
1483         char ac = nextChar();
1484         for (int i = 0; i < ac; i++) {
1485             Name attrName = poolReader.getName(nextChar());
1486             int attrLen = nextInt();
1487             AttributeReader r = attributeReaders.get(attrName);
1488             if (r != null && r.accepts(kind))
1489                 r.read(sym, attrLen);
1490             else  {
1491                 bp = bp + attrLen;
1492             }
1493         }
1494     }
1495 
1496     private boolean readingClassAttr = false;
1497     private List<Type> missingTypeVariables = List.nil();
1498     private List<Type> foundTypeVariables = List.nil();
1499 
1500     /** Read class attributes.
1501      */
1502     void readClassAttrs(ClassSymbol c) {
1503         readAttrs(c, AttributeKind.CLASS);
1504     }
1505 
1506     /** Read code block.
1507      */
1508     Code readCode(Symbol owner) {
1509         nextChar(); // max_stack
1510         nextChar(); // max_locals
1511         final int  code_length = nextInt();
1512         bp += code_length;
1513         final char exception_table_length = nextChar();
1514         bp += exception_table_length * 8;
1515         readMemberAttrs(owner);
1516         return null;
1517     }
1518 
1519 /* **********************************************************************
1520  * Reading Java-language annotations
1521  ***********************************************************************/
1522 
1523     /**
1524      * Save annotations.
1525      */
1526     List<CompoundAnnotationProxy> readAnnotations() {
1527         int numAttributes = nextChar();
1528         ListBuffer<CompoundAnnotationProxy> annotations = new ListBuffer<>();
1529         for (int i = 0; i < numAttributes; i++) {
1530             annotations.append(readCompoundAnnotation());
1531         }
1532         return annotations.toList();
1533     }
1534 
1535     /** Attach annotations.
1536      */
1537     void attachAnnotations(final Symbol sym) {
1538         attachAnnotations(sym, readAnnotations());
1539     }
1540 
1541     /**
1542      * Attach annotations.
1543      */
1544     void attachAnnotations(final Symbol sym, List<CompoundAnnotationProxy> annotations) {
1545         if (annotations.isEmpty()) {
1546             return;
1547         }
1548         ListBuffer<CompoundAnnotationProxy> proxies = new ListBuffer<>();
1549         for (CompoundAnnotationProxy proxy : annotations) {
1550             if (proxy.type.tsym.flatName() == syms.proprietaryType.tsym.flatName())
1551                 sym.flags_field |= PROPRIETARY;
1552             else if (proxy.type.tsym.flatName() == syms.profileType.tsym.flatName()) {
1553                 if (profile != Profile.DEFAULT) {
1554                     for (Pair<Name, Attribute> v : proxy.values) {
1555                         if (v.fst == names.value && v.snd instanceof Attribute.Constant constant) {
1556                             if (constant.type == syms.intType && ((Integer) constant.value) > profile.value) {
1557                                 sym.flags_field |= NOT_IN_PROFILE;
1558                             }
1559                         }
1560                     }
1561                 }
1562             } else if (proxy.type.tsym.flatName() == syms.previewFeatureInternalType.tsym.flatName()) {
1563                 sym.flags_field |= PREVIEW_API;
1564                 setFlagIfAttributeTrue(proxy, sym, names.reflective, PREVIEW_REFLECTIVE);
1565             } else if (proxy.type.tsym.flatName() == syms.valueBasedInternalType.tsym.flatName()) {
1566                 Assert.check(sym.kind == TYP);
1567                 sym.flags_field |= VALUE_BASED;
1568             } else if (proxy.type.tsym.flatName() == syms.migratedValueClassInternalType.tsym.flatName()) {
1569                 Assert.check(sym.kind == TYP);
1570                 sym.flags_field |= MIGRATED_VALUE_CLASS;
1571                 if (needsValueFlag(sym, sym.flags_field)) {
1572                     sym.flags_field |= VALUE_CLASS;
1573                     sym.flags_field &= ~IDENTITY_TYPE;
1574                 }
1575             } else if (proxy.type.tsym.flatName() == syms.restrictedInternalType.tsym.flatName()) {
1576                 Assert.check(sym.kind == MTH);
1577                 sym.flags_field |= RESTRICTED;
1578             } else {
1579                 if (proxy.type.tsym == syms.annotationTargetType.tsym) {
1580                     target = proxy;
1581                 } else if (proxy.type.tsym == syms.repeatableType.tsym) {
1582                     repeatable = proxy;
1583                 } else if (proxy.type.tsym == syms.deprecatedType.tsym) {
1584                     sym.flags_field |= (DEPRECATED | DEPRECATED_ANNOTATION);
1585                     setFlagIfAttributeTrue(proxy, sym, names.forRemoval, DEPRECATED_REMOVAL);
1586                 }  else if (proxy.type.tsym == syms.previewFeatureType.tsym) {
1587                     sym.flags_field |= PREVIEW_API;
1588                     setFlagIfAttributeTrue(proxy, sym, names.reflective, PREVIEW_REFLECTIVE);
1589                 }  else if (proxy.type.tsym == syms.valueBasedType.tsym && sym.kind == TYP) {
1590                     sym.flags_field |= VALUE_BASED;
1591                 }  else if (proxy.type.tsym == syms.migratedValueClassType.tsym && sym.kind == TYP) {
1592                     sym.flags_field |= MIGRATED_VALUE_CLASS;
1593                     if (needsValueFlag(sym, sym.flags_field)) {
1594                         sym.flags_field |= VALUE_CLASS;
1595                         sym.flags_field &= ~IDENTITY_TYPE;
1596                     }
1597                 }  else if (proxy.type.tsym == syms.restrictedType.tsym) {
1598                     Assert.check(sym.kind == MTH);
1599                     sym.flags_field |= RESTRICTED;
1600                 }
1601                 proxies.append(proxy);
1602             }
1603         }
1604         annotate.normal(new AnnotationCompleter(sym, proxies.toList()));
1605     }
1606     //where:
1607         private void setFlagIfAttributeTrue(CompoundAnnotationProxy proxy, Symbol sym, Name attribute, long flag) {
1608             for (Pair<Name, Attribute> v : proxy.values) {
1609                 if (v.fst == attribute && v.snd instanceof Attribute.Constant constant) {
1610                     if (constant.type == syms.booleanType && ((Integer) constant.value) != 0) {
1611                         sym.flags_field |= flag;
1612                     }
1613                 }
1614             }
1615         }
1616 
1617     /** Read parameter annotations.
1618      */
1619     void readParameterAnnotations(Symbol meth) {
1620         int numParameters;
1621         try {
1622             numParameters = buf.getByte(bp++) & 0xFF;
1623         } catch (UnderflowException e) {
1624             throw badClassFile(Fragments.BadClassTruncatedAtOffset(e.getLength()));
1625         }
1626         if (parameterAnnotations == null) {
1627             parameterAnnotations = new ParameterAnnotations[numParameters];
1628         } else if (parameterAnnotations.length != numParameters) {
1629             //the RuntimeVisibleParameterAnnotations and RuntimeInvisibleParameterAnnotations
1630             //provide annotations for a different number of parameters, ignore:
1631             if (lintClassfile) {
1632                 log.warning(LintCategory.CLASSFILE, Warnings.RuntimeVisibleInvisibleParamAnnotationsMismatch(currentClassFile));
1633             }
1634             for (int pnum = 0; pnum < numParameters; pnum++) {
1635                 readAnnotations();
1636             }
1637             parameterAnnotations = null;
1638             return ;
1639         }
1640         for (int pnum = 0; pnum < numParameters; pnum++) {
1641             if (parameterAnnotations[pnum] == null) {
1642                 parameterAnnotations[pnum] = new ParameterAnnotations();
1643             }
1644             parameterAnnotations[pnum].add(readAnnotations());
1645         }
1646     }
1647 
1648     void attachTypeAnnotations(final Symbol sym) {
1649         int numAttributes = nextChar();
1650         if (numAttributes != 0) {
1651             ListBuffer<TypeAnnotationProxy> proxies = new ListBuffer<>();
1652             for (int i = 0; i < numAttributes; i++)
1653                 proxies.append(readTypeAnnotation());
1654             annotate.normal(new TypeAnnotationCompleter(sym, proxies.toList()));
1655         }
1656     }
1657 
1658     /** Attach the default value for an annotation element.
1659      */
1660     void attachAnnotationDefault(final Symbol sym) {
1661         final MethodSymbol meth = (MethodSymbol)sym; // only on methods
1662         final Attribute value = readAttributeValue();
1663 
1664         // The default value is set later during annotation. It might
1665         // be the case that the Symbol sym is annotated _after_ the
1666         // repeating instances that depend on this default value,
1667         // because of this we set an interim value that tells us this
1668         // element (most likely) has a default.
1669         //
1670         // Set interim value for now, reset just before we do this
1671         // properly at annotate time.
1672         meth.defaultValue = value;
1673         annotate.normal(new AnnotationDefaultCompleter(meth, value));
1674     }
1675 
1676     Type readTypeOrClassSymbol(int i) {
1677         return readTypeToProxy(i);
1678     }
1679     Type readTypeToProxy(int i) {
1680         if (currentModule.module_info == currentOwner) {
1681             return new ProxyType(i);
1682         } else {
1683             return poolReader.getType(i);
1684         }
1685     }
1686 
1687     CompoundAnnotationProxy readCompoundAnnotation() {
1688         Type t;
1689         if (currentModule.module_info == currentOwner) {
1690             int cpIndex = nextChar();
1691             t = new ProxyType(cpIndex);
1692         } else {
1693             t = readTypeOrClassSymbol(nextChar());
1694         }
1695         int numFields = nextChar();
1696         ListBuffer<Pair<Name,Attribute>> pairs = new ListBuffer<>();
1697         for (int i=0; i<numFields; i++) {
1698             Name name = poolReader.getName(nextChar());
1699             Attribute value = readAttributeValue();
1700             pairs.append(new Pair<>(name, value));
1701         }
1702         return new CompoundAnnotationProxy(t, pairs.toList());
1703     }
1704 
1705     TypeAnnotationProxy readTypeAnnotation() {
1706         TypeAnnotationPosition position = readPosition();
1707         CompoundAnnotationProxy proxy = readCompoundAnnotation();
1708 
1709         return new TypeAnnotationProxy(proxy, position);
1710     }
1711 
1712     TypeAnnotationPosition readPosition() {
1713         int tag = nextByte(); // TargetType tag is a byte
1714 
1715         if (!TargetType.isValidTargetTypeValue(tag))
1716             throw badClassFile("bad.type.annotation.value", String.format("0x%02X", tag));
1717 
1718         TargetType type = TargetType.fromTargetTypeValue(tag);
1719 
1720         switch (type) {
1721         // instanceof
1722         case INSTANCEOF: {
1723             final int offset = nextChar();
1724             final TypeAnnotationPosition position =
1725                 TypeAnnotationPosition.instanceOf(readTypePath());
1726             position.offset = offset;
1727             return position;
1728         }
1729         // new expression
1730         case NEW: {
1731             final int offset = nextChar();
1732             final TypeAnnotationPosition position =
1733                 TypeAnnotationPosition.newObj(readTypePath());
1734             position.offset = offset;
1735             return position;
1736         }
1737         // constructor/method reference receiver
1738         case CONSTRUCTOR_REFERENCE: {
1739             final int offset = nextChar();
1740             final TypeAnnotationPosition position =
1741                 TypeAnnotationPosition.constructorRef(readTypePath());
1742             position.offset = offset;
1743             return position;
1744         }
1745         case METHOD_REFERENCE: {
1746             final int offset = nextChar();
1747             final TypeAnnotationPosition position =
1748                 TypeAnnotationPosition.methodRef(readTypePath());
1749             position.offset = offset;
1750             return position;
1751         }
1752         // local variable
1753         case LOCAL_VARIABLE: {
1754             final int table_length = nextChar();
1755             final int[] newLvarOffset = new int[table_length];
1756             final int[] newLvarLength = new int[table_length];
1757             final int[] newLvarIndex = new int[table_length];
1758 
1759             for (int i = 0; i < table_length; ++i) {
1760                 newLvarOffset[i] = nextChar();
1761                 newLvarLength[i] = nextChar();
1762                 newLvarIndex[i] = nextChar();
1763             }
1764 
1765             final TypeAnnotationPosition position =
1766                     TypeAnnotationPosition.localVariable(readTypePath());
1767             position.lvarOffset = newLvarOffset;
1768             position.lvarLength = newLvarLength;
1769             position.lvarIndex = newLvarIndex;
1770             return position;
1771         }
1772         // resource variable
1773         case RESOURCE_VARIABLE: {
1774             final int table_length = nextChar();
1775             final int[] newLvarOffset = new int[table_length];
1776             final int[] newLvarLength = new int[table_length];
1777             final int[] newLvarIndex = new int[table_length];
1778 
1779             for (int i = 0; i < table_length; ++i) {
1780                 newLvarOffset[i] = nextChar();
1781                 newLvarLength[i] = nextChar();
1782                 newLvarIndex[i] = nextChar();
1783             }
1784 
1785             final TypeAnnotationPosition position =
1786                     TypeAnnotationPosition.resourceVariable(readTypePath());
1787             position.lvarOffset = newLvarOffset;
1788             position.lvarLength = newLvarLength;
1789             position.lvarIndex = newLvarIndex;
1790             return position;
1791         }
1792         // exception parameter
1793         case EXCEPTION_PARAMETER: {
1794             final int exception_index = nextChar();
1795             final TypeAnnotationPosition position =
1796                 TypeAnnotationPosition.exceptionParameter(readTypePath());
1797             position.setExceptionIndex(exception_index);
1798             return position;
1799         }
1800         // method receiver
1801         case METHOD_RECEIVER:
1802             return TypeAnnotationPosition.methodReceiver(readTypePath());
1803         // type parameter
1804         case CLASS_TYPE_PARAMETER: {
1805             final int parameter_index = nextByte();
1806             return TypeAnnotationPosition
1807                 .typeParameter(readTypePath(), parameter_index);
1808         }
1809         case METHOD_TYPE_PARAMETER: {
1810             final int parameter_index = nextByte();
1811             return TypeAnnotationPosition
1812                 .methodTypeParameter(readTypePath(), parameter_index);
1813         }
1814         // type parameter bound
1815         case CLASS_TYPE_PARAMETER_BOUND: {
1816             final int parameter_index = nextByte();
1817             final int bound_index = nextByte();
1818             return TypeAnnotationPosition
1819                 .typeParameterBound(readTypePath(), parameter_index,
1820                                     bound_index);
1821         }
1822         case METHOD_TYPE_PARAMETER_BOUND: {
1823             final int parameter_index = nextByte();
1824             final int bound_index = nextByte();
1825             return TypeAnnotationPosition
1826                 .methodTypeParameterBound(readTypePath(), parameter_index,
1827                                           bound_index);
1828         }
1829         // class extends or implements clause
1830         case CLASS_EXTENDS: {
1831             final int type_index = nextChar();
1832             return TypeAnnotationPosition.classExtends(readTypePath(),
1833                                                        type_index);
1834         }
1835         // throws
1836         case THROWS: {
1837             final int type_index = nextChar();
1838             return TypeAnnotationPosition.methodThrows(readTypePath(),
1839                                                        type_index);
1840         }
1841         // method parameter
1842         case METHOD_FORMAL_PARAMETER: {
1843             final int parameter_index = nextByte();
1844             return TypeAnnotationPosition.methodParameter(readTypePath(),
1845                                                           parameter_index);
1846         }
1847         // type cast
1848         case CAST: {
1849             final int offset = nextChar();
1850             final int type_index = nextByte();
1851             final TypeAnnotationPosition position =
1852                 TypeAnnotationPosition.typeCast(readTypePath(), type_index);
1853             position.offset = offset;
1854             return position;
1855         }
1856         // method/constructor/reference type argument
1857         case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: {
1858             final int offset = nextChar();
1859             final int type_index = nextByte();
1860             final TypeAnnotationPosition position = TypeAnnotationPosition
1861                 .constructorInvocationTypeArg(readTypePath(), type_index);
1862             position.offset = offset;
1863             return position;
1864         }
1865         case METHOD_INVOCATION_TYPE_ARGUMENT: {
1866             final int offset = nextChar();
1867             final int type_index = nextByte();
1868             final TypeAnnotationPosition position = TypeAnnotationPosition
1869                 .methodInvocationTypeArg(readTypePath(), type_index);
1870             position.offset = offset;
1871             return position;
1872         }
1873         case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: {
1874             final int offset = nextChar();
1875             final int type_index = nextByte();
1876             final TypeAnnotationPosition position = TypeAnnotationPosition
1877                 .constructorRefTypeArg(readTypePath(), type_index);
1878             position.offset = offset;
1879             return position;
1880         }
1881         case METHOD_REFERENCE_TYPE_ARGUMENT: {
1882             final int offset = nextChar();
1883             final int type_index = nextByte();
1884             final TypeAnnotationPosition position = TypeAnnotationPosition
1885                 .methodRefTypeArg(readTypePath(), type_index);
1886             position.offset = offset;
1887             return position;
1888         }
1889         // We don't need to worry about these
1890         case METHOD_RETURN:
1891             return TypeAnnotationPosition.methodReturn(readTypePath());
1892         case FIELD:
1893             return TypeAnnotationPosition.field(readTypePath());
1894         case UNKNOWN:
1895             throw new AssertionError("jvm.ClassReader: UNKNOWN target type should never occur!");
1896         default:
1897             throw new AssertionError("jvm.ClassReader: Unknown target type for position: " + type);
1898         }
1899     }
1900 
1901     List<TypeAnnotationPosition.TypePathEntry> readTypePath() {
1902         int len = nextByte();
1903         ListBuffer<Integer> loc = new ListBuffer<>();
1904         for (int i = 0; i < len * TypeAnnotationPosition.TypePathEntry.bytesPerEntry; ++i)
1905             loc = loc.append(nextByte());
1906 
1907         return TypeAnnotationPosition.getTypePathFromBinary(loc.toList());
1908 
1909     }
1910 
1911     /**
1912      * Helper function to read an optional pool entry (with given function); this is used while parsing
1913      * InnerClasses and EnclosingMethod attributes, as well as when parsing supertype descriptor,
1914      * as per JVMS.
1915      */
1916     <Z> Z optPoolEntry(int index, IntFunction<Z> poolFunc, Z defaultValue) {
1917         return (index == 0) ?
1918                 defaultValue :
1919                 poolFunc.apply(index);
1920     }
1921 
1922     Attribute readAttributeValue() {
1923         char c;
1924         try {
1925             c = (char)buf.getByte(bp++);
1926         } catch (UnderflowException e) {
1927             throw badClassFile(Fragments.BadClassTruncatedAtOffset(e.getLength()));
1928         }
1929         switch (c) {
1930         case 'B':
1931             return new Attribute.Constant(syms.byteType, poolReader.getConstant(nextChar()));
1932         case 'C':
1933             return new Attribute.Constant(syms.charType, poolReader.getConstant(nextChar()));
1934         case 'D':
1935             return new Attribute.Constant(syms.doubleType, poolReader.getConstant(nextChar()));
1936         case 'F':
1937             return new Attribute.Constant(syms.floatType, poolReader.getConstant(nextChar()));
1938         case 'I':
1939             return new Attribute.Constant(syms.intType, poolReader.getConstant(nextChar()));
1940         case 'J':
1941             return new Attribute.Constant(syms.longType, poolReader.getConstant(nextChar()));
1942         case 'S':
1943             return new Attribute.Constant(syms.shortType, poolReader.getConstant(nextChar()));
1944         case 'Z':
1945             return new Attribute.Constant(syms.booleanType, poolReader.getConstant(nextChar()));
1946         case 's':
1947             return new Attribute.Constant(syms.stringType, poolReader.getName(nextChar()).toString());
1948         case 'e':
1949             return new EnumAttributeProxy(readTypeToProxy(nextChar()), poolReader.getName(nextChar()));
1950         case 'c':
1951             return new ClassAttributeProxy(readTypeOrClassSymbol(nextChar()));
1952         case '[': {
1953             int n = nextChar();
1954             ListBuffer<Attribute> l = new ListBuffer<>();
1955             for (int i=0; i<n; i++)
1956                 l.append(readAttributeValue());
1957             return new ArrayAttributeProxy(l.toList());
1958         }
1959         case '@':
1960             return readCompoundAnnotation();
1961         default:
1962             throw new AssertionError("unknown annotation tag '" + c + "'");
1963         }
1964     }
1965 
1966     interface ProxyVisitor extends Attribute.Visitor {
1967         void visitEnumAttributeProxy(EnumAttributeProxy proxy);
1968         void visitClassAttributeProxy(ClassAttributeProxy proxy);
1969         void visitArrayAttributeProxy(ArrayAttributeProxy proxy);
1970         void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy);
1971     }
1972 
1973     static class EnumAttributeProxy extends Attribute {
1974         Type enumType;
1975         Name enumerator;
1976         public EnumAttributeProxy(Type enumType, Name enumerator) {
1977             super(null);
1978             this.enumType = enumType;
1979             this.enumerator = enumerator;
1980         }
1981         public void accept(Visitor v) { ((ProxyVisitor)v).visitEnumAttributeProxy(this); }
1982         @Override @DefinedBy(Api.LANGUAGE_MODEL)
1983         public String toString() {
1984             return "/*proxy enum*/" + enumType + "." + enumerator;
1985         }
1986     }
1987 
1988     static class ClassAttributeProxy extends Attribute {
1989         Type classType;
1990         public ClassAttributeProxy(Type classType) {
1991             super(null);
1992             this.classType = classType;
1993         }
1994         public void accept(Visitor v) { ((ProxyVisitor)v).visitClassAttributeProxy(this); }
1995         @Override @DefinedBy(Api.LANGUAGE_MODEL)
1996         public String toString() {
1997             return "/*proxy class*/" + classType + ".class";
1998         }
1999     }
2000 
2001     static class ArrayAttributeProxy extends Attribute {
2002         List<Attribute> values;
2003         ArrayAttributeProxy(List<Attribute> values) {
2004             super(null);
2005             this.values = values;
2006         }
2007         public void accept(Visitor v) { ((ProxyVisitor)v).visitArrayAttributeProxy(this); }
2008         @Override @DefinedBy(Api.LANGUAGE_MODEL)
2009         public String toString() {
2010             return "{" + values + "}";
2011         }
2012     }
2013 
2014     /** A temporary proxy representing a compound attribute.
2015      */
2016     static class CompoundAnnotationProxy extends Attribute {
2017         final List<Pair<Name,Attribute>> values;
2018         public CompoundAnnotationProxy(Type type,
2019                                       List<Pair<Name,Attribute>> values) {
2020             super(type);
2021             this.values = values;
2022         }
2023         public void accept(Visitor v) { ((ProxyVisitor)v).visitCompoundAnnotationProxy(this); }
2024         @Override @DefinedBy(Api.LANGUAGE_MODEL)
2025         public String toString() {
2026             StringBuilder buf = new StringBuilder();
2027             buf.append("@");
2028             buf.append(type.tsym.getQualifiedName());
2029             buf.append("/*proxy*/{");
2030             boolean first = true;
2031             for (List<Pair<Name,Attribute>> v = values;
2032                  v.nonEmpty(); v = v.tail) {
2033                 Pair<Name,Attribute> value = v.head;
2034                 if (!first) buf.append(",");
2035                 first = false;
2036                 buf.append(value.fst);
2037                 buf.append("=");
2038                 buf.append(value.snd);
2039             }
2040             buf.append("}");
2041             return buf.toString();
2042         }
2043     }
2044 
2045     /** A temporary proxy representing a type annotation.
2046      */
2047     static class TypeAnnotationProxy {
2048         final CompoundAnnotationProxy compound;
2049         final TypeAnnotationPosition position;
2050         public TypeAnnotationProxy(CompoundAnnotationProxy compound,
2051                 TypeAnnotationPosition position) {
2052             this.compound = compound;
2053             this.position = position;
2054         }
2055     }
2056 
2057     class AnnotationDeproxy implements ProxyVisitor {
2058         private ClassSymbol requestingOwner;
2059 
2060         AnnotationDeproxy(ClassSymbol owner) {
2061             this.requestingOwner = owner;
2062         }
2063 
2064         List<Attribute.Compound> deproxyCompoundList(List<CompoundAnnotationProxy> pl) {
2065             // also must fill in types!!!!
2066             ListBuffer<Attribute.Compound> buf = new ListBuffer<>();
2067             for (List<CompoundAnnotationProxy> l = pl; l.nonEmpty(); l=l.tail) {
2068                 buf.append(deproxyCompound(l.head));
2069             }
2070             return buf.toList();
2071         }
2072 
2073         Attribute.Compound deproxyCompound(CompoundAnnotationProxy a) {
2074             Type annotationType = resolvePossibleProxyType(a.type);
2075             ListBuffer<Pair<Symbol.MethodSymbol,Attribute>> buf = new ListBuffer<>();
2076             for (List<Pair<Name,Attribute>> l = a.values;
2077                  l.nonEmpty();
2078                  l = l.tail) {
2079                 MethodSymbol meth = findAccessMethod(annotationType, l.head.fst);
2080                 buf.append(new Pair<>(meth, deproxy(meth.type.getReturnType(), l.head.snd)));
2081             }
2082             return new Attribute.Compound(annotationType, buf.toList());
2083         }
2084 
2085         MethodSymbol findAccessMethod(Type container, Name name) {
2086             CompletionFailure failure = null;
2087             try {
2088                 for (Symbol sym : container.tsym.members().getSymbolsByName(name)) {
2089                     if (sym.kind == MTH && sym.type.getParameterTypes().length() == 0)
2090                         return (MethodSymbol) sym;
2091                 }
2092             } catch (CompletionFailure ex) {
2093                 failure = ex;
2094             }
2095             // The method wasn't found: emit a warning and recover
2096             JavaFileObject prevSource = log.useSource(requestingOwner.classfile);
2097             try {
2098                 if (lintClassfile) {
2099                     if (failure == null) {
2100                         log.warning(Warnings.AnnotationMethodNotFound(container, name));
2101                     } else {
2102                         log.warning(Warnings.AnnotationMethodNotFoundReason(container,
2103                                                                             name,
2104                                                                             failure.getDetailValue()));//diagnostic, if present
2105                     }
2106                 }
2107             } finally {
2108                 log.useSource(prevSource);
2109             }
2110             // Construct a new method type and symbol.  Use bottom
2111             // type (typeof null) as return type because this type is
2112             // a subtype of all reference types and can be converted
2113             // to primitive types by unboxing.
2114             MethodType mt = new MethodType(List.nil(),
2115                                            syms.botType,
2116                                            List.nil(),
2117                                            syms.methodClass);
2118             return new MethodSymbol(PUBLIC | ABSTRACT, name, mt, container.tsym);
2119         }
2120 
2121         Attribute result;
2122         Type type;
2123         Attribute deproxy(Type t, Attribute a) {
2124             Type oldType = type;
2125             try {
2126                 type = t;
2127                 a.accept(this);
2128                 return result;
2129             } finally {
2130                 type = oldType;
2131             }
2132         }
2133 
2134         // implement Attribute.Visitor below
2135 
2136         public void visitConstant(Attribute.Constant value) {
2137             // assert value.type == type;
2138             result = value;
2139         }
2140 
2141         public void visitClass(Attribute.Class clazz) {
2142             result = clazz;
2143         }
2144 
2145         public void visitEnum(Attribute.Enum e) {
2146             throw new AssertionError(); // shouldn't happen
2147         }
2148 
2149         public void visitCompound(Attribute.Compound compound) {
2150             throw new AssertionError(); // shouldn't happen
2151         }
2152 
2153         public void visitArray(Attribute.Array array) {
2154             throw new AssertionError(); // shouldn't happen
2155         }
2156 
2157         public void visitError(Attribute.Error e) {
2158             throw new AssertionError(); // shouldn't happen
2159         }
2160 
2161         public void visitEnumAttributeProxy(EnumAttributeProxy proxy) {
2162             // type.tsym.flatName() should == proxy.enumFlatName
2163             Type enumType = resolvePossibleProxyType(proxy.enumType);
2164             TypeSymbol enumTypeSym = enumType.tsym;
2165             VarSymbol enumerator = null;
2166             CompletionFailure failure = null;
2167             try {
2168                 for (Symbol sym : enumTypeSym.members().getSymbolsByName(proxy.enumerator)) {
2169                     if (sym.kind == VAR) {
2170                         enumerator = (VarSymbol)sym;
2171                         break;
2172                     }
2173                 }
2174             }
2175             catch (CompletionFailure ex) {
2176                 failure = ex;
2177             }
2178             if (enumerator == null) {
2179                 if (failure != null) {
2180                     log.warning(Warnings.UnknownEnumConstantReason(currentClassFile,
2181                                                                    enumTypeSym,
2182                                                                    proxy.enumerator,
2183                                                                    failure.getDiagnostic()));
2184                 } else {
2185                     log.warning(Warnings.UnknownEnumConstant(currentClassFile,
2186                                                              enumTypeSym,
2187                                                              proxy.enumerator));
2188                 }
2189                 result = new Attribute.Enum(enumTypeSym.type,
2190                         new VarSymbol(0, proxy.enumerator, syms.botType, enumTypeSym));
2191             } else {
2192                 result = new Attribute.Enum(enumTypeSym.type, enumerator);
2193             }
2194         }
2195 
2196         @Override
2197         public void visitClassAttributeProxy(ClassAttributeProxy proxy) {
2198             Type classType = resolvePossibleProxyType(proxy.classType);
2199             result = new Attribute.Class(types, classType);
2200         }
2201 
2202         public void visitArrayAttributeProxy(ArrayAttributeProxy proxy) {
2203             int length = proxy.values.length();
2204             Attribute[] ats = new Attribute[length];
2205             Type elemtype = types.elemtype(type);
2206             int i = 0;
2207             for (List<Attribute> p = proxy.values; p.nonEmpty(); p = p.tail) {
2208                 ats[i++] = deproxy(elemtype, p.head);
2209             }
2210             result = new Attribute.Array(type, ats);
2211         }
2212 
2213         public void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy) {
2214             result = deproxyCompound(proxy);
2215         }
2216 
2217         Type resolvePossibleProxyType(Type t) {
2218             if (t instanceof ProxyType proxyType) {
2219                 Assert.check(requestingOwner.owner instanceof ModuleSymbol);
2220                 ModuleSymbol prevCurrentModule = currentModule;
2221                 currentModule = (ModuleSymbol) requestingOwner.owner;
2222                 try {
2223                     return proxyType.resolve();
2224                 } finally {
2225                     currentModule = prevCurrentModule;
2226                 }
2227             } else {
2228                 return t;
2229             }
2230         }
2231     }
2232 
2233     class AnnotationDefaultCompleter extends AnnotationDeproxy implements Runnable {
2234         final MethodSymbol sym;
2235         final Attribute value;
2236         final JavaFileObject classFile = currentClassFile;
2237 
2238         AnnotationDefaultCompleter(MethodSymbol sym, Attribute value) {
2239             super(currentOwner.kind == MTH
2240                     ? currentOwner.enclClass() : (ClassSymbol)currentOwner);
2241             this.sym = sym;
2242             this.value = value;
2243         }
2244 
2245         @Override
2246         public void run() {
2247             JavaFileObject previousClassFile = currentClassFile;
2248             try {
2249                 // Reset the interim value set earlier in
2250                 // attachAnnotationDefault().
2251                 sym.defaultValue = null;
2252                 currentClassFile = classFile;
2253                 sym.defaultValue = deproxy(sym.type.getReturnType(), value);
2254             } finally {
2255                 currentClassFile = previousClassFile;
2256             }
2257         }
2258 
2259         @Override
2260         public String toString() {
2261             return " ClassReader store default for " + sym.owner + "." + sym + " is " + value;
2262         }
2263     }
2264 
2265     class AnnotationCompleter extends AnnotationDeproxy implements Runnable {
2266         final Symbol sym;
2267         final List<CompoundAnnotationProxy> l;
2268         final JavaFileObject classFile;
2269 
2270         AnnotationCompleter(Symbol sym, List<CompoundAnnotationProxy> l) {
2271             super(currentOwner.kind == MTH
2272                     ? currentOwner.enclClass() : (ClassSymbol)currentOwner);
2273             if (sym.kind == TYP && sym.owner.kind == MDL) {
2274                 this.sym = sym.owner;
2275             } else {
2276                 this.sym = sym;
2277             }
2278             this.l = l;
2279             this.classFile = currentClassFile;
2280         }
2281 
2282         @Override
2283         public void run() {
2284             JavaFileObject previousClassFile = currentClassFile;
2285             try {
2286                 currentClassFile = classFile;
2287                 List<Attribute.Compound> newList = deproxyCompoundList(l);
2288                 for (Attribute.Compound attr : newList) {
2289                     if (attr.type.tsym == syms.deprecatedType.tsym) {
2290                         sym.flags_field |= (DEPRECATED | DEPRECATED_ANNOTATION);
2291                         Attribute forRemoval = attr.member(names.forRemoval);
2292                         if (forRemoval instanceof Attribute.Constant constant) {
2293                             if (constant.type == syms.booleanType && ((Integer) constant.value) != 0) {
2294                                 sym.flags_field |= DEPRECATED_REMOVAL;
2295                             }
2296                         }
2297                     }
2298                 }
2299                 if (sym.annotationsPendingCompletion()) {
2300                     sym.setDeclarationAttributes(newList);
2301                 } else {
2302                     sym.appendAttributes(newList);
2303                 }
2304             } finally {
2305                 currentClassFile = previousClassFile;
2306             }
2307         }
2308 
2309         @Override
2310         public String toString() {
2311             return " ClassReader annotate " + sym.owner + "." + sym + " with " + l;
2312         }
2313     }
2314 
2315     class TypeAnnotationCompleter extends AnnotationCompleter {
2316 
2317         List<TypeAnnotationProxy> proxies;
2318 
2319         TypeAnnotationCompleter(Symbol sym,
2320                 List<TypeAnnotationProxy> proxies) {
2321             super(sym, List.nil());
2322             this.proxies = proxies;
2323         }
2324 
2325         List<Attribute.TypeCompound> deproxyTypeCompoundList(List<TypeAnnotationProxy> proxies) {
2326             ListBuffer<Attribute.TypeCompound> buf = new ListBuffer<>();
2327             for (TypeAnnotationProxy proxy: proxies) {
2328                 Attribute.Compound compound = deproxyCompound(proxy.compound);
2329                 Attribute.TypeCompound typeCompound = new Attribute.TypeCompound(compound, proxy.position);
2330                 buf.add(typeCompound);
2331             }
2332             return buf.toList();
2333         }
2334 
2335         @Override
2336         public void run() {
2337             JavaFileObject previousClassFile = currentClassFile;
2338             try {
2339                 currentClassFile = classFile;
2340                 List<Attribute.TypeCompound> newList = deproxyTypeCompoundList(proxies);
2341                 sym.setTypeAttributes(newList.prependList(sym.getRawTypeAttributes()));
2342                 addTypeAnnotationsToSymbol(sym, newList);
2343             } finally {
2344                 currentClassFile = previousClassFile;
2345             }
2346         }
2347     }
2348 
2349     /**
2350      * Rewrites types in the given symbol to include type annotations.
2351      *
2352      * <p>The list of type annotations includes annotations for all types in the signature of the
2353      * symbol. Associating the annotations with the correct type requires interpreting the JVMS
2354      * 4.7.20-A target_type to locate the correct type to rewrite, and then interpreting the JVMS
2355      * 4.7.20.2 type_path to associate the annotation with the correct contained type.
2356      */
2357     private void addTypeAnnotationsToSymbol(Symbol s, List<Attribute.TypeCompound> attributes) {
2358         try {
2359             new TypeAnnotationSymbolVisitor(attributes).visit(s, null);
2360         } catch (CompletionFailure ex) {
2361             JavaFileObject prev = log.useSource(currentClassFile);
2362             try {
2363                 log.error(Errors.CantAttachTypeAnnotations(attributes, s.owner, s.name, ex.getDetailValue()));
2364             } finally {
2365                 log.useSource(prev);
2366             }
2367         }
2368     }
2369 
2370     private static class TypeAnnotationSymbolVisitor
2371             extends Types.DefaultSymbolVisitor<Void, Void> {
2372 
2373         private final List<Attribute.TypeCompound> attributes;
2374 
2375         private TypeAnnotationSymbolVisitor(List<Attribute.TypeCompound> attributes) {
2376             this.attributes = attributes;
2377         }
2378 
2379         /**
2380          * A supertype_index value of 65535 specifies that the annotation appears on the superclass
2381          * in an extends clause of a class declaration, see JVMS 4.7.20.1
2382          */
2383         public static final int SUPERCLASS_INDEX = 65535;
2384 
2385         @Override
2386         public Void visitClassSymbol(Symbol.ClassSymbol s, Void unused) {
2387             ClassType t = (ClassType) s.type;
2388             int i = 0;
2389             ListBuffer<Type> interfaces = new ListBuffer<>();
2390             for (Type itf : t.interfaces_field) {
2391                 interfaces.add(addTypeAnnotations(itf, classExtends(i++)));
2392             }
2393             t.interfaces_field = interfaces.toList();
2394             t.supertype_field = addTypeAnnotations(t.supertype_field, classExtends(SUPERCLASS_INDEX));
2395             if (t.typarams_field != null) {
2396                 t.typarams_field =
2397                         rewriteTypeParameters(
2398                                 t.typarams_field, TargetType.CLASS_TYPE_PARAMETER_BOUND);
2399             }
2400             return null;
2401         }
2402 
2403         @Override
2404         public Void visitMethodSymbol(Symbol.MethodSymbol s, Void unused) {
2405             Type t = s.type;
2406             if (t.hasTag(TypeTag.FORALL)) {
2407                 Type.ForAll fa = (Type.ForAll) t;
2408                 fa.tvars = rewriteTypeParameters(fa.tvars, TargetType.METHOD_TYPE_PARAMETER_BOUND);
2409                 t = fa.qtype;
2410             }
2411             MethodType mt = (MethodType) t;
2412             ListBuffer<Type> argtypes = new ListBuffer<>();
2413             int i = 0;
2414             for (Symbol.VarSymbol param : s.params) {
2415                 param.type = addTypeAnnotations(param.type, methodFormalParameter(i++));
2416                 argtypes.add(param.type);
2417             }
2418             mt.argtypes = argtypes.toList();
2419             ListBuffer<Type> thrown = new ListBuffer<>();
2420             i = 0;
2421             for (Type thrownType : mt.thrown) {
2422                 thrown.add(addTypeAnnotations(thrownType, thrownType(i++)));
2423             }
2424             mt.thrown = thrown.toList();
2425             /* possible information loss if the type of the method is void then we can't add type
2426              * annotations to it
2427              */
2428             if (!mt.restype.hasTag(TypeTag.VOID)) {
2429                 mt.restype = addTypeAnnotations(mt.restype, TargetType.METHOD_RETURN);
2430             }
2431 
2432             Type recvtype = mt.recvtype != null ? mt.recvtype : s.implicitReceiverType();
2433             if (recvtype != null) {
2434                 Type annotated = addTypeAnnotations(recvtype, TargetType.METHOD_RECEIVER);
2435                 if (annotated != recvtype) {
2436                     mt.recvtype = annotated;
2437                 }
2438             }
2439             return null;
2440         }
2441 
2442         @Override
2443         public Void visitVarSymbol(Symbol.VarSymbol s, Void unused) {
2444             s.type = addTypeAnnotations(s.type, TargetType.FIELD);
2445             return null;
2446         }
2447 
2448         @Override
2449         public Void visitSymbol(Symbol s, Void unused) {
2450             return null;
2451         }
2452 
2453         private List<Type> rewriteTypeParameters(List<Type> tvars, TargetType boundType) {
2454             ListBuffer<Type> tvarbuf = new ListBuffer<>();
2455             int typeVariableIndex = 0;
2456             for (Type tvar : tvars) {
2457                 Type bound = tvar.getUpperBound();
2458                 if (bound.isCompound()) {
2459                     ClassType ct = (ClassType) bound;
2460                     int boundIndex = 0;
2461                     if (ct.supertype_field != null) {
2462                         ct.supertype_field =
2463                                 addTypeAnnotations(
2464                                         ct.supertype_field,
2465                                         typeParameterBound(
2466                                                 boundType, typeVariableIndex, boundIndex++));
2467                     }
2468                     ListBuffer<Type> itfbuf = new ListBuffer<>();
2469                     for (Type itf : ct.interfaces_field) {
2470                         itfbuf.add(
2471                                 addTypeAnnotations(
2472                                         itf,
2473                                         typeParameterBound(
2474                                                 boundType, typeVariableIndex, boundIndex++)));
2475                     }
2476                     ct.interfaces_field = itfbuf.toList();
2477                 } else {
2478                     bound =
2479                             addTypeAnnotations(
2480                                     bound,
2481                                     typeParameterBound(
2482                                             boundType,
2483                                             typeVariableIndex,
2484                                             bound.isInterface() ? 1 : 0));
2485                 }
2486                 ((TypeVar) tvar).setUpperBound(bound);
2487                 tvarbuf.add(tvar);
2488                 typeVariableIndex++;
2489             }
2490             return tvarbuf.toList();
2491         }
2492 
2493         private Type addTypeAnnotations(Type type, TargetType targetType) {
2494             return addTypeAnnotations(type, pos -> pos.type == targetType);
2495         }
2496 
2497         private Type addTypeAnnotations(Type type, Predicate<TypeAnnotationPosition> filter) {
2498             Assert.checkNonNull(type);
2499 
2500             // Find type annotations that match the given target type
2501             ListBuffer<Attribute.TypeCompound> filtered = new ListBuffer<>();
2502             for (Attribute.TypeCompound attribute : this.attributes) {
2503                 if (filter.test(attribute.position)) {
2504                     filtered.add(attribute);
2505                 }
2506             }
2507             if (filtered.isEmpty()) {
2508                 return type;
2509             }
2510 
2511             // Group the matching annotations by their type path. Each group of annotations will be
2512             // added to a type at that location.
2513             Map<List<TypeAnnotationPosition.TypePathEntry>, ListBuffer<Attribute.TypeCompound>>
2514                     attributesByPath = new HashMap<>();
2515             for (Attribute.TypeCompound attribute : filtered.toList()) {
2516                 attributesByPath
2517                         .computeIfAbsent(attribute.position.location, k -> new ListBuffer<>())
2518                         .add(attribute);
2519             }
2520 
2521             // Rewrite the type and add the annotations
2522             type = new TypeAnnotationStructuralTypeMapping(attributesByPath).visit(type, List.nil());
2523 
2524             return type;
2525         }
2526 
2527         private static Predicate<TypeAnnotationPosition> typeParameterBound(
2528                 TargetType targetType, int parameterIndex, int boundIndex) {
2529             return pos ->
2530                     pos.type == targetType
2531                             && pos.parameter_index == parameterIndex
2532                             && pos.bound_index == boundIndex;
2533         }
2534 
2535         private static Predicate<TypeAnnotationPosition> methodFormalParameter(int index) {
2536             return pos ->
2537                     pos.type == TargetType.METHOD_FORMAL_PARAMETER && pos.parameter_index == index;
2538         }
2539 
2540         private static Predicate<TypeAnnotationPosition> thrownType(int index) {
2541             return pos -> pos.type == TargetType.THROWS && pos.type_index == index;
2542         }
2543 
2544         private static Predicate<TypeAnnotationPosition> classExtends(int index) {
2545             return pos -> pos.type == TargetType.CLASS_EXTENDS && pos.type_index == index;
2546         }
2547     }
2548 
2549     /**
2550      * A type mapping that rewrites the type to include type annotations.
2551      *
2552      * <p>This logic is similar to {@link Type.StructuralTypeMapping}, but also tracks the path to
2553      * the contained types being rewritten, and so cannot easily share the existing logic.
2554      */
2555     private static final class TypeAnnotationStructuralTypeMapping
2556             extends Types.TypeMapping<List<TypeAnnotationPosition.TypePathEntry>> {
2557 
2558         private final Map<List<TypeAnnotationPosition.TypePathEntry>,
2559                 ListBuffer<Attribute.TypeCompound>> attributesByPath;
2560 
2561         private TypeAnnotationStructuralTypeMapping(
2562                 Map<List<TypeAnnotationPosition.TypePathEntry>, ListBuffer<Attribute.TypeCompound>>
2563                     attributesByPath) {
2564             this.attributesByPath = attributesByPath;
2565         }
2566 
2567 
2568         @Override
2569         public Type visitClassType(ClassType t, List<TypeAnnotationPosition.TypePathEntry> path) {
2570             // As described in JVMS 4.7.20.2, type annotations on nested types are located with
2571             // 'left-to-right' steps starting on 'the outermost part of the type for which a type
2572             // annotation is admissible'. So the current path represents the outermost containing
2573             // type of the type being visited, and we add type path steps for every contained nested
2574             // type.
2575             Type outer = t.getEnclosingType();
2576             Type outer1 = outer != Type.noType ? visit(outer, path) : outer;
2577             for (Type curr = t.getEnclosingType();
2578                     curr != Type.noType;
2579                     curr = curr.getEnclosingType()) {
2580                 path = path.append(TypeAnnotationPosition.TypePathEntry.INNER_TYPE);
2581             }
2582             List<Type> typarams = t.getTypeArguments();
2583             List<Type> typarams1 = rewriteTypeParams(path, typarams);
2584             if (outer1 != outer || typarams != typarams1) {
2585                 t = new ClassType(outer1, typarams1, t.tsym, t.getMetadata());
2586             }
2587             return reannotate(t, path);
2588         }
2589 
2590         private List<Type> rewriteTypeParams(
2591                 List<TypeAnnotationPosition.TypePathEntry> path, List<Type> typarams) {
2592             var i = IntStream.iterate(0, x -> x + 1).iterator();
2593             return typarams.map(typaram -> visit(typaram,
2594                     path.append(new TypeAnnotationPosition.TypePathEntry(
2595                             TypeAnnotationPosition.TypePathEntryKind.TYPE_ARGUMENT, i.nextInt()))));
2596         }
2597 
2598         @Override
2599         public Type visitWildcardType(
2600                 WildcardType wt, List<TypeAnnotationPosition.TypePathEntry> path) {
2601             Type t = wt.type;
2602             if (t != null) {
2603                 t = visit(t, path.append(TypeAnnotationPosition.TypePathEntry.WILDCARD));
2604             }
2605             if (t != wt.type) {
2606                 wt = new WildcardType(t, wt.kind, wt.tsym, wt.bound, wt.getMetadata());
2607             }
2608             return reannotate(wt, path);
2609         }
2610 
2611         @Override
2612         public Type visitArrayType(ArrayType t, List<TypeAnnotationPosition.TypePathEntry> path) {
2613             Type elemtype = t.elemtype;
2614             Type elemtype1 =
2615                     visit(elemtype, path.append(TypeAnnotationPosition.TypePathEntry.ARRAY));
2616             if (elemtype1 != elemtype)  {
2617                 t = new ArrayType(elemtype1, t.tsym, t.getMetadata());
2618             }
2619             return reannotate(t, path);
2620         }
2621 
2622         @Override
2623         public Type visitType(Type t, List<TypeAnnotationPosition.TypePathEntry> path) {
2624             return reannotate(t, path);
2625         }
2626 
2627         Type reannotate(Type type, List<TypeAnnotationPosition.TypePathEntry> path) {
2628             List<Attribute.TypeCompound> attributes = attributesForPath(path);
2629             if (attributes.isEmpty()) {
2630                 return type;
2631             }
2632             // Runtime-visible and -invisible annotations are completed separately, so if the same
2633             // type has annotations from both it will get annotated twice.
2634             TypeMetadata.Annotations existing = type.getMetadata(TypeMetadata.Annotations.class);
2635             if (existing != null) {
2636                 existing.annotationBuffer().addAll(attributes);
2637                 return type;
2638             }
2639             return type.annotatedType(attributes);
2640         }
2641 
2642         List<Attribute.TypeCompound> attributesForPath(
2643                 List<TypeAnnotationPosition.TypePathEntry> path) {
2644             ListBuffer<Attribute.TypeCompound> attributes = attributesByPath.remove(path);
2645             return attributes != null ? attributes.toList() : List.nil();
2646         }
2647     }
2648 
2649 /* **********************************************************************
2650  * Reading Symbols
2651  ***********************************************************************/
2652 
2653     /** Read a field.
2654      */
2655     VarSymbol readField() {
2656         char rawFlags = nextChar();
2657         long flags = adjustFieldFlags(rawFlags);
2658         Name name = poolReader.getName(nextChar());
2659         Type type = poolReader.getType(nextChar());
2660         VarSymbol v = new VarSymbol(flags, name, type, currentOwner);
2661         readMemberAttrs(v);
2662         if (Integer.bitCount(rawFlags & (PUBLIC | PRIVATE | PROTECTED)) > 1 ||
2663             Integer.bitCount(rawFlags & (FINAL | VOLATILE)) > 1)
2664             throw badClassFile("illegal.flag.combo", Flags.toString((long)rawFlags), "field", v);
2665         return v;
2666     }
2667 
2668     /** Read a method.
2669      */
2670     MethodSymbol readMethod() {
2671         char rawFlags = nextChar();
2672         long flags = adjustMethodFlags(rawFlags);
2673         Name name = poolReader.getName(nextChar());
2674         Type descriptorType = poolReader.getType(nextChar());
2675         Type type = descriptorType;
2676         if (currentOwner.isInterface() &&
2677                 (flags & ABSTRACT) == 0 && !name.equals(names.clinit)) {
2678             if (majorVersion > Version.V52.major ||
2679                     (majorVersion == Version.V52.major && minorVersion >= Version.V52.minor)) {
2680                 if ((flags & (STATIC | PRIVATE)) == 0) {
2681                     currentOwner.flags_field |= DEFAULT;
2682                     flags |= DEFAULT | ABSTRACT;
2683                 }
2684             } else {
2685                 //protect against ill-formed classfiles
2686                 throw badClassFile((flags & STATIC) == 0 ? "invalid.default.interface" : "invalid.static.interface",
2687                                    Integer.toString(majorVersion),
2688                                    Integer.toString(minorVersion));
2689             }
2690         }
2691         validateMethodType(name, type);
2692         boolean forceLocal = false;
2693         if (name == names.init && currentOwner.hasOuterInstance()) {
2694             // Sometimes anonymous classes don't have an outer
2695             // instance, however, there is no reliable way to tell so
2696             // we never strip this$n
2697             // ditto for local classes. Local classes that have an enclosing method set
2698             // won't pass the "hasOuterInstance" check above, but those that don't have an
2699             // enclosing method (i.e. from initializers) will pass that check.
2700             boolean local = forceLocal =
2701                     !currentOwner.owner.members().includes(currentOwner, LookupKind.NON_RECURSIVE);
2702             if (!currentOwner.name.isEmpty() && !local)
2703                 type = new MethodType(adjustMethodParams(flags, type.getParameterTypes()),
2704                                       type.getReturnType(),
2705                                       type.getThrownTypes(),
2706                                       syms.methodClass);
2707         }
2708         MethodSymbol m = new MethodSymbol(flags, name, type, currentOwner);
2709         if (types.isSignaturePolymorphic(m)) {
2710             m.flags_field |= SIGNATURE_POLYMORPHIC;
2711         }
2712         if (saveParameterNames)
2713             initParameterNames(m);
2714         Symbol prevOwner = currentOwner;
2715         currentOwner = m;
2716         try {
2717             readMemberAttrs(m);
2718         } finally {
2719             currentOwner = prevOwner;
2720         }
2721         validateMethodType(name, m.type);
2722         adjustParameterAnnotations(m, descriptorType, forceLocal);
2723         setParameters(m, type);
2724 
2725         if (Integer.bitCount(rawFlags & (PUBLIC | PRIVATE | PROTECTED)) > 1)
2726             throw badClassFile("illegal.flag.combo", Flags.toString((long)rawFlags), "method", m);
2727         if ((flags & VARARGS) != 0) {
2728             final Type last = type.getParameterTypes().last();
2729             if (last == null || !last.hasTag(ARRAY)) {
2730                 m.flags_field &= ~VARARGS;
2731                 throw badClassFile("malformed.vararg.method", m);
2732             }
2733         }
2734 
2735         return m;
2736     }
2737 
2738     void validateMethodType(Name name, Type t) {
2739         if ((!t.hasTag(TypeTag.METHOD) && !t.hasTag(TypeTag.FORALL)) ||
2740             (name == names.init && !t.getReturnType().hasTag(TypeTag.VOID))) {
2741             throw badClassFile("method.descriptor.invalid", name);
2742         }
2743     }
2744 
2745     private List<Type> adjustMethodParams(long flags, List<Type> args) {
2746         if (args.isEmpty()) {
2747             return args;
2748         }
2749         boolean isVarargs = (flags & VARARGS) != 0;
2750         if (isVarargs) {
2751             Type varargsElem = args.last();
2752             ListBuffer<Type> adjustedArgs = new ListBuffer<>();
2753             for (Type t : args) {
2754                 adjustedArgs.append(t != varargsElem ?
2755                     t :
2756                     ((ArrayType)t).makeVarargs());
2757             }
2758             args = adjustedArgs.toList();
2759         }
2760         return args.tail;
2761     }
2762 
2763     /**
2764      * Init the parameter names array.
2765      * Parameter names are currently inferred from the names in the
2766      * LocalVariableTable attributes of a Code attribute.
2767      * (Note: this means parameter names are currently not available for
2768      * methods without a Code attribute.)
2769      * This method initializes an array in which to store the name indexes
2770      * of parameter names found in LocalVariableTable attributes. It is
2771      * slightly supersized to allow for additional slots with a start_pc of 0.
2772      */
2773     void initParameterNames(MethodSymbol sym) {
2774         // make allowance for synthetic parameters.
2775         final int excessSlots = 4;
2776         int expectedParameterSlots =
2777                 Code.width(sym.type.getParameterTypes()) + excessSlots;
2778         if (parameterNameIndicesLvt == null
2779                 || parameterNameIndicesLvt.length < expectedParameterSlots) {
2780             parameterNameIndicesLvt = new int[expectedParameterSlots];
2781         } else
2782             Arrays.fill(parameterNameIndicesLvt, 0);
2783     }
2784 
2785     /**
2786      * Set the parameters for a method symbol, including any names and
2787      * annotations that were read.
2788      *
2789      * <p>The type of the symbol may have changed while reading the
2790      * method attributes (see the Signature attribute). This may be
2791      * because of generic information or because anonymous synthetic
2792      * parameters were added.   The original type (as read from the
2793      * method descriptor) is used to help guess the existence of
2794      * anonymous synthetic parameters.
2795      */
2796     void setParameters(MethodSymbol sym, Type jvmType) {
2797         int firstParamLvt = ((sym.flags() & STATIC) == 0) ? 1 : 0;
2798         // the code in readMethod may have skipped the first
2799         // parameter when setting up the MethodType. If so, we
2800         // make a corresponding allowance here for the position of
2801         // the first parameter.  Note that this assumes the
2802         // skipped parameter has a width of 1 -- i.e. it is not
2803         // a double width type (long or double.)
2804         if (sym.name == names.init && currentOwner.hasOuterInstance()) {
2805             // Sometimes anonymous classes don't have an outer
2806             // instance, however, there is no reliable way to tell so
2807             // we never strip this$n
2808             if (!currentOwner.name.isEmpty())
2809                 firstParamLvt += 1;
2810         }
2811 
2812         if (sym.type != jvmType) {
2813             // reading the method attributes has caused the
2814             // symbol's type to be changed. (i.e. the Signature
2815             // attribute.)  This may happen if there are hidden
2816             // (synthetic) parameters in the descriptor, but not
2817             // in the Signature.  The position of these hidden
2818             // parameters is unspecified; for now, assume they are
2819             // at the beginning, and so skip over them. The
2820             // primary case for this is two hidden parameters
2821             // passed into Enum constructors.
2822             int skip = Code.width(jvmType.getParameterTypes())
2823                     - Code.width(sym.type.getParameterTypes());
2824             firstParamLvt += skip;
2825         }
2826         Set<Name> paramNames = new HashSet<>();
2827         ListBuffer<VarSymbol> params = new ListBuffer<>();
2828         // we maintain two index pointers, one for the LocalVariableTable attribute
2829         // and the other for the MethodParameters attribute.
2830         // This is needed as the MethodParameters attribute may contain
2831         // name_index = 0 in which case we want to fall back to the LocalVariableTable.
2832         // In such case, we still want to read the flags from the MethodParameters with that index.
2833         int nameIndexLvt = firstParamLvt;
2834         int nameIndexMp = 0;
2835         int annotationIndex = 0;
2836         for (Type t: sym.type.getParameterTypes()) {
2837             VarSymbol param = parameter(nameIndexMp, nameIndexLvt, t, sym, paramNames);
2838             params.append(param);
2839             if (parameterAnnotations != null) {
2840                 ParameterAnnotations annotations = parameterAnnotations[annotationIndex];
2841                 if (annotations != null && annotations.proxies != null
2842                         && !annotations.proxies.isEmpty()) {
2843                     annotate.normal(new AnnotationCompleter(param, annotations.proxies));
2844                 }
2845             }
2846             nameIndexLvt += Code.width(t);
2847             nameIndexMp++;
2848             annotationIndex++;
2849         }
2850         Assert.check(parameterAnnotations == null ||
2851                      parameterAnnotations.length == annotationIndex);
2852         Assert.checkNull(sym.params);
2853         sym.params = params.toList();
2854         parameterAnnotations = null;
2855         parameterNameIndicesLvt = null;
2856         parameterNameIndicesMp = null;
2857         allParameterAccessFlags = null;
2858         parameterAccessFlags = null;
2859     }
2860 
2861     void adjustParameterAnnotations(MethodSymbol sym, Type methodDescriptor,
2862                                     boolean forceLocal) {
2863         if (parameterAnnotations == null) {
2864             return ;
2865         }
2866 
2867         //the specification for Runtime(In)VisibleParameterAnnotations does not
2868         //enforce any mapping between the method parameters and the recorded
2869         //parameter annotation. Attempt a number of heuristics to adjust the
2870         //adjust parameterAnnotations to the percieved number of parameters:
2871 
2872         int methodParameterCount = sym.type.getParameterTypes().size();
2873 
2874         if (methodParameterCount == parameterAnnotations.length) {
2875             //we've got exactly as many parameter annotations as are parameters
2876             //of the method (after considering a possible Signature attribute),
2877             //no need to do anything. the parameter creation code will use
2878             //the 1-1 mapping to restore the annotations:
2879             return ;
2880         }
2881 
2882         if (allParameterAccessFlags != null) {
2883             //MethodParameters attribute present, use it:
2884 
2885             //count the number of non-synthetic and non-mandatory parameters:
2886             int realParameters = 0;
2887 
2888             for (int i = 0; i < allParameterAccessFlags.length; i++) {
2889                 if ((allParameterAccessFlags[i] & (SYNTHETIC | MANDATED)) == 0) {
2890                     realParameters++;
2891                 }
2892             }
2893 
2894             int methodDescriptorParameterCount = methodDescriptor.getParameterTypes().size();
2895 
2896             if (realParameters == parameterAnnotations.length &&
2897                 allParameterAccessFlags.length == methodDescriptorParameterCount) {
2898                 //if we have parameter annotations for each non-synthetic/mandatory parameter,
2899                 //and if Signature was not present, expand the parameterAnnotations to cover
2900                 //all the method descriptor's parameters:
2901                 if (sym.type == methodDescriptor) {
2902                     ParameterAnnotations[] newParameterAnnotations =
2903                             new ParameterAnnotations[methodParameterCount];
2904                     int srcIndex = 0;
2905 
2906                     for (int i = 0; i < methodParameterCount; i++) {
2907                         if ((allParameterAccessFlags[i] & (SYNTHETIC | MANDATED)) == 0) {
2908                             newParameterAnnotations[i] = parameterAnnotations[srcIndex++];
2909                         }
2910                     }
2911 
2912                     parameterAnnotations = newParameterAnnotations;
2913                 } else {
2914                     dropParameterAnnotations();
2915                 }
2916             } else if (realParameters == methodParameterCount &&
2917                        methodDescriptorParameterCount == parameterAnnotations.length &&
2918                        allParameterAccessFlags.length == methodDescriptorParameterCount) {
2919                 //if there are as many parameter annotations as parameters in
2920                 //the method descriptor, and as many real parameters as parameters
2921                 //in the method's type (after accounting for Signature), shrink
2922                 //the parameterAnnotations to only cover the parameters from
2923                 //the method's type:
2924                 ParameterAnnotations[] newParameterAnnotations =
2925                         new ParameterAnnotations[methodParameterCount];
2926                 int targetIndex = 0;
2927 
2928                 for (int i = 0; i < parameterAnnotations.length; i++) {
2929                     if ((allParameterAccessFlags[i] & (SYNTHETIC | MANDATED)) == 0) {
2930                         newParameterAnnotations[targetIndex++] = parameterAnnotations[i];
2931                     }
2932                 }
2933 
2934                 parameterAnnotations = newParameterAnnotations;
2935             } else {
2936                 dropParameterAnnotations();
2937             }
2938             return ;
2939         }
2940 
2941         if (!sym.isConstructor()) {
2942             //if the number of parameter annotations and the number of parameters
2943             //don't match, we don't have any heuristics to map one to the other
2944             //unless the method is a constructor:
2945             dropParameterAnnotations();
2946             return ;
2947         }
2948 
2949         if (sym.owner.isEnum()) {
2950             if (methodParameterCount == parameterAnnotations.length + 2 &&
2951                 sym.type == methodDescriptor) {
2952                 //handle constructors of enum types without the Signature attribute -
2953                 //there are the two synthetic parameters (name and ordinal) in the
2954                 //constructor, but there may be only parameter annotations for the
2955                 //real non-synthetic parameters:
2956                 ParameterAnnotations[] newParameterAnnotations = new ParameterAnnotations[parameterAnnotations.length + 2];
2957                 System.arraycopy(parameterAnnotations, 0, newParameterAnnotations, 2, parameterAnnotations.length);
2958                 parameterAnnotations = newParameterAnnotations;
2959                 return ;
2960             }
2961         } else if (sym.owner.isDirectlyOrIndirectlyLocal() || forceLocal) {
2962             //local class may capture the enclosing instance (as the first parameter),
2963             //and local variables (as trailing parameters)
2964             //if there are less parameter annotations than parameters, put the existing
2965             //ones starting with offset:
2966             if (methodParameterCount > parameterAnnotations.length &&
2967                 sym.type == methodDescriptor) {
2968                 ParameterAnnotations[] newParameterAnnotations = new ParameterAnnotations[methodParameterCount];
2969                 System.arraycopy(parameterAnnotations, 0, newParameterAnnotations, 1, parameterAnnotations.length);
2970                 parameterAnnotations = newParameterAnnotations;
2971                 return ;
2972             }
2973         }
2974 
2975         //no heuristics worked, drop the annotations:
2976         dropParameterAnnotations();
2977     }
2978 
2979     private void dropParameterAnnotations() {
2980         parameterAnnotations = null;
2981         if (lintClassfile) {
2982             log.warning(LintCategory.CLASSFILE, Warnings.RuntimeInvisibleParameterAnnotations(currentClassFile));
2983         }
2984     }
2985     /**
2986      * Creates the parameter at the position {@code mpIndex} in the parameter list of the owning method.
2987      * Flags are optionally read from the MethodParameters attribute.
2988      * Names are optionally read from the MethodParameters attribute. If the constant pool index
2989      * of the name is 0, then the name is optionally read from the LocalVariableTable attribute.
2990      * @param mpIndex the index of the parameter in the MethodParameters attribute
2991      * @param lvtIndex the index of the parameter in the LocalVariableTable attribute
2992      */
2993     private VarSymbol parameter(int mpIndex, int lvtIndex, Type t, MethodSymbol owner, Set<Name> exclude) {
2994         long flags = PARAMETER;
2995         Name argName;
2996         if (parameterAccessFlags != null && mpIndex < parameterAccessFlags.length
2997                 && parameterAccessFlags[mpIndex] != 0) {
2998             flags |= parameterAccessFlags[mpIndex];
2999         }
3000         if (parameterNameIndicesMp != null && mpIndex < parameterNameIndicesMp.length
3001                 // if name_index is 0, then we might still get a name from the LocalVariableTable
3002                 && parameterNameIndicesMp[mpIndex] != 0) {
3003             argName = optPoolEntry(parameterNameIndicesMp[mpIndex], poolReader::getName, names.empty);
3004             flags |= NAME_FILLED;
3005         } else if (parameterNameIndicesLvt != null && lvtIndex < parameterNameIndicesLvt.length
3006                 && parameterNameIndicesLvt[lvtIndex] != 0) {
3007             argName = optPoolEntry(parameterNameIndicesLvt[lvtIndex], poolReader::getName, names.empty);
3008             flags |= NAME_FILLED;
3009         } else {
3010             String prefix = "arg";
3011             while (true) {
3012                 argName = names.fromString(prefix + exclude.size());
3013                 if (!exclude.contains(argName))
3014                     break;
3015                 prefix += "$";
3016             }
3017         }
3018         exclude.add(argName);
3019         return new ParamSymbol(flags, argName, t, owner);
3020     }
3021 
3022     /**
3023      * skip n bytes
3024      */
3025     void skipBytes(int n) {
3026         bp = bp + n;
3027     }
3028 
3029     /** Skip a field or method
3030      */
3031     void skipMember() {
3032         bp = bp + 6;
3033         char ac = nextChar();
3034         for (int i = 0; i < ac; i++) {
3035             bp = bp + 2;
3036             int attrLen = nextInt();
3037             bp = bp + attrLen;
3038         }
3039     }
3040 
3041     void skipInnerClasses() {
3042         int n = nextChar();
3043         for (int i = 0; i < n; i++) {
3044             nextChar();
3045             nextChar();
3046             nextChar();
3047             nextChar();
3048         }
3049     }
3050 
3051     /** Enter type variables of this classtype and all enclosing ones in
3052      *  `typevars'.
3053      */
3054     protected void enterTypevars(Symbol sym, Type t) {
3055         if (t.getEnclosingType() != null) {
3056             if (!t.getEnclosingType().hasTag(TypeTag.NONE)) {
3057                 enterTypevars(sym.owner, t.getEnclosingType());
3058             }
3059         } else if (sym.kind == MTH && !sym.isStatic()) {
3060             enterTypevars(sym.owner, sym.owner.type);
3061         }
3062         for (List<Type> xs = t.getTypeArguments(); xs.nonEmpty(); xs = xs.tail) {
3063             typevars.enter(xs.head.tsym);
3064         }
3065     }
3066 
3067     protected ClassSymbol enterClass(Name name) {
3068         return syms.enterClass(currentModule, name);
3069     }
3070 
3071     protected ClassSymbol enterClass(Name name, TypeSymbol owner) {
3072         return syms.enterClass(currentModule, name, owner);
3073     }
3074 
3075     /** Read contents of a given class symbol `c'. Both external and internal
3076      *  versions of an inner class are read.
3077      */
3078     void readClass(ClassSymbol c) {
3079         ClassType ct = (ClassType)c.type;
3080 
3081         // allocate scope for members
3082         c.members_field = WriteableScope.create(c);
3083 
3084         // prepare type variable table
3085         typevars = typevars.dup(currentOwner);
3086         if (ct.getEnclosingType().hasTag(CLASS))
3087             enterTypevars(c.owner, ct.getEnclosingType());
3088 
3089         // read flags, or skip if this is an inner class
3090         long f = nextChar();
3091         long flags = adjustClassFlags(c, f);
3092         if ((flags & MODULE) == 0) {
3093             if (c.owner.kind == PCK || c.owner.kind == ERR) c.flags_field = flags;
3094             // read own class name and check that it matches
3095             currentModule = c.packge().modle;
3096             ClassSymbol self = poolReader.getClass(nextChar());
3097             if (c != self) {
3098                 throw badClassFile("class.file.wrong.class",
3099                                    self.flatname);
3100             }
3101         } else {
3102             if (majorVersion < Version.V53.major) {
3103                 throw badClassFile("anachronistic.module.info",
3104                         Integer.toString(majorVersion),
3105                         Integer.toString(minorVersion));
3106             }
3107             c.flags_field = flags;
3108             if (c.owner.kind != MDL) {
3109                 throw badClassFile("module.info.definition.expected");
3110             }
3111             currentModule = (ModuleSymbol) c.owner;
3112             int this_class = nextChar();
3113             // temp, no check on this_class
3114         }
3115 
3116         // class attributes must be read before class
3117         // skip ahead to read class attributes
3118         int startbp = bp;
3119         nextChar();
3120         char interfaceCount = nextChar();
3121         bp += interfaceCount * 2;
3122         char fieldCount = nextChar();
3123         for (int i = 0; i < fieldCount; i++) skipMember();
3124         char methodCount = nextChar();
3125         for (int i = 0; i < methodCount; i++) skipMember();
3126         readClassAttrs(c);
3127 
3128         if (!c.getPermittedSubclasses().isEmpty()) {
3129             c.flags_field |= SEALED;
3130         }
3131 
3132         // reset and read rest of classinfo
3133         bp = startbp;
3134         int n = nextChar();
3135         if ((flags & MODULE) != 0 && n > 0) {
3136             throw badClassFile("module.info.invalid.super.class");
3137         }
3138         if (ct.supertype_field == null)
3139             ct.supertype_field =
3140                     optPoolEntry(n, idx -> poolReader.getClass(idx).erasure(types), Type.noType);
3141         n = nextChar();
3142         List<Type> is = List.nil();
3143         for (int i = 0; i < n; i++) {
3144             Type _inter = poolReader.getClass(nextChar()).erasure(types);
3145             is = is.prepend(_inter);
3146         }
3147         if (ct.interfaces_field == null)
3148             ct.interfaces_field = is.reverse();
3149 
3150         Assert.check(fieldCount == nextChar());
3151         for (int i = 0; i < fieldCount; i++) enterMember(c, readField());
3152         Assert.check(methodCount == nextChar());
3153         for (int i = 0; i < methodCount; i++) enterMember(c, readMethod());
3154         if (c.isRecord()) {
3155             for (RecordComponent rc: c.getRecordComponents()) {
3156                 rc.accessor = lookupMethod(c, rc.name, List.nil());
3157             }
3158         }
3159         typevars = typevars.leave();
3160     }
3161 
3162     private MethodSymbol lookupMethod(TypeSymbol tsym, Name name, List<Type> argtypes) {
3163         for (Symbol s : tsym.members().getSymbolsByName(name, s -> s.kind == MTH)) {
3164             if (types.isSameTypes(s.type.getParameterTypes(), argtypes)) {
3165                 return (MethodSymbol) s;
3166             }
3167         }
3168         return null;
3169     }
3170 
3171     /** Read inner class info. For each inner/outer pair allocate a
3172      *  member class.
3173      */
3174     void readInnerClasses(ClassSymbol c) {
3175         int n = nextChar();
3176         for (int i = 0; i < n; i++) {
3177             nextChar(); // skip inner class symbol
3178             int outerIdx = nextChar();
3179             int nameIdx = nextChar();
3180             ClassSymbol outer = optPoolEntry(outerIdx, poolReader::getClass, null);
3181             Name name = optPoolEntry(nameIdx, poolReader::getName, names.empty);
3182             if (name == null) name = names.empty;
3183             long flags = adjustClassFlags(c, nextChar());
3184             if (outer != null) { // we have a member class
3185                 if (name == names.empty)
3186                     name = names.one;
3187                 ClassSymbol member = enterClass(name, outer);
3188                 if ((flags & STATIC) == 0) {
3189                     ((ClassType)member.type).setEnclosingType(outer.type);
3190                     if (member.erasure_field != null)
3191                         ((ClassType)member.erasure_field).setEnclosingType(types.erasure(outer.type));
3192                 }
3193                 if (c == outer && member.owner == c) {
3194                     member.flags_field = flags;
3195                     enterMember(c, member);
3196                 }
3197             }
3198         }
3199     }
3200 
3201     /** Read a class definition from the bytes in buf.
3202      */
3203     private void readClassBuffer(ClassSymbol c) throws IOException {
3204         int magic = nextInt();
3205         if (magic != JAVA_MAGIC)
3206             throw badClassFile("illegal.start.of.class.file");
3207 
3208         minorVersion = nextChar();
3209         majorVersion = nextChar();
3210         int maxMajor = Version.MAX().major;
3211         int maxMinor = Version.MAX().minor;
3212         boolean previewClassFile =
3213                 minorVersion == ClassFile.PREVIEW_MINOR_VERSION;
3214         if (majorVersion > maxMajor ||
3215             majorVersion * 1000 + minorVersion <
3216             Version.MIN().major * 1000 + Version.MIN().minor) {
3217             if (majorVersion == (maxMajor + 1) && !previewClassFile)
3218                 log.warning(Warnings.BigMajorVersion(currentClassFile,
3219                                                      majorVersion,
3220                                                      maxMajor));
3221             else
3222                 throw badClassFile("wrong.version",
3223                                    Integer.toString(majorVersion),
3224                                    Integer.toString(minorVersion),
3225                                    Integer.toString(maxMajor),
3226                                    Integer.toString(maxMinor));
3227         }
3228         utf8validation = majorVersion < V48.major ? Convert.Validation.PREJDK14 : Convert.Validation.STRICT;
3229 
3230         if (previewClassFile) {
3231             if (!preview.isEnabled()) {
3232                 log.error(preview.disabledError(currentClassFile, majorVersion));
3233             } else {
3234                 preview.warnPreview(c.classfile, majorVersion);
3235             }
3236         }
3237 
3238         poolReader = new PoolReader(this, names, syms);
3239         bp = poolReader.readPool(buf, bp);
3240         if (signatureBuffer.length < bp) {
3241             int ns = Integer.highestOneBit(bp) << 1;
3242             signatureBuffer = new byte[ns];
3243         }
3244         readClass(c);
3245     }
3246 
3247     public void readClassFile(ClassSymbol c) {
3248         currentOwner = c;
3249         currentClassFile = c.classfile;
3250         warnedAttrs.clear();
3251         filling = true;
3252         target = null;
3253         repeatable = null;
3254         try {
3255             bp = 0;
3256             buf.reset();
3257             try (InputStream input = c.classfile.openInputStream()) {
3258                 buf.appendStream(input);
3259             }
3260             readClassBuffer(c);
3261             if (!missingTypeVariables.isEmpty() && !foundTypeVariables.isEmpty()) {
3262                 List<Type> missing = missingTypeVariables;
3263                 List<Type> found = foundTypeVariables;
3264                 missingTypeVariables = List.nil();
3265                 foundTypeVariables = List.nil();
3266                 interimUses = List.nil();
3267                 interimProvides = List.nil();
3268                 filling = false;
3269                 ClassType ct = (ClassType)currentOwner.type;
3270                 ct.supertype_field =
3271                     types.subst(ct.supertype_field, missing, found);
3272                 ct.interfaces_field =
3273                     types.subst(ct.interfaces_field, missing, found);
3274                 ct.typarams_field =
3275                     types.substBounds(ct.typarams_field, missing, found);
3276                 for (List<Type> types = ct.typarams_field; types.nonEmpty(); types = types.tail) {
3277                     types.head.tsym.type = types.head;
3278                 }
3279             } else if (missingTypeVariables.isEmpty() !=
3280                        foundTypeVariables.isEmpty()) {
3281                 Name name = missingTypeVariables.head.tsym.name;
3282                 throw badClassFile("undecl.type.var", name);
3283             }
3284 
3285             if ((c.flags_field & Flags.ANNOTATION) != 0) {
3286                 c.setAnnotationTypeMetadata(new AnnotationTypeMetadata(c, new CompleterDeproxy(c, target, repeatable)));
3287             } else {
3288                 c.setAnnotationTypeMetadata(AnnotationTypeMetadata.notAnAnnotationType());
3289             }
3290 
3291             if (c == currentModule.module_info) {
3292                 if (interimUses.nonEmpty() || interimProvides.nonEmpty()) {
3293                     Assert.check(currentModule.isCompleted());
3294                     currentModule.usesProvidesCompleter =
3295                             new UsesProvidesCompleter(currentModule, interimUses, interimProvides);
3296                 } else {
3297                     currentModule.uses = List.nil();
3298                     currentModule.provides = List.nil();
3299                 }
3300             }
3301         } catch (IOException | ClosedFileSystemException ex) {
3302             throw badClassFile("unable.to.access.file", ex.toString());
3303         } catch (ArrayIndexOutOfBoundsException ex) {
3304             throw badClassFile("bad.class.file", c.flatname);
3305         } finally {
3306             interimUses = List.nil();
3307             interimProvides = List.nil();
3308             missingTypeVariables = List.nil();
3309             foundTypeVariables = List.nil();
3310             filling = false;
3311         }
3312     }
3313 
3314     /** We can only read a single class file at a time; this
3315      *  flag keeps track of when we are currently reading a class
3316      *  file.
3317      */
3318     public boolean filling = false;
3319 
3320 /* **********************************************************************
3321  * Adjusting flags
3322  ***********************************************************************/
3323 
3324     long adjustFieldFlags(long flags) {
3325         boolean previewClassFile = minorVersion == ClassFile.PREVIEW_MINOR_VERSION;
3326         if (allowValueClasses && previewClassFile && (flags & ACC_STRICT) != 0) {
3327             flags &= ~ACC_STRICT;
3328             flags |= STRICT;
3329         }
3330         return flags;
3331     }
3332 
3333     long adjustMethodFlags(long flags) {
3334         if ((flags & ACC_BRIDGE) != 0) {
3335             flags &= ~ACC_BRIDGE;
3336             flags |= BRIDGE;
3337         }
3338         if ((flags & ACC_VARARGS) != 0) {
3339             flags &= ~ACC_VARARGS;
3340             flags |= VARARGS;
3341         }
3342         return flags;
3343     }
3344 
3345     long adjustClassFlags(ClassSymbol c, long flags) {
3346         if ((flags & ACC_MODULE) != 0) {
3347             flags &= ~ACC_MODULE;
3348             flags |= MODULE;
3349         }
3350         if (((flags & ACC_IDENTITY) != 0 && !isMigratedValueClass(flags)) || (majorVersion < V67.major && (flags & INTERFACE) == 0)) {
3351             flags |= IDENTITY_TYPE;
3352         } else if (needsValueFlag(c, flags)) {
3353             flags |= VALUE_CLASS;
3354             flags &= ~IDENTITY_TYPE;
3355         }
3356         flags &= ~ACC_IDENTITY; // ACC_IDENTITY and SYNCHRONIZED bits overloaded
3357         return flags;
3358     }
3359 
3360     private boolean needsValueFlag(Symbol c, long flags) {
3361         boolean previewClassFile = minorVersion == ClassFile.PREVIEW_MINOR_VERSION;
3362         if (allowValueClasses) {
3363             if (previewClassFile && majorVersion >= V67.major && (flags & INTERFACE) == 0 ||
3364                     majorVersion >= V67.major && isMigratedValueClass(flags)) {
3365                 return true;
3366             }
3367         }
3368         return false;
3369     }
3370 
3371     private boolean isMigratedValueClass(long flags) {
3372         return allowValueClasses && ((flags & MIGRATED_VALUE_CLASS) != 0);
3373     }
3374 
3375     /**
3376      * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
3377      * The attribute is only the last component of the original filename, so is unlikely
3378      * to be valid as is, so operations other than those to access the name throw
3379      * UnsupportedOperationException
3380      */
3381     private static class SourceFileObject implements JavaFileObject {
3382 
3383         /** The file's name.
3384          */
3385         private final Name name;
3386 
3387         public SourceFileObject(Name name) {
3388             this.name = name;
3389         }
3390 
3391         @Override @DefinedBy(Api.COMPILER)
3392         public URI toUri() {
3393             try {
3394                 return new URI(null, name.toString(), null);
3395             } catch (URISyntaxException e) {
3396                 throw new PathFileObject.CannotCreateUriError(name.toString(), e);
3397             }
3398         }
3399 
3400         @Override @DefinedBy(Api.COMPILER)
3401         public String getName() {
3402             return name.toString();
3403         }
3404 
3405         @Override @DefinedBy(Api.COMPILER)
3406         public JavaFileObject.Kind getKind() {
3407             return BaseFileManager.getKind(getName());
3408         }
3409 
3410         @Override @DefinedBy(Api.COMPILER)
3411         public InputStream openInputStream() {
3412             throw new UnsupportedOperationException();
3413         }
3414 
3415         @Override @DefinedBy(Api.COMPILER)
3416         public OutputStream openOutputStream() {
3417             throw new UnsupportedOperationException();
3418         }
3419 
3420         @Override @DefinedBy(Api.COMPILER)
3421         public CharBuffer getCharContent(boolean ignoreEncodingErrors) {
3422             throw new UnsupportedOperationException();
3423         }
3424 
3425         @Override @DefinedBy(Api.COMPILER)
3426         public Reader openReader(boolean ignoreEncodingErrors) {
3427             throw new UnsupportedOperationException();
3428         }
3429 
3430         @Override @DefinedBy(Api.COMPILER)
3431         public Writer openWriter() {
3432             throw new UnsupportedOperationException();
3433         }
3434 
3435         @Override @DefinedBy(Api.COMPILER)
3436         public long getLastModified() {
3437             throw new UnsupportedOperationException();
3438         }
3439 
3440         @Override @DefinedBy(Api.COMPILER)
3441         public boolean delete() {
3442             throw new UnsupportedOperationException();
3443         }
3444 
3445         @Override @DefinedBy(Api.COMPILER)
3446         public boolean isNameCompatible(String simpleName, JavaFileObject.Kind kind) {
3447             return true; // fail-safe mode
3448         }
3449 
3450         @Override @DefinedBy(Api.COMPILER)
3451         public NestingKind getNestingKind() {
3452             return null;
3453         }
3454 
3455         @Override @DefinedBy(Api.COMPILER)
3456         public Modifier getAccessLevel() {
3457             return null;
3458         }
3459 
3460         /**
3461          * Check if two file objects are equal.
3462          * SourceFileObjects are just placeholder objects for the value of a
3463          * SourceFile attribute, and do not directly represent specific files.
3464          * Two SourceFileObjects are equal if their names are equal.
3465          */
3466         @Override
3467         public boolean equals(Object other) {
3468             if (this == other)
3469                 return true;
3470             return (other instanceof SourceFileObject sourceFileObject)
3471                     && name.equals(sourceFileObject.name);
3472         }
3473 
3474         @Override
3475         public int hashCode() {
3476             return name.hashCode();
3477         }
3478     }
3479 
3480     private class CompleterDeproxy implements AnnotationTypeCompleter {
3481         ClassSymbol proxyOn;
3482         CompoundAnnotationProxy target;
3483         CompoundAnnotationProxy repeatable;
3484 
3485         public CompleterDeproxy(ClassSymbol c, CompoundAnnotationProxy target,
3486                 CompoundAnnotationProxy repeatable)
3487         {
3488             this.proxyOn = c;
3489             this.target = target;
3490             this.repeatable = repeatable;
3491         }
3492 
3493         @Override
3494         public void complete(ClassSymbol sym) {
3495             Assert.check(proxyOn == sym);
3496             Attribute.Compound theTarget = null, theRepeatable = null;
3497             AnnotationDeproxy deproxy;
3498 
3499             try {
3500                 if (target != null) {
3501                     deproxy = new AnnotationDeproxy(proxyOn);
3502                     theTarget = deproxy.deproxyCompound(target);
3503                 }
3504 
3505                 if (repeatable != null) {
3506                     deproxy = new AnnotationDeproxy(proxyOn);
3507                     theRepeatable = deproxy.deproxyCompound(repeatable);
3508                 }
3509             } catch (Exception e) {
3510                 throw new CompletionFailure(sym,
3511                                             () -> ClassReader.this.diagFactory.fragment(Fragments.ExceptionMessage(e.getMessage())),
3512                                             dcfh);
3513             }
3514 
3515             sym.getAnnotationTypeMetadata().setTarget(theTarget);
3516             sym.getAnnotationTypeMetadata().setRepeatable(theRepeatable);
3517         }
3518     }
3519 
3520     private class ProxyType extends Type {
3521 
3522         private final Name name;
3523 
3524         public ProxyType(int index) {
3525             super(syms.noSymbol, List.nil());
3526             this.name = poolReader.getName(index);
3527         }
3528 
3529         @Override
3530         public TypeTag getTag() {
3531             return TypeTag.NONE;
3532         }
3533 
3534         public Type resolve() {
3535             return name.map(ClassReader.this::sigToType);
3536         }
3537 
3538         @Override @DefinedBy(Api.LANGUAGE_MODEL)
3539         public String toString() {
3540             return "<ProxyType>";
3541         }
3542 
3543     }
3544 
3545     private static final class InterimUsesDirective {
3546         public final Name service;
3547 
3548         public InterimUsesDirective(Name service) {
3549             this.service = service;
3550         }
3551 
3552     }
3553 
3554     private static final class InterimProvidesDirective {
3555         public final Name service;
3556         public final List<Name> impls;
3557 
3558         public InterimProvidesDirective(Name service, List<Name> impls) {
3559             this.service = service;
3560             this.impls = impls;
3561         }
3562 
3563     }
3564 
3565     private final class UsesProvidesCompleter implements Completer {
3566         private final ModuleSymbol currentModule;
3567         private final List<InterimUsesDirective> interimUsesCopy;
3568         private final List<InterimProvidesDirective> interimProvidesCopy;
3569 
3570         public UsesProvidesCompleter(ModuleSymbol currentModule, List<InterimUsesDirective> interimUsesCopy, List<InterimProvidesDirective> interimProvidesCopy) {
3571             this.currentModule = currentModule;
3572             this.interimUsesCopy = interimUsesCopy;
3573             this.interimProvidesCopy = interimProvidesCopy;
3574         }
3575 
3576         @Override
3577         public void complete(Symbol sym) throws CompletionFailure {
3578             ListBuffer<Directive> directives = new ListBuffer<>();
3579             directives.addAll(currentModule.directives);
3580             ListBuffer<UsesDirective> uses = new ListBuffer<>();
3581             for (InterimUsesDirective interim : interimUsesCopy) {
3582                 UsesDirective d = new UsesDirective(syms.enterClass(currentModule, interim.service));
3583                 uses.add(d);
3584                 directives.add(d);
3585             }
3586             currentModule.uses = uses.toList();
3587             ListBuffer<ProvidesDirective> provides = new ListBuffer<>();
3588             for (InterimProvidesDirective interim : interimProvidesCopy) {
3589                 ListBuffer<ClassSymbol> impls = new ListBuffer<>();
3590                 for (Name impl : interim.impls) {
3591                     impls.append(syms.enterClass(currentModule, impl));
3592                 }
3593                 ProvidesDirective d = new ProvidesDirective(syms.enterClass(currentModule, interim.service),
3594                                                             impls.toList());
3595                 provides.add(d);
3596                 directives.add(d);
3597             }
3598             currentModule.provides = provides.toList();
3599             currentModule.directives = directives.toList();
3600         }
3601     }
3602 }