< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java

Print this page

 150         diags = JCDiagnostic.Factory.instance(context);
 151         Options options = Options.instance(context);
 152         lint = Lint.instance(context);
 153         fileManager = context.get(JavaFileManager.class);
 154 
 155         source = Source.instance(context);
 156         target = Target.instance(context);
 157         warnOnAnyAccessToMembers = options.isSet("warnOnAccessToMembers");
 158 
 159         disablePreviewCheck = false;
 160 
 161         Target target = Target.instance(context);
 162         syntheticNameChar = target.syntheticNameChar();
 163 
 164         profile = Profile.instance(context);
 165         preview = Preview.instance(context);
 166 
 167         allowModules = Feature.MODULES.allowedInSource(source);
 168         allowRecords = Feature.RECORDS.allowedInSource(source);
 169         allowSealed = Feature.SEALED_CLASSES.allowedInSource(source);


 170     }
 171 
 172     /** Character for synthetic names
 173      */
 174     char syntheticNameChar;
 175 
 176     /** A table mapping flat names of all compiled classes for each module in this run
 177      *  to their symbols; maintained from outside.
 178      */
 179     private Map<Pair<ModuleSymbol, Name>,ClassSymbol> compiled = new HashMap<>();
 180 
 181     /** Are modules allowed
 182      */
 183     private final boolean allowModules;
 184 
 185     /** Are records allowed
 186      */
 187     private final boolean allowRecords;
 188 
 189     /** Are sealed classes allowed
 190      */
 191     private final boolean allowSealed;
 192 




 193     /** Whether to force suppression of deprecation and preview warnings.
 194      *  This happens when attributing import statements for JDK 9+.
 195      *  @see Feature#DEPRECATION_ON_IMPORT
 196      */
 197     private boolean importSuppression;
 198 
 199 /* *************************************************************************
 200  * Errors and Warnings
 201  **************************************************************************/
 202 
 203     Lint setLint(Lint newLint) {
 204         Lint prev = lint;
 205         lint = newLint;
 206         return prev;
 207     }
 208 
 209     boolean setImportSuppression(boolean newImportSuppression) {
 210         boolean prev = importSuppression;
 211         importSuppression = newImportSuppression;
 212         return prev;

 650     /** Check that type is a class or interface type.
 651      *  @param pos           Position to be used for error reporting.
 652      *  @param t             The type to be checked.
 653      */
 654     Type checkClassType(DiagnosticPosition pos, Type t) {
 655         if (!t.hasTag(CLASS) && !t.hasTag(ERROR)) {
 656             return typeTagError(pos,
 657                                 diags.fragment(Fragments.TypeReqClass),
 658                                 asTypeParam(t));
 659         } else {
 660             return t;
 661         }
 662     }
 663     //where
 664         private Object asTypeParam(Type t) {
 665             return (t.hasTag(TYPEVAR))
 666                                     ? diags.fragment(Fragments.TypeParameter(t))
 667                                     : t;
 668         }
 669 

























 670     /** Check that type is a valid qualifier for a constructor reference expression
 671      */
 672     Type checkConstructorRefType(DiagnosticPosition pos, Type t) {
 673         t = checkClassOrArrayType(pos, t);
 674         if (t.hasTag(CLASS)) {
 675             if ((t.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) {
 676                 log.error(pos, Errors.AbstractCantBeInstantiated(t.tsym));
 677                 t = types.createErrorType(t);
 678             } else if ((t.tsym.flags() & ENUM) != 0) {
 679                 log.error(pos, Errors.EnumCantBeInstantiated);
 680                 t = types.createErrorType(t);
 681             } else {
 682                 t = checkClassType(pos, t, true);
 683             }
 684         } else if (t.hasTag(ARRAY)) {
 685             if (!types.isReifiable(((ArrayType)t).elemtype)) {
 686                 log.error(pos, Errors.GenericArrayCreation);
 687                 t = types.createErrorType(t);
 688             }
 689         }

 707                 args = args.tail;
 708             }
 709         }
 710         return t;
 711     }
 712 
 713     /** Check that type is a reference type, i.e. a class, interface or array type
 714      *  or a type variable.
 715      *  @param pos           Position to be used for error reporting.
 716      *  @param t             The type to be checked.
 717      */
 718     Type checkRefType(DiagnosticPosition pos, Type t) {
 719         if (t.isReference())
 720             return t;
 721         else
 722             return typeTagError(pos,
 723                                 diags.fragment(Fragments.TypeReqRef),
 724                                 t);
 725     }
 726 


























 727     /** Check that each type is a reference type, i.e. a class, interface or array type
 728      *  or a type variable.
 729      *  @param trees         Original trees, used for error reporting.
 730      *  @param types         The types to be checked.
 731      */
 732     List<Type> checkRefTypes(List<JCExpression> trees, List<Type> types) {
 733         List<JCExpression> tl = trees;
 734         for (List<Type> l = types; l.nonEmpty(); l = l.tail) {
 735             l.head = checkRefType(tl.head.pos(), l.head);
 736             tl = tl.tail;
 737         }
 738         return types;
 739     }
 740 
 741     /** Check that type is a null or reference type.
 742      *  @param pos           Position to be used for error reporting.
 743      *  @param t             The type to be checked.
 744      */
 745     Type checkNullOrRefType(DiagnosticPosition pos, Type t) {
 746         if (t.isReference() || t.hasTag(BOT))

1098      *  Warning: we can't use flags() here since this method
1099      *  is called during class enter, when flags() would cause a premature
1100      *  completion.
1101      *  @param flags         The set of modifiers given in a definition.
1102      *  @param sym           The defined symbol.
1103      *  @param tree          The declaration
1104      */
1105     long checkFlags(long flags, Symbol sym, JCTree tree) {
1106         final DiagnosticPosition pos = tree.pos();
1107         long mask;
1108         long implicit = 0;
1109 
1110         switch (sym.kind) {
1111         case VAR:
1112             if (TreeInfo.isReceiverParam(tree))
1113                 mask = ReceiverParamFlags;
1114             else if (sym.owner.kind != TYP)
1115                 mask = LocalVarFlags;
1116             else if ((sym.owner.flags_field & INTERFACE) != 0)
1117                 mask = implicit = InterfaceVarFlags;
1118             else
1119                 mask = VarFlags;









1120             break;
1121         case MTH:
1122             if (sym.name == names.init) {
1123                 if ((sym.owner.flags_field & ENUM) != 0) {
1124                     // enum constructors cannot be declared public or
1125                     // protected and must be implicitly or explicitly
1126                     // private
1127                     implicit = PRIVATE;
1128                     mask = PRIVATE;
1129                 } else
1130                     mask = ConstructorFlags;
1131             }  else if ((sym.owner.flags_field & INTERFACE) != 0) {
1132                 if ((sym.owner.flags_field & ANNOTATION) != 0) {
1133                     mask = AnnotationTypeElementMask;
1134                     implicit = PUBLIC | ABSTRACT;
1135                 } else if ((flags & (DEFAULT | STATIC | PRIVATE)) != 0) {
1136                     mask = InterfaceMethodMask;
1137                     implicit = (flags & PRIVATE) != 0 ? 0 : PUBLIC;
1138                     if ((flags & DEFAULT) != 0) {
1139                         implicit |= ABSTRACT;
1140                     }
1141                 } else {
1142                     mask = implicit = InterfaceMethodFlags;
1143                 }
1144             } else if ((sym.owner.flags_field & RECORD) != 0) {
1145                 mask = RecordMethodFlags;

1146             } else {
1147                 mask = MethodFlags;


1148             }
1149             if ((flags & STRICTFP) != 0) {
1150                 log.warning(tree.pos(), LintWarnings.Strictfp);
1151             }
1152             // Imply STRICTFP if owner has STRICTFP set.
1153             if (((flags|implicit) & Flags.ABSTRACT) == 0 ||
1154                 ((flags) & Flags.DEFAULT) != 0)
1155                 implicit |= sym.owner.flags_field & STRICTFP;
1156             break;
1157         case TYP:
1158             if (sym.owner.kind.matches(KindSelector.VAL_MTH) ||
1159                     (sym.isDirectlyOrIndirectlyLocal() && (flags & ANNOTATION) != 0)) {
1160                 boolean implicitlyStatic = !sym.isAnonymous() &&
1161                         ((flags & RECORD) != 0 || (flags & ENUM) != 0 || (flags & INTERFACE) != 0);
1162                 boolean staticOrImplicitlyStatic = (flags & STATIC) != 0 || implicitlyStatic;
1163                 // local statics are allowed only if records are allowed too
1164                 mask = staticOrImplicitlyStatic && allowRecords && (flags & ANNOTATION) == 0 ? StaticLocalFlags : LocalClassFlags;
1165                 implicit = implicitlyStatic ? STATIC : implicit;
1166             } else if (sym.owner.kind == TYP) {
1167                 // statics in inner classes are allowed only if records are allowed too
1168                 mask = ((flags & STATIC) != 0) && allowRecords && (flags & ANNOTATION) == 0 ? ExtendedMemberStaticClassFlags : ExtendedMemberClassFlags;
1169                 if (sym.owner.owner.kind == PCK ||
1170                     (sym.owner.flags_field & STATIC) != 0) {
1171                     mask |= STATIC;
1172                 } else if (!allowRecords && ((flags & ENUM) != 0 || (flags & RECORD) != 0)) {
1173                     log.error(pos, Errors.StaticDeclarationNotAllowedInInnerClasses);
1174                 }
1175                 // Nested interfaces and enums are always STATIC (Spec ???)
1176                 if ((flags & (INTERFACE | ENUM | RECORD)) != 0 ) implicit = STATIC;
1177             } else {
1178                 mask = ExtendedClassFlags;
1179             }




1180             // Interfaces are always ABSTRACT
1181             if ((flags & INTERFACE) != 0) implicit |= ABSTRACT;
1182 




1183             if ((flags & ENUM) != 0) {
1184                 // enums can't be declared abstract, final, sealed or non-sealed
1185                 mask &= ~(ABSTRACT | FINAL | SEALED | NON_SEALED);
1186                 implicit |= implicitEnumFinalFlag(tree);
1187             }
1188             if ((flags & RECORD) != 0) {
1189                 // records can't be declared abstract
1190                 mask &= ~ABSTRACT;
1191                 implicit |= FINAL;
1192             }
1193             if ((flags & STRICTFP) != 0) {
1194                 log.warning(tree.pos(), LintWarnings.Strictfp);
1195             }
1196             // Imply STRICTFP if owner has STRICTFP set.
1197             implicit |= sym.owner.flags_field & STRICTFP;





1198             break;
1199         default:
1200             throw new AssertionError();
1201         }
1202         long illegal = flags & ExtendedStandardFlags & ~mask;
1203         if (illegal != 0) {
1204             if ((illegal & INTERFACE) != 0) {
1205                 log.error(pos, ((flags & ANNOTATION) != 0) ? Errors.AnnotationDeclNotAllowedHere : Errors.IntfNotAllowedHere);
1206                 mask |= INTERFACE;
1207             }
1208             else {
1209                 log.error(pos,
1210                         Errors.ModNotAllowedHere(asFlagSet(illegal)));
1211             }
1212         }
1213         else if ((sym.kind == TYP ||
1214                   // ISSUE: Disallowing abstract&private is no longer appropriate
1215                   // in the presence of inner classes. Should it be deleted here?
1216                   checkDisjoint(pos, flags,
1217                                 ABSTRACT,
1218                                 PRIVATE | STATIC | DEFAULT))
1219                  &&
1220                  checkDisjoint(pos, flags,
1221                                 STATIC | PRIVATE,
1222                                 DEFAULT)
1223                  &&
1224                  checkDisjoint(pos, flags,
1225                                ABSTRACT | INTERFACE,
1226                                FINAL | NATIVE | SYNCHRONIZED)
1227                  &&
1228                  checkDisjoint(pos, flags,
1229                                PUBLIC,
1230                                PRIVATE | PROTECTED)
1231                  &&
1232                  checkDisjoint(pos, flags,
1233                                PRIVATE,
1234                                PUBLIC | PROTECTED)
1235                  &&
1236                  checkDisjoint(pos, flags,

1237                                FINAL,
1238                                VOLATILE)
1239                  &&
1240                  (sym.kind == TYP ||
1241                   checkDisjoint(pos, flags,
1242                                 ABSTRACT | NATIVE,
1243                                 STRICTFP))
1244                  && checkDisjoint(pos, flags,
1245                                 FINAL,
1246                            SEALED | NON_SEALED)
1247                  && checkDisjoint(pos, flags,
1248                                 SEALED,
1249                            FINAL | NON_SEALED)
1250                  && checkDisjoint(pos, flags,
1251                                 SEALED,
1252                                 ANNOTATION)) {






1253             // skip
1254         }
1255         return flags & (mask | ~ExtendedStandardFlags) | implicit;
1256     }
1257 
1258     /** Determine if this enum should be implicitly final.
1259      *
1260      *  If the enum has no specialized enum constants, it is final.
1261      *
1262      *  If the enum does have specialized enum constants, it is
1263      *  <i>not</i> final.
1264      */
1265     private long implicitEnumFinalFlag(JCTree tree) {
1266         if (!tree.hasTag(CLASSDEF)) return 0;
1267         class SpecialTreeVisitor extends JCTree.Visitor {
1268             boolean specialized;
1269             SpecialTreeVisitor() {
1270                 this.specialized = false;
1271             }
1272 

2029                     return true;
2030                 }
2031             }
2032         }
2033         return false;
2034     }
2035 
2036     /** Check that a given method conforms with any method it overrides.
2037      *  @param tree         The tree from which positions are extracted
2038      *                      for errors.
2039      *  @param m            The overriding method.
2040      */
2041     void checkOverride(Env<AttrContext> env, JCMethodDecl tree, MethodSymbol m) {
2042         ClassSymbol origin = (ClassSymbol)m.owner;
2043         if ((origin.flags() & ENUM) != 0 && names.finalize.equals(m.name)) {
2044             if (m.overrides(syms.enumFinalFinalize, origin, types, false)) {
2045                 log.error(tree.pos(), Errors.EnumNoFinalize);
2046                 return;
2047             }
2048         }





2049         if (allowRecords && origin.isRecord()) {
2050             // let's find out if this is a user defined accessor in which case the @Override annotation is acceptable
2051             Optional<? extends RecordComponent> recordComponent = origin.getRecordComponents().stream()
2052                     .filter(rc -> rc.accessor == tree.sym && (rc.accessor.flags_field & GENERATED_MEMBER) == 0).findFirst();
2053             if (recordComponent.isPresent()) {
2054                 return;
2055             }
2056         }
2057 
2058         for (Type t = origin.type; t.hasTag(CLASS);
2059              t = types.supertype(t)) {
2060             if (t != origin.type) {
2061                 checkOverride(tree, t, origin, m);
2062             }
2063             for (Type t2 : types.interfaces(t)) {
2064                 checkOverride(tree, t2, origin, m);
2065             }
2066         }
2067 
2068         final boolean explicitOverride = m.attribute(syms.overrideType.tsym) != null;

2464     /** Check that all abstract methods implemented by a class are
2465      *  mutually compatible.
2466      *  @param pos          Position to be used for error reporting.
2467      *  @param c            The class whose interfaces are checked.
2468      */
2469     void checkCompatibleSupertypes(DiagnosticPosition pos, Type c) {
2470         List<Type> supertypes = types.interfaces(c);
2471         Type supertype = types.supertype(c);
2472         if (supertype.hasTag(CLASS) &&
2473             (supertype.tsym.flags() & ABSTRACT) != 0)
2474             supertypes = supertypes.prepend(supertype);
2475         for (List<Type> l = supertypes; l.nonEmpty(); l = l.tail) {
2476             if (!l.head.getTypeArguments().isEmpty() &&
2477                 !checkCompatibleAbstracts(pos, l.head, l.head, c))
2478                 return;
2479             for (List<Type> m = supertypes; m != l; m = m.tail)
2480                 if (!checkCompatibleAbstracts(pos, l.head, m.head, c))
2481                     return;
2482         }
2483         checkCompatibleConcretes(pos, c);












2484     }
2485 
2486     /** Check that all non-override equivalent methods accessible from 'site'
2487      *  are mutually compatible (JLS 8.4.8/9.4.1).
2488      *
2489      *  @param pos  Position to be used for error reporting.
2490      *  @param site The class whose methods are checked.
2491      *  @param sym  The method symbol to be checked.
2492      */
2493     void checkOverrideClashes(DiagnosticPosition pos, Type site, MethodSymbol sym) {
2494          ClashFilter cf = new ClashFilter(site);
2495         //for each method m1 that is overridden (directly or indirectly)
2496         //by method 'sym' in 'site'...
2497 
2498         ArrayList<Symbol> symbolsByName = new ArrayList<>();
2499         types.membersClosure(site, false).getSymbolsByName(sym.name, cf).forEach(symbolsByName::add);
2500         for (Symbol m1 : symbolsByName) {
2501             if (!sym.overrides(m1, site.tsym, types, false)) {
2502                 continue;
2503             }

4797                 }
4798             } else {
4799                 Assert.error("Unknown pattern: " + currentPattern.getTag());
4800             }
4801             return false;
4802         }
4803 
4804     /** check if a type is a subtype of Externalizable, if that is available. */
4805     boolean isExternalizable(Type t) {
4806         try {
4807             syms.externalizableType.complete();
4808         } catch (CompletionFailure e) {
4809             return false;
4810         }
4811         return types.isSubtype(t, syms.externalizableType);
4812     }
4813 
4814     /**
4815      * Check structure of serialization declarations.
4816      */
4817     public void checkSerialStructure(JCClassDecl tree, ClassSymbol c) {
4818         (new SerialTypeVisitor()).visit(c, tree);
4819     }
4820 
4821     /**
4822      * This visitor will warn if a serialization-related field or
4823      * method is declared in a suspicious or incorrect way. In
4824      * particular, it will warn for cases where the runtime
4825      * serialization mechanism will silently ignore a mis-declared
4826      * entity.
4827      *
4828      * Distinguished serialization-related fields and methods:
4829      *
4830      * Methods:
4831      *
4832      * private void writeObject(ObjectOutputStream stream) throws IOException
4833      * ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException
4834      *
4835      * private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException
4836      * private void readObjectNoData() throws ObjectStreamException
4837      * ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException
4838      *
4839      * Fields:
4840      *
4841      * private static final long serialVersionUID
4842      * private static final ObjectStreamField[] serialPersistentFields
4843      *
4844      * Externalizable: methods defined on the interface
4845      * public void writeExternal(ObjectOutput) throws IOException
4846      * public void readExternal(ObjectInput) throws IOException
4847      */
4848     private class SerialTypeVisitor extends ElementKindVisitor14<Void, JCClassDecl> {
4849         SerialTypeVisitor() {

4850             this.lint = Check.this.lint;

4851         }
4852 
4853         private static final Set<String> serialMethodNames =
4854             Set.of("writeObject", "writeReplace",
4855                    "readObject",  "readObjectNoData",
4856                    "readResolve");
4857 
4858         private static final Set<String> serialFieldNames =
4859             Set.of("serialVersionUID", "serialPersistentFields");
4860 
4861         // Type of serialPersistentFields
4862         private final Type OSF_TYPE = new Type.ArrayType(syms.objectStreamFieldType, syms.arrayClass);
4863 
4864         Lint lint;
4865 
4866         @Override
4867         public Void defaultAction(Element e, JCClassDecl p) {
4868             throw new IllegalArgumentException(Objects.requireNonNullElse(e.toString(), ""));
4869         }
4870 

4890                 if (sym.kind == VAR) {
4891                     svuidSym = (VarSymbol)sym;
4892                     break;
4893                 }
4894             }
4895 
4896             if (svuidSym == null) {
4897                 log.warning(p.pos(), LintWarnings.MissingSVUID(c));
4898             }
4899 
4900             // Check for serialPersistentFields to gate checks for
4901             // non-serializable non-transient instance fields
4902             boolean serialPersistentFieldsPresent =
4903                     c.members()
4904                      .getSymbolsByName(names.serialPersistentFields, sym -> sym.kind == VAR)
4905                      .iterator()
4906                      .hasNext();
4907 
4908             // Check declarations of serialization-related methods and
4909             // fields

4910             for(Symbol el : c.getEnclosedElements()) {
4911                 runUnderLint(el, p, (enclosed, tree) -> {
4912                     String name = null;
4913                     switch(enclosed.getKind()) {
4914                     case FIELD -> {
4915                         if (!serialPersistentFieldsPresent) {
4916                             var flags = enclosed.flags();
4917                             if ( ((flags & TRANSIENT) == 0) &&
4918                                  ((flags & STATIC) == 0)) {
4919                                 Type varType = enclosed.asType();
4920                                 if (!canBeSerialized(varType)) {
4921                                     // Note per JLS arrays are
4922                                     // serializable even if the
4923                                     // component type is not.
4924                                     log.warning(
4925                                             TreeInfo.diagnosticPositionFor(enclosed, tree),
4926                                                 LintWarnings.NonSerializableInstanceField);
4927                                 } else if (varType.hasTag(ARRAY)) {
4928                                     ArrayType arrayType = (ArrayType)varType;
4929                                     Type elementType = arrayType.elemtype;

4964                     // will also pull in default methods from
4965                     // superinterfaces. In other words, the runtime checks
4966                     // (which long predate default methods on interfaces)
4967                     // do not admit the possibility of inheriting methods
4968                     // this way, a difference from general inheritance.
4969 
4970                     // The current implementation just checks the enclosed
4971                     // elements and does not directly check the inherited
4972                     // methods. If all the types are being checked this is
4973                     // less of a concern; however, there are cases that
4974                     // could be missed. In particular, readResolve and
4975                     // writeReplace could, in principle, by inherited from
4976                     // a non-serializable superclass and thus not checked
4977                     // even if compiled with a serializable child class.
4978                     case METHOD -> {
4979                         var method = (MethodSymbol)enclosed;
4980                         name = method.getSimpleName().toString();
4981                         if (serialMethodNames.contains(name)) {
4982                             switch (name) {
4983                             case "writeObject"      -> checkWriteObject(tree, e, method);
4984                             case "writeReplace"     -> checkWriteReplace(tree,e, method);
4985                             case "readObject"       -> checkReadObject(tree,e, method);
4986                             case "readObjectNoData" -> checkReadObjectNoData(tree, e, method);
4987                             case "readResolve"      -> checkReadResolve(tree, e, method);
4988                             default ->  throw new AssertionError();
4989                             }
4990                         }
4991                     }
4992                     }
4993                 });
4994             }
4995 



















4996             return null;
4997         }
4998 
4999         boolean canBeSerialized(Type type) {
5000             return type.isPrimitive() || rs.isSerializable(type);
5001         }
5002 
















5003         /**
5004          * Check that Externalizable class needs a public no-arg
5005          * constructor.
5006          *
5007          * Check that a Serializable class has access to the no-arg
5008          * constructor of its first nonserializable superclass.
5009          */
5010         private void checkCtorAccess(JCClassDecl tree, ClassSymbol c) {
5011             if (isExternalizable(c.type)) {
5012                 for(var sym : c.getEnclosedElements()) {
5013                     if (sym.isConstructor() &&
5014                         ((sym.flags() & PUBLIC) == PUBLIC)) {
5015                         if (((MethodSymbol)sym).getParameters().isEmpty()) {
5016                             return;
5017                         }
5018                     }
5019                 }
5020                 log.warning(tree.pos(),
5021                             LintWarnings.ExternalizableMissingPublicNoArgCtor);
5022             } else {

5106             // Warn if serialPersistentFields is initialized to a
5107             // literal null.
5108             JCTree spfDecl = TreeInfo.declarationFor(spf, tree);
5109             if (spfDecl != null && spfDecl.getTag() == VARDEF) {
5110                 JCVariableDecl variableDef = (JCVariableDecl) spfDecl;
5111                 JCExpression initExpr = variableDef.init;
5112                  if (initExpr != null && TreeInfo.isNull(initExpr)) {
5113                      log.warning(initExpr.pos(),
5114                                  LintWarnings.SPFNullInit);
5115                  }
5116             }
5117         }
5118 
5119         private void checkWriteObject(JCClassDecl tree, Element e, MethodSymbol method) {
5120             // The "synchronized" modifier is seen in the wild on
5121             // readObject and writeObject methods and is generally
5122             // innocuous.
5123 
5124             // private void writeObject(ObjectOutputStream stream) throws IOException
5125             checkPrivateNonStaticMethod(tree, method);
5126             checkReturnType(tree, e, method, syms.voidType);
5127             checkOneArg(tree, e, method, syms.objectOutputStreamType);
5128             checkExceptions(tree, e, method, syms.ioExceptionType);
5129             checkExternalizable(tree, e, method);
5130         }
5131 
5132         private void checkWriteReplace(JCClassDecl tree, Element e, MethodSymbol method) {
5133             // ANY-ACCESS-MODIFIER Object writeReplace() throws
5134             // ObjectStreamException
5135 
5136             // Excluding abstract, could have a more complicated
5137             // rule based on abstract-ness of the class
5138             checkConcreteInstanceMethod(tree, e, method);
5139             checkReturnType(tree, e, method, syms.objectType);
5140             checkNoArgs(tree, e, method);
5141             checkExceptions(tree, e, method, syms.objectStreamExceptionType);
5142         }
5143 
5144         private void checkReadObject(JCClassDecl tree, Element e, MethodSymbol method) {
5145             // The "synchronized" modifier is seen in the wild on
5146             // readObject and writeObject methods and is generally
5147             // innocuous.
5148 
5149             // private void readObject(ObjectInputStream stream)
5150             //   throws IOException, ClassNotFoundException
5151             checkPrivateNonStaticMethod(tree, method);
5152             checkReturnType(tree, e, method, syms.voidType);
5153             checkOneArg(tree, e, method, syms.objectInputStreamType);
5154             checkExceptions(tree, e, method, syms.ioExceptionType, syms.classNotFoundExceptionType);
5155             checkExternalizable(tree, e, method);
5156         }
5157 
5158         private void checkReadObjectNoData(JCClassDecl tree, Element e, MethodSymbol method) {
5159             // private void readObjectNoData() throws ObjectStreamException
5160             checkPrivateNonStaticMethod(tree, method);
5161             checkReturnType(tree, e, method, syms.voidType);
5162             checkNoArgs(tree, e, method);
5163             checkExceptions(tree, e, method, syms.objectStreamExceptionType);
5164             checkExternalizable(tree, e, method);
5165         }
5166 
5167         private void checkReadResolve(JCClassDecl tree, Element e, MethodSymbol method) {
5168             // ANY-ACCESS-MODIFIER Object readResolve()
5169             // throws ObjectStreamException
5170 
5171             // Excluding abstract, could have a more complicated
5172             // rule based on abstract-ness of the class
5173             checkConcreteInstanceMethod(tree, e, method);
5174             checkReturnType(tree,e, method, syms.objectType);
5175             checkNoArgs(tree, e, method);
5176             checkExceptions(tree, e, method, syms.objectStreamExceptionType);
5177         }
5178 
5179         private void checkWriteExternalRecord(JCClassDecl tree, Element e, MethodSymbol method, boolean isExtern) {
5180             //public void writeExternal(ObjectOutput) throws IOException
5181             checkExternMethodRecord(tree, e, method, syms.objectOutputType, isExtern);
5182         }
5183 
5184         private void checkReadExternalRecord(JCClassDecl tree, Element e, MethodSymbol method, boolean isExtern) {
5185             // public void readExternal(ObjectInput) throws IOException
5186             checkExternMethodRecord(tree, e, method, syms.objectInputType, isExtern);
5187          }
5188 
5189         private void checkExternMethodRecord(JCClassDecl tree, Element e, MethodSymbol method, Type argType,
5190                                              boolean isExtern) {
5191             if (isExtern && isExternMethod(tree, e, method, argType)) {
5192                 log.warning(
5193                         TreeInfo.diagnosticPositionFor(method, tree),
5194                             LintWarnings.IneffectualExternalizableMethodRecord(method.getSimpleName().toString()));
5195             }
5196         }

5406                     case FIELD -> {
5407                         var field = (VarSymbol)enclosed;
5408                         switch(name) {
5409                         case "serialPersistentFields" -> {
5410                             log.warning(
5411                                     TreeInfo.diagnosticPositionFor(field, tree),
5412                                         LintWarnings.IneffectualSerialFieldRecord);
5413                         }
5414 
5415                         case "serialVersionUID" -> {
5416                             // Could generate additional warning that
5417                             // svuid value is not checked to match for
5418                             // records.
5419                             checkSerialVersionUID(tree, e, field);
5420                         }}
5421                     }
5422 
5423                     case METHOD -> {
5424                         var method = (MethodSymbol)enclosed;
5425                         switch(name) {
5426                         case "writeReplace" -> checkWriteReplace(tree, e, method);
5427                         case "readResolve"  -> checkReadResolve(tree, e, method);
5428 
5429                         case "writeExternal" -> checkWriteExternalRecord(tree, e, method, isExtern);
5430                         case "readExternal"  -> checkReadExternalRecord(tree, e, method, isExtern);
5431 
5432                         default -> {
5433                             if (serialMethodNames.contains(name)) {
5434                                 log.warning(
5435                                         TreeInfo.diagnosticPositionFor(method, tree),
5436                                             LintWarnings.IneffectualSerialMethodRecord(name));
5437                             }
5438                         }}
5439                     }}});
5440             }
5441             return null;
5442         }
5443 
5444         void checkConcreteInstanceMethod(JCClassDecl tree,
5445                                          Element enclosing,
5446                                          MethodSymbol method) {
5447             if ((method.flags() & (STATIC | ABSTRACT)) != 0) {

5448                     log.warning(
5449                             TreeInfo.diagnosticPositionFor(method, tree),
5450                                 LintWarnings.SerialConcreteInstanceMethod(method.getSimpleName()));


5451             }

5452         }
5453 
5454         private void checkReturnType(JCClassDecl tree,
5455                                      Element enclosing,
5456                                      MethodSymbol method,
5457                                      Type expectedReturnType) {
5458             // Note: there may be complications checking writeReplace
5459             // and readResolve since they return Object and could, in
5460             // principle, have covariant overrides and any synthetic
5461             // bridge method would not be represented here for
5462             // checking.
5463             Type rtype = method.getReturnType();
5464             if (!types.isSameType(expectedReturnType, rtype)) {
5465                 log.warning(
5466                         TreeInfo.diagnosticPositionFor(method, tree),

5467                             LintWarnings.SerialMethodUnexpectedReturnType(method.getSimpleName(),
5468                                                                       rtype, expectedReturnType));


5469             }

5470         }
5471 
5472         private void checkOneArg(JCClassDecl tree,
5473                                  Element enclosing,
5474                                  MethodSymbol method,
5475                                  Type expectedType) {
5476             String name = method.getSimpleName().toString();
5477 
5478             var parameters= method.getParameters();
5479 
5480             if (parameters.size() != 1) {
5481                 log.warning(
5482                         TreeInfo.diagnosticPositionFor(method, tree),
5483                             LintWarnings.SerialMethodOneArg(method.getSimpleName(), parameters.size()));
5484                 return;
5485             }
5486 
5487             Type parameterType = parameters.get(0).asType();
5488             if (!types.isSameType(parameterType, expectedType)) {
5489                 log.warning(
5490                         TreeInfo.diagnosticPositionFor(method, tree),
5491                             LintWarnings.SerialMethodParameterType(method.getSimpleName(),
5492                                                                expectedType,
5493                                                                parameterType));
5494             }
5495         }
5496 
5497         private boolean hasExactlyOneArgWithType(JCClassDecl tree,
5498                                                  Element enclosing,
5499                                                  MethodSymbol method,
5500                                                  Type expectedType) {
5501             var parameters = method.getParameters();
5502             return (parameters.size() == 1) &&
5503                 types.isSameType(parameters.get(0).asType(), expectedType);
5504         }
5505 
5506 
5507         private void checkNoArgs(JCClassDecl tree, Element enclosing, MethodSymbol method) {
5508             var parameters = method.getParameters();
5509             if (!parameters.isEmpty()) {
5510                 log.warning(
5511                         TreeInfo.diagnosticPositionFor(parameters.get(0), tree),

5512                             LintWarnings.SerialMethodNoArgs(method.getSimpleName()));


5513             }

5514         }
5515 
5516         private void checkExternalizable(JCClassDecl tree, Element enclosing, MethodSymbol method) {
5517             // If the enclosing class is externalizable, warn for the method
5518             if (isExternalizable((Type)enclosing.asType())) {
5519                 log.warning(
5520                         TreeInfo.diagnosticPositionFor(method, tree),
5521                             LintWarnings.IneffectualSerialMethodExternalizable(method.getSimpleName()));
5522             }
5523             return;
5524         }
5525 
5526         private void checkExceptions(JCClassDecl tree,
5527                                      Element enclosing,
5528                                      MethodSymbol method,
5529                                      Type... declaredExceptions) {
5530             for (Type thrownType: method.getThrownTypes()) {
5531                 // For each exception in the throws clause of the
5532                 // method, if not an Error and not a RuntimeException,
5533                 // check if the exception is a subtype of a declared
5534                 // exception from the throws clause of the
5535                 // serialization method in question.
5536                 if (types.isSubtype(thrownType, syms.runtimeExceptionType) ||
5537                     types.isSubtype(thrownType, syms.errorType) ) {
5538                     continue;
5539                 } else {
5540                     boolean declared = false;
5541                     for (Type declaredException : declaredExceptions) {
5542                         if (types.isSubtype(thrownType, declaredException)) {
5543                             declared = true;
5544                             continue;
5545                         }
5546                     }
5547                     if (!declared) {
5548                         log.warning(
5549                                 TreeInfo.diagnosticPositionFor(method, tree),

5550                                     LintWarnings.SerialMethodUnexpectedException(method.getSimpleName(),
5551                                                                              thrownType));


5552                     }
5553                 }
5554             }
5555             return;
5556         }
5557 
5558         private <E extends Element> Void runUnderLint(E symbol, JCClassDecl p, BiConsumer<E, JCClassDecl> task) {
5559             Lint prevLint = lint;
5560             try {
5561                 lint = lint.augment((Symbol) symbol);
5562 
5563                 if (lint.isEnabled(LintCategory.SERIAL)) {
5564                     task.accept(symbol, p);
5565                 }
5566 
5567                 return null;
5568             } finally {
5569                 lint = prevLint;
5570             }
5571         }
5572 
5573     }
5574 
5575     void checkRequiresIdentity(JCTree tree, Lint lint) {

 150         diags = JCDiagnostic.Factory.instance(context);
 151         Options options = Options.instance(context);
 152         lint = Lint.instance(context);
 153         fileManager = context.get(JavaFileManager.class);
 154 
 155         source = Source.instance(context);
 156         target = Target.instance(context);
 157         warnOnAnyAccessToMembers = options.isSet("warnOnAccessToMembers");
 158 
 159         disablePreviewCheck = false;
 160 
 161         Target target = Target.instance(context);
 162         syntheticNameChar = target.syntheticNameChar();
 163 
 164         profile = Profile.instance(context);
 165         preview = Preview.instance(context);
 166 
 167         allowModules = Feature.MODULES.allowedInSource(source);
 168         allowRecords = Feature.RECORDS.allowedInSource(source);
 169         allowSealed = Feature.SEALED_CLASSES.allowedInSource(source);
 170         allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
 171                 Feature.VALUE_CLASSES.allowedInSource(source);
 172     }
 173 
 174     /** Character for synthetic names
 175      */
 176     char syntheticNameChar;
 177 
 178     /** A table mapping flat names of all compiled classes for each module in this run
 179      *  to their symbols; maintained from outside.
 180      */
 181     private Map<Pair<ModuleSymbol, Name>,ClassSymbol> compiled = new HashMap<>();
 182 
 183     /** Are modules allowed
 184      */
 185     private final boolean allowModules;
 186 
 187     /** Are records allowed
 188      */
 189     private final boolean allowRecords;
 190 
 191     /** Are sealed classes allowed
 192      */
 193     private final boolean allowSealed;
 194 
 195     /** Are value classes allowed
 196      */
 197     private final boolean allowValueClasses;
 198 
 199     /** Whether to force suppression of deprecation and preview warnings.
 200      *  This happens when attributing import statements for JDK 9+.
 201      *  @see Feature#DEPRECATION_ON_IMPORT
 202      */
 203     private boolean importSuppression;
 204 
 205 /* *************************************************************************
 206  * Errors and Warnings
 207  **************************************************************************/
 208 
 209     Lint setLint(Lint newLint) {
 210         Lint prev = lint;
 211         lint = newLint;
 212         return prev;
 213     }
 214 
 215     boolean setImportSuppression(boolean newImportSuppression) {
 216         boolean prev = importSuppression;
 217         importSuppression = newImportSuppression;
 218         return prev;

 656     /** Check that type is a class or interface type.
 657      *  @param pos           Position to be used for error reporting.
 658      *  @param t             The type to be checked.
 659      */
 660     Type checkClassType(DiagnosticPosition pos, Type t) {
 661         if (!t.hasTag(CLASS) && !t.hasTag(ERROR)) {
 662             return typeTagError(pos,
 663                                 diags.fragment(Fragments.TypeReqClass),
 664                                 asTypeParam(t));
 665         } else {
 666             return t;
 667         }
 668     }
 669     //where
 670         private Object asTypeParam(Type t) {
 671             return (t.hasTag(TYPEVAR))
 672                                     ? diags.fragment(Fragments.TypeParameter(t))
 673                                     : t;
 674         }
 675 
 676     void checkConstraintsOfValueClass(JCClassDecl tree, ClassSymbol c) {
 677         DiagnosticPosition pos = tree.pos();
 678         for (Type st : types.closure(c.type)) {
 679             if (st == null || st.tsym == null || st.tsym.kind == ERR)
 680                 continue;
 681             if  (st.tsym == syms.objectType.tsym || st.tsym == syms.recordType.tsym || st.isInterface())
 682                 continue;
 683             if (!st.tsym.isAbstract()) {
 684                 if (c != st.tsym) {
 685                     log.error(pos, Errors.ConcreteSupertypeForValueClass(c, st));
 686                 }
 687                 continue;
 688             }
 689             // dealing with an abstract value or value super class below.
 690             for (Symbol s : st.tsym.members().getSymbols(NON_RECURSIVE)) {
 691                 if (s.kind == MTH) {
 692                     if ((s.flags() & (SYNCHRONIZED | STATIC)) == SYNCHRONIZED) {
 693                         log.error(pos, Errors.SuperClassMethodCannotBeSynchronized(s, c, st));
 694                     }
 695                     break;
 696                 }
 697             }
 698         }
 699     }
 700 
 701     /** Check that type is a valid qualifier for a constructor reference expression
 702      */
 703     Type checkConstructorRefType(DiagnosticPosition pos, Type t) {
 704         t = checkClassOrArrayType(pos, t);
 705         if (t.hasTag(CLASS)) {
 706             if ((t.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) {
 707                 log.error(pos, Errors.AbstractCantBeInstantiated(t.tsym));
 708                 t = types.createErrorType(t);
 709             } else if ((t.tsym.flags() & ENUM) != 0) {
 710                 log.error(pos, Errors.EnumCantBeInstantiated);
 711                 t = types.createErrorType(t);
 712             } else {
 713                 t = checkClassType(pos, t, true);
 714             }
 715         } else if (t.hasTag(ARRAY)) {
 716             if (!types.isReifiable(((ArrayType)t).elemtype)) {
 717                 log.error(pos, Errors.GenericArrayCreation);
 718                 t = types.createErrorType(t);
 719             }
 720         }

 738                 args = args.tail;
 739             }
 740         }
 741         return t;
 742     }
 743 
 744     /** Check that type is a reference type, i.e. a class, interface or array type
 745      *  or a type variable.
 746      *  @param pos           Position to be used for error reporting.
 747      *  @param t             The type to be checked.
 748      */
 749     Type checkRefType(DiagnosticPosition pos, Type t) {
 750         if (t.isReference())
 751             return t;
 752         else
 753             return typeTagError(pos,
 754                                 diags.fragment(Fragments.TypeReqRef),
 755                                 t);
 756     }
 757 
 758     /** Check that type is an identity type, i.e. not a value type.
 759      *  When not discernible statically, give it the benefit of doubt
 760      *  and defer to runtime.
 761      *
 762      *  @param pos           Position to be used for error reporting.
 763      *  @param t             The type to be checked.
 764      */
 765     boolean checkIdentityType(DiagnosticPosition pos, Type t) {
 766         if (t.hasTag(TYPEVAR)) {
 767             t = types.skipTypeVars(t, false);
 768         }
 769         if (t.isIntersection()) {
 770             IntersectionClassType ict = (IntersectionClassType)t;
 771             boolean result = true;
 772             for (Type component : ict.getExplicitComponents()) {
 773                 result &= checkIdentityType(pos, component);
 774             }
 775             return result;
 776         }
 777         if (t.isPrimitive() || (t.isValueClass() && !t.tsym.isAbstract())) {
 778             typeTagError(pos, diags.fragment(Fragments.TypeReqIdentity), t);
 779             return false;
 780         }
 781         return true;
 782     }
 783 
 784     /** Check that each type is a reference type, i.e. a class, interface or array type
 785      *  or a type variable.
 786      *  @param trees         Original trees, used for error reporting.
 787      *  @param types         The types to be checked.
 788      */
 789     List<Type> checkRefTypes(List<JCExpression> trees, List<Type> types) {
 790         List<JCExpression> tl = trees;
 791         for (List<Type> l = types; l.nonEmpty(); l = l.tail) {
 792             l.head = checkRefType(tl.head.pos(), l.head);
 793             tl = tl.tail;
 794         }
 795         return types;
 796     }
 797 
 798     /** Check that type is a null or reference type.
 799      *  @param pos           Position to be used for error reporting.
 800      *  @param t             The type to be checked.
 801      */
 802     Type checkNullOrRefType(DiagnosticPosition pos, Type t) {
 803         if (t.isReference() || t.hasTag(BOT))

1155      *  Warning: we can't use flags() here since this method
1156      *  is called during class enter, when flags() would cause a premature
1157      *  completion.
1158      *  @param flags         The set of modifiers given in a definition.
1159      *  @param sym           The defined symbol.
1160      *  @param tree          The declaration
1161      */
1162     long checkFlags(long flags, Symbol sym, JCTree tree) {
1163         final DiagnosticPosition pos = tree.pos();
1164         long mask;
1165         long implicit = 0;
1166 
1167         switch (sym.kind) {
1168         case VAR:
1169             if (TreeInfo.isReceiverParam(tree))
1170                 mask = ReceiverParamFlags;
1171             else if (sym.owner.kind != TYP)
1172                 mask = LocalVarFlags;
1173             else if ((sym.owner.flags_field & INTERFACE) != 0)
1174                 mask = implicit = InterfaceVarFlags;
1175             else {
1176                 boolean isInstanceField = (flags & STATIC) == 0;
1177                 boolean isInstanceFieldOfValueClass = isInstanceField && sym.owner.type.isValueClass();
1178                 boolean isRecordField = isInstanceField && (sym.owner.flags_field & RECORD) != 0;
1179                 if (allowValueClasses && (isInstanceFieldOfValueClass || isRecordField)) {
1180                     implicit |= FINAL | STRICT;
1181                     mask = ValueFieldFlags;
1182                 } else {
1183                     mask = VarFlags;
1184                 }
1185             }
1186             break;
1187         case MTH:
1188             if (sym.name == names.init) {
1189                 if ((sym.owner.flags_field & ENUM) != 0) {
1190                     // enum constructors cannot be declared public or
1191                     // protected and must be implicitly or explicitly
1192                     // private
1193                     implicit = PRIVATE;
1194                     mask = PRIVATE;
1195                 } else
1196                     mask = ConstructorFlags;
1197             }  else if ((sym.owner.flags_field & INTERFACE) != 0) {
1198                 if ((sym.owner.flags_field & ANNOTATION) != 0) {
1199                     mask = AnnotationTypeElementMask;
1200                     implicit = PUBLIC | ABSTRACT;
1201                 } else if ((flags & (DEFAULT | STATIC | PRIVATE)) != 0) {
1202                     mask = InterfaceMethodMask;
1203                     implicit = (flags & PRIVATE) != 0 ? 0 : PUBLIC;
1204                     if ((flags & DEFAULT) != 0) {
1205                         implicit |= ABSTRACT;
1206                     }
1207                 } else {
1208                     mask = implicit = InterfaceMethodFlags;
1209                 }
1210             } else if ((sym.owner.flags_field & RECORD) != 0) {
1211                 mask = ((sym.owner.flags_field & VALUE_CLASS) != 0 && (flags & Flags.STATIC) == 0) ?
1212                         RecordMethodFlags & ~SYNCHRONIZED : RecordMethodFlags;
1213             } else {
1214                 // value objects do not have an associated monitor/lock
1215                 mask = ((sym.owner.flags_field & VALUE_CLASS) != 0 && (flags & Flags.STATIC) == 0) ?
1216                         MethodFlags & ~SYNCHRONIZED : MethodFlags;
1217             }
1218             if ((flags & STRICTFP) != 0) {
1219                 log.warning(tree.pos(), LintWarnings.Strictfp);
1220             }
1221             // Imply STRICTFP if owner has STRICTFP set.
1222             if (((flags|implicit) & Flags.ABSTRACT) == 0 ||
1223                 ((flags) & Flags.DEFAULT) != 0)
1224                 implicit |= sym.owner.flags_field & STRICTFP;
1225             break;
1226         case TYP:
1227             if (sym.owner.kind.matches(KindSelector.VAL_MTH) ||
1228                     (sym.isDirectlyOrIndirectlyLocal() && (flags & ANNOTATION) != 0)) {
1229                 boolean implicitlyStatic = !sym.isAnonymous() &&
1230                         ((flags & RECORD) != 0 || (flags & ENUM) != 0 || (flags & INTERFACE) != 0);
1231                 boolean staticOrImplicitlyStatic = (flags & STATIC) != 0 || implicitlyStatic;
1232                 // local statics are allowed only if records are allowed too
1233                 mask = staticOrImplicitlyStatic && allowRecords && (flags & ANNOTATION) == 0 ? ExtendedStaticLocalClassFlags : ExtendedLocalClassFlags;
1234                 implicit = implicitlyStatic ? STATIC : implicit;
1235             } else if (sym.owner.kind == TYP) {
1236                 // statics in inner classes are allowed only if records are allowed too
1237                 mask = ((flags & STATIC) != 0) && allowRecords && (flags & ANNOTATION) == 0 ? ExtendedMemberStaticClassFlags : ExtendedMemberClassFlags;
1238                 if (sym.owner.owner.kind == PCK ||
1239                     (sym.owner.flags_field & STATIC) != 0) {
1240                     mask |= STATIC;
1241                 } else if (!allowRecords && ((flags & ENUM) != 0 || (flags & RECORD) != 0)) {
1242                     log.error(pos, Errors.StaticDeclarationNotAllowedInInnerClasses);
1243                 }
1244                 // Nested interfaces and enums are always STATIC (Spec ???)
1245                 if ((flags & (INTERFACE | ENUM | RECORD)) != 0 ) implicit = STATIC;
1246             } else {
1247                 mask = ExtendedClassFlags;
1248             }
1249             if ((flags & (VALUE_CLASS | SEALED | ABSTRACT)) == (VALUE_CLASS | SEALED) ||
1250                 (flags & (VALUE_CLASS | NON_SEALED | ABSTRACT)) == (VALUE_CLASS | NON_SEALED)) {
1251                 log.error(pos, Errors.NonAbstractValueClassCantBeSealedOrNonSealed);
1252             }
1253             // Interfaces are always ABSTRACT
1254             if ((flags & INTERFACE) != 0) implicit |= ABSTRACT;
1255 
1256             if ((flags & (INTERFACE | VALUE_CLASS)) == 0) {
1257                 implicit |= IDENTITY_TYPE;
1258             }
1259 
1260             if ((flags & ENUM) != 0) {
1261                 // enums can't be declared abstract, final, sealed or non-sealed or value
1262                 mask &= ~(ABSTRACT | FINAL | SEALED | NON_SEALED | VALUE_CLASS);
1263                 implicit |= implicitEnumFinalFlag(tree);
1264             }
1265             if ((flags & RECORD) != 0) {
1266                 // records can't be declared abstract
1267                 mask &= ~ABSTRACT;
1268                 implicit |= FINAL;
1269             }
1270             if ((flags & STRICTFP) != 0) {
1271                 log.warning(tree.pos(), LintWarnings.Strictfp);
1272             }
1273             // Imply STRICTFP if owner has STRICTFP set.
1274             implicit |= sym.owner.flags_field & STRICTFP;
1275 
1276             // concrete value classes are implicitly final
1277             if ((flags & (ABSTRACT | INTERFACE | VALUE_CLASS)) == VALUE_CLASS) {
1278                 implicit |= FINAL;
1279             }
1280             break;
1281         default:
1282             throw new AssertionError();
1283         }
1284         long illegal = flags & ExtendedStandardFlags & ~mask;
1285         if (illegal != 0) {
1286             if ((illegal & INTERFACE) != 0) {
1287                 log.error(pos, ((flags & ANNOTATION) != 0) ? Errors.AnnotationDeclNotAllowedHere : Errors.IntfNotAllowedHere);
1288                 mask |= INTERFACE;
1289             }
1290             else {
1291                 log.error(pos,
1292                         Errors.ModNotAllowedHere(asFlagSet(illegal)));
1293             }
1294         } else if ((sym.kind == TYP ||

1295                   // ISSUE: Disallowing abstract&private is no longer appropriate
1296                   // in the presence of inner classes. Should it be deleted here?
1297                   checkDisjoint(pos, flags,
1298                                 ABSTRACT,
1299                                 PRIVATE | STATIC | DEFAULT))
1300                  &&
1301                  checkDisjoint(pos, flags,
1302                                 STATIC | PRIVATE,
1303                                 DEFAULT)
1304                  &&
1305                  checkDisjoint(pos, flags,
1306                                ABSTRACT | INTERFACE,
1307                                FINAL | NATIVE | SYNCHRONIZED)
1308                  &&
1309                  checkDisjoint(pos, flags,
1310                                PUBLIC,
1311                                PRIVATE | PROTECTED)
1312                  &&
1313                  checkDisjoint(pos, flags,
1314                                PRIVATE,
1315                                PUBLIC | PROTECTED)
1316                  &&
1317                  // we are using `implicit` here as instance fields of value classes are implicitly final
1318                  checkDisjoint(pos, flags | implicit,
1319                                FINAL,
1320                                VOLATILE)
1321                  &&
1322                  (sym.kind == TYP ||
1323                   checkDisjoint(pos, flags,
1324                                 ABSTRACT | NATIVE,
1325                                 STRICTFP))
1326                  && checkDisjoint(pos, flags,
1327                                 FINAL,
1328                            SEALED | NON_SEALED)
1329                  && checkDisjoint(pos, flags,
1330                                 SEALED,
1331                            FINAL | NON_SEALED)
1332                  && checkDisjoint(pos, flags,
1333                                 SEALED,
1334                                 ANNOTATION)
1335                 && checkDisjoint(pos, flags,
1336                                 VALUE_CLASS,
1337                                 ANNOTATION)
1338                 && checkDisjoint(pos, flags,
1339                                 VALUE_CLASS,
1340                                 INTERFACE) ) {
1341             // skip
1342         }
1343         return flags & (mask | ~ExtendedStandardFlags) | implicit;
1344     }
1345 
1346     /** Determine if this enum should be implicitly final.
1347      *
1348      *  If the enum has no specialized enum constants, it is final.
1349      *
1350      *  If the enum does have specialized enum constants, it is
1351      *  <i>not</i> final.
1352      */
1353     private long implicitEnumFinalFlag(JCTree tree) {
1354         if (!tree.hasTag(CLASSDEF)) return 0;
1355         class SpecialTreeVisitor extends JCTree.Visitor {
1356             boolean specialized;
1357             SpecialTreeVisitor() {
1358                 this.specialized = false;
1359             }
1360 

2117                     return true;
2118                 }
2119             }
2120         }
2121         return false;
2122     }
2123 
2124     /** Check that a given method conforms with any method it overrides.
2125      *  @param tree         The tree from which positions are extracted
2126      *                      for errors.
2127      *  @param m            The overriding method.
2128      */
2129     void checkOverride(Env<AttrContext> env, JCMethodDecl tree, MethodSymbol m) {
2130         ClassSymbol origin = (ClassSymbol)m.owner;
2131         if ((origin.flags() & ENUM) != 0 && names.finalize.equals(m.name)) {
2132             if (m.overrides(syms.enumFinalFinalize, origin, types, false)) {
2133                 log.error(tree.pos(), Errors.EnumNoFinalize);
2134                 return;
2135             }
2136         }
2137         if (allowValueClasses && origin.isValueClass() && names.finalize.equals(m.name)) {
2138             if (m.overrides(syms.objectFinalize, origin, types, false)) {
2139                 log.warning(tree.pos(), Warnings.ValueFinalize);
2140             }
2141         }
2142         if (allowRecords && origin.isRecord()) {
2143             // let's find out if this is a user defined accessor in which case the @Override annotation is acceptable
2144             Optional<? extends RecordComponent> recordComponent = origin.getRecordComponents().stream()
2145                     .filter(rc -> rc.accessor == tree.sym && (rc.accessor.flags_field & GENERATED_MEMBER) == 0).findFirst();
2146             if (recordComponent.isPresent()) {
2147                 return;
2148             }
2149         }
2150 
2151         for (Type t = origin.type; t.hasTag(CLASS);
2152              t = types.supertype(t)) {
2153             if (t != origin.type) {
2154                 checkOverride(tree, t, origin, m);
2155             }
2156             for (Type t2 : types.interfaces(t)) {
2157                 checkOverride(tree, t2, origin, m);
2158             }
2159         }
2160 
2161         final boolean explicitOverride = m.attribute(syms.overrideType.tsym) != null;

2557     /** Check that all abstract methods implemented by a class are
2558      *  mutually compatible.
2559      *  @param pos          Position to be used for error reporting.
2560      *  @param c            The class whose interfaces are checked.
2561      */
2562     void checkCompatibleSupertypes(DiagnosticPosition pos, Type c) {
2563         List<Type> supertypes = types.interfaces(c);
2564         Type supertype = types.supertype(c);
2565         if (supertype.hasTag(CLASS) &&
2566             (supertype.tsym.flags() & ABSTRACT) != 0)
2567             supertypes = supertypes.prepend(supertype);
2568         for (List<Type> l = supertypes; l.nonEmpty(); l = l.tail) {
2569             if (!l.head.getTypeArguments().isEmpty() &&
2570                 !checkCompatibleAbstracts(pos, l.head, l.head, c))
2571                 return;
2572             for (List<Type> m = supertypes; m != l; m = m.tail)
2573                 if (!checkCompatibleAbstracts(pos, l.head, m.head, c))
2574                     return;
2575         }
2576         checkCompatibleConcretes(pos, c);
2577 
2578         Type identitySuper = null;
2579         for (Type t : types.closure(c)) {
2580             if (t != c) {
2581                 if (t.isIdentityClass() && (t.tsym.flags() & VALUE_BASED) == 0)
2582                     identitySuper = t;
2583                 if (c.isValueClass() && identitySuper != null && identitySuper.tsym != syms.objectType.tsym) { // Object is special
2584                     log.error(pos, Errors.ValueTypeHasIdentitySuperType(c, identitySuper));
2585                     break;
2586                 }
2587             }
2588         }
2589     }
2590 
2591     /** Check that all non-override equivalent methods accessible from 'site'
2592      *  are mutually compatible (JLS 8.4.8/9.4.1).
2593      *
2594      *  @param pos  Position to be used for error reporting.
2595      *  @param site The class whose methods are checked.
2596      *  @param sym  The method symbol to be checked.
2597      */
2598     void checkOverrideClashes(DiagnosticPosition pos, Type site, MethodSymbol sym) {
2599          ClashFilter cf = new ClashFilter(site);
2600         //for each method m1 that is overridden (directly or indirectly)
2601         //by method 'sym' in 'site'...
2602 
2603         ArrayList<Symbol> symbolsByName = new ArrayList<>();
2604         types.membersClosure(site, false).getSymbolsByName(sym.name, cf).forEach(symbolsByName::add);
2605         for (Symbol m1 : symbolsByName) {
2606             if (!sym.overrides(m1, site.tsym, types, false)) {
2607                 continue;
2608             }

4902                 }
4903             } else {
4904                 Assert.error("Unknown pattern: " + currentPattern.getTag());
4905             }
4906             return false;
4907         }
4908 
4909     /** check if a type is a subtype of Externalizable, if that is available. */
4910     boolean isExternalizable(Type t) {
4911         try {
4912             syms.externalizableType.complete();
4913         } catch (CompletionFailure e) {
4914             return false;
4915         }
4916         return types.isSubtype(t, syms.externalizableType);
4917     }
4918 
4919     /**
4920      * Check structure of serialization declarations.
4921      */
4922     public void checkSerialStructure(Env<AttrContext> env, JCClassDecl tree, ClassSymbol c) {
4923         (new SerialTypeVisitor(env)).visit(c, tree);
4924     }
4925 
4926     /**
4927      * This visitor will warn if a serialization-related field or
4928      * method is declared in a suspicious or incorrect way. In
4929      * particular, it will warn for cases where the runtime
4930      * serialization mechanism will silently ignore a mis-declared
4931      * entity.
4932      *
4933      * Distinguished serialization-related fields and methods:
4934      *
4935      * Methods:
4936      *
4937      * private void writeObject(ObjectOutputStream stream) throws IOException
4938      * ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException
4939      *
4940      * private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException
4941      * private void readObjectNoData() throws ObjectStreamException
4942      * ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException
4943      *
4944      * Fields:
4945      *
4946      * private static final long serialVersionUID
4947      * private static final ObjectStreamField[] serialPersistentFields
4948      *
4949      * Externalizable: methods defined on the interface
4950      * public void writeExternal(ObjectOutput) throws IOException
4951      * public void readExternal(ObjectInput) throws IOException
4952      */
4953     private class SerialTypeVisitor extends ElementKindVisitor14<Void, JCClassDecl> {
4954         Env<AttrContext> env;
4955         SerialTypeVisitor(Env<AttrContext> env) {
4956             this.lint = Check.this.lint;
4957             this.env = env;
4958         }
4959 
4960         private static final Set<String> serialMethodNames =
4961             Set.of("writeObject", "writeReplace",
4962                    "readObject",  "readObjectNoData",
4963                    "readResolve");
4964 
4965         private static final Set<String> serialFieldNames =
4966             Set.of("serialVersionUID", "serialPersistentFields");
4967 
4968         // Type of serialPersistentFields
4969         private final Type OSF_TYPE = new Type.ArrayType(syms.objectStreamFieldType, syms.arrayClass);
4970 
4971         Lint lint;
4972 
4973         @Override
4974         public Void defaultAction(Element e, JCClassDecl p) {
4975             throw new IllegalArgumentException(Objects.requireNonNullElse(e.toString(), ""));
4976         }
4977 

4997                 if (sym.kind == VAR) {
4998                     svuidSym = (VarSymbol)sym;
4999                     break;
5000                 }
5001             }
5002 
5003             if (svuidSym == null) {
5004                 log.warning(p.pos(), LintWarnings.MissingSVUID(c));
5005             }
5006 
5007             // Check for serialPersistentFields to gate checks for
5008             // non-serializable non-transient instance fields
5009             boolean serialPersistentFieldsPresent =
5010                     c.members()
5011                      .getSymbolsByName(names.serialPersistentFields, sym -> sym.kind == VAR)
5012                      .iterator()
5013                      .hasNext();
5014 
5015             // Check declarations of serialization-related methods and
5016             // fields
5017             final boolean[] hasWriteReplace = {false};
5018             for(Symbol el : c.getEnclosedElements()) {
5019                 runUnderLint(el, p, (enclosed, tree) -> {
5020                     String name = null;
5021                     switch(enclosed.getKind()) {
5022                     case FIELD -> {
5023                         if (!serialPersistentFieldsPresent) {
5024                             var flags = enclosed.flags();
5025                             if ( ((flags & TRANSIENT) == 0) &&
5026                                  ((flags & STATIC) == 0)) {
5027                                 Type varType = enclosed.asType();
5028                                 if (!canBeSerialized(varType)) {
5029                                     // Note per JLS arrays are
5030                                     // serializable even if the
5031                                     // component type is not.
5032                                     log.warning(
5033                                             TreeInfo.diagnosticPositionFor(enclosed, tree),
5034                                                 LintWarnings.NonSerializableInstanceField);
5035                                 } else if (varType.hasTag(ARRAY)) {
5036                                     ArrayType arrayType = (ArrayType)varType;
5037                                     Type elementType = arrayType.elemtype;

5072                     // will also pull in default methods from
5073                     // superinterfaces. In other words, the runtime checks
5074                     // (which long predate default methods on interfaces)
5075                     // do not admit the possibility of inheriting methods
5076                     // this way, a difference from general inheritance.
5077 
5078                     // The current implementation just checks the enclosed
5079                     // elements and does not directly check the inherited
5080                     // methods. If all the types are being checked this is
5081                     // less of a concern; however, there are cases that
5082                     // could be missed. In particular, readResolve and
5083                     // writeReplace could, in principle, by inherited from
5084                     // a non-serializable superclass and thus not checked
5085                     // even if compiled with a serializable child class.
5086                     case METHOD -> {
5087                         var method = (MethodSymbol)enclosed;
5088                         name = method.getSimpleName().toString();
5089                         if (serialMethodNames.contains(name)) {
5090                             switch (name) {
5091                             case "writeObject"      -> checkWriteObject(tree, e, method);
5092                             case "writeReplace"     -> {hasWriteReplace[0] = true; hasAppropriateWriteReplace(tree, method, true);}
5093                             case "readObject"       -> checkReadObject(tree,e, method);
5094                             case "readObjectNoData" -> checkReadObjectNoData(tree, e, method);
5095                             case "readResolve"      -> checkReadResolve(tree, e, method);
5096                             default ->  throw new AssertionError();
5097                             }
5098                         }
5099                     }
5100                     }
5101                 });
5102             }
5103             if (!hasWriteReplace[0] &&
5104                     (c.isValueClass() || hasAbstractValueSuperClass(c, Set.of(syms.numberType.tsym))) &&
5105                     !c.isAbstract() && !c.isRecord() &&
5106                     types.unboxedType(c.type) == Type.noType) {
5107                 // we need to check if the class is inheriting an appropriate writeReplace method
5108                 MethodSymbol ms = null;
5109                 Log.DiagnosticHandler discardHandler = log.new DiscardDiagnosticHandler();
5110                 try {
5111                     ms = rs.resolveInternalMethod(env.tree, env, c.type, names.writeReplace, List.nil(), List.nil());
5112                 } catch (FatalError fe) {
5113                     // ignore no method was found
5114                 } finally {
5115                     log.popDiagnosticHandler(discardHandler);
5116                 }
5117                 if (ms == null || !hasAppropriateWriteReplace(p, ms, false)) {
5118                     log.warning(p.pos(),
5119                             c.isValueClass() ? LintWarnings.SerializableValueClassWithoutWriteReplace1 :
5120                                     LintWarnings.SerializableValueClassWithoutWriteReplace2);
5121                 }
5122             }
5123             return null;
5124         }
5125 
5126         boolean canBeSerialized(Type type) {
5127             return type.isPrimitive() || rs.isSerializable(type);
5128         }
5129 
5130         private boolean hasAbstractValueSuperClass(Symbol c, Set<Symbol> excluding) {
5131             while (c.getKind() == ElementKind.CLASS) {
5132                 Type sup = ((ClassSymbol)c).getSuperclass();
5133                 if (!sup.hasTag(CLASS) || sup.isErroneous() ||
5134                         sup.tsym == syms.objectType.tsym) {
5135                     return false;
5136                 }
5137                 // if it is a value super class it has to be abstract
5138                 if (sup.isValueClass() && !excluding.contains(sup.tsym)) {
5139                     return true;
5140                 }
5141                 c = sup.tsym;
5142             }
5143             return false;
5144         }
5145 
5146         /**
5147          * Check that Externalizable class needs a public no-arg
5148          * constructor.
5149          *
5150          * Check that a Serializable class has access to the no-arg
5151          * constructor of its first nonserializable superclass.
5152          */
5153         private void checkCtorAccess(JCClassDecl tree, ClassSymbol c) {
5154             if (isExternalizable(c.type)) {
5155                 for(var sym : c.getEnclosedElements()) {
5156                     if (sym.isConstructor() &&
5157                         ((sym.flags() & PUBLIC) == PUBLIC)) {
5158                         if (((MethodSymbol)sym).getParameters().isEmpty()) {
5159                             return;
5160                         }
5161                     }
5162                 }
5163                 log.warning(tree.pos(),
5164                             LintWarnings.ExternalizableMissingPublicNoArgCtor);
5165             } else {

5249             // Warn if serialPersistentFields is initialized to a
5250             // literal null.
5251             JCTree spfDecl = TreeInfo.declarationFor(spf, tree);
5252             if (spfDecl != null && spfDecl.getTag() == VARDEF) {
5253                 JCVariableDecl variableDef = (JCVariableDecl) spfDecl;
5254                 JCExpression initExpr = variableDef.init;
5255                  if (initExpr != null && TreeInfo.isNull(initExpr)) {
5256                      log.warning(initExpr.pos(),
5257                                  LintWarnings.SPFNullInit);
5258                  }
5259             }
5260         }
5261 
5262         private void checkWriteObject(JCClassDecl tree, Element e, MethodSymbol method) {
5263             // The "synchronized" modifier is seen in the wild on
5264             // readObject and writeObject methods and is generally
5265             // innocuous.
5266 
5267             // private void writeObject(ObjectOutputStream stream) throws IOException
5268             checkPrivateNonStaticMethod(tree, method);
5269             isExpectedReturnType(tree, method, syms.voidType, true);
5270             checkOneArg(tree, e, method, syms.objectOutputStreamType);
5271             hasExpectedExceptions(tree, method, true, syms.ioExceptionType);
5272             checkExternalizable(tree, e, method);
5273         }
5274 
5275         private boolean hasAppropriateWriteReplace(JCClassDecl tree, MethodSymbol method, boolean warn) {
5276             // ANY-ACCESS-MODIFIER Object writeReplace() throws
5277             // ObjectStreamException
5278 
5279             // Excluding abstract, could have a more complicated
5280             // rule based on abstract-ness of the class
5281             return isConcreteInstanceMethod(tree, method, warn) &&
5282                     isExpectedReturnType(tree, method, syms.objectType, warn) &&
5283                     hasNoArgs(tree, method, warn) &&
5284                     hasExpectedExceptions(tree, method, warn, syms.objectStreamExceptionType);
5285         }
5286 
5287         private void checkReadObject(JCClassDecl tree, Element e, MethodSymbol method) {
5288             // The "synchronized" modifier is seen in the wild on
5289             // readObject and writeObject methods and is generally
5290             // innocuous.
5291 
5292             // private void readObject(ObjectInputStream stream)
5293             //   throws IOException, ClassNotFoundException
5294             checkPrivateNonStaticMethod(tree, method);
5295             isExpectedReturnType(tree, method, syms.voidType, true);
5296             checkOneArg(tree, e, method, syms.objectInputStreamType);
5297             hasExpectedExceptions(tree, method, true, syms.ioExceptionType, syms.classNotFoundExceptionType);
5298             checkExternalizable(tree, e, method);
5299         }
5300 
5301         private void checkReadObjectNoData(JCClassDecl tree, Element e, MethodSymbol method) {
5302             // private void readObjectNoData() throws ObjectStreamException
5303             checkPrivateNonStaticMethod(tree, method);
5304             isExpectedReturnType(tree, method, syms.voidType, true);
5305             hasNoArgs(tree, method, true);
5306             hasExpectedExceptions(tree, method, true, syms.objectStreamExceptionType);
5307             checkExternalizable(tree, e, method);
5308         }
5309 
5310         private void checkReadResolve(JCClassDecl tree, Element e, MethodSymbol method) {
5311             // ANY-ACCESS-MODIFIER Object readResolve()
5312             // throws ObjectStreamException
5313 
5314             // Excluding abstract, could have a more complicated
5315             // rule based on abstract-ness of the class
5316             isConcreteInstanceMethod(tree, method, true);
5317             isExpectedReturnType(tree, method, syms.objectType, true);
5318             hasNoArgs(tree, method, true);
5319             hasExpectedExceptions(tree, method, true, syms.objectStreamExceptionType);
5320         }
5321 
5322         private void checkWriteExternalRecord(JCClassDecl tree, Element e, MethodSymbol method, boolean isExtern) {
5323             //public void writeExternal(ObjectOutput) throws IOException
5324             checkExternMethodRecord(tree, e, method, syms.objectOutputType, isExtern);
5325         }
5326 
5327         private void checkReadExternalRecord(JCClassDecl tree, Element e, MethodSymbol method, boolean isExtern) {
5328             // public void readExternal(ObjectInput) throws IOException
5329             checkExternMethodRecord(tree, e, method, syms.objectInputType, isExtern);
5330          }
5331 
5332         private void checkExternMethodRecord(JCClassDecl tree, Element e, MethodSymbol method, Type argType,
5333                                              boolean isExtern) {
5334             if (isExtern && isExternMethod(tree, e, method, argType)) {
5335                 log.warning(
5336                         TreeInfo.diagnosticPositionFor(method, tree),
5337                             LintWarnings.IneffectualExternalizableMethodRecord(method.getSimpleName().toString()));
5338             }
5339         }

5549                     case FIELD -> {
5550                         var field = (VarSymbol)enclosed;
5551                         switch(name) {
5552                         case "serialPersistentFields" -> {
5553                             log.warning(
5554                                     TreeInfo.diagnosticPositionFor(field, tree),
5555                                         LintWarnings.IneffectualSerialFieldRecord);
5556                         }
5557 
5558                         case "serialVersionUID" -> {
5559                             // Could generate additional warning that
5560                             // svuid value is not checked to match for
5561                             // records.
5562                             checkSerialVersionUID(tree, e, field);
5563                         }}
5564                     }
5565 
5566                     case METHOD -> {
5567                         var method = (MethodSymbol)enclosed;
5568                         switch(name) {
5569                         case "writeReplace" -> hasAppropriateWriteReplace(tree, method, true);
5570                         case "readResolve"  -> checkReadResolve(tree, e, method);
5571 
5572                         case "writeExternal" -> checkWriteExternalRecord(tree, e, method, isExtern);
5573                         case "readExternal"  -> checkReadExternalRecord(tree, e, method, isExtern);
5574 
5575                         default -> {
5576                             if (serialMethodNames.contains(name)) {
5577                                 log.warning(
5578                                         TreeInfo.diagnosticPositionFor(method, tree),
5579                                             LintWarnings.IneffectualSerialMethodRecord(name));
5580                             }
5581                         }}
5582                     }}});
5583             }
5584             return null;
5585         }
5586 
5587         boolean isConcreteInstanceMethod(JCClassDecl tree,
5588                                          MethodSymbol method,
5589                                          boolean warn) {
5590             if ((method.flags() & (STATIC | ABSTRACT)) != 0) {
5591                 if (warn) {
5592                     log.warning(
5593                             TreeInfo.diagnosticPositionFor(method, tree),
5594                                 LintWarnings.SerialConcreteInstanceMethod(method.getSimpleName()));
5595                 }
5596                 return false;
5597             }
5598             return true;
5599         }
5600 
5601         private boolean isExpectedReturnType(JCClassDecl tree,
5602                                           MethodSymbol method,
5603                                           Type expectedReturnType,
5604                                           boolean warn) {
5605             // Note: there may be complications checking writeReplace
5606             // and readResolve since they return Object and could, in
5607             // principle, have covariant overrides and any synthetic
5608             // bridge method would not be represented here for
5609             // checking.
5610             Type rtype = method.getReturnType();
5611             if (!types.isSameType(expectedReturnType, rtype)) {
5612                 if (warn) {
5613                     log.warning(
5614                             TreeInfo.diagnosticPositionFor(method, tree),
5615                             LintWarnings.SerialMethodUnexpectedReturnType(method.getSimpleName(),
5616                                                                       rtype, expectedReturnType));
5617                 }
5618                 return false;
5619             }
5620             return true;
5621         }
5622 
5623         private void checkOneArg(JCClassDecl tree,
5624                                  Element enclosing,
5625                                  MethodSymbol method,
5626                                  Type expectedType) {
5627             String name = method.getSimpleName().toString();
5628 
5629             var parameters= method.getParameters();
5630 
5631             if (parameters.size() != 1) {
5632                 log.warning(
5633                         TreeInfo.diagnosticPositionFor(method, tree),
5634                             LintWarnings.SerialMethodOneArg(method.getSimpleName(), parameters.size()));
5635                 return;
5636             }
5637 
5638             Type parameterType = parameters.get(0).asType();
5639             if (!types.isSameType(parameterType, expectedType)) {
5640                 log.warning(
5641                         TreeInfo.diagnosticPositionFor(method, tree),
5642                             LintWarnings.SerialMethodParameterType(method.getSimpleName(),
5643                                                                expectedType,
5644                                                                parameterType));
5645             }
5646         }
5647 
5648         private boolean hasExactlyOneArgWithType(JCClassDecl tree,
5649                                                  Element enclosing,
5650                                                  MethodSymbol method,
5651                                                  Type expectedType) {
5652             var parameters = method.getParameters();
5653             return (parameters.size() == 1) &&
5654                 types.isSameType(parameters.get(0).asType(), expectedType);
5655         }
5656 
5657 
5658         boolean hasNoArgs(JCClassDecl tree, MethodSymbol method, boolean warn) {
5659             var parameters = method.getParameters();
5660             if (!parameters.isEmpty()) {
5661                 if (warn) {
5662                     log.warning(
5663                             TreeInfo.diagnosticPositionFor(parameters.get(0), tree),
5664                             LintWarnings.SerialMethodNoArgs(method.getSimpleName()));
5665                 }
5666                 return false;
5667             }
5668             return true;
5669         }
5670 
5671         private void checkExternalizable(JCClassDecl tree, Element enclosing, MethodSymbol method) {
5672             // If the enclosing class is externalizable, warn for the method
5673             if (isExternalizable((Type)enclosing.asType())) {
5674                 log.warning(
5675                         TreeInfo.diagnosticPositionFor(method, tree),
5676                             LintWarnings.IneffectualSerialMethodExternalizable(method.getSimpleName()));
5677             }
5678             return;
5679         }
5680 
5681         private boolean hasExpectedExceptions(JCClassDecl tree,
5682                                               MethodSymbol method,
5683                                               boolean warn,
5684                                               Type... declaredExceptions) {
5685             for (Type thrownType: method.getThrownTypes()) {
5686                 // For each exception in the throws clause of the
5687                 // method, if not an Error and not a RuntimeException,
5688                 // check if the exception is a subtype of a declared
5689                 // exception from the throws clause of the
5690                 // serialization method in question.
5691                 if (types.isSubtype(thrownType, syms.runtimeExceptionType) ||
5692                     types.isSubtype(thrownType, syms.errorType) ) {
5693                     continue;
5694                 } else {
5695                     boolean declared = false;
5696                     for (Type declaredException : declaredExceptions) {
5697                         if (types.isSubtype(thrownType, declaredException)) {
5698                             declared = true;
5699                             continue;
5700                         }
5701                     }
5702                     if (!declared) {
5703                         if (warn) {
5704                             log.warning(
5705                                     TreeInfo.diagnosticPositionFor(method, tree),
5706                                     LintWarnings.SerialMethodUnexpectedException(method.getSimpleName(),
5707                                                                              thrownType));
5708                         }
5709                         return false;
5710                     }
5711                 }
5712             }
5713             return true;
5714         }
5715 
5716         private <E extends Element> Void runUnderLint(E symbol, JCClassDecl p, BiConsumer<E, JCClassDecl> task) {
5717             Lint prevLint = lint;
5718             try {
5719                 lint = lint.augment((Symbol) symbol);
5720 
5721                 if (lint.isEnabled(LintCategory.SERIAL)) {
5722                     task.accept(symbol, p);
5723                 }
5724 
5725                 return null;
5726             } finally {
5727                 lint = prevLint;
5728             }
5729         }
5730 
5731     }
5732 
5733     void checkRequiresIdentity(JCTree tree, Lint lint) {
< prev index next >