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