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