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