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