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