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