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