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