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