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