1 /*
   2  * Copyright (c) 1999, 2025, 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.LintWarnings;
  69 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
  70 import com.sun.tools.javac.tree.JCTree;
  71 import com.sun.tools.javac.util.*;
  72 import com.sun.tools.javac.util.ByteBuffer.UnderflowException;
  73 import com.sun.tools.javac.util.DefinedBy.Api;
  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     /** Switch: warn (instead of error) on illegal UTF-8
 130      */
 131     boolean warnOnIllegalUtf8;
 132 
 133     /** Switch: preserve parameter names from the variable table.
 134      */
 135     public boolean saveParameterNames;
 136 
 137     /**
 138      * The currently selected profile.
 139      */
 140     public final Profile profile;
 141 
 142     /** The log to use for verbose output
 143      */
 144     final Log log;
 145 
 146     /** The symbol table. */
 147     Symtab syms;
 148 
 149     /** The root Lint config. */
 150     Lint lint;
 151 
 152     Types types;
 153 
 154     /** The name table. */
 155     final Names names;
 156 
 157     /** Access to files
 158      */
 159     private final JavaFileManager fileManager;
 160 
 161     /** Factory for diagnostics
 162      */
 163     JCDiagnostic.Factory diagFactory;
 164 
 165     DeferredCompletionFailureHandler dcfh;
 166 
 167     /**
 168      * Support for preview language features.
 169      */
 170     Preview preview;
 171 
 172     /** The current scope where type variables are entered.
 173      */
 174     protected WriteableScope typevars;
 175 
 176     private List<InterimUsesDirective> interimUses = List.nil();
 177     private List<InterimProvidesDirective> interimProvides = List.nil();
 178 
 179     /** The path name of the class file currently being read.
 180      */
 181     protected JavaFileObject currentClassFile = null;
 182 
 183     /** The class or method currently being read.
 184      */
 185     protected Symbol currentOwner = null;
 186 
 187     /** The module containing the class currently being read.
 188      */
 189     protected ModuleSymbol currentModule = null;
 190 
 191     /** The buffer containing the currently read class file.
 192      */
 193     ByteBuffer buf = new ByteBuffer(INITIAL_BUFFER_SIZE);
 194 
 195     /** The current input pointer.
 196      */
 197     protected int bp;
 198 
 199     /** The pool reader.
 200      */
 201     PoolReader poolReader;
 202 
 203     /** The major version number of the class file being read. */
 204     int majorVersion;
 205     /** The minor version number of the class file being read. */
 206     int minorVersion;
 207 
 208     /** true if the class file being read is a preview class file. */
 209     boolean previewClassFile;
 210 
 211     /** UTF-8 validation level */
 212     Convert.Validation utf8validation;
 213 
 214     /** A table to hold the constant pool indices for method parameter
 215      * names, as given in LocalVariableTable attributes.
 216      */
 217     int[] parameterNameIndicesLvt;
 218 
 219     /**
 220      * A table to hold the constant pool indices for method parameter
 221      * names, as given in the MethodParameters attribute.
 222      */
 223     int[] parameterNameIndicesMp;
 224 
 225     /**
 226      * A table to hold the access flags of the method parameters.
 227      */
 228     int[] parameterAccessFlags;
 229 
 230     /**
 231      * A table to hold the access flags of the method parameters,
 232      * for all parameters including synthetic and mandated ones.
 233      */
 234     int[] allParameterAccessFlags;
 235 
 236     /**
 237      * A table to hold annotations for method parameters.
 238      */
 239     ParameterAnnotations[] parameterAnnotations;
 240 
 241     /**
 242      * A holder for parameter annotations.
 243      */
 244     static class ParameterAnnotations {
 245         List<CompoundAnnotationProxy> proxies;
 246 
 247         void add(List<CompoundAnnotationProxy> newAnnotations) {
 248             if (proxies == null) {
 249                 proxies = newAnnotations;
 250             } else {
 251                 proxies = proxies.prependList(newAnnotations);
 252             }
 253         }
 254     }
 255 
 256     /**
 257      * The set of attribute names for which warnings have been generated for the current class
 258      */
 259     Set<Name> warnedAttrs = new HashSet<>();
 260 
 261     /**
 262      * The prototype @Target Attribute.Compound if this class is an annotation annotated with
 263      * {@code @Target}
 264      */
 265     CompoundAnnotationProxy target;
 266 
 267     /**
 268      * The prototype @Repeatable Attribute.Compound if this class is an annotation annotated with
 269      * {@code @Repeatable}
 270      */
 271     CompoundAnnotationProxy repeatable;
 272 
 273     /** Get the ClassReader instance for this invocation. */
 274     public static ClassReader instance(Context context) {
 275         ClassReader instance = context.get(classReaderKey);
 276         if (instance == null)
 277             instance = new ClassReader(context);
 278         return instance;
 279     }
 280 
 281     /** Construct a new class reader. */
 282     @SuppressWarnings("this-escape")
 283     protected ClassReader(Context context) {
 284         context.put(classReaderKey, this);
 285         annotate = Annotate.instance(context);
 286         names = Names.instance(context);
 287         syms = Symtab.instance(context);
 288         types = Types.instance(context);
 289         fileManager = context.get(JavaFileManager.class);
 290         if (fileManager == null)
 291             throw new AssertionError("FileManager initialization error");
 292         diagFactory = JCDiagnostic.Factory.instance(context);
 293         dcfh = DeferredCompletionFailureHandler.instance(context);
 294 
 295         log = Log.instance(context);
 296 
 297         Options options = Options.instance(context);
 298         verbose         = options.isSet(Option.VERBOSE);
 299 
 300         Source source = Source.instance(context);
 301         preview = Preview.instance(context);
 302         allowModules     = Feature.MODULES.allowedInSource(source);
 303         allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
 304                 Feature.VALUE_CLASSES.allowedInSource(source);
 305         allowRecords = Feature.RECORDS.allowedInSource(source);
 306         allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
 307         warnOnIllegalUtf8 = Feature.WARN_ON_ILLEGAL_UTF8.allowedInSource(source);
 308 
 309         saveParameterNames = options.isSet(PARAMETERS);
 310 
 311         profile = Profile.instance(context);
 312 
 313         typevars = WriteableScope.create(syms.noSymbol);
 314 
 315         lint = Lint.instance(context);
 316 
 317         initAttributeReaders();
 318     }
 319 
 320     /** Add member to class unless it is synthetic.
 321      */
 322     private void enterMember(ClassSymbol c, Symbol sym) {
 323         // Synthetic members are not entered -- reason lost to history (optimization?).
 324         // Lambda methods must be entered because they may have inner classes (which reference them)
 325         if ((sym.flags_field & (SYNTHETIC|BRIDGE)) != SYNTHETIC || sym.name.startsWith(names.lambda))
 326             c.members_field.enter(sym);
 327     }
 328 
 329 /* **********************************************************************
 330  * Error Diagnoses
 331  ***********************************************************************/
 332 
 333     public ClassFinder.BadClassFile badClassFile(String key, Object... args) {
 334         return badClassFile(diagFactory.fragment(key, args));
 335     }
 336 
 337     public ClassFinder.BadClassFile badClassFile(Fragment fragment) {
 338         return badClassFile(diagFactory.fragment(fragment));
 339     }
 340 
 341     public ClassFinder.BadClassFile badClassFile(JCDiagnostic diagnostic) {
 342         return new ClassFinder.BadClassFile (
 343             currentOwner.enclClass(),
 344             currentClassFile,
 345             diagnostic,
 346             diagFactory,
 347             dcfh);
 348     }
 349 
 350     public ClassFinder.BadEnclosingMethodAttr badEnclosingMethod(Symbol sym) {
 351         return new ClassFinder.BadEnclosingMethodAttr (
 352             currentOwner.enclClass(),
 353             currentClassFile,
 354             diagFactory.fragment(Fragments.BadEnclosingMethod(sym)),
 355             diagFactory,
 356             dcfh);
 357     }
 358 
 359 /* **********************************************************************
 360  * Buffer Access
 361  ***********************************************************************/
 362 
 363     /** Read a character.
 364      */
 365     char nextChar() {
 366         char res;
 367         try {
 368             res = buf.getChar(bp);
 369         } catch (UnderflowException e) {
 370             throw badClassFile(Fragments.BadClassTruncatedAtOffset(e.getLength()));
 371         }
 372         bp += 2;
 373         return res;
 374     }
 375 
 376     /** Read a byte.
 377      */
 378     int nextByte() {
 379         try {
 380             return buf.getByte(bp++) & 0xFF;
 381         } catch (UnderflowException e) {
 382             throw badClassFile(Fragments.BadClassTruncatedAtOffset(e.getLength()));
 383         }
 384     }
 385 
 386     /** Read an integer.
 387      */
 388     int nextInt() {
 389         int res;
 390         try {
 391             res = buf.getInt(bp);
 392         } catch (UnderflowException e) {
 393             throw badClassFile(Fragments.BadClassTruncatedAtOffset(e.getLength()));
 394         }
 395         bp += 4;
 396         return res;
 397     }
 398 
 399 /* **********************************************************************
 400  * Constant Pool Access
 401  ***********************************************************************/
 402 
 403     /** Read module_flags.
 404      */
 405     Set<ModuleFlags> readModuleFlags(int flags) {
 406         Set<ModuleFlags> set = EnumSet.noneOf(ModuleFlags.class);
 407         for (ModuleFlags f : ModuleFlags.values()) {
 408             if ((flags & f.value) != 0)
 409                 set.add(f);
 410         }
 411         return set;
 412     }
 413 
 414     /** Read resolution_flags.
 415      */
 416     Set<ModuleResolutionFlags> readModuleResolutionFlags(int flags) {
 417         Set<ModuleResolutionFlags> set = EnumSet.noneOf(ModuleResolutionFlags.class);
 418         for (ModuleResolutionFlags f : ModuleResolutionFlags.values()) {
 419             if ((flags & f.value) != 0)
 420                 set.add(f);
 421         }
 422         return set;
 423     }
 424 
 425     /** Read exports_flags.
 426      */
 427     Set<ExportsFlag> readExportsFlags(int flags) {
 428         Set<ExportsFlag> set = EnumSet.noneOf(ExportsFlag.class);
 429         for (ExportsFlag f: ExportsFlag.values()) {
 430             if ((flags & f.value) != 0)
 431                 set.add(f);
 432         }
 433         return set;
 434     }
 435 
 436     /** Read opens_flags.
 437      */
 438     Set<OpensFlag> readOpensFlags(int flags) {
 439         Set<OpensFlag> set = EnumSet.noneOf(OpensFlag.class);
 440         for (OpensFlag f: OpensFlag.values()) {
 441             if ((flags & f.value) != 0)
 442                 set.add(f);
 443         }
 444         return set;
 445     }
 446 
 447     /** Read requires_flags.
 448      */
 449     Set<RequiresFlag> readRequiresFlags(int flags) {
 450         Set<RequiresFlag> set = EnumSet.noneOf(RequiresFlag.class);
 451         for (RequiresFlag f: RequiresFlag.values()) {
 452             if ((flags & f.value) != 0)
 453                 set.add(f);
 454         }
 455         return set;
 456     }
 457 
 458 /* **********************************************************************
 459  * Reading Types
 460  ***********************************************************************/
 461 
 462     /** The unread portion of the currently read type is
 463      *  signature[sigp..siglimit-1].
 464      */
 465     byte[] signature;
 466     int sigp;
 467     int siglimit;
 468     boolean sigEnterPhase = false;
 469 
 470     /** Convert signature to type, where signature is a byte array segment.
 471      */
 472     Type sigToType(byte[] sig, int offset, int len) {
 473         signature = sig;
 474         sigp = offset;
 475         siglimit = offset + len;
 476         return sigToType();
 477     }
 478 
 479     /** Convert signature to type, where signature is implicit.
 480      */
 481     Type sigToType() {
 482         switch ((char) signature[sigp]) {
 483         case 'T':
 484             sigp++;
 485             int start = sigp;
 486             while (signature[sigp] != ';') sigp++;
 487             sigp++;
 488             return sigEnterPhase
 489                 ? Type.noType
 490                 : findTypeVar(readName(signature, start, sigp - 1 - start));
 491         case '+': {
 492             sigp++;
 493             Type t = sigToType();
 494             return new WildcardType(t, BoundKind.EXTENDS, syms.boundClass);
 495         }
 496         case '*':
 497             sigp++;
 498             return new WildcardType(syms.objectType, BoundKind.UNBOUND,
 499                                     syms.boundClass);
 500         case '-': {
 501             sigp++;
 502             Type t = sigToType();
 503             return new WildcardType(t, BoundKind.SUPER, syms.boundClass);
 504         }
 505         case 'B':
 506             sigp++;
 507             return syms.byteType;
 508         case 'C':
 509             sigp++;
 510             return syms.charType;
 511         case 'D':
 512             sigp++;
 513             return syms.doubleType;
 514         case 'F':
 515             sigp++;
 516             return syms.floatType;
 517         case 'I':
 518             sigp++;
 519             return syms.intType;
 520         case 'J':
 521             sigp++;
 522             return syms.longType;
 523         case 'L':
 524             {
 525                 // int oldsigp = sigp;
 526                 Type t = classSigToType();
 527                 if (sigp < siglimit && signature[sigp] == '.')
 528                     throw badClassFile("deprecated inner class signature syntax " +
 529                                        "(please recompile from source)");
 530                 /*
 531                 System.err.println(" decoded " +
 532                                    new String(signature, oldsigp, sigp-oldsigp) +
 533                                    " => " + t + " outer " + t.outer());
 534                 */
 535                 return t;
 536             }
 537         case 'S':
 538             sigp++;
 539             return syms.shortType;
 540         case 'V':
 541             sigp++;
 542             return syms.voidType;
 543         case 'Z':
 544             sigp++;
 545             return syms.booleanType;
 546         case '[':
 547             sigp++;
 548             return new ArrayType(sigToType(), syms.arrayClass);
 549         case '(':
 550             sigp++;
 551             List<Type> argtypes = sigToTypes(')');
 552             Type restype = sigToType();
 553             List<Type> thrown = List.nil();
 554             while (sigp < siglimit && signature[sigp] == '^') {
 555                 sigp++;
 556                 thrown = thrown.prepend(sigToType());
 557             }
 558             // if there is a typevar in the throws clause we should state it.
 559             for (List<Type> l = thrown; l.nonEmpty(); l = l.tail) {
 560                 if (l.head.hasTag(TYPEVAR)) {
 561                     l.head.tsym.flags_field |= THROWS;
 562                 }
 563             }
 564             return new MethodType(argtypes,
 565                                   restype,
 566                                   thrown.reverse(),
 567                                   syms.methodClass);
 568         case '<':
 569             typevars = typevars.dup(currentOwner);
 570             Type poly = new ForAll(sigToTypeParams(), sigToType());
 571             typevars = typevars.leave();
 572             return poly;
 573         default:
 574             throw badClassFile("bad.signature", quoteBadSignature());
 575         }
 576     }
 577 
 578     byte[] signatureBuffer = new byte[0];
 579     int sbp = 0;
 580     /** Convert class signature to type, where signature is implicit.
 581      */
 582     Type classSigToType() {
 583         if (signature[sigp] != 'L')
 584             throw badClassFile("bad.class.signature", quoteBadSignature());
 585         sigp++;
 586         Type outer = Type.noType;
 587         int startSbp = sbp;
 588 
 589         while (true) {
 590             final byte c = signature[sigp++];
 591             switch (c) {
 592 
 593             case ';': {         // end
 594                 ClassSymbol t = enterClass(readName(signatureBuffer,
 595                                                          startSbp,
 596                                                          sbp - startSbp));
 597 
 598                 try {
 599                     if (outer == Type.noType) {
 600                         ClassType et = (ClassType) t.erasure(types);
 601                         return new ClassType(et.getEnclosingType(), List.nil(), et.tsym, et.getMetadata());
 602                     }
 603                     return new ClassType(outer, List.nil(), t, List.nil());
 604                 } finally {
 605                     sbp = startSbp;
 606                 }
 607             }
 608 
 609             case '<':           // generic arguments
 610                 ClassSymbol t = enterClass(readName(signatureBuffer,
 611                                                          startSbp,
 612                                                          sbp - startSbp));
 613                 List<Type> actuals = sigToTypes('>');
 614                 List<Type> formals = ((ClassType)t.type.tsym.type).typarams_field;
 615                 if (formals != null) {
 616                     if (actuals.isEmpty())
 617                         actuals = formals;
 618                 }
 619                 /* actualsCp is final as it will be captured by the inner class below. We could avoid defining
 620                  * this additional local variable and depend on field ClassType::typarams_field which `actuals` is
 621                  * assigned to but then we would have a dependendy on the internal representation of ClassType which
 622                  * could change in the future
 623                  */
 624                 final List<Type> actualsCp = actuals;
 625                 outer = new ClassType(outer, actuals, t, List.nil()) {
 626                         boolean completed = false;
 627                         boolean typeArgsSet = false;
 628                         @Override @DefinedBy(Api.LANGUAGE_MODEL)
 629                         public Type getEnclosingType() {
 630                             if (!completed) {
 631                                 completed = true;
 632                                 tsym.apiComplete();
 633                                 Type enclosingType = tsym.type.getEnclosingType();
 634                                 if (enclosingType != Type.noType) {
 635                                     List<Type> typeArgs =
 636                                         super.getEnclosingType().allparams();
 637                                     List<Type> typeParams =
 638                                         enclosingType.allparams();
 639                                     if (typeParams.length() != typeArgs.length()) {
 640                                         // no "rare" types
 641                                         super.setEnclosingType(types.erasure(enclosingType));
 642                                     } else {
 643                                         super.setEnclosingType(types.subst(enclosingType,
 644                                                                            typeParams,
 645                                                                            typeArgs));
 646                                     }
 647                                 } else {
 648                                     super.setEnclosingType(Type.noType);
 649                                 }
 650                             }
 651                             return super.getEnclosingType();
 652                         }
 653                         @Override
 654                         public void setEnclosingType(Type outer) {
 655                             throw new UnsupportedOperationException();
 656                         }
 657 
 658                         @Override
 659                         public List<Type> getTypeArguments() {
 660                             if (!typeArgsSet) {
 661                                 typeArgsSet = true;
 662                                 List<Type> formalsCp = ((ClassType)t.type.tsym.type).typarams_field;
 663                                 if (formalsCp != null && !formalsCp.isEmpty()) {
 664                                     if (actualsCp.length() == formalsCp.length()) {
 665                                         List<Type> a = actualsCp;
 666                                         List<Type> f = formalsCp;
 667                                         while (a.nonEmpty()) {
 668                                             a.head = a.head.withTypeVar(f.head);
 669                                             a = a.tail;
 670                                             f = f.tail;
 671                                         }
 672                                     }
 673                                 }
 674                             }
 675                             return super.getTypeArguments();
 676                         }
 677                 };
 678                 switch (signature[sigp++]) {
 679                 case ';':
 680                     if (sigp < siglimit && signature[sigp] == '.') {
 681                         // support old-style GJC signatures
 682                         // The signature produced was
 683                         // Lfoo/Outer<Lfoo/X;>;.Lfoo/Outer$Inner<Lfoo/Y;>;
 684                         // rather than say
 685                         // Lfoo/Outer<Lfoo/X;>.Inner<Lfoo/Y;>;
 686                         // so we skip past ".Lfoo/Outer$"
 687                         sigp += (sbp - startSbp) + // "foo/Outer"
 688                             3;  // ".L" and "$"
 689                         signatureBuffer[sbp++] = (byte)'$';
 690                         break;
 691                     } else {
 692                         sbp = startSbp;
 693                         return outer;
 694                     }
 695                 case '.':
 696                     signatureBuffer[sbp++] = (byte)'$';
 697                     break;
 698                 default:
 699                     throw new AssertionError(signature[sigp-1]);
 700                 }
 701                 continue;
 702 
 703             case '.':
 704                 //we have seen an enclosing non-generic class
 705                 if (outer != Type.noType) {
 706                     t = enterClass(readName(signatureBuffer,
 707                                                  startSbp,
 708                                                  sbp - startSbp));
 709                     outer = new ClassType(outer, List.nil(), t, List.nil());
 710                 }
 711                 signatureBuffer[sbp++] = (byte)'$';
 712                 continue;
 713             case '/':
 714                 signatureBuffer[sbp++] = (byte)'.';
 715                 continue;
 716             default:
 717                 signatureBuffer[sbp++] = c;
 718                 continue;
 719             }
 720         }
 721     }
 722 
 723     /** Quote a bogus signature for display inside an error message.
 724      */
 725     String quoteBadSignature() {
 726         String sigString;
 727         try {
 728             sigString = Convert.utf2string(signature, sigp, siglimit - sigp, Convert.Validation.NONE);
 729         } catch (InvalidUtfException e) {
 730             throw new AssertionError(e);
 731         }
 732         if (sigString.length() > 32)
 733             sigString = sigString.substring(0, 32) + "...";
 734         return "\"" + sigString + "\"";
 735     }
 736 
 737     /** Convert (implicit) signature to list of types
 738      *  until `terminator' is encountered.
 739      */
 740     List<Type> sigToTypes(char terminator) {
 741         List<Type> head = List.of(null);
 742         List<Type> tail = head;
 743         while (signature[sigp] != terminator)
 744             tail = tail.setTail(List.of(sigToType()));
 745         sigp++;
 746         return head.tail;
 747     }
 748 
 749     /** Convert signature to type parameters, where signature is a byte
 750      *  array segment.
 751      */
 752     List<Type> sigToTypeParams(byte[] sig, int offset, int len) {
 753         signature = sig;
 754         sigp = offset;
 755         siglimit = offset + len;
 756         return sigToTypeParams();
 757     }
 758 
 759     /** Convert signature to type parameters, where signature is implicit.
 760      */
 761     List<Type> sigToTypeParams() {
 762         List<Type> tvars = List.nil();
 763         if (signature[sigp] == '<') {
 764             sigp++;
 765             int start = sigp;
 766             sigEnterPhase = true;
 767             while (signature[sigp] != '>')
 768                 tvars = tvars.prepend(sigToTypeParam());
 769             sigEnterPhase = false;
 770             sigp = start;
 771             while (signature[sigp] != '>')
 772                 sigToTypeParam();
 773             sigp++;
 774         }
 775         return tvars.reverse();
 776     }
 777 
 778     /** Convert (implicit) signature to type parameter.
 779      */
 780     Type sigToTypeParam() {
 781         int start = sigp;
 782         while (signature[sigp] != ':') sigp++;
 783         Name name = readName(signature, start, sigp - start);
 784         TypeVar tvar;
 785         if (sigEnterPhase) {
 786             tvar = new TypeVar(name, currentOwner, syms.botType);
 787             typevars.enter(tvar.tsym);
 788         } else {
 789             tvar = (TypeVar)findTypeVar(name);
 790         }
 791         List<Type> bounds = List.nil();
 792         boolean allInterfaces = false;
 793         if (signature[sigp] == ':' && signature[sigp+1] == ':') {
 794             sigp++;
 795             allInterfaces = true;
 796         }
 797         while (signature[sigp] == ':') {
 798             sigp++;
 799             bounds = bounds.prepend(sigToType());
 800         }
 801         if (!sigEnterPhase) {
 802             types.setBounds(tvar, bounds.reverse(), allInterfaces);
 803         }
 804         return tvar;
 805     }
 806 
 807     /** Find type variable with given name in `typevars' scope.
 808      */
 809     Type findTypeVar(Name name) {
 810         Symbol s = typevars.findFirst(name);
 811         if (s != null) {
 812             return s.type;
 813         } else {
 814             if (readingClassAttr) {
 815                 // While reading the class attribute, the supertypes
 816                 // might refer to a type variable from an enclosing element
 817                 // (method or class).
 818                 // If the type variable is defined in the enclosing class,
 819                 // we can actually find it in
 820                 // currentOwner.owner.type.getTypeArguments()
 821                 // However, until we have read the enclosing method attribute
 822                 // we don't know for sure if this owner is correct.  It could
 823                 // be a method and there is no way to tell before reading the
 824                 // enclosing method attribute.
 825                 TypeVar t = new TypeVar(name, currentOwner, syms.botType);
 826                 missingTypeVariables = missingTypeVariables.prepend(t);
 827                 // System.err.println("Missing type var " + name);
 828                 return t;
 829             }
 830             throw badClassFile("undecl.type.var", name);
 831         }
 832     }
 833 
 834     private Name readName(byte[] buf, int off, int len) {
 835         try {
 836             return names.fromUtf(buf, off, len, utf8validation);
 837         } catch (InvalidUtfException e) {
 838             if (warnOnIllegalUtf8) {
 839                 log.warning(Warnings.InvalidUtf8InClassfile(currentClassFile,
 840                     Fragments.BadUtf8ByteSequenceAt(sigp)));
 841                 return names.fromUtfLax(buf, off, len);
 842             }
 843             throw badClassFile(Fragments.BadUtf8ByteSequenceAt(sigp));
 844         }
 845     }
 846 
 847 /* **********************************************************************
 848  * Reading Attributes
 849  ***********************************************************************/
 850 
 851     protected enum AttributeKind { CLASS, MEMBER }
 852 
 853     protected abstract class AttributeReader {
 854         protected AttributeReader(Name name, ClassFile.Version version, Set<AttributeKind> kinds) {
 855             this.name = name;
 856             this.version = version;
 857             this.kinds = kinds;
 858         }
 859 
 860         protected boolean accepts(AttributeKind kind) {
 861             if (kinds.contains(kind)) {
 862                 if (majorVersion > version.major || (majorVersion == version.major && minorVersion >= version.minor))
 863                     return true;
 864 
 865                 if (!warnedAttrs.contains(name)) {
 866                     JavaFileObject prev = log.useSource(currentClassFile);
 867                     try {
 868                         lint.logIfEnabled(log,
 869                                     LintWarnings.FutureAttr(name, version.major, version.minor, majorVersion, minorVersion));
 870                     } finally {
 871                         log.useSource(prev);
 872                     }
 873                     warnedAttrs.add(name);
 874                 }
 875             }
 876             return false;
 877         }
 878 
 879         protected abstract void read(Symbol sym, int attrLen);
 880 
 881         protected final Name name;
 882         protected final ClassFile.Version version;
 883         protected final Set<AttributeKind> kinds;
 884     }
 885 
 886     protected Set<AttributeKind> CLASS_ATTRIBUTE =
 887             EnumSet.of(AttributeKind.CLASS);
 888     protected Set<AttributeKind> MEMBER_ATTRIBUTE =
 889             EnumSet.of(AttributeKind.MEMBER);
 890     protected Set<AttributeKind> CLASS_OR_MEMBER_ATTRIBUTE =
 891             EnumSet.of(AttributeKind.CLASS, AttributeKind.MEMBER);
 892 
 893     protected Map<Name, AttributeReader> attributeReaders = new HashMap<>();
 894 
 895     private void initAttributeReaders() {
 896         AttributeReader[] readers = {
 897             // v45.3 attributes
 898 
 899             new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) {
 900                 protected void read(Symbol sym, int attrLen) {
 901                     if (saveParameterNames)
 902                         ((MethodSymbol)sym).code = readCode(sym);
 903                     else
 904                         bp = bp + attrLen;
 905                 }
 906             },
 907 
 908             new AttributeReader(names.ConstantValue, V45_3, MEMBER_ATTRIBUTE) {
 909                 protected void read(Symbol sym, int attrLen) {
 910                     Object v = poolReader.getConstant(nextChar());
 911                     // Ignore ConstantValue attribute if field not final.
 912                     if ((sym.flags() & FINAL) == 0) {
 913                         return;
 914                     }
 915                     VarSymbol var = (VarSymbol) sym;
 916                     switch (var.type.getTag()) {
 917                        case BOOLEAN:
 918                        case BYTE:
 919                        case CHAR:
 920                        case SHORT:
 921                        case INT:
 922                            checkType(var, Integer.class, v);
 923                            break;
 924                        case LONG:
 925                            checkType(var, Long.class, v);
 926                            break;
 927                        case FLOAT:
 928                            checkType(var, Float.class, v);
 929                            break;
 930                        case DOUBLE:
 931                            checkType(var, Double.class, v);
 932                            break;
 933                        case CLASS:
 934                            if (var.type.tsym == syms.stringType.tsym) {
 935                                checkType(var, String.class, v);
 936                            } else {
 937                                throw badClassFile("bad.constant.value.type", var.type);
 938                            }
 939                            break;
 940                        default:
 941                            // ignore ConstantValue attribute if type is not primitive or String
 942                            return;
 943                     }
 944                     if (v instanceof Integer intVal && !var.type.getTag().checkRange(intVal)) {
 945                         throw badClassFile("bad.constant.range", v, var, var.type);
 946                     }
 947                     var.setData(v);
 948                 }
 949 
 950                 void checkType(Symbol var, Class<?> clazz, Object value) {
 951                     if (!clazz.isInstance(value)) {
 952                         throw badClassFile("bad.constant.value", value, var, clazz.getSimpleName());
 953                     }
 954                 }
 955             },
 956 
 957             new AttributeReader(names.Deprecated, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
 958                 protected void read(Symbol sym, int attrLen) {
 959                     Symbol s = sym.owner.kind == MDL ? sym.owner : sym;
 960 
 961                     s.flags_field |= DEPRECATED;
 962                 }
 963             },
 964 
 965             new AttributeReader(names.Exceptions, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
 966                 protected void read(Symbol sym, int attrLen) {
 967                     int nexceptions = nextChar();
 968                     List<Type> thrown = List.nil();
 969                     for (int j = 0; j < nexceptions; j++)
 970                         thrown = thrown.prepend(poolReader.getClass(nextChar()).type);
 971                     if (sym.type.getThrownTypes().isEmpty())
 972                         sym.type.asMethodType().thrown = thrown.reverse();
 973                 }
 974             },
 975 
 976             new AttributeReader(names.InnerClasses, V45_3, CLASS_ATTRIBUTE) {
 977                 protected void read(Symbol sym, int attrLen) {
 978                     ClassSymbol c = (ClassSymbol) sym;
 979                     if (currentModule.module_info == c) {
 980                         //prevent entering the classes too soon:
 981                         skipInnerClasses();
 982                     } else {
 983                         readInnerClasses(c);
 984                     }
 985                 }
 986             },
 987 
 988             new AttributeReader(names.LocalVariableTable, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
 989                 protected void read(Symbol sym, int attrLen) {
 990                     int newbp = bp + attrLen;
 991                     if (saveParameterNames) {
 992                         // Pick up parameter names from the variable table.
 993                         // Parameter names are not explicitly identified as such,
 994                         // but all parameter name entries in the LocalVariableTable
 995                         // have a start_pc of 0.  Therefore, we record the name
 996                         // indices of all slots with a start_pc of zero in the
 997                         // parameterNameIndices array.
 998                         // Note that this implicitly honors the JVMS spec that
 999                         // there may be more than one LocalVariableTable, and that
1000                         // there is no specified ordering for the entries.
1001                         int numEntries = nextChar();
1002                         for (int i = 0; i < numEntries; i++) {
1003                             int start_pc = nextChar();
1004                             int length = nextChar();
1005                             int nameIndex = nextChar();
1006                             int sigIndex = nextChar();
1007                             int register = nextChar();
1008                             if (start_pc == 0) {
1009                                 // ensure array large enough
1010                                 if (register >= parameterNameIndicesLvt.length) {
1011                                     int newSize =
1012                                             Math.max(register + 1, parameterNameIndicesLvt.length + 8);
1013                                     parameterNameIndicesLvt =
1014                                             Arrays.copyOf(parameterNameIndicesLvt, newSize);
1015                                 }
1016                                 parameterNameIndicesLvt[register] = nameIndex;
1017                             }
1018                         }
1019                     }
1020                     bp = newbp;
1021                 }
1022             },
1023 
1024             new AttributeReader(names.SourceFile, V45_3, CLASS_ATTRIBUTE) {
1025                 protected void read(Symbol sym, int attrLen) {
1026                     ClassSymbol c = (ClassSymbol) sym;
1027                     Name n = poolReader.getName(nextChar());
1028                     c.sourcefile = new SourceFileObject(n);
1029                     // If the class is a toplevel class, originating from a Java source file,
1030                     // but the class name does not match the file name, then it is
1031                     // an auxiliary class.
1032                     String sn = n.toString();
1033                     if (c.owner.kind == PCK &&
1034                         sn.endsWith(".java") &&
1035                         !sn.equals(c.name.toString()+".java")) {
1036                         c.flags_field |= AUXILIARY;
1037                     }
1038                 }
1039             },
1040 
1041             new AttributeReader(names.Synthetic, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
1042                 protected void read(Symbol sym, int attrLen) {
1043                     sym.flags_field |= SYNTHETIC;
1044                 }
1045             },
1046 
1047             // standard v49 attributes
1048 
1049             new AttributeReader(names.EnclosingMethod, V49, CLASS_ATTRIBUTE) {
1050                 protected void read(Symbol sym, int attrLen) {
1051                     int newbp = bp + attrLen;
1052                     readEnclosingMethodAttr(sym);
1053                     bp = newbp;
1054                 }
1055             },
1056 
1057             new AttributeReader(names.Signature, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1058                 protected void read(Symbol sym, int attrLen) {
1059                     if (sym.kind == TYP) {
1060                         ClassSymbol c = (ClassSymbol) sym;
1061                         readingClassAttr = true;
1062                         try {
1063                             ClassType ct1 = (ClassType)c.type;
1064                             Assert.check(c == currentOwner);
1065                             ct1.typarams_field = poolReader.getName(nextChar())
1066                                     .map(ClassReader.this::sigToTypeParams);
1067                             ct1.supertype_field = sigToType();
1068                             ListBuffer<Type> is = new ListBuffer<>();
1069                             while (sigp != siglimit) is.append(sigToType());
1070                             ct1.interfaces_field = is.toList();
1071                         } finally {
1072                             readingClassAttr = false;
1073                         }
1074                     } else {
1075                         List<Type> thrown = sym.type.getThrownTypes();
1076                         sym.type = poolReader.getType(nextChar());
1077                         //- System.err.println(" # " + sym.type);
1078                         if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty())
1079                             sym.type.asMethodType().thrown = thrown;
1080 
1081                     }
1082                 }
1083             },
1084 
1085             // v49 annotation attributes
1086 
1087             new AttributeReader(names.AnnotationDefault, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1088                 protected void read(Symbol sym, int attrLen) {
1089                     attachAnnotationDefault(sym);
1090                 }
1091             },
1092 
1093             new AttributeReader(names.RuntimeInvisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1094                 protected void read(Symbol sym, int attrLen) {
1095                     attachAnnotations(sym);
1096                 }
1097             },
1098 
1099             new AttributeReader(names.RuntimeInvisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1100                 protected void read(Symbol sym, int attrLen) {
1101                     readParameterAnnotations(sym);
1102                 }
1103             },
1104 
1105             new AttributeReader(names.RuntimeVisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1106                 protected void read(Symbol sym, int attrLen) {
1107                     attachAnnotations(sym);
1108                 }
1109             },
1110 
1111             new AttributeReader(names.RuntimeVisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1112                 protected void read(Symbol sym, int attrLen) {
1113                     readParameterAnnotations(sym);
1114                 }
1115             },
1116 
1117             // additional "legacy" v49 attributes, superseded by flags
1118 
1119             new AttributeReader(names.Annotation, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1120                 protected void read(Symbol sym, int attrLen) {
1121                     sym.flags_field |= ANNOTATION;
1122                 }
1123             },
1124 
1125             new AttributeReader(names.Bridge, V49, MEMBER_ATTRIBUTE) {
1126                 protected void read(Symbol sym, int attrLen) {
1127                     sym.flags_field |= BRIDGE;
1128                 }
1129             },
1130 
1131             new AttributeReader(names.Enum, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1132                 protected void read(Symbol sym, int attrLen) {
1133                     sym.flags_field |= ENUM;
1134                 }
1135             },
1136 
1137             new AttributeReader(names.Varargs, V49, CLASS_OR_MEMBER_ATTRIBUTE) {
1138                 protected void read(Symbol sym, int attrLen) {
1139                     sym.flags_field |= VARARGS;
1140                 }
1141             },
1142 
1143             new AttributeReader(names.RuntimeVisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) {
1144                 protected void read(Symbol sym, int attrLen) {
1145                     attachTypeAnnotations(sym);
1146                 }
1147             },
1148 
1149             new AttributeReader(names.RuntimeInvisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) {
1150                 protected void read(Symbol sym, int attrLen) {
1151                     attachTypeAnnotations(sym);
1152                 }
1153             },
1154 
1155             // The following attributes for a Code attribute are not currently handled
1156             // StackMapTable
1157             // SourceDebugExtension
1158             // LineNumberTable
1159             // LocalVariableTypeTable
1160 
1161             // standard v52 attributes
1162 
1163             new AttributeReader(names.MethodParameters, V52, MEMBER_ATTRIBUTE) {
1164                 protected void read(Symbol sym, int attrlen) {
1165                     int newbp = bp + attrlen;
1166                     if (saveParameterNames) {
1167                         int numEntries = nextByte();
1168                         allParameterAccessFlags = new int[numEntries];
1169                         parameterNameIndicesMp = new int[numEntries];
1170                         parameterAccessFlags = new int[numEntries];
1171                         int allParamIndex = 0;
1172                         int index = 0;
1173                         for (int i = 0; i < numEntries; i++) {
1174                             int nameIndex = nextChar();
1175                             int flags = nextChar();
1176                             allParameterAccessFlags[allParamIndex++] = flags;
1177                             if ((flags & (Flags.MANDATED | Flags.SYNTHETIC)) != 0) {
1178                                 continue;
1179                             }
1180                             parameterNameIndicesMp[index] = nameIndex;
1181                             parameterAccessFlags[index] = flags;
1182                             index++;
1183                         }
1184                     }
1185                     bp = newbp;
1186                 }
1187             },
1188 
1189             // standard v53 attributes
1190 
1191             new AttributeReader(names.Module, V53, CLASS_ATTRIBUTE) {
1192                 @Override
1193                 protected boolean accepts(AttributeKind kind) {
1194                     return super.accepts(kind) && allowModules;
1195                 }
1196                 protected void read(Symbol sym, int attrLen) {
1197                     if (sym.kind == TYP && sym.owner.kind == MDL) {
1198                         ModuleSymbol msym = (ModuleSymbol) sym.owner;
1199                         ListBuffer<Directive> directives = new ListBuffer<>();
1200 
1201                         Name moduleName = poolReader.peekModuleName(nextChar(), ClassReader.this::readName);
1202                         if (currentModule.name != moduleName) {
1203                             throw badClassFile("module.name.mismatch", moduleName, currentModule.name);
1204                         }
1205 
1206                         Set<ModuleFlags> moduleFlags = readModuleFlags(nextChar());
1207                         msym.flags.addAll(moduleFlags);
1208                         msym.version = optPoolEntry(nextChar(), poolReader::getName, null);
1209 
1210                         ListBuffer<RequiresDirective> requires = new ListBuffer<>();
1211                         int nrequires = nextChar();
1212                         for (int i = 0; i < nrequires; i++) {
1213                             ModuleSymbol rsym = poolReader.getModule(nextChar());
1214                             Set<RequiresFlag> flags = readRequiresFlags(nextChar());
1215                             if (rsym == syms.java_base && majorVersion >= V54.major) {
1216                                 if (flags.contains(RequiresFlag.TRANSITIVE) &&
1217                                     (majorVersion != Version.MAX().major || !previewClassFile) &&
1218                                     !preview.participatesInPreview(syms, msym)) {
1219                                     throw badClassFile("bad.requires.flag", RequiresFlag.TRANSITIVE);
1220                                 }
1221                                 if (flags.contains(RequiresFlag.STATIC_PHASE)) {
1222                                     throw badClassFile("bad.requires.flag", RequiresFlag.STATIC_PHASE);
1223                                 }
1224                             }
1225                             nextChar(); // skip compiled version
1226                             requires.add(new RequiresDirective(rsym, flags));
1227                         }
1228                         msym.requires = requires.toList();
1229                         directives.addAll(msym.requires);
1230 
1231                         ListBuffer<ExportsDirective> exports = new ListBuffer<>();
1232                         int nexports = nextChar();
1233                         for (int i = 0; i < nexports; i++) {
1234                             PackageSymbol p = poolReader.getPackage(nextChar());
1235                             Set<ExportsFlag> flags = readExportsFlags(nextChar());
1236                             int nto = nextChar();
1237                             List<ModuleSymbol> to;
1238                             if (nto == 0) {
1239                                 to = null;
1240                             } else {
1241                                 ListBuffer<ModuleSymbol> lb = new ListBuffer<>();
1242                                 for (int t = 0; t < nto; t++)
1243                                     lb.append(poolReader.getModule(nextChar()));
1244                                 to = lb.toList();
1245                             }
1246                             exports.add(new ExportsDirective(p, to, flags));
1247                         }
1248                         msym.exports = exports.toList();
1249                         directives.addAll(msym.exports);
1250                         ListBuffer<OpensDirective> opens = new ListBuffer<>();
1251                         int nopens = nextChar();
1252                         if (nopens != 0 && msym.flags.contains(ModuleFlags.OPEN)) {
1253                             throw badClassFile("module.non.zero.opens", currentModule.name);
1254                         }
1255                         for (int i = 0; i < nopens; i++) {
1256                             PackageSymbol p = poolReader.getPackage(nextChar());
1257                             Set<OpensFlag> flags = readOpensFlags(nextChar());
1258                             int nto = nextChar();
1259                             List<ModuleSymbol> to;
1260                             if (nto == 0) {
1261                                 to = null;
1262                             } else {
1263                                 ListBuffer<ModuleSymbol> lb = new ListBuffer<>();
1264                                 for (int t = 0; t < nto; t++)
1265                                     lb.append(poolReader.getModule(nextChar()));
1266                                 to = lb.toList();
1267                             }
1268                             opens.add(new OpensDirective(p, to, flags));
1269                         }
1270                         msym.opens = opens.toList();
1271                         directives.addAll(msym.opens);
1272 
1273                         msym.directives = directives.toList();
1274 
1275                         ListBuffer<InterimUsesDirective> uses = new ListBuffer<>();
1276                         int nuses = nextChar();
1277                         for (int i = 0; i < nuses; i++) {
1278                             Name srvc = poolReader.peekClassName(nextChar(), this::classNameMapper);
1279                             uses.add(new InterimUsesDirective(srvc));
1280                         }
1281                         interimUses = uses.toList();
1282 
1283                         ListBuffer<InterimProvidesDirective> provides = new ListBuffer<>();
1284                         int nprovides = nextChar();
1285                         for (int p = 0; p < nprovides; p++) {
1286                             Name srvc = poolReader.peekClassName(nextChar(), this::classNameMapper);
1287                             int nimpls = nextChar();
1288                             ListBuffer<Name> impls = new ListBuffer<>();
1289                             for (int i = 0; i < nimpls; i++) {
1290                                 impls.append(poolReader.peekClassName(nextChar(), this::classNameMapper));
1291                             provides.add(new InterimProvidesDirective(srvc, impls.toList()));
1292                             }
1293                         }
1294                         interimProvides = provides.toList();
1295                     }
1296                 }
1297 
1298                 private Name classNameMapper(byte[] arr, int offset, int length) throws InvalidUtfException {
1299                     byte[] buf = ClassFile.internalize(arr, offset, length);
1300                     try {
1301                         return names.fromUtf(buf, 0, buf.length, utf8validation);
1302                     } catch (InvalidUtfException e) {
1303                         if (warnOnIllegalUtf8) {
1304                             log.warning(Warnings.InvalidUtf8InClassfile(currentClassFile,
1305                                 Fragments.BadUtf8ByteSequenceAt(e.getOffset())));
1306                             return names.fromUtfLax(buf, 0, buf.length);
1307                         }
1308                         throw e;
1309                     }
1310                 }
1311             },
1312 
1313             new AttributeReader(names.ModuleResolution, V53, CLASS_ATTRIBUTE) {
1314                 @Override
1315                 protected boolean accepts(AttributeKind kind) {
1316                     return super.accepts(kind) && allowModules;
1317                 }
1318                 protected void read(Symbol sym, int attrLen) {
1319                     if (sym.kind == TYP && sym.owner.kind == MDL) {
1320                         ModuleSymbol msym = (ModuleSymbol) sym.owner;
1321                         msym.resolutionFlags.addAll(readModuleResolutionFlags(nextChar()));
1322                     }
1323                 }
1324             },
1325 
1326             new AttributeReader(names.Record, V58, CLASS_ATTRIBUTE) {
1327                 @Override
1328                 protected boolean accepts(AttributeKind kind) {
1329                     return super.accepts(kind) && allowRecords;
1330                 }
1331                 protected void read(Symbol sym, int attrLen) {
1332                     if (sym.kind == TYP) {
1333                         sym.flags_field |= RECORD;
1334                     }
1335                     int componentCount = nextChar();
1336                     ListBuffer<RecordComponent> components = new ListBuffer<>();
1337                     for (int i = 0; i < componentCount; i++) {
1338                         Name name = poolReader.getName(nextChar());
1339                         Type type = poolReader.getType(nextChar());
1340                         RecordComponent c = new RecordComponent(name, type, sym);
1341                         readAttrs(c, AttributeKind.MEMBER);
1342                         components.add(c);
1343                     }
1344                     ((ClassSymbol) sym).setRecordComponents(components.toList());
1345                 }
1346             },
1347             new AttributeReader(names.PermittedSubclasses, V59, CLASS_ATTRIBUTE) {
1348                 @Override
1349                 protected boolean accepts(AttributeKind kind) {
1350                     return super.accepts(kind) && allowSealedTypes;
1351                 }
1352                 protected void read(Symbol sym, int attrLen) {
1353                     if (sym.kind == TYP) {
1354                         ListBuffer<Symbol> subtypes = new ListBuffer<>();
1355                         int numberOfPermittedSubtypes = nextChar();
1356                         for (int i = 0; i < numberOfPermittedSubtypes; i++) {
1357                             subtypes.add(poolReader.getClass(nextChar()));
1358                         }
1359                         ((ClassSymbol)sym).setPermittedSubclasses(subtypes.toList());
1360                     }
1361                 }
1362             },
1363         };
1364 
1365         for (AttributeReader r: readers)
1366             attributeReaders.put(r.name, r);
1367     }
1368 
1369     protected void readEnclosingMethodAttr(Symbol sym) {
1370         // sym is a nested class with an "Enclosing Method" attribute
1371         // remove sym from it's current owners scope and place it in
1372         // the scope specified by the attribute
1373         sym.owner.members().remove(sym);
1374         ClassSymbol self = (ClassSymbol)sym;
1375         ClassSymbol c = poolReader.getClass(nextChar());
1376         NameAndType nt = optPoolEntry(nextChar(), poolReader::getNameAndType, null);
1377 
1378         if (c.members_field == null || c.kind != TYP)
1379             throw badClassFile("bad.enclosing.class", self, c);
1380 
1381         MethodSymbol m = findMethod(nt, c.members_field, self.flags());
1382         if (nt != null && m == null)
1383             throw badEnclosingMethod(self);
1384 
1385         self.name = simpleBinaryName(self.flatname, c.flatname) ;
1386         self.owner = m != null ? m : c;
1387         if (self.name.isEmpty())
1388             self.fullname = names.empty;
1389         else
1390             self.fullname = ClassSymbol.formFullName(self.name, self.owner);
1391 
1392         if (m != null) {
1393             ((ClassType)sym.type).setEnclosingType(m.type);
1394         } else if ((self.flags_field & STATIC) == 0) {
1395             ((ClassType)sym.type).setEnclosingType(c.type);
1396         } else {
1397             ((ClassType)sym.type).setEnclosingType(Type.noType);
1398         }
1399         enterTypevars(self, self.type);
1400         if (!missingTypeVariables.isEmpty()) {
1401             ListBuffer<Type> typeVars =  new ListBuffer<>();
1402             for (Type typevar : missingTypeVariables) {
1403                 typeVars.append(findTypeVar(typevar.tsym.name));
1404             }
1405             foundTypeVariables = typeVars.toList();
1406         } else {
1407             foundTypeVariables = List.nil();
1408         }
1409     }
1410 
1411     // See java.lang.Class
1412     private Name simpleBinaryName(Name self, Name enclosing) {
1413         if (!self.startsWith(enclosing)) {
1414             throw badClassFile("bad.enclosing.method", self);
1415         }
1416 
1417         String simpleBinaryName = self.toString().substring(enclosing.toString().length());
1418         if (simpleBinaryName.length() < 1 || simpleBinaryName.charAt(0) != '$')
1419             throw badClassFile("bad.enclosing.method", self);
1420         int index = 1;
1421         while (index < simpleBinaryName.length() &&
1422                isAsciiDigit(simpleBinaryName.charAt(index)))
1423             index++;
1424         return names.fromString(simpleBinaryName.substring(index));
1425     }
1426 
1427     private MethodSymbol findMethod(NameAndType nt, Scope scope, long flags) {
1428         if (nt == null)
1429             return null;
1430 
1431         MethodType type = nt.type.asMethodType();
1432 
1433         for (Symbol sym : scope.getSymbolsByName(nt.name)) {
1434             if (sym.kind == MTH && isSameBinaryType(sym.type.asMethodType(), type))
1435                 return (MethodSymbol)sym;
1436         }
1437 
1438         if (nt.name != names.init)
1439             // not a constructor
1440             return null;
1441         if ((flags & INTERFACE) != 0)
1442             // no enclosing instance
1443             return null;
1444         if (nt.type.getParameterTypes().isEmpty())
1445             // no parameters
1446             return null;
1447 
1448         // A constructor of an inner class.
1449         // Remove the first argument (the enclosing instance)
1450         nt = new NameAndType(nt.name, new MethodType(nt.type.getParameterTypes().tail,
1451                                  nt.type.getReturnType(),
1452                                  nt.type.getThrownTypes(),
1453                                  syms.methodClass));
1454         // Try searching again
1455         return findMethod(nt, scope, flags);
1456     }
1457 
1458     /** Similar to Types.isSameType but avoids completion */
1459     private boolean isSameBinaryType(MethodType mt1, MethodType mt2) {
1460         List<Type> types1 = types.erasure(mt1.getParameterTypes())
1461             .prepend(types.erasure(mt1.getReturnType()));
1462         List<Type> types2 = mt2.getParameterTypes().prepend(mt2.getReturnType());
1463         while (!types1.isEmpty() && !types2.isEmpty()) {
1464             if (types1.head.tsym != types2.head.tsym)
1465                 return false;
1466             types1 = types1.tail;
1467             types2 = types2.tail;
1468         }
1469         return types1.isEmpty() && types2.isEmpty();
1470     }
1471 
1472     /**
1473      * Character.isDigit answers <tt>true</tt> to some non-ascii
1474      * digits.  This one does not.  <b>copied from java.lang.Class</b>
1475      */
1476     private static boolean isAsciiDigit(char c) {
1477         return '0' <= c && c <= '9';
1478     }
1479 
1480     /** Read member attributes.
1481      */
1482     void readMemberAttrs(Symbol sym) {
1483         readAttrs(sym, AttributeKind.MEMBER);
1484     }
1485 
1486     void readAttrs(Symbol sym, AttributeKind kind) {
1487         char ac = nextChar();
1488         for (int i = 0; i < ac; i++) {
1489             Name attrName = poolReader.getName(nextChar());
1490             int attrLen = nextInt();
1491             AttributeReader r = attributeReaders.get(attrName);
1492             if (r != null && r.accepts(kind))
1493                 r.read(sym, attrLen);
1494             else  {
1495                 bp = bp + attrLen;
1496             }
1497         }
1498     }
1499 
1500     private boolean readingClassAttr = false;
1501     private List<Type> missingTypeVariables = List.nil();
1502     private List<Type> foundTypeVariables = List.nil();
1503 
1504     /** Read class attributes.
1505      */
1506     void readClassAttrs(ClassSymbol c) {
1507         readAttrs(c, AttributeKind.CLASS);
1508     }
1509 
1510     /** Read code block.
1511      */
1512     Code readCode(Symbol owner) {
1513         nextChar(); // max_stack
1514         nextChar(); // max_locals
1515         final int  code_length = nextInt();
1516         bp += code_length;
1517         final char exception_table_length = nextChar();
1518         bp += exception_table_length * 8;
1519         readMemberAttrs(owner);
1520         return null;
1521     }
1522 
1523 /* **********************************************************************
1524  * Reading Java-language annotations
1525  ***********************************************************************/
1526 
1527     /**
1528      * Save annotations.
1529      */
1530     List<CompoundAnnotationProxy> readAnnotations() {
1531         int numAttributes = nextChar();
1532         ListBuffer<CompoundAnnotationProxy> annotations = new ListBuffer<>();
1533         for (int i = 0; i < numAttributes; i++) {
1534             annotations.append(readCompoundAnnotation());
1535         }
1536         return annotations.toList();
1537     }
1538 
1539     /** Attach annotations.
1540      */
1541     void attachAnnotations(final Symbol sym) {
1542         attachAnnotations(sym, readAnnotations());
1543     }
1544 
1545     /**
1546      * Attach annotations.
1547      */
1548     void attachAnnotations(final Symbol sym, List<CompoundAnnotationProxy> annotations) {
1549         if (annotations.isEmpty()) {
1550             return;
1551         }
1552         ListBuffer<CompoundAnnotationProxy> proxies = new ListBuffer<>();
1553         for (CompoundAnnotationProxy proxy : annotations) {
1554             if (proxy.type.tsym.flatName() == syms.proprietaryType.tsym.flatName())
1555                 sym.flags_field |= PROPRIETARY;
1556             else if (proxy.type.tsym.flatName() == syms.profileType.tsym.flatName()) {
1557                 if (profile != Profile.DEFAULT) {
1558                     for (Pair<Name, Attribute> v : proxy.values) {
1559                         if (v.fst == names.value && v.snd instanceof Attribute.Constant constant) {
1560                             if (constant.type == syms.intType && ((Integer) constant.value) > profile.value) {
1561                                 sym.flags_field |= NOT_IN_PROFILE;
1562                             }
1563                         }
1564                     }
1565                 }
1566             } else if (proxy.type.tsym.flatName() == syms.previewFeatureInternalType.tsym.flatName()) {
1567                 sym.flags_field |= PREVIEW_API;
1568                 setFlagIfAttributeTrue(proxy, sym, names.reflective, PREVIEW_REFLECTIVE);
1569             } else if (proxy.type.tsym.flatName() == syms.valueBasedInternalType.tsym.flatName()) {
1570                 Assert.check(sym.kind == TYP);
1571                 sym.flags_field |= VALUE_BASED;
1572             } else if (proxy.type.tsym.flatName() == syms.migratedValueClassInternalType.tsym.flatName()) {
1573                 Assert.check(sym.kind == TYP);
1574                 sym.flags_field |= MIGRATED_VALUE_CLASS;
1575                 if (needsValueFlag(sym, sym.flags_field)) {
1576                     sym.flags_field |= VALUE_CLASS;
1577                     sym.flags_field &= ~IDENTITY_TYPE;
1578                 }
1579             } else if (proxy.type.tsym.flatName() == syms.restrictedInternalType.tsym.flatName()) {
1580                 Assert.check(sym.kind == MTH);
1581                 sym.flags_field |= RESTRICTED;
1582             } else {
1583                 if (proxy.type.tsym == syms.annotationTargetType.tsym) {
1584                     target = proxy;
1585                 } else if (proxy.type.tsym == syms.repeatableType.tsym) {
1586                     repeatable = proxy;
1587                 } else if (proxy.type.tsym == syms.deprecatedType.tsym) {
1588                     sym.flags_field |= (DEPRECATED | DEPRECATED_ANNOTATION);
1589                     setFlagIfAttributeTrue(proxy, sym, names.forRemoval, DEPRECATED_REMOVAL);
1590                 }  else if (proxy.type.tsym == syms.previewFeatureType.tsym) {
1591                     sym.flags_field |= PREVIEW_API;
1592                     setFlagIfAttributeTrue(proxy, sym, names.reflective, PREVIEW_REFLECTIVE);
1593                 }  else if (proxy.type.tsym == syms.valueBasedType.tsym && sym.kind == TYP) {
1594                     sym.flags_field |= VALUE_BASED;
1595                 }  else if (proxy.type.tsym == syms.migratedValueClassType.tsym && sym.kind == TYP) {
1596                     sym.flags_field |= MIGRATED_VALUE_CLASS;
1597                     if (needsValueFlag(sym, sym.flags_field)) {
1598                         sym.flags_field |= VALUE_CLASS;
1599                         sym.flags_field &= ~IDENTITY_TYPE;
1600                     }
1601                 }  else if (proxy.type.tsym == syms.restrictedType.tsym) {
1602                     Assert.check(sym.kind == MTH);
1603                     sym.flags_field |= RESTRICTED;
1604                 }
1605                 proxies.append(proxy);
1606             }
1607         }
1608         annotate.normal(new AnnotationCompleter(sym, proxies.toList()));
1609     }
1610     //where:
1611         private void setFlagIfAttributeTrue(CompoundAnnotationProxy proxy, Symbol sym, Name attribute, long flag) {
1612             for (Pair<Name, Attribute> v : proxy.values) {
1613                 if (v.fst == attribute && v.snd instanceof Attribute.Constant constant) {
1614                     if (constant.type == syms.booleanType && ((Integer) constant.value) != 0) {
1615                         sym.flags_field |= flag;
1616                     }
1617                 }
1618             }
1619         }
1620 
1621     /** Read parameter annotations.
1622      */
1623     void readParameterAnnotations(Symbol meth) {
1624         int numParameters;
1625         try {
1626             numParameters = buf.getByte(bp++) & 0xFF;
1627         } catch (UnderflowException e) {
1628             throw badClassFile(Fragments.BadClassTruncatedAtOffset(e.getLength()));
1629         }
1630         if (parameterAnnotations == null) {
1631             parameterAnnotations = new ParameterAnnotations[numParameters];
1632         } else if (parameterAnnotations.length != numParameters) {
1633             //the RuntimeVisibleParameterAnnotations and RuntimeInvisibleParameterAnnotations
1634             //provide annotations for a different number of parameters, ignore:
1635             lint.logIfEnabled(log, LintWarnings.RuntimeVisibleInvisibleParamAnnotationsMismatch(currentClassFile));
1636             for (int pnum = 0; pnum < numParameters; pnum++) {
1637                 readAnnotations();
1638             }
1639             parameterAnnotations = null;
1640             return ;
1641         }
1642         for (int pnum = 0; pnum < numParameters; pnum++) {
1643             if (parameterAnnotations[pnum] == null) {
1644                 parameterAnnotations[pnum] = new ParameterAnnotations();
1645             }
1646             parameterAnnotations[pnum].add(readAnnotations());
1647         }
1648     }
1649 
1650     void attachTypeAnnotations(final Symbol sym) {
1651         int numAttributes = nextChar();
1652         if (numAttributes != 0) {
1653             ListBuffer<TypeAnnotationProxy> proxies = new ListBuffer<>();
1654             for (int i = 0; i < numAttributes; i++)
1655                 proxies.append(readTypeAnnotation());
1656             annotate.normal(new TypeAnnotationCompleter(sym, proxies.toList()));
1657         }
1658     }
1659 
1660     /** Attach the default value for an annotation element.
1661      */
1662     void attachAnnotationDefault(final Symbol sym) {
1663         final MethodSymbol meth = (MethodSymbol)sym; // only on methods
1664         final Attribute value = readAttributeValue();
1665 
1666         // The default value is set later during annotation. It might
1667         // be the case that the Symbol sym is annotated _after_ the
1668         // repeating instances that depend on this default value,
1669         // because of this we set an interim value that tells us this
1670         // element (most likely) has a default.
1671         //
1672         // Set interim value for now, reset just before we do this
1673         // properly at annotate time.
1674         meth.defaultValue = value;
1675         annotate.normal(new AnnotationDefaultCompleter(meth, value));
1676     }
1677 
1678     Type readTypeOrClassSymbol(int i) {
1679         return readTypeToProxy(i);
1680     }
1681     Type readTypeToProxy(int i) {
1682         if (currentModule.module_info == currentOwner) {
1683             return new ProxyType(i);
1684         } else {
1685             return poolReader.getType(i);
1686         }
1687     }
1688 
1689     CompoundAnnotationProxy readCompoundAnnotation() {
1690         Type t;
1691         if (currentModule.module_info == currentOwner) {
1692             int cpIndex = nextChar();
1693             t = new ProxyType(cpIndex);
1694         } else {
1695             t = readTypeOrClassSymbol(nextChar());
1696         }
1697         int numFields = nextChar();
1698         ListBuffer<Pair<Name,Attribute>> pairs = new ListBuffer<>();
1699         for (int i=0; i<numFields; i++) {
1700             Name name = poolReader.getName(nextChar());
1701             Attribute value = readAttributeValue();
1702             pairs.append(new Pair<>(name, value));
1703         }
1704         return new CompoundAnnotationProxy(t, pairs.toList());
1705     }
1706 
1707     TypeAnnotationProxy readTypeAnnotation() {
1708         TypeAnnotationPosition position = readPosition();
1709         CompoundAnnotationProxy proxy = readCompoundAnnotation();
1710 
1711         return new TypeAnnotationProxy(proxy, position);
1712     }
1713 
1714     TypeAnnotationPosition readPosition() {
1715         int tag = nextByte(); // TargetType tag is a byte
1716 
1717         if (!TargetType.isValidTargetTypeValue(tag))
1718             throw badClassFile("bad.type.annotation.value", String.format("0x%02X", tag));
1719 
1720         TargetType type = TargetType.fromTargetTypeValue(tag);
1721 
1722         switch (type) {
1723         // instanceof
1724         case INSTANCEOF: {
1725             final int offset = nextChar();
1726             final TypeAnnotationPosition position =
1727                 TypeAnnotationPosition.instanceOf(readTypePath());
1728             position.offset = offset;
1729             return position;
1730         }
1731         // new expression
1732         case NEW: {
1733             final int offset = nextChar();
1734             final TypeAnnotationPosition position =
1735                 TypeAnnotationPosition.newObj(readTypePath());
1736             position.offset = offset;
1737             return position;
1738         }
1739         // constructor/method reference receiver
1740         case CONSTRUCTOR_REFERENCE: {
1741             final int offset = nextChar();
1742             final TypeAnnotationPosition position =
1743                 TypeAnnotationPosition.constructorRef(readTypePath());
1744             position.offset = offset;
1745             return position;
1746         }
1747         case METHOD_REFERENCE: {
1748             final int offset = nextChar();
1749             final TypeAnnotationPosition position =
1750                 TypeAnnotationPosition.methodRef(readTypePath());
1751             position.offset = offset;
1752             return position;
1753         }
1754         // local variable
1755         case LOCAL_VARIABLE: {
1756             final int table_length = nextChar();
1757             final int[] newLvarOffset = new int[table_length];
1758             final int[] newLvarLength = new int[table_length];
1759             final int[] newLvarIndex = new int[table_length];
1760 
1761             for (int i = 0; i < table_length; ++i) {
1762                 newLvarOffset[i] = nextChar();
1763                 newLvarLength[i] = nextChar();
1764                 newLvarIndex[i] = nextChar();
1765             }
1766 
1767             final TypeAnnotationPosition position =
1768                     TypeAnnotationPosition.localVariable(readTypePath());
1769             position.lvarOffset = newLvarOffset;
1770             position.lvarLength = newLvarLength;
1771             position.lvarIndex = newLvarIndex;
1772             return position;
1773         }
1774         // resource variable
1775         case RESOURCE_VARIABLE: {
1776             final int table_length = nextChar();
1777             final int[] newLvarOffset = new int[table_length];
1778             final int[] newLvarLength = new int[table_length];
1779             final int[] newLvarIndex = new int[table_length];
1780 
1781             for (int i = 0; i < table_length; ++i) {
1782                 newLvarOffset[i] = nextChar();
1783                 newLvarLength[i] = nextChar();
1784                 newLvarIndex[i] = nextChar();
1785             }
1786 
1787             final TypeAnnotationPosition position =
1788                     TypeAnnotationPosition.resourceVariable(readTypePath());
1789             position.lvarOffset = newLvarOffset;
1790             position.lvarLength = newLvarLength;
1791             position.lvarIndex = newLvarIndex;
1792             return position;
1793         }
1794         // exception parameter
1795         case EXCEPTION_PARAMETER: {
1796             final int exception_index = nextChar();
1797             final TypeAnnotationPosition position =
1798                 TypeAnnotationPosition.exceptionParameter(readTypePath());
1799             position.setExceptionIndex(exception_index);
1800             return position;
1801         }
1802         // method receiver
1803         case METHOD_RECEIVER:
1804             return TypeAnnotationPosition.methodReceiver(readTypePath());
1805         // type parameter
1806         case CLASS_TYPE_PARAMETER: {
1807             final int parameter_index = nextByte();
1808             return TypeAnnotationPosition
1809                 .typeParameter(readTypePath(), parameter_index);
1810         }
1811         case METHOD_TYPE_PARAMETER: {
1812             final int parameter_index = nextByte();
1813             return TypeAnnotationPosition
1814                 .methodTypeParameter(readTypePath(), parameter_index);
1815         }
1816         // type parameter bound
1817         case CLASS_TYPE_PARAMETER_BOUND: {
1818             final int parameter_index = nextByte();
1819             final int bound_index = nextByte();
1820             return TypeAnnotationPosition
1821                 .typeParameterBound(readTypePath(), parameter_index,
1822                                     bound_index);
1823         }
1824         case METHOD_TYPE_PARAMETER_BOUND: {
1825             final int parameter_index = nextByte();
1826             final int bound_index = nextByte();
1827             return TypeAnnotationPosition
1828                 .methodTypeParameterBound(readTypePath(), parameter_index,
1829                                           bound_index);
1830         }
1831         // class extends or implements clause
1832         case CLASS_EXTENDS: {
1833             final int type_index = nextChar();
1834             return TypeAnnotationPosition.classExtends(readTypePath(),
1835                                                        type_index);
1836         }
1837         // throws
1838         case THROWS: {
1839             final int type_index = nextChar();
1840             return TypeAnnotationPosition.methodThrows(readTypePath(),
1841                                                        type_index);
1842         }
1843         // method parameter
1844         case METHOD_FORMAL_PARAMETER: {
1845             final int parameter_index = nextByte();
1846             return TypeAnnotationPosition.methodParameter(readTypePath(),
1847                                                           parameter_index);
1848         }
1849         // type cast
1850         case CAST: {
1851             final int offset = nextChar();
1852             final int type_index = nextByte();
1853             final TypeAnnotationPosition position =
1854                 TypeAnnotationPosition.typeCast(readTypePath(), type_index);
1855             position.offset = offset;
1856             return position;
1857         }
1858         // method/constructor/reference type argument
1859         case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: {
1860             final int offset = nextChar();
1861             final int type_index = nextByte();
1862             final TypeAnnotationPosition position = TypeAnnotationPosition
1863                 .constructorInvocationTypeArg(readTypePath(), type_index);
1864             position.offset = offset;
1865             return position;
1866         }
1867         case METHOD_INVOCATION_TYPE_ARGUMENT: {
1868             final int offset = nextChar();
1869             final int type_index = nextByte();
1870             final TypeAnnotationPosition position = TypeAnnotationPosition
1871                 .methodInvocationTypeArg(readTypePath(), type_index);
1872             position.offset = offset;
1873             return position;
1874         }
1875         case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: {
1876             final int offset = nextChar();
1877             final int type_index = nextByte();
1878             final TypeAnnotationPosition position = TypeAnnotationPosition
1879                 .constructorRefTypeArg(readTypePath(), type_index);
1880             position.offset = offset;
1881             return position;
1882         }
1883         case METHOD_REFERENCE_TYPE_ARGUMENT: {
1884             final int offset = nextChar();
1885             final int type_index = nextByte();
1886             final TypeAnnotationPosition position = TypeAnnotationPosition
1887                 .methodRefTypeArg(readTypePath(), type_index);
1888             position.offset = offset;
1889             return position;
1890         }
1891         // We don't need to worry about these
1892         case METHOD_RETURN:
1893             return TypeAnnotationPosition.methodReturn(readTypePath());
1894         case FIELD:
1895             return TypeAnnotationPosition.field(readTypePath());
1896         case UNKNOWN:
1897             throw new AssertionError("jvm.ClassReader: UNKNOWN target type should never occur!");
1898         default:
1899             throw new AssertionError("jvm.ClassReader: Unknown target type for position: " + type);
1900         }
1901     }
1902 
1903     List<TypeAnnotationPosition.TypePathEntry> readTypePath() {
1904         int len = nextByte();
1905         ListBuffer<Integer> loc = new ListBuffer<>();
1906         for (int i = 0; i < len * TypeAnnotationPosition.TypePathEntry.bytesPerEntry; ++i)
1907             loc = loc.append(nextByte());
1908 
1909         return TypeAnnotationPosition.getTypePathFromBinary(loc.toList());
1910 
1911     }
1912 
1913     /**
1914      * Helper function to read an optional pool entry (with given function); this is used while parsing
1915      * InnerClasses and EnclosingMethod attributes, as well as when parsing supertype descriptor,
1916      * as per JVMS.
1917      */
1918     <Z> Z optPoolEntry(int index, IntFunction<Z> poolFunc, Z defaultValue) {
1919         return (index == 0) ?
1920                 defaultValue :
1921                 poolFunc.apply(index);
1922     }
1923 
1924     Attribute readAttributeValue() {
1925         char c;
1926         try {
1927             c = (char)buf.getByte(bp++);
1928         } catch (UnderflowException e) {
1929             throw badClassFile(Fragments.BadClassTruncatedAtOffset(e.getLength()));
1930         }
1931         switch (c) {
1932         case 'B':
1933             return new Attribute.Constant(syms.byteType, poolReader.getConstant(nextChar()));
1934         case 'C':
1935             return new Attribute.Constant(syms.charType, poolReader.getConstant(nextChar()));
1936         case 'D':
1937             return new Attribute.Constant(syms.doubleType, poolReader.getConstant(nextChar()));
1938         case 'F':
1939             return new Attribute.Constant(syms.floatType, poolReader.getConstant(nextChar()));
1940         case 'I':
1941             return new Attribute.Constant(syms.intType, poolReader.getConstant(nextChar()));
1942         case 'J':
1943             return new Attribute.Constant(syms.longType, poolReader.getConstant(nextChar()));
1944         case 'S':
1945             return new Attribute.Constant(syms.shortType, poolReader.getConstant(nextChar()));
1946         case 'Z':
1947             return new Attribute.Constant(syms.booleanType, poolReader.getConstant(nextChar()));
1948         case 's':
1949             return new Attribute.Constant(syms.stringType, poolReader.getName(nextChar()).toString());
1950         case 'e':
1951             return new EnumAttributeProxy(readTypeToProxy(nextChar()), poolReader.getName(nextChar()));
1952         case 'c':
1953             return new ClassAttributeProxy(readTypeOrClassSymbol(nextChar()));
1954         case '[': {
1955             int n = nextChar();
1956             ListBuffer<Attribute> l = new ListBuffer<>();
1957             for (int i=0; i<n; i++)
1958                 l.append(readAttributeValue());
1959             return new ArrayAttributeProxy(l.toList());
1960         }
1961         case '@':
1962             return readCompoundAnnotation();
1963         default:
1964             throw new AssertionError("unknown annotation tag '" + c + "'");
1965         }
1966     }
1967 
1968     interface ProxyVisitor extends Attribute.Visitor {
1969         void visitEnumAttributeProxy(EnumAttributeProxy proxy);
1970         void visitClassAttributeProxy(ClassAttributeProxy proxy);
1971         void visitArrayAttributeProxy(ArrayAttributeProxy proxy);
1972         void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy);
1973     }
1974 
1975     static class EnumAttributeProxy extends Attribute {
1976         Type enumType;
1977         Name enumerator;
1978         public EnumAttributeProxy(Type enumType, Name enumerator) {
1979             super(null);
1980             this.enumType = enumType;
1981             this.enumerator = enumerator;
1982         }
1983         public void accept(Visitor v) { ((ProxyVisitor)v).visitEnumAttributeProxy(this); }
1984         @Override @DefinedBy(Api.LANGUAGE_MODEL)
1985         public String toString() {
1986             return "/*proxy enum*/" + enumType + "." + enumerator;
1987         }
1988     }
1989 
1990     static class ClassAttributeProxy extends Attribute {
1991         Type classType;
1992         public ClassAttributeProxy(Type classType) {
1993             super(null);
1994             this.classType = classType;
1995         }
1996         public void accept(Visitor v) { ((ProxyVisitor)v).visitClassAttributeProxy(this); }
1997         @Override @DefinedBy(Api.LANGUAGE_MODEL)
1998         public String toString() {
1999             return "/*proxy class*/" + classType + ".class";
2000         }
2001     }
2002 
2003     static class ArrayAttributeProxy extends Attribute {
2004         List<Attribute> values;
2005         ArrayAttributeProxy(List<Attribute> values) {
2006             super(null);
2007             this.values = values;
2008         }
2009         public void accept(Visitor v) { ((ProxyVisitor)v).visitArrayAttributeProxy(this); }
2010         @Override @DefinedBy(Api.LANGUAGE_MODEL)
2011         public String toString() {
2012             return "{" + values + "}";
2013         }
2014     }
2015 
2016     /** A temporary proxy representing a compound attribute.
2017      */
2018     static class CompoundAnnotationProxy extends Attribute {
2019         final List<Pair<Name,Attribute>> values;
2020         public CompoundAnnotationProxy(Type type,
2021                                       List<Pair<Name,Attribute>> values) {
2022             super(type);
2023             this.values = values;
2024         }
2025         public void accept(Visitor v) { ((ProxyVisitor)v).visitCompoundAnnotationProxy(this); }
2026         @Override @DefinedBy(Api.LANGUAGE_MODEL)
2027         public String toString() {
2028             StringBuilder buf = new StringBuilder();
2029             buf.append("@");
2030             buf.append(type.tsym.getQualifiedName());
2031             buf.append("/*proxy*/{");
2032             boolean first = true;
2033             for (List<Pair<Name,Attribute>> v = values;
2034                  v.nonEmpty(); v = v.tail) {
2035                 Pair<Name,Attribute> value = v.head;
2036                 if (!first) buf.append(",");
2037                 first = false;
2038                 buf.append(value.fst);
2039                 buf.append("=");
2040                 buf.append(value.snd);
2041             }
2042             buf.append("}");
2043             return buf.toString();
2044         }
2045     }
2046 
2047     /** A temporary proxy representing a type annotation.
2048      */
2049     static class TypeAnnotationProxy {
2050         final CompoundAnnotationProxy compound;
2051         final TypeAnnotationPosition position;
2052         public TypeAnnotationProxy(CompoundAnnotationProxy compound,
2053                 TypeAnnotationPosition position) {
2054             this.compound = compound;
2055             this.position = position;
2056         }
2057     }
2058 
2059     class AnnotationDeproxy implements ProxyVisitor {
2060         private ClassSymbol requestingOwner;
2061 
2062         AnnotationDeproxy(ClassSymbol owner) {
2063             this.requestingOwner = owner;
2064         }
2065 
2066         List<Attribute.Compound> deproxyCompoundList(List<CompoundAnnotationProxy> pl) {
2067             // also must fill in types!!!!
2068             ListBuffer<Attribute.Compound> buf = new ListBuffer<>();
2069             for (List<CompoundAnnotationProxy> l = pl; l.nonEmpty(); l=l.tail) {
2070                 buf.append(deproxyCompound(l.head));
2071             }
2072             return buf.toList();
2073         }
2074 
2075         Attribute.Compound deproxyCompound(CompoundAnnotationProxy a) {
2076             Type annotationType = resolvePossibleProxyType(a.type);
2077             ListBuffer<Pair<Symbol.MethodSymbol,Attribute>> buf = new ListBuffer<>();
2078             for (List<Pair<Name,Attribute>> l = a.values;
2079                  l.nonEmpty();
2080                  l = l.tail) {
2081                 MethodSymbol meth = findAccessMethod(annotationType, l.head.fst);
2082                 buf.append(new Pair<>(meth, deproxy(meth.type.getReturnType(), l.head.snd)));
2083             }
2084             return new Attribute.Compound(annotationType, buf.toList());
2085         }
2086 
2087         MethodSymbol findAccessMethod(Type container, Name name) {
2088             CompletionFailure failure = null;
2089             try {
2090                 for (Symbol sym : container.tsym.members().getSymbolsByName(name)) {
2091                     if (sym.kind == MTH && sym.type.getParameterTypes().length() == 0)
2092                         return (MethodSymbol) sym;
2093                 }
2094             } catch (CompletionFailure ex) {
2095                 failure = ex;
2096             }
2097             // The method wasn't found: emit a warning and recover
2098             JavaFileObject prevSource = log.useSource(requestingOwner.classfile);
2099             try {
2100                 if (failure == null) {
2101                     lint.logIfEnabled(log, LintWarnings.AnnotationMethodNotFound(container, name));
2102                 } else {
2103                     lint.logIfEnabled(log, LintWarnings.AnnotationMethodNotFoundReason(container,
2104                                                                             name,
2105                                                                             failure.getDetailValue()));//diagnostic, if present
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         lint.logIfEnabled(log, LintWarnings.RuntimeInvisibleParameterAnnotations(currentClassFile));
2982     }
2983     /**
2984      * Creates the parameter at the position {@code mpIndex} in the parameter list of the owning method.
2985      * Flags are optionally read from the MethodParameters attribute.
2986      * Names are optionally read from the MethodParameters attribute. If the constant pool index
2987      * of the name is 0, then the name is optionally read from the LocalVariableTable attribute.
2988      * @param mpIndex the index of the parameter in the MethodParameters attribute
2989      * @param lvtIndex the index of the parameter in the LocalVariableTable attribute
2990      */
2991     private VarSymbol parameter(int mpIndex, int lvtIndex, Type t, MethodSymbol owner, Set<Name> exclude) {
2992         long flags = PARAMETER;
2993         Name argName;
2994         if (parameterAccessFlags != null && mpIndex < parameterAccessFlags.length
2995                 && parameterAccessFlags[mpIndex] != 0) {
2996             flags |= parameterAccessFlags[mpIndex];
2997         }
2998         if (parameterNameIndicesMp != null && mpIndex < parameterNameIndicesMp.length
2999                 // if name_index is 0, then we might still get a name from the LocalVariableTable
3000                 && parameterNameIndicesMp[mpIndex] != 0) {
3001             argName = optPoolEntry(parameterNameIndicesMp[mpIndex], poolReader::getName, names.empty);
3002             flags |= NAME_FILLED;
3003         } else if (parameterNameIndicesLvt != null && lvtIndex < parameterNameIndicesLvt.length
3004                 && parameterNameIndicesLvt[lvtIndex] != 0) {
3005             argName = optPoolEntry(parameterNameIndicesLvt[lvtIndex], poolReader::getName, names.empty);
3006             flags |= NAME_FILLED;
3007         } else {
3008             String prefix = "arg";
3009             while (true) {
3010                 argName = names.fromString(prefix + exclude.size());
3011                 if (!exclude.contains(argName))
3012                     break;
3013                 prefix += "$";
3014             }
3015         }
3016         exclude.add(argName);
3017         return new ParamSymbol(flags, argName, t, owner);
3018     }
3019 
3020     /**
3021      * skip n bytes
3022      */
3023     void skipBytes(int n) {
3024         bp = bp + n;
3025     }
3026 
3027     /** Skip a field or method
3028      */
3029     void skipMember() {
3030         bp = bp + 6;
3031         char ac = nextChar();
3032         for (int i = 0; i < ac; i++) {
3033             bp = bp + 2;
3034             int attrLen = nextInt();
3035             bp = bp + attrLen;
3036         }
3037     }
3038 
3039     void skipInnerClasses() {
3040         int n = nextChar();
3041         for (int i = 0; i < n; i++) {
3042             nextChar();
3043             nextChar();
3044             nextChar();
3045             nextChar();
3046         }
3047     }
3048 
3049     /** Enter type variables of this classtype and all enclosing ones in
3050      *  `typevars'.
3051      */
3052     protected void enterTypevars(Symbol sym, Type t) {
3053         if (t.getEnclosingType() != null) {
3054             if (!t.getEnclosingType().hasTag(TypeTag.NONE)) {
3055                 enterTypevars(sym.owner, t.getEnclosingType());
3056             }
3057         } else if (sym.kind == MTH && !sym.isStatic()) {
3058             enterTypevars(sym.owner, sym.owner.type);
3059         }
3060         for (List<Type> xs = t.getTypeArguments(); xs.nonEmpty(); xs = xs.tail) {
3061             typevars.enter(xs.head.tsym);
3062         }
3063     }
3064 
3065     protected ClassSymbol enterClass(Name name) {
3066         return syms.enterClass(currentModule, name);
3067     }
3068 
3069     protected ClassSymbol enterClass(Name name, TypeSymbol owner) {
3070         return syms.enterClass(currentModule, name, owner);
3071     }
3072 
3073     /** Read contents of a given class symbol `c'. Both external and internal
3074      *  versions of an inner class are read.
3075      */
3076     void readClass(ClassSymbol c) {
3077         ClassType ct = (ClassType)c.type;
3078 
3079         // allocate scope for members
3080         c.members_field = WriteableScope.create(c);
3081 
3082         // prepare type variable table
3083         typevars = typevars.dup(currentOwner);
3084         if (ct.getEnclosingType().hasTag(CLASS))
3085             enterTypevars(c.owner, ct.getEnclosingType());
3086 
3087         // read flags, or skip if this is an inner class
3088         long f = nextChar();
3089         long flags = adjustClassFlags(c, f);
3090         if ((flags & MODULE) == 0) {
3091             if (c.owner.kind == PCK || c.owner.kind == ERR) c.flags_field = flags;
3092             // read own class name and check that it matches
3093             currentModule = c.packge().modle;
3094             ClassSymbol self = poolReader.getClass(nextChar());
3095             if (c != self) {
3096                 throw badClassFile("class.file.wrong.class",
3097                                    self.flatname);
3098             }
3099         } else {
3100             if (majorVersion < Version.V53.major) {
3101                 throw badClassFile("anachronistic.module.info",
3102                         Integer.toString(majorVersion),
3103                         Integer.toString(minorVersion));
3104             }
3105             c.flags_field = flags;
3106             if (c.owner.kind != MDL) {
3107                 throw badClassFile("module.info.definition.expected");
3108             }
3109             currentModule = (ModuleSymbol) c.owner;
3110             int this_class = nextChar();
3111             // temp, no check on this_class
3112         }
3113 
3114         // class attributes must be read before class
3115         // skip ahead to read class attributes
3116         int startbp = bp;
3117         nextChar();
3118         char interfaceCount = nextChar();
3119         bp += interfaceCount * 2;
3120         char fieldCount = nextChar();
3121         for (int i = 0; i < fieldCount; i++) skipMember();
3122         char methodCount = nextChar();
3123         for (int i = 0; i < methodCount; i++) skipMember();
3124         readClassAttrs(c);
3125 
3126         if (!c.getPermittedSubclasses().isEmpty()) {
3127             c.flags_field |= SEALED;
3128         }
3129 
3130         // reset and read rest of classinfo
3131         bp = startbp;
3132         int n = nextChar();
3133         if ((flags & MODULE) != 0 && n > 0) {
3134             throw badClassFile("module.info.invalid.super.class");
3135         }
3136         if (ct.supertype_field == null)
3137             ct.supertype_field =
3138                     optPoolEntry(n, idx -> poolReader.getClass(idx).erasure(types), Type.noType);
3139         n = nextChar();
3140         List<Type> is = List.nil();
3141         for (int i = 0; i < n; i++) {
3142             Type _inter = poolReader.getClass(nextChar()).erasure(types);
3143             is = is.prepend(_inter);
3144         }
3145         if (ct.interfaces_field == null)
3146             ct.interfaces_field = is.reverse();
3147 
3148         Assert.check(fieldCount == nextChar());
3149         for (int i = 0; i < fieldCount; i++) enterMember(c, readField());
3150         Assert.check(methodCount == nextChar());
3151         for (int i = 0; i < methodCount; i++) enterMember(c, readMethod());
3152         if (c.isRecord()) {
3153             for (RecordComponent rc: c.getRecordComponents()) {
3154                 rc.accessor = lookupMethod(c, rc.name, List.nil());
3155             }
3156         }
3157         typevars = typevars.leave();
3158     }
3159 
3160     private MethodSymbol lookupMethod(TypeSymbol tsym, Name name, List<Type> argtypes) {
3161         for (Symbol s : tsym.members().getSymbolsByName(name, s -> s.kind == MTH)) {
3162             if (types.isSameTypes(s.type.getParameterTypes(), argtypes)) {
3163                 return (MethodSymbol) s;
3164             }
3165         }
3166         return null;
3167     }
3168 
3169     /** Read inner class info. For each inner/outer pair allocate a
3170      *  member class.
3171      */
3172     void readInnerClasses(ClassSymbol c) {
3173         int n = nextChar();
3174         for (int i = 0; i < n; i++) {
3175             nextChar(); // skip inner class symbol
3176             int outerIdx = nextChar();
3177             int nameIdx = nextChar();
3178             ClassSymbol outer = optPoolEntry(outerIdx, poolReader::getClass, null);
3179             Name name = optPoolEntry(nameIdx, poolReader::getName, names.empty);
3180             if (name == null) name = names.empty;
3181             long flags = adjustClassFlags(c, nextChar());
3182             if (outer != null) { // we have a member class
3183                 if (name == names.empty)
3184                     name = names.one;
3185                 ClassSymbol member = enterClass(name, outer);
3186                 if ((flags & STATIC) == 0) {
3187                     ((ClassType)member.type).setEnclosingType(outer.type);
3188                     if (member.erasure_field != null)
3189                         ((ClassType)member.erasure_field).setEnclosingType(types.erasure(outer.type));
3190                 }
3191                 if (c == outer && member.owner == c) {
3192                     member.flags_field = flags;
3193                     enterMember(c, member);
3194                 }
3195             }
3196         }
3197     }
3198 
3199     /** Read a class definition from the bytes in buf.
3200      */
3201     private void readClassBuffer(ClassSymbol c) throws IOException {
3202         int magic = nextInt();
3203         if (magic != JAVA_MAGIC)
3204             throw badClassFile("illegal.start.of.class.file");
3205 
3206         minorVersion = nextChar();
3207         majorVersion = nextChar();
3208         int maxMajor = Version.MAX().major;
3209         int maxMinor = Version.MAX().minor;
3210         previewClassFile =
3211                 minorVersion == ClassFile.PREVIEW_MINOR_VERSION;
3212         if (majorVersion > maxMajor ||
3213             majorVersion * 1000 + minorVersion <
3214             Version.MIN().major * 1000 + Version.MIN().minor) {
3215             if (majorVersion == (maxMajor + 1) && !previewClassFile)
3216                 log.warning(Warnings.BigMajorVersion(currentClassFile,
3217                                                      majorVersion,
3218                                                      maxMajor));
3219             else
3220                 throw badClassFile("wrong.version",
3221                                    Integer.toString(majorVersion),
3222                                    Integer.toString(minorVersion),
3223                                    Integer.toString(maxMajor),
3224                                    Integer.toString(maxMinor));
3225         }
3226         utf8validation = majorVersion < V48.major ? Convert.Validation.PREJDK14 : Convert.Validation.STRICT;
3227 
3228         if (previewClassFile) {
3229             if (!preview.isEnabled()) {
3230                 log.error(preview.disabledError(currentClassFile, majorVersion));
3231             } else {
3232                 preview.warnPreview(c.classfile, majorVersion);
3233             }
3234         }
3235 
3236         poolReader = new PoolReader(this, names, syms);
3237         bp = poolReader.readPool(buf, bp);
3238         if (signatureBuffer.length < bp) {
3239             int ns = Integer.highestOneBit(bp) << 1;
3240             signatureBuffer = new byte[ns];
3241         }
3242         readClass(c);
3243     }
3244 
3245     public void readClassFile(ClassSymbol c) {
3246         currentOwner = c;
3247         currentClassFile = c.classfile;
3248         warnedAttrs.clear();
3249         filling = true;
3250         target = null;
3251         repeatable = null;
3252         try {
3253             bp = 0;
3254             buf.reset();
3255             try (InputStream input = c.classfile.openInputStream()) {
3256                 buf.appendStream(input);
3257             }
3258             readClassBuffer(c);
3259             if (!missingTypeVariables.isEmpty() && !foundTypeVariables.isEmpty()) {
3260                 List<Type> missing = missingTypeVariables;
3261                 List<Type> found = foundTypeVariables;
3262                 missingTypeVariables = List.nil();
3263                 foundTypeVariables = List.nil();
3264                 interimUses = List.nil();
3265                 interimProvides = List.nil();
3266                 filling = false;
3267                 ClassType ct = (ClassType)currentOwner.type;
3268                 ct.supertype_field =
3269                     types.subst(ct.supertype_field, missing, found);
3270                 ct.interfaces_field =
3271                     types.subst(ct.interfaces_field, missing, found);
3272                 ct.typarams_field =
3273                     types.substBounds(ct.typarams_field, missing, found);
3274                 for (List<Type> types = ct.typarams_field; types.nonEmpty(); types = types.tail) {
3275                     types.head.tsym.type = types.head;
3276                 }
3277             } else if (missingTypeVariables.isEmpty() !=
3278                        foundTypeVariables.isEmpty()) {
3279                 Name name = missingTypeVariables.head.tsym.name;
3280                 throw badClassFile("undecl.type.var", name);
3281             }
3282 
3283             if ((c.flags_field & Flags.ANNOTATION) != 0) {
3284                 c.setAnnotationTypeMetadata(new AnnotationTypeMetadata(c, new CompleterDeproxy(c, target, repeatable)));
3285             } else {
3286                 c.setAnnotationTypeMetadata(AnnotationTypeMetadata.notAnAnnotationType());
3287             }
3288 
3289             if (c == currentModule.module_info) {
3290                 if (interimUses.nonEmpty() || interimProvides.nonEmpty()) {
3291                     Assert.check(currentModule.isCompleted());
3292                     currentModule.usesProvidesCompleter =
3293                             new UsesProvidesCompleter(currentModule, interimUses, interimProvides);
3294                 } else {
3295                     currentModule.uses = List.nil();
3296                     currentModule.provides = List.nil();
3297                 }
3298             }
3299         } catch (IOException | ClosedFileSystemException ex) {
3300             throw badClassFile("unable.to.access.file", ex.toString());
3301         } catch (ArrayIndexOutOfBoundsException ex) {
3302             throw badClassFile("bad.class.file", c.flatname);
3303         } finally {
3304             interimUses = List.nil();
3305             interimProvides = List.nil();
3306             missingTypeVariables = List.nil();
3307             foundTypeVariables = List.nil();
3308             filling = false;
3309         }
3310     }
3311 
3312     /** We can only read a single class file at a time; this
3313      *  flag keeps track of when we are currently reading a class
3314      *  file.
3315      */
3316     public boolean filling = false;
3317 
3318 /* **********************************************************************
3319  * Adjusting flags
3320  ***********************************************************************/
3321 
3322     long adjustFieldFlags(long flags) {
3323         boolean previewClassFile = minorVersion == ClassFile.PREVIEW_MINOR_VERSION;
3324         if (allowValueClasses && previewClassFile && (flags & ACC_STRICT) != 0) {
3325             flags &= ~ACC_STRICT;
3326             flags |= STRICT;
3327         }
3328         return flags;
3329     }
3330 
3331     long adjustMethodFlags(long flags) {
3332         if ((flags & ACC_BRIDGE) != 0) {
3333             flags &= ~ACC_BRIDGE;
3334             flags |= BRIDGE;
3335         }
3336         if ((flags & ACC_VARARGS) != 0) {
3337             flags &= ~ACC_VARARGS;
3338             flags |= VARARGS;
3339         }
3340         return flags;
3341     }
3342 
3343     long adjustClassFlags(ClassSymbol c, long flags) {
3344         if ((flags & ACC_MODULE) != 0) {
3345             flags &= ~ACC_MODULE;
3346             flags |= MODULE;
3347         }
3348         if (((flags & ACC_IDENTITY) != 0 && !isMigratedValueClass(flags)) || (majorVersion < V67.major && (flags & INTERFACE) == 0)) {
3349             flags |= IDENTITY_TYPE;
3350         } else if (needsValueFlag(c, flags)) {
3351             flags |= VALUE_CLASS;
3352             flags &= ~IDENTITY_TYPE;
3353         }
3354         flags &= ~ACC_IDENTITY; // ACC_IDENTITY and SYNCHRONIZED bits overloaded
3355         return flags;
3356     }
3357 
3358     private boolean needsValueFlag(Symbol c, long flags) {
3359         boolean previewClassFile = minorVersion == ClassFile.PREVIEW_MINOR_VERSION;
3360         if (allowValueClasses) {
3361             if (previewClassFile && majorVersion >= V67.major && (flags & INTERFACE) == 0 ||
3362                     majorVersion >= V67.major && isMigratedValueClass(flags)) {
3363                 return true;
3364             }
3365         }
3366         return false;
3367     }
3368 
3369     private boolean isMigratedValueClass(long flags) {
3370         return allowValueClasses && ((flags & MIGRATED_VALUE_CLASS) != 0);
3371     }
3372 
3373     /**
3374      * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
3375      * The attribute is only the last component of the original filename, so is unlikely
3376      * to be valid as is, so operations other than those to access the name throw
3377      * UnsupportedOperationException
3378      */
3379     private static class SourceFileObject implements JavaFileObject {
3380 
3381         /** The file's name.
3382          */
3383         private final Name name;
3384 
3385         public SourceFileObject(Name name) {
3386             this.name = name;
3387         }
3388 
3389         @Override @DefinedBy(Api.COMPILER)
3390         public URI toUri() {
3391             try {
3392                 return new URI(null, name.toString(), null);
3393             } catch (URISyntaxException e) {
3394                 throw new PathFileObject.CannotCreateUriError(name.toString(), e);
3395             }
3396         }
3397 
3398         @Override @DefinedBy(Api.COMPILER)
3399         public String getName() {
3400             return name.toString();
3401         }
3402 
3403         @Override @DefinedBy(Api.COMPILER)
3404         public JavaFileObject.Kind getKind() {
3405             return BaseFileManager.getKind(getName());
3406         }
3407 
3408         @Override @DefinedBy(Api.COMPILER)
3409         public InputStream openInputStream() {
3410             throw new UnsupportedOperationException();
3411         }
3412 
3413         @Override @DefinedBy(Api.COMPILER)
3414         public OutputStream openOutputStream() {
3415             throw new UnsupportedOperationException();
3416         }
3417 
3418         @Override @DefinedBy(Api.COMPILER)
3419         public CharBuffer getCharContent(boolean ignoreEncodingErrors) {
3420             throw new UnsupportedOperationException();
3421         }
3422 
3423         @Override @DefinedBy(Api.COMPILER)
3424         public Reader openReader(boolean ignoreEncodingErrors) {
3425             throw new UnsupportedOperationException();
3426         }
3427 
3428         @Override @DefinedBy(Api.COMPILER)
3429         public Writer openWriter() {
3430             throw new UnsupportedOperationException();
3431         }
3432 
3433         @Override @DefinedBy(Api.COMPILER)
3434         public long getLastModified() {
3435             throw new UnsupportedOperationException();
3436         }
3437 
3438         @Override @DefinedBy(Api.COMPILER)
3439         public boolean delete() {
3440             throw new UnsupportedOperationException();
3441         }
3442 
3443         @Override @DefinedBy(Api.COMPILER)
3444         public boolean isNameCompatible(String simpleName, JavaFileObject.Kind kind) {
3445             return true; // fail-safe mode
3446         }
3447 
3448         @Override @DefinedBy(Api.COMPILER)
3449         public NestingKind getNestingKind() {
3450             return null;
3451         }
3452 
3453         @Override @DefinedBy(Api.COMPILER)
3454         public Modifier getAccessLevel() {
3455             return null;
3456         }
3457 
3458         /**
3459          * Check if two file objects are equal.
3460          * SourceFileObjects are just placeholder objects for the value of a
3461          * SourceFile attribute, and do not directly represent specific files.
3462          * Two SourceFileObjects are equal if their names are equal.
3463          */
3464         @Override
3465         public boolean equals(Object other) {
3466             if (this == other)
3467                 return true;
3468             return (other instanceof SourceFileObject sourceFileObject)
3469                     && name.equals(sourceFileObject.name);
3470         }
3471 
3472         @Override
3473         public int hashCode() {
3474             return name.hashCode();
3475         }
3476     }
3477 
3478     private class CompleterDeproxy implements AnnotationTypeCompleter {
3479         ClassSymbol proxyOn;
3480         CompoundAnnotationProxy target;
3481         CompoundAnnotationProxy repeatable;
3482 
3483         public CompleterDeproxy(ClassSymbol c, CompoundAnnotationProxy target,
3484                 CompoundAnnotationProxy repeatable)
3485         {
3486             this.proxyOn = c;
3487             this.target = target;
3488             this.repeatable = repeatable;
3489         }
3490 
3491         @Override
3492         public void complete(ClassSymbol sym) {
3493             Assert.check(proxyOn == sym);
3494             Attribute.Compound theTarget = null, theRepeatable = null;
3495             AnnotationDeproxy deproxy;
3496 
3497             try {
3498                 if (target != null) {
3499                     deproxy = new AnnotationDeproxy(proxyOn);
3500                     theTarget = deproxy.deproxyCompound(target);
3501                 }
3502 
3503                 if (repeatable != null) {
3504                     deproxy = new AnnotationDeproxy(proxyOn);
3505                     theRepeatable = deproxy.deproxyCompound(repeatable);
3506                 }
3507             } catch (Exception e) {
3508                 throw new CompletionFailure(sym,
3509                                             () -> ClassReader.this.diagFactory.fragment(Fragments.ExceptionMessage(e.getMessage())),
3510                                             dcfh);
3511             }
3512 
3513             sym.getAnnotationTypeMetadata().setTarget(theTarget);
3514             sym.getAnnotationTypeMetadata().setRepeatable(theRepeatable);
3515         }
3516     }
3517 
3518     private class ProxyType extends Type {
3519 
3520         private final Name name;
3521 
3522         public ProxyType(int index) {
3523             super(syms.noSymbol, List.nil());
3524             this.name = poolReader.getName(index);
3525         }
3526 
3527         @Override
3528         public TypeTag getTag() {
3529             return TypeTag.NONE;
3530         }
3531 
3532         public Type resolve() {
3533             return name.map(ClassReader.this::sigToType);
3534         }
3535 
3536         @Override @DefinedBy(Api.LANGUAGE_MODEL)
3537         public String toString() {
3538             return "<ProxyType>";
3539         }
3540 
3541     }
3542 
3543     private static final class InterimUsesDirective {
3544         public final Name service;
3545 
3546         public InterimUsesDirective(Name service) {
3547             this.service = service;
3548         }
3549 
3550     }
3551 
3552     private static final class InterimProvidesDirective {
3553         public final Name service;
3554         public final List<Name> impls;
3555 
3556         public InterimProvidesDirective(Name service, List<Name> impls) {
3557             this.service = service;
3558             this.impls = impls;
3559         }
3560 
3561     }
3562 
3563     private final class UsesProvidesCompleter implements Completer {
3564         private final ModuleSymbol currentModule;
3565         private final List<InterimUsesDirective> interimUsesCopy;
3566         private final List<InterimProvidesDirective> interimProvidesCopy;
3567 
3568         public UsesProvidesCompleter(ModuleSymbol currentModule, List<InterimUsesDirective> interimUsesCopy, List<InterimProvidesDirective> interimProvidesCopy) {
3569             this.currentModule = currentModule;
3570             this.interimUsesCopy = interimUsesCopy;
3571             this.interimProvidesCopy = interimProvidesCopy;
3572         }
3573 
3574         @Override
3575         public void complete(Symbol sym) throws CompletionFailure {
3576             ListBuffer<Directive> directives = new ListBuffer<>();
3577             directives.addAll(currentModule.directives);
3578             ListBuffer<UsesDirective> uses = new ListBuffer<>();
3579             for (InterimUsesDirective interim : interimUsesCopy) {
3580                 UsesDirective d = new UsesDirective(syms.enterClass(currentModule, interim.service));
3581                 uses.add(d);
3582                 directives.add(d);
3583             }
3584             currentModule.uses = uses.toList();
3585             ListBuffer<ProvidesDirective> provides = new ListBuffer<>();
3586             for (InterimProvidesDirective interim : interimProvidesCopy) {
3587                 ListBuffer<ClassSymbol> impls = new ListBuffer<>();
3588                 for (Name impl : interim.impls) {
3589                     impls.append(syms.enterClass(currentModule, impl));
3590                 }
3591                 ProvidesDirective d = new ProvidesDirective(syms.enterClass(currentModule, interim.service),
3592                                                             impls.toList());
3593                 provides.add(d);
3594                 directives.add(d);
3595             }
3596             currentModule.provides = provides.toList();
3597             currentModule.directives = directives.toList();
3598         }
3599     }
3600 }