1 /* 2 * Copyright (c) 1999, 2022, 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.comp; 27 28 import java.util.*; 29 import java.util.function.BiConsumer; 30 import java.util.function.BiPredicate; 31 import java.util.function.Consumer; 32 import java.util.function.Predicate; 33 import java.util.function.Supplier; 34 import java.util.function.ToIntBiFunction; 35 import java.util.stream.Collectors; 36 import java.util.stream.StreamSupport; 37 38 import javax.lang.model.element.ElementKind; 39 import javax.lang.model.element.NestingKind; 40 import javax.tools.JavaFileManager; 41 42 import com.sun.source.tree.CaseTree; 43 import com.sun.tools.javac.code.*; 44 import com.sun.tools.javac.code.Attribute.Compound; 45 import com.sun.tools.javac.code.Directive.ExportsDirective; 46 import com.sun.tools.javac.code.Directive.RequiresDirective; 47 import com.sun.tools.javac.code.Source.Feature; 48 import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata; 49 import com.sun.tools.javac.jvm.*; 50 import com.sun.tools.javac.resources.CompilerProperties.Errors; 51 import com.sun.tools.javac.resources.CompilerProperties.Fragments; 52 import com.sun.tools.javac.resources.CompilerProperties.Warnings; 53 import com.sun.tools.javac.tree.*; 54 import com.sun.tools.javac.util.*; 55 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; 56 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 57 import com.sun.tools.javac.util.JCDiagnostic.Error; 58 import com.sun.tools.javac.util.JCDiagnostic.Fragment; 59 import com.sun.tools.javac.util.JCDiagnostic.Warning; 60 import com.sun.tools.javac.util.List; 61 62 import com.sun.tools.javac.code.Lint; 63 import com.sun.tools.javac.code.Lint.LintCategory; 64 import com.sun.tools.javac.code.Scope.WriteableScope; 65 import com.sun.tools.javac.code.Type.*; 66 import com.sun.tools.javac.code.Symbol.*; 67 import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext; 68 import com.sun.tools.javac.tree.JCTree.*; 69 70 import static com.sun.tools.javac.code.Flags.*; 71 import static com.sun.tools.javac.code.Flags.ANNOTATION; 72 import static com.sun.tools.javac.code.Flags.SYNCHRONIZED; 73 import static com.sun.tools.javac.code.Kinds.*; 74 import static com.sun.tools.javac.code.Kinds.Kind.*; 75 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE; 76 import static com.sun.tools.javac.code.Scope.LookupKind.RECURSIVE; 77 import static com.sun.tools.javac.code.TypeTag.*; 78 import static com.sun.tools.javac.code.TypeTag.WILDCARD; 79 80 import static com.sun.tools.javac.tree.JCTree.Tag.*; 81 import javax.lang.model.element.Element; 82 import javax.lang.model.element.ExecutableElement; 83 import javax.lang.model.element.TypeElement; 84 import javax.lang.model.type.DeclaredType; 85 import javax.lang.model.type.TypeMirror; 86 import javax.lang.model.util.ElementFilter; 87 import javax.lang.model.util.ElementKindVisitor14; 88 89 /** Type checking helper class for the attribution phase. 90 * 91 * <p><b>This is NOT part of any supported API. 92 * If you write code that depends on this, you do so at your own risk. 93 * This code and its internal interfaces are subject to change or 94 * deletion without notice.</b> 95 */ 96 public class Check { 97 protected static final Context.Key<Check> checkKey = new Context.Key<>(); 98 99 // Flag bits indicating which item(s) chosen from a pair of items 100 private static final int FIRST = 0x01; 101 private static final int SECOND = 0x02; 102 103 private final Names names; 104 private final Log log; 105 private final Resolve rs; 106 private final Symtab syms; 107 private final Enter enter; 108 private final DeferredAttr deferredAttr; 109 private final Infer infer; 110 private final Types types; 111 private final TypeAnnotations typeAnnotations; 112 private final JCDiagnostic.Factory diags; 113 private final JavaFileManager fileManager; 114 private final Source source; 115 private final Target target; 116 private final Profile profile; 117 private final Preview preview; 118 private final boolean warnOnAnyAccessToMembers; 119 120 // The set of lint options currently in effect. It is initialized 121 // from the context, and then is set/reset as needed by Attr as it 122 // visits all the various parts of the trees during attribution. 123 private Lint lint; 124 125 // The method being analyzed in Attr - it is set/reset as needed by 126 // Attr as it visits new method declarations. 127 private MethodSymbol method; 128 129 public static Check instance(Context context) { 130 Check instance = context.get(checkKey); 131 if (instance == null) 132 instance = new Check(context); 133 return instance; 134 } 135 136 @SuppressWarnings("this-escape") 137 protected Check(Context context) { 138 context.put(checkKey, this); 139 140 names = Names.instance(context); 141 log = Log.instance(context); 142 rs = Resolve.instance(context); 143 syms = Symtab.instance(context); 144 enter = Enter.instance(context); 145 deferredAttr = DeferredAttr.instance(context); 146 infer = Infer.instance(context); 147 types = Types.instance(context); 148 typeAnnotations = TypeAnnotations.instance(context); 149 diags = JCDiagnostic.Factory.instance(context); 150 Options options = Options.instance(context); 151 lint = Lint.instance(context); 152 fileManager = context.get(JavaFileManager.class); 153 154 source = Source.instance(context); 155 target = Target.instance(context); 156 warnOnAnyAccessToMembers = options.isSet("warnOnAccessToMembers"); 157 158 Target target = Target.instance(context); 159 syntheticNameChar = target.syntheticNameChar(); 160 161 profile = Profile.instance(context); 162 preview = Preview.instance(context); 163 164 boolean verboseDeprecated = lint.isEnabled(LintCategory.DEPRECATION); 165 boolean verboseRemoval = lint.isEnabled(LintCategory.REMOVAL); 166 boolean verboseUnchecked = lint.isEnabled(LintCategory.UNCHECKED); 167 boolean enforceMandatoryWarnings = true; 168 169 deprecationHandler = new MandatoryWarningHandler(log, null, verboseDeprecated, 170 enforceMandatoryWarnings, "deprecated", LintCategory.DEPRECATION); 171 removalHandler = new MandatoryWarningHandler(log, null, verboseRemoval, 172 enforceMandatoryWarnings, "removal", LintCategory.REMOVAL); 173 uncheckedHandler = new MandatoryWarningHandler(log, null, verboseUnchecked, 174 enforceMandatoryWarnings, "unchecked", LintCategory.UNCHECKED); 175 sunApiHandler = new MandatoryWarningHandler(log, null, false, 176 enforceMandatoryWarnings, "sunapi", null); 177 178 deferredLintHandler = DeferredLintHandler.instance(context); 179 180 allowModules = Feature.MODULES.allowedInSource(source); 181 allowRecords = Feature.RECORDS.allowedInSource(source); 182 allowSealed = Feature.SEALED_CLASSES.allowedInSource(source); 183 } 184 185 /** Character for synthetic names 186 */ 187 char syntheticNameChar; 188 189 /** A table mapping flat names of all compiled classes for each module in this run 190 * to their symbols; maintained from outside. 191 */ 192 private Map<Pair<ModuleSymbol, Name>,ClassSymbol> compiled = new HashMap<>(); 193 194 /** A handler for messages about deprecated usage. 195 */ 196 private MandatoryWarningHandler deprecationHandler; 197 198 /** A handler for messages about deprecated-for-removal usage. 199 */ 200 private MandatoryWarningHandler removalHandler; 201 202 /** A handler for messages about unchecked or unsafe usage. 203 */ 204 private MandatoryWarningHandler uncheckedHandler; 205 206 /** A handler for messages about using proprietary API. 207 */ 208 private MandatoryWarningHandler sunApiHandler; 209 210 /** A handler for deferred lint warnings. 211 */ 212 private DeferredLintHandler deferredLintHandler; 213 214 /** Are modules allowed 215 */ 216 private final boolean allowModules; 217 218 /** Are records allowed 219 */ 220 private final boolean allowRecords; 221 222 /** Are sealed classes allowed 223 */ 224 private final boolean allowSealed; 225 226 /* ************************************************************************* 227 * Errors and Warnings 228 **************************************************************************/ 229 230 Lint setLint(Lint newLint) { 231 Lint prev = lint; 232 lint = newLint; 233 return prev; 234 } 235 236 MethodSymbol setMethod(MethodSymbol newMethod) { 237 MethodSymbol prev = method; 238 method = newMethod; 239 return prev; 240 } 241 242 /** Warn about deprecated symbol. 243 * @param pos Position to be used for error reporting. 244 * @param sym The deprecated symbol. 245 */ 246 void warnDeprecated(DiagnosticPosition pos, Symbol sym) { 247 if (sym.isDeprecatedForRemoval()) { 248 if (!lint.isSuppressed(LintCategory.REMOVAL)) { 249 if (sym.kind == MDL) { 250 removalHandler.report(pos, Warnings.HasBeenDeprecatedForRemovalModule(sym)); 251 } else { 252 removalHandler.report(pos, Warnings.HasBeenDeprecatedForRemoval(sym, sym.location())); 253 } 254 } 255 } else if (!lint.isSuppressed(LintCategory.DEPRECATION)) { 256 if (sym.kind == MDL) { 257 deprecationHandler.report(pos, Warnings.HasBeenDeprecatedModule(sym)); 258 } else { 259 deprecationHandler.report(pos, Warnings.HasBeenDeprecated(sym, sym.location())); 260 } 261 } 262 } 263 264 /** Log a preview warning. 265 * @param pos Position to be used for error reporting. 266 * @param msg A Warning describing the problem. 267 */ 268 public void warnPreviewAPI(DiagnosticPosition pos, Warning warnKey) { 269 if (!lint.isSuppressed(LintCategory.PREVIEW)) 270 preview.reportPreviewWarning(pos, warnKey); 271 } 272 273 /** Log a preview warning. 274 * @param pos Position to be used for error reporting. 275 * @param msg A Warning describing the problem. 276 */ 277 public void warnDeclaredUsingPreview(DiagnosticPosition pos, Symbol sym) { 278 if (!lint.isSuppressed(LintCategory.PREVIEW)) 279 preview.reportPreviewWarning(pos, Warnings.DeclaredUsingPreview(kindName(sym), sym)); 280 } 281 282 /** Warn about unchecked operation. 283 * @param pos Position to be used for error reporting. 284 * @param msg A string describing the problem. 285 */ 286 public void warnUnchecked(DiagnosticPosition pos, Warning warnKey) { 287 if (!lint.isSuppressed(LintCategory.UNCHECKED)) 288 uncheckedHandler.report(pos, warnKey); 289 } 290 291 /** Warn about unsafe vararg method decl. 292 * @param pos Position to be used for error reporting. 293 */ 294 void warnUnsafeVararg(DiagnosticPosition pos, Warning warnKey) { 295 if (lint.isEnabled(LintCategory.VARARGS)) 296 log.warning(LintCategory.VARARGS, pos, warnKey); 297 } 298 299 public void warnStatic(DiagnosticPosition pos, Warning warnKey) { 300 if (lint.isEnabled(LintCategory.STATIC)) 301 log.warning(LintCategory.STATIC, pos, warnKey); 302 } 303 304 /** Warn about division by integer constant zero. 305 * @param pos Position to be used for error reporting. 306 */ 307 void warnDivZero(DiagnosticPosition pos) { 308 if (lint.isEnabled(LintCategory.DIVZERO)) 309 log.warning(LintCategory.DIVZERO, pos, Warnings.DivZero); 310 } 311 312 /** 313 * Report any deferred diagnostics. 314 */ 315 public void reportDeferredDiagnostics() { 316 deprecationHandler.reportDeferredDiagnostic(); 317 removalHandler.reportDeferredDiagnostic(); 318 uncheckedHandler.reportDeferredDiagnostic(); 319 sunApiHandler.reportDeferredDiagnostic(); 320 } 321 322 323 /** Report a failure to complete a class. 324 * @param pos Position to be used for error reporting. 325 * @param ex The failure to report. 326 */ 327 public Type completionError(DiagnosticPosition pos, CompletionFailure ex) { 328 log.error(JCDiagnostic.DiagnosticFlag.NON_DEFERRABLE, pos, Errors.CantAccess(ex.sym, ex.getDetailValue())); 329 return syms.errType; 330 } 331 332 /** Report an error that wrong type tag was found. 333 * @param pos Position to be used for error reporting. 334 * @param required An internationalized string describing the type tag 335 * required. 336 * @param found The type that was found. 337 */ 338 Type typeTagError(DiagnosticPosition pos, JCDiagnostic required, Object found) { 339 // this error used to be raised by the parser, 340 // but has been delayed to this point: 341 if (found instanceof Type type && type.hasTag(VOID)) { 342 log.error(pos, Errors.IllegalStartOfType); 343 return syms.errType; 344 } 345 log.error(pos, Errors.TypeFoundReq(found, required)); 346 return types.createErrorType(found instanceof Type type ? type : syms.errType); 347 } 348 349 /** Report an error that symbol cannot be referenced before super 350 * has been called. 351 * @param pos Position to be used for error reporting. 352 * @param sym The referenced symbol. 353 */ 354 void earlyRefError(DiagnosticPosition pos, Symbol sym) { 355 log.error(pos, Errors.CantRefBeforeCtorCalled(sym)); 356 } 357 358 /** Report duplicate declaration error. 359 */ 360 void duplicateError(DiagnosticPosition pos, Symbol sym) { 361 if (!sym.type.isErroneous()) { 362 Symbol location = sym.location(); 363 if (location.kind == MTH && 364 ((MethodSymbol)location).isStaticOrInstanceInit()) { 365 log.error(pos, 366 Errors.AlreadyDefinedInClinit(kindName(sym), 367 sym, 368 kindName(sym.location()), 369 kindName(sym.location().enclClass()), 370 sym.location().enclClass())); 371 } else { 372 /* dont error if this is a duplicated parameter of a generated canonical constructor 373 * as we should have issued an error for the duplicated fields 374 */ 375 if (location.kind != MTH || 376 ((sym.owner.flags_field & GENERATEDCONSTR) == 0) || 377 ((sym.owner.flags_field & RECORD) == 0)) { 378 log.error(pos, 379 Errors.AlreadyDefined(kindName(sym), 380 sym, 381 kindName(sym.location()), 382 sym.location())); 383 } 384 } 385 } 386 } 387 388 /** Report array/varargs duplicate declaration 389 */ 390 void varargsDuplicateError(DiagnosticPosition pos, Symbol sym1, Symbol sym2) { 391 if (!sym1.type.isErroneous() && !sym2.type.isErroneous()) { 392 log.error(pos, Errors.ArrayAndVarargs(sym1, sym2, sym2.location())); 393 } 394 } 395 396 /* ************************************************************************ 397 * duplicate declaration checking 398 *************************************************************************/ 399 400 /** Check that variable does not hide variable with same name in 401 * immediately enclosing local scope. 402 * @param pos Position for error reporting. 403 * @param v The symbol. 404 * @param s The scope. 405 */ 406 void checkTransparentVar(DiagnosticPosition pos, VarSymbol v, Scope s) { 407 for (Symbol sym : s.getSymbolsByName(v.name)) { 408 if (sym.owner != v.owner) break; 409 if (sym.kind == VAR && 410 sym.owner.kind.matches(KindSelector.VAL_MTH) && 411 v.name != names.error) { 412 duplicateError(pos, sym); 413 return; 414 } 415 } 416 } 417 418 /** Check that a class or interface does not hide a class or 419 * interface with same name in immediately enclosing local scope. 420 * @param pos Position for error reporting. 421 * @param c The symbol. 422 * @param s The scope. 423 */ 424 void checkTransparentClass(DiagnosticPosition pos, ClassSymbol c, Scope s) { 425 for (Symbol sym : s.getSymbolsByName(c.name)) { 426 if (sym.owner != c.owner) break; 427 if (sym.kind == TYP && !sym.type.hasTag(TYPEVAR) && 428 sym.owner.kind.matches(KindSelector.VAL_MTH) && 429 c.name != names.error) { 430 duplicateError(pos, sym); 431 return; 432 } 433 } 434 } 435 436 /** Check that class does not have the same name as one of 437 * its enclosing classes, or as a class defined in its enclosing scope. 438 * return true if class is unique in its enclosing scope. 439 * @param pos Position for error reporting. 440 * @param name The class name. 441 * @param s The enclosing scope. 442 */ 443 boolean checkUniqueClassName(DiagnosticPosition pos, Name name, Scope s) { 444 for (Symbol sym : s.getSymbolsByName(name, NON_RECURSIVE)) { 445 if (sym.kind == TYP && sym.name != names.error) { 446 duplicateError(pos, sym); 447 return false; 448 } 449 } 450 for (Symbol sym = s.owner; sym != null; sym = sym.owner) { 451 if (sym.kind == TYP && sym.name == name && sym.name != names.error) { 452 duplicateError(pos, sym); 453 return true; 454 } 455 } 456 return true; 457 } 458 459 /* ************************************************************************* 460 * Class name generation 461 **************************************************************************/ 462 463 464 private Map<Pair<Name, Name>, Integer> localClassNameIndexes = new HashMap<>(); 465 466 /** Return name of local class. 467 * This is of the form {@code <enclClass> $ n <classname> } 468 * where 469 * enclClass is the flat name of the enclosing class, 470 * classname is the simple name of the local class 471 */ 472 public Name localClassName(ClassSymbol c) { 473 Name enclFlatname = c.owner.enclClass().flatname; 474 String enclFlatnameStr = enclFlatname.toString(); 475 Pair<Name, Name> key = new Pair<>(enclFlatname, c.name); 476 Integer index = localClassNameIndexes.get(key); 477 for (int i = (index == null) ? 1 : index; ; i++) { 478 Name flatname = names.fromString(enclFlatnameStr 479 + syntheticNameChar + i + c.name); 480 if (getCompiled(c.packge().modle, flatname) == null) { 481 localClassNameIndexes.put(key, i + 1); 482 return flatname; 483 } 484 } 485 } 486 487 public void clearLocalClassNameIndexes(ClassSymbol c) { 488 if (c.owner != null && c.owner.kind != NIL) { 489 localClassNameIndexes.remove(new Pair<>( 490 c.owner.enclClass().flatname, c.name)); 491 } 492 } 493 494 public void newRound() { 495 compiled.clear(); 496 localClassNameIndexes.clear(); 497 } 498 499 public void clear() { 500 deprecationHandler.clear(); 501 removalHandler.clear(); 502 uncheckedHandler.clear(); 503 sunApiHandler.clear(); 504 } 505 506 public void putCompiled(ClassSymbol csym) { 507 compiled.put(Pair.of(csym.packge().modle, csym.flatname), csym); 508 } 509 510 public ClassSymbol getCompiled(ClassSymbol csym) { 511 return compiled.get(Pair.of(csym.packge().modle, csym.flatname)); 512 } 513 514 public ClassSymbol getCompiled(ModuleSymbol msym, Name flatname) { 515 return compiled.get(Pair.of(msym, flatname)); 516 } 517 518 public void removeCompiled(ClassSymbol csym) { 519 compiled.remove(Pair.of(csym.packge().modle, csym.flatname)); 520 } 521 522 /* ************************************************************************* 523 * Type Checking 524 **************************************************************************/ 525 526 /** 527 * A check context is an object that can be used to perform compatibility 528 * checks - depending on the check context, meaning of 'compatibility' might 529 * vary significantly. 530 */ 531 public interface CheckContext { 532 /** 533 * Is type 'found' compatible with type 'req' in given context 534 */ 535 boolean compatible(Type found, Type req, Warner warn); 536 /** 537 * Report a check error 538 */ 539 void report(DiagnosticPosition pos, JCDiagnostic details); 540 /** 541 * Obtain a warner for this check context 542 */ 543 public Warner checkWarner(DiagnosticPosition pos, Type found, Type req); 544 545 public InferenceContext inferenceContext(); 546 547 public DeferredAttr.DeferredAttrContext deferredAttrContext(); 548 } 549 550 /** 551 * This class represent a check context that is nested within another check 552 * context - useful to check sub-expressions. The default behavior simply 553 * redirects all method calls to the enclosing check context leveraging 554 * the forwarding pattern. 555 */ 556 static class NestedCheckContext implements CheckContext { 557 CheckContext enclosingContext; 558 559 NestedCheckContext(CheckContext enclosingContext) { 560 this.enclosingContext = enclosingContext; 561 } 562 563 public boolean compatible(Type found, Type req, Warner warn) { 564 return enclosingContext.compatible(found, req, warn); 565 } 566 567 public void report(DiagnosticPosition pos, JCDiagnostic details) { 568 enclosingContext.report(pos, details); 569 } 570 571 public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) { 572 return enclosingContext.checkWarner(pos, found, req); 573 } 574 575 public InferenceContext inferenceContext() { 576 return enclosingContext.inferenceContext(); 577 } 578 579 public DeferredAttrContext deferredAttrContext() { 580 return enclosingContext.deferredAttrContext(); 581 } 582 } 583 584 /** 585 * Check context to be used when evaluating assignment/return statements 586 */ 587 CheckContext basicHandler = new CheckContext() { 588 public void report(DiagnosticPosition pos, JCDiagnostic details) { 589 log.error(pos, Errors.ProbFoundReq(details)); 590 } 591 public boolean compatible(Type found, Type req, Warner warn) { 592 return types.isAssignable(found, req, warn); 593 } 594 595 public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) { 596 return convertWarner(pos, found, req); 597 } 598 599 public InferenceContext inferenceContext() { 600 return infer.emptyContext; 601 } 602 603 public DeferredAttrContext deferredAttrContext() { 604 return deferredAttr.emptyDeferredAttrContext; 605 } 606 607 @Override 608 public String toString() { 609 return "CheckContext: basicHandler"; 610 } 611 }; 612 613 /** Check that a given type is assignable to a given proto-type. 614 * If it is, return the type, otherwise return errType. 615 * @param pos Position to be used for error reporting. 616 * @param found The type that was found. 617 * @param req The type that was required. 618 */ 619 public Type checkType(DiagnosticPosition pos, Type found, Type req) { 620 return checkType(pos, found, req, basicHandler); 621 } 622 623 Type checkType(final DiagnosticPosition pos, final Type found, final Type req, final CheckContext checkContext) { 624 final InferenceContext inferenceContext = checkContext.inferenceContext(); 625 if (inferenceContext.free(req) || inferenceContext.free(found)) { 626 inferenceContext.addFreeTypeListener(List.of(req, found), 627 solvedContext -> checkType(pos, solvedContext.asInstType(found), solvedContext.asInstType(req), checkContext)); 628 } 629 if (req.hasTag(ERROR)) 630 return req; 631 if (req.hasTag(NONE)) 632 return found; 633 if (checkContext.compatible(found, req, checkContext.checkWarner(pos, found, req))) { 634 return found; 635 } else { 636 if (found.isNumeric() && req.isNumeric()) { 637 checkContext.report(pos, diags.fragment(Fragments.PossibleLossOfPrecision(found, req))); 638 return types.createErrorType(found); 639 } 640 checkContext.report(pos, diags.fragment(Fragments.InconvertibleTypes(found, req))); 641 return types.createErrorType(found); 642 } 643 } 644 645 /** Check that a given type can be cast to a given target type. 646 * Return the result of the cast. 647 * @param pos Position to be used for error reporting. 648 * @param found The type that is being cast. 649 * @param req The target type of the cast. 650 */ 651 Type checkCastable(DiagnosticPosition pos, Type found, Type req) { 652 return checkCastable(pos, found, req, basicHandler); 653 } 654 Type checkCastable(DiagnosticPosition pos, Type found, Type req, CheckContext checkContext) { 655 if (types.isCastable(found, req, castWarner(pos, found, req))) { 656 return req; 657 } else { 658 checkContext.report(pos, diags.fragment(Fragments.InconvertibleTypes(found, req))); 659 return types.createErrorType(found); 660 } 661 } 662 663 /** Check for redundant casts (i.e. where source type is a subtype of target type) 664 * The problem should only be reported for non-292 cast 665 */ 666 public void checkRedundantCast(Env<AttrContext> env, final JCTypeCast tree) { 667 if (!tree.type.isErroneous() 668 && types.isSameType(tree.expr.type, tree.clazz.type) 669 && !(ignoreAnnotatedCasts && TreeInfo.containsTypeAnnotation(tree.clazz)) 670 && !is292targetTypeCast(tree)) { 671 deferredLintHandler.report(() -> { 672 if (lint.isEnabled(LintCategory.CAST)) 673 log.warning(LintCategory.CAST, 674 tree.pos(), Warnings.RedundantCast(tree.clazz.type)); 675 }); 676 } 677 } 678 //where 679 private boolean is292targetTypeCast(JCTypeCast tree) { 680 boolean is292targetTypeCast = false; 681 JCExpression expr = TreeInfo.skipParens(tree.expr); 682 if (expr.hasTag(APPLY)) { 683 JCMethodInvocation apply = (JCMethodInvocation)expr; 684 Symbol sym = TreeInfo.symbol(apply.meth); 685 is292targetTypeCast = sym != null && 686 sym.kind == MTH && 687 (sym.flags() & HYPOTHETICAL) != 0; 688 } 689 return is292targetTypeCast; 690 } 691 692 private static final boolean ignoreAnnotatedCasts = true; 693 694 /** Check that a type is within some bounds. 695 * 696 * Used in TypeApply to verify that, e.g., X in {@code V<X>} is a valid 697 * type argument. 698 * @param a The type that should be bounded by bs. 699 * @param bound The bound. 700 */ 701 private boolean checkExtends(Type a, Type bound) { 702 if (a.isUnbound()) { 703 return true; 704 } else if (!a.hasTag(WILDCARD)) { 705 a = types.cvarUpperBound(a); 706 return types.isSubtype(a, bound); 707 } else if (a.isExtendsBound()) { 708 return types.isCastable(bound, types.wildUpperBound(a), types.noWarnings); 709 } else if (a.isSuperBound()) { 710 return !types.notSoftSubtype(types.wildLowerBound(a), bound); 711 } 712 return true; 713 } 714 715 /** Check that type is different from 'void'. 716 * @param pos Position to be used for error reporting. 717 * @param t The type to be checked. 718 */ 719 Type checkNonVoid(DiagnosticPosition pos, Type t) { 720 if (t.hasTag(VOID)) { 721 log.error(pos, Errors.VoidNotAllowedHere); 722 return types.createErrorType(t); 723 } else { 724 return t; 725 } 726 } 727 728 Type checkClassOrArrayType(DiagnosticPosition pos, Type t) { 729 if (!t.hasTag(CLASS) && !t.hasTag(ARRAY) && !t.hasTag(ERROR)) { 730 return typeTagError(pos, 731 diags.fragment(Fragments.TypeReqClassArray), 732 asTypeParam(t)); 733 } else { 734 return t; 735 } 736 } 737 738 /** Check that type is a class or interface type. 739 * @param pos Position to be used for error reporting. 740 * @param t The type to be checked. 741 */ 742 Type checkClassType(DiagnosticPosition pos, Type t) { 743 if (!t.hasTag(CLASS) && !t.hasTag(ERROR)) { 744 return typeTagError(pos, 745 diags.fragment(Fragments.TypeReqClass), 746 asTypeParam(t)); 747 } else { 748 return t; 749 } 750 } 751 //where 752 private Object asTypeParam(Type t) { 753 return (t.hasTag(TYPEVAR)) 754 ? diags.fragment(Fragments.TypeParameter(t)) 755 : t; 756 } 757 758 /** Check that type is a valid qualifier for a constructor reference expression 759 */ 760 Type checkConstructorRefType(DiagnosticPosition pos, Type t) { 761 t = checkClassOrArrayType(pos, t); 762 if (t.hasTag(CLASS)) { 763 if ((t.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) { 764 log.error(pos, Errors.AbstractCantBeInstantiated(t.tsym)); 765 t = types.createErrorType(t); 766 } else if ((t.tsym.flags() & ENUM) != 0) { 767 log.error(pos, Errors.EnumCantBeInstantiated); 768 t = types.createErrorType(t); 769 } else { 770 t = checkClassType(pos, t, true); 771 } 772 } else if (t.hasTag(ARRAY)) { 773 if (!types.isReifiable(((ArrayType)t).elemtype)) { 774 log.error(pos, Errors.GenericArrayCreation); 775 t = types.createErrorType(t); 776 } 777 } 778 return t; 779 } 780 781 /** Check that type is a class or interface type. 782 * @param pos Position to be used for error reporting. 783 * @param t The type to be checked. 784 * @param noBounds True if type bounds are illegal here. 785 */ 786 Type checkClassType(DiagnosticPosition pos, Type t, boolean noBounds) { 787 t = checkClassType(pos, t); 788 if (noBounds && t.isParameterized()) { 789 List<Type> args = t.getTypeArguments(); 790 while (args.nonEmpty()) { 791 if (args.head.hasTag(WILDCARD)) 792 return typeTagError(pos, 793 diags.fragment(Fragments.TypeReqExact), 794 args.head); 795 args = args.tail; 796 } 797 } 798 return t; 799 } 800 801 /** Check that type is a reference type, i.e. a class, interface or array type 802 * or a type variable. 803 * @param pos Position to be used for error reporting. 804 * @param t The type to be checked. 805 */ 806 Type checkRefType(DiagnosticPosition pos, Type t) { 807 if (t.isReference()) 808 return t; 809 else 810 return typeTagError(pos, 811 diags.fragment(Fragments.TypeReqRef), 812 t); 813 } 814 815 /** Check that each type is a reference type, i.e. a class, interface or array type 816 * or a type variable. 817 * @param trees Original trees, used for error reporting. 818 * @param types The types to be checked. 819 */ 820 List<Type> checkRefTypes(List<JCExpression> trees, List<Type> types) { 821 List<JCExpression> tl = trees; 822 for (List<Type> l = types; l.nonEmpty(); l = l.tail) { 823 l.head = checkRefType(tl.head.pos(), l.head); 824 tl = tl.tail; 825 } 826 return types; 827 } 828 829 /** Check that type is a null or reference type. 830 * @param pos Position to be used for error reporting. 831 * @param t The type to be checked. 832 */ 833 Type checkNullOrRefType(DiagnosticPosition pos, Type t) { 834 if (t.isReference() || t.hasTag(BOT)) 835 return t; 836 else 837 return typeTagError(pos, 838 diags.fragment(Fragments.TypeReqRef), 839 t); 840 } 841 842 /** Check that flag set does not contain elements of two conflicting sets. s 843 * Return true if it doesn't. 844 * @param pos Position to be used for error reporting. 845 * @param flags The set of flags to be checked. 846 * @param set1 Conflicting flags set #1. 847 * @param set2 Conflicting flags set #2. 848 */ 849 boolean checkDisjoint(DiagnosticPosition pos, long flags, long set1, long set2) { 850 if ((flags & set1) != 0 && (flags & set2) != 0) { 851 log.error(pos, 852 Errors.IllegalCombinationOfModifiers(asFlagSet(TreeInfo.firstFlag(flags & set1)), 853 asFlagSet(TreeInfo.firstFlag(flags & set2)))); 854 return false; 855 } else 856 return true; 857 } 858 859 /** Check that usage of diamond operator is correct (i.e. diamond should not 860 * be used with non-generic classes or in anonymous class creation expressions) 861 */ 862 Type checkDiamond(JCNewClass tree, Type t) { 863 if (!TreeInfo.isDiamond(tree) || 864 t.isErroneous()) { 865 return checkClassType(tree.clazz.pos(), t, true); 866 } else { 867 if (tree.def != null && !Feature.DIAMOND_WITH_ANONYMOUS_CLASS_CREATION.allowedInSource(source)) { 868 log.error(DiagnosticFlag.SOURCE_LEVEL, tree.clazz.pos(), 869 Errors.CantApplyDiamond1(t, Feature.DIAMOND_WITH_ANONYMOUS_CLASS_CREATION.fragment(source.name))); 870 } 871 if (t.tsym.type.getTypeArguments().isEmpty()) { 872 log.error(tree.clazz.pos(), 873 Errors.CantApplyDiamond1(t, 874 Fragments.DiamondNonGeneric(t))); 875 return types.createErrorType(t); 876 } else if (tree.typeargs != null && 877 tree.typeargs.nonEmpty()) { 878 log.error(tree.clazz.pos(), 879 Errors.CantApplyDiamond1(t, 880 Fragments.DiamondAndExplicitParams(t))); 881 return types.createErrorType(t); 882 } else { 883 return t; 884 } 885 } 886 } 887 888 /** Check that the type inferred using the diamond operator does not contain 889 * non-denotable types such as captured types or intersection types. 890 * @param t the type inferred using the diamond operator 891 * @return the (possibly empty) list of non-denotable types. 892 */ 893 List<Type> checkDiamondDenotable(ClassType t) { 894 ListBuffer<Type> buf = new ListBuffer<>(); 895 for (Type arg : t.allparams()) { 896 if (!checkDenotable(arg)) { 897 buf.append(arg); 898 } 899 } 900 return buf.toList(); 901 } 902 903 public boolean checkDenotable(Type t) { 904 return denotableChecker.visit(t, null); 905 } 906 // where 907 908 /** diamondTypeChecker: A type visitor that descends down the given type looking for non-denotable 909 * types. The visit methods return false as soon as a non-denotable type is encountered and true 910 * otherwise. 911 */ 912 private static final Types.SimpleVisitor<Boolean, Void> denotableChecker = new Types.SimpleVisitor<Boolean, Void>() { 913 @Override 914 public Boolean visitType(Type t, Void s) { 915 return true; 916 } 917 @Override 918 public Boolean visitClassType(ClassType t, Void s) { 919 if (t.isUnion() || t.isIntersection()) { 920 return false; 921 } 922 for (Type targ : t.allparams()) { 923 if (!visit(targ, s)) { 924 return false; 925 } 926 } 927 return true; 928 } 929 930 @Override 931 public Boolean visitTypeVar(TypeVar t, Void s) { 932 /* Any type variable mentioned in the inferred type must have been declared as a type parameter 933 (i.e cannot have been produced by inference (18.4)) 934 */ 935 return (t.tsym.flags() & SYNTHETIC) == 0; 936 } 937 938 @Override 939 public Boolean visitCapturedType(CapturedType t, Void s) { 940 /* Any type variable mentioned in the inferred type must have been declared as a type parameter 941 (i.e cannot have been produced by capture conversion (5.1.10)) 942 */ 943 return false; 944 } 945 946 @Override 947 public Boolean visitArrayType(ArrayType t, Void s) { 948 return visit(t.elemtype, s); 949 } 950 951 @Override 952 public Boolean visitWildcardType(WildcardType t, Void s) { 953 return visit(t.type, s); 954 } 955 }; 956 957 void checkVarargsMethodDecl(Env<AttrContext> env, JCMethodDecl tree) { 958 MethodSymbol m = tree.sym; 959 boolean hasTrustMeAnno = m.attribute(syms.trustMeType.tsym) != null; 960 Type varargElemType = null; 961 if (m.isVarArgs()) { 962 varargElemType = types.elemtype(tree.params.last().type); 963 } 964 if (hasTrustMeAnno && !isTrustMeAllowedOnMethod(m)) { 965 if (varargElemType != null) { 966 JCDiagnostic msg = Feature.PRIVATE_SAFE_VARARGS.allowedInSource(source) ? 967 diags.fragment(Fragments.VarargsTrustmeOnVirtualVarargs(m)) : 968 diags.fragment(Fragments.VarargsTrustmeOnVirtualVarargsFinalOnly(m)); 969 log.error(tree, 970 Errors.VarargsInvalidTrustmeAnno(syms.trustMeType.tsym, 971 msg)); 972 } else { 973 log.error(tree, 974 Errors.VarargsInvalidTrustmeAnno(syms.trustMeType.tsym, 975 Fragments.VarargsTrustmeOnNonVarargsMeth(m))); 976 } 977 } else if (hasTrustMeAnno && varargElemType != null && 978 types.isReifiable(varargElemType)) { 979 warnUnsafeVararg(tree, Warnings.VarargsRedundantTrustmeAnno( 980 syms.trustMeType.tsym, 981 diags.fragment(Fragments.VarargsTrustmeOnReifiableVarargs(varargElemType)))); 982 } 983 else if (!hasTrustMeAnno && varargElemType != null && 984 !types.isReifiable(varargElemType)) { 985 warnUnchecked(tree.params.head.pos(), Warnings.UncheckedVarargsNonReifiableType(varargElemType)); 986 } 987 } 988 //where 989 private boolean isTrustMeAllowedOnMethod(Symbol s) { 990 return (s.flags() & VARARGS) != 0 && 991 (s.isConstructor() || 992 (s.flags() & (STATIC | FINAL | 993 (Feature.PRIVATE_SAFE_VARARGS.allowedInSource(source) ? PRIVATE : 0) )) != 0); 994 } 995 996 Type checkLocalVarType(DiagnosticPosition pos, Type t, Name name) { 997 //check that resulting type is not the null type 998 if (t.hasTag(BOT)) { 999 log.error(pos, Errors.CantInferLocalVarType(name, Fragments.LocalCantInferNull)); 1000 return types.createErrorType(t); 1001 } else if (t.hasTag(VOID)) { 1002 log.error(pos, Errors.CantInferLocalVarType(name, Fragments.LocalCantInferVoid)); 1003 return types.createErrorType(t); 1004 } 1005 1006 //upward project the initializer type 1007 return types.upward(t, types.captures(t)).baseType(); 1008 } 1009 1010 Type checkMethod(final Type mtype, 1011 final Symbol sym, 1012 final Env<AttrContext> env, 1013 final List<JCExpression> argtrees, 1014 final List<Type> argtypes, 1015 final boolean useVarargs, 1016 InferenceContext inferenceContext) { 1017 // System.out.println("call : " + env.tree); 1018 // System.out.println("method : " + owntype); 1019 // System.out.println("actuals: " + argtypes); 1020 if (inferenceContext.free(mtype)) { 1021 inferenceContext.addFreeTypeListener(List.of(mtype), 1022 solvedContext -> checkMethod(solvedContext.asInstType(mtype), sym, env, argtrees, argtypes, useVarargs, solvedContext)); 1023 return mtype; 1024 } 1025 Type owntype = mtype; 1026 List<Type> formals = owntype.getParameterTypes(); 1027 List<Type> nonInferred = sym.type.getParameterTypes(); 1028 if (nonInferred.length() != formals.length()) nonInferred = formals; 1029 Type last = useVarargs ? formals.last() : null; 1030 if (sym.name == names.init && sym.owner == syms.enumSym) { 1031 formals = formals.tail.tail; 1032 nonInferred = nonInferred.tail.tail; 1033 } 1034 if ((sym.flags() & ANONCONSTR_BASED) != 0) { 1035 formals = formals.tail; 1036 nonInferred = nonInferred.tail; 1037 } 1038 List<JCExpression> args = argtrees; 1039 if (args != null) { 1040 //this is null when type-checking a method reference 1041 while (formals.head != last) { 1042 JCTree arg = args.head; 1043 Warner warn = convertWarner(arg.pos(), arg.type, nonInferred.head); 1044 assertConvertible(arg, arg.type, formals.head, warn); 1045 args = args.tail; 1046 formals = formals.tail; 1047 nonInferred = nonInferred.tail; 1048 } 1049 if (useVarargs) { 1050 Type varArg = types.elemtype(last); 1051 while (args.tail != null) { 1052 JCTree arg = args.head; 1053 Warner warn = convertWarner(arg.pos(), arg.type, varArg); 1054 assertConvertible(arg, arg.type, varArg, warn); 1055 args = args.tail; 1056 } 1057 } else if ((sym.flags() & (VARARGS | SIGNATURE_POLYMORPHIC)) == VARARGS) { 1058 // non-varargs call to varargs method 1059 Type varParam = owntype.getParameterTypes().last(); 1060 Type lastArg = argtypes.last(); 1061 if (types.isSubtypeUnchecked(lastArg, types.elemtype(varParam)) && 1062 !types.isSameType(types.erasure(varParam), types.erasure(lastArg))) 1063 log.warning(argtrees.last().pos(), 1064 Warnings.InexactNonVarargsCall(types.elemtype(varParam),varParam)); 1065 } 1066 } 1067 if (useVarargs) { 1068 Type argtype = owntype.getParameterTypes().last(); 1069 if (!types.isReifiable(argtype) && 1070 (sym.baseSymbol().attribute(syms.trustMeType.tsym) == null || 1071 !isTrustMeAllowedOnMethod(sym))) { 1072 warnUnchecked(env.tree.pos(), Warnings.UncheckedGenericArrayCreation(argtype)); 1073 } 1074 TreeInfo.setVarargsElement(env.tree, types.elemtype(argtype)); 1075 } 1076 return owntype; 1077 } 1078 //where 1079 private void assertConvertible(JCTree tree, Type actual, Type formal, Warner warn) { 1080 if (types.isConvertible(actual, formal, warn)) 1081 return; 1082 1083 if (formal.isCompound() 1084 && types.isSubtype(actual, types.supertype(formal)) 1085 && types.isSubtypeUnchecked(actual, types.interfaces(formal), warn)) 1086 return; 1087 } 1088 1089 /** 1090 * Check that type 't' is a valid instantiation of a generic class 1091 * (see JLS 4.5) 1092 * 1093 * @param t class type to be checked 1094 * @return true if 't' is well-formed 1095 */ 1096 public boolean checkValidGenericType(Type t) { 1097 return firstIncompatibleTypeArg(t) == null; 1098 } 1099 //WHERE 1100 private Type firstIncompatibleTypeArg(Type type) { 1101 List<Type> formals = type.tsym.type.allparams(); 1102 List<Type> actuals = type.allparams(); 1103 List<Type> args = type.getTypeArguments(); 1104 List<Type> forms = type.tsym.type.getTypeArguments(); 1105 ListBuffer<Type> bounds_buf = new ListBuffer<>(); 1106 1107 // For matching pairs of actual argument types `a' and 1108 // formal type parameters with declared bound `b' ... 1109 while (args.nonEmpty() && forms.nonEmpty()) { 1110 // exact type arguments needs to know their 1111 // bounds (for upper and lower bound 1112 // calculations). So we create new bounds where 1113 // type-parameters are replaced with actuals argument types. 1114 bounds_buf.append(types.subst(forms.head.getUpperBound(), formals, actuals)); 1115 args = args.tail; 1116 forms = forms.tail; 1117 } 1118 1119 args = type.getTypeArguments(); 1120 List<Type> tvars_cap = types.substBounds(formals, 1121 formals, 1122 types.capture(type).allparams()); 1123 while (args.nonEmpty() && tvars_cap.nonEmpty()) { 1124 // Let the actual arguments know their bound 1125 args.head.withTypeVar((TypeVar)tvars_cap.head); 1126 args = args.tail; 1127 tvars_cap = tvars_cap.tail; 1128 } 1129 1130 args = type.getTypeArguments(); 1131 List<Type> bounds = bounds_buf.toList(); 1132 1133 while (args.nonEmpty() && bounds.nonEmpty()) { 1134 Type actual = args.head; 1135 if (!isTypeArgErroneous(actual) && 1136 !bounds.head.isErroneous() && 1137 !checkExtends(actual, bounds.head)) { 1138 return args.head; 1139 } 1140 args = args.tail; 1141 bounds = bounds.tail; 1142 } 1143 1144 args = type.getTypeArguments(); 1145 bounds = bounds_buf.toList(); 1146 1147 for (Type arg : types.capture(type).getTypeArguments()) { 1148 if (arg.hasTag(TYPEVAR) && 1149 arg.getUpperBound().isErroneous() && 1150 !bounds.head.isErroneous() && 1151 !isTypeArgErroneous(args.head)) { 1152 return args.head; 1153 } 1154 bounds = bounds.tail; 1155 args = args.tail; 1156 } 1157 1158 return null; 1159 } 1160 //where 1161 boolean isTypeArgErroneous(Type t) { 1162 return isTypeArgErroneous.visit(t); 1163 } 1164 1165 Types.UnaryVisitor<Boolean> isTypeArgErroneous = new Types.UnaryVisitor<Boolean>() { 1166 public Boolean visitType(Type t, Void s) { 1167 return t.isErroneous(); 1168 } 1169 @Override 1170 public Boolean visitTypeVar(TypeVar t, Void s) { 1171 return visit(t.getUpperBound()); 1172 } 1173 @Override 1174 public Boolean visitCapturedType(CapturedType t, Void s) { 1175 return visit(t.getUpperBound()) || 1176 visit(t.getLowerBound()); 1177 } 1178 @Override 1179 public Boolean visitWildcardType(WildcardType t, Void s) { 1180 return visit(t.type); 1181 } 1182 }; 1183 1184 /** Check that given modifiers are legal for given symbol and 1185 * return modifiers together with any implicit modifiers for that symbol. 1186 * Warning: we can't use flags() here since this method 1187 * is called during class enter, when flags() would cause a premature 1188 * completion. 1189 * @param pos Position to be used for error reporting. 1190 * @param flags The set of modifiers given in a definition. 1191 * @param sym The defined symbol. 1192 */ 1193 long checkFlags(DiagnosticPosition pos, long flags, Symbol sym, JCTree tree) { 1194 long mask; 1195 long implicit = 0; 1196 1197 switch (sym.kind) { 1198 case VAR: 1199 if (TreeInfo.isReceiverParam(tree)) 1200 mask = ReceiverParamFlags; 1201 else if (sym.owner.kind != TYP) 1202 mask = LocalVarFlags; 1203 else if ((sym.owner.flags_field & INTERFACE) != 0) 1204 mask = implicit = InterfaceVarFlags; 1205 else 1206 mask = VarFlags; 1207 break; 1208 case MTH: 1209 if (sym.name == names.init) { 1210 if ((sym.owner.flags_field & ENUM) != 0) { 1211 // enum constructors cannot be declared public or 1212 // protected and must be implicitly or explicitly 1213 // private 1214 implicit = PRIVATE; 1215 mask = PRIVATE; 1216 } else 1217 mask = ConstructorFlags; 1218 } else if ((sym.owner.flags_field & INTERFACE) != 0) { 1219 if ((sym.owner.flags_field & ANNOTATION) != 0) { 1220 mask = AnnotationTypeElementMask; 1221 implicit = PUBLIC | ABSTRACT; 1222 } else if ((flags & (DEFAULT | STATIC | PRIVATE)) != 0) { 1223 mask = InterfaceMethodMask; 1224 implicit = (flags & PRIVATE) != 0 ? 0 : PUBLIC; 1225 if ((flags & DEFAULT) != 0) { 1226 implicit |= ABSTRACT; 1227 } 1228 } else { 1229 mask = implicit = InterfaceMethodFlags; 1230 } 1231 } else if ((sym.owner.flags_field & RECORD) != 0) { 1232 mask = RecordMethodFlags; 1233 } else { 1234 mask = MethodFlags; 1235 } 1236 if ((flags & STRICTFP) != 0) { 1237 warnOnExplicitStrictfp(pos); 1238 } 1239 // Imply STRICTFP if owner has STRICTFP set. 1240 if (((flags|implicit) & Flags.ABSTRACT) == 0 || 1241 ((flags) & Flags.DEFAULT) != 0) 1242 implicit |= sym.owner.flags_field & STRICTFP; 1243 break; 1244 case TYP: 1245 if (sym.owner.kind.matches(KindSelector.VAL_MTH) || 1246 (sym.isDirectlyOrIndirectlyLocal() && (flags & ANNOTATION) != 0)) { 1247 boolean implicitlyStatic = !sym.isAnonymous() && 1248 ((flags & RECORD) != 0 || (flags & ENUM) != 0 || (flags & INTERFACE) != 0); 1249 boolean staticOrImplicitlyStatic = (flags & STATIC) != 0 || implicitlyStatic; 1250 // local statics are allowed only if records are allowed too 1251 mask = staticOrImplicitlyStatic && allowRecords && (flags & ANNOTATION) == 0 ? StaticLocalFlags : LocalClassFlags; 1252 implicit = implicitlyStatic ? STATIC : implicit; 1253 } else if (sym.owner.kind == TYP) { 1254 // statics in inner classes are allowed only if records are allowed too 1255 mask = ((flags & STATIC) != 0) && allowRecords && (flags & ANNOTATION) == 0 ? ExtendedMemberStaticClassFlags : ExtendedMemberClassFlags; 1256 if (sym.owner.owner.kind == PCK || 1257 (sym.owner.flags_field & STATIC) != 0) { 1258 mask |= STATIC; 1259 } else if (!allowRecords && ((flags & ENUM) != 0 || (flags & RECORD) != 0)) { 1260 log.error(pos, Errors.StaticDeclarationNotAllowedInInnerClasses); 1261 } 1262 // Nested interfaces and enums are always STATIC (Spec ???) 1263 if ((flags & (INTERFACE | ENUM | RECORD)) != 0 ) implicit = STATIC; 1264 } else { 1265 mask = ExtendedClassFlags; 1266 } 1267 // Interfaces are always ABSTRACT 1268 if ((flags & INTERFACE) != 0) implicit |= ABSTRACT; 1269 1270 if ((flags & ENUM) != 0) { 1271 // enums can't be declared abstract, final, sealed or non-sealed 1272 mask &= ~(ABSTRACT | FINAL | SEALED | NON_SEALED); 1273 implicit |= implicitEnumFinalFlag(tree); 1274 } 1275 if ((flags & RECORD) != 0) { 1276 // records can't be declared abstract 1277 mask &= ~ABSTRACT; 1278 implicit |= FINAL; 1279 } 1280 if ((flags & STRICTFP) != 0) { 1281 warnOnExplicitStrictfp(pos); 1282 } 1283 // Imply STRICTFP if owner has STRICTFP set. 1284 implicit |= sym.owner.flags_field & STRICTFP; 1285 break; 1286 default: 1287 throw new AssertionError(); 1288 } 1289 long illegal = flags & ExtendedStandardFlags & ~mask; 1290 if (illegal != 0) { 1291 if ((illegal & INTERFACE) != 0) { 1292 log.error(pos, ((flags & ANNOTATION) != 0) ? Errors.AnnotationDeclNotAllowedHere : Errors.IntfNotAllowedHere); 1293 mask |= INTERFACE; 1294 } 1295 else { 1296 log.error(pos, 1297 Errors.ModNotAllowedHere(asFlagSet(illegal))); 1298 } 1299 } 1300 else if ((sym.kind == TYP || 1301 // ISSUE: Disallowing abstract&private is no longer appropriate 1302 // in the presence of inner classes. Should it be deleted here? 1303 checkDisjoint(pos, flags, 1304 ABSTRACT, 1305 PRIVATE | STATIC | DEFAULT)) 1306 && 1307 checkDisjoint(pos, flags, 1308 STATIC | PRIVATE, 1309 DEFAULT) 1310 && 1311 checkDisjoint(pos, flags, 1312 ABSTRACT | INTERFACE, 1313 FINAL | NATIVE | SYNCHRONIZED) 1314 && 1315 checkDisjoint(pos, flags, 1316 PUBLIC, 1317 PRIVATE | PROTECTED) 1318 && 1319 checkDisjoint(pos, flags, 1320 PRIVATE, 1321 PUBLIC | PROTECTED) 1322 && 1323 checkDisjoint(pos, flags, 1324 FINAL, 1325 VOLATILE) 1326 && 1327 (sym.kind == TYP || 1328 checkDisjoint(pos, flags, 1329 ABSTRACT | NATIVE, 1330 STRICTFP)) 1331 && checkDisjoint(pos, flags, 1332 FINAL, 1333 SEALED | NON_SEALED) 1334 && checkDisjoint(pos, flags, 1335 SEALED, 1336 FINAL | NON_SEALED) 1337 && checkDisjoint(pos, flags, 1338 SEALED, 1339 ANNOTATION)) { 1340 // skip 1341 } 1342 return flags & (mask | ~ExtendedStandardFlags) | implicit; 1343 } 1344 1345 private void warnOnExplicitStrictfp(DiagnosticPosition pos) { 1346 DiagnosticPosition prevLintPos = deferredLintHandler.setPos(pos); 1347 try { 1348 deferredLintHandler.report(() -> { 1349 if (lint.isEnabled(LintCategory.STRICTFP)) { 1350 log.warning(LintCategory.STRICTFP, 1351 pos, Warnings.Strictfp); } 1352 }); 1353 } finally { 1354 deferredLintHandler.setPos(prevLintPos); 1355 } 1356 } 1357 1358 1359 /** Determine if this enum should be implicitly final. 1360 * 1361 * If the enum has no specialized enum constants, it is final. 1362 * 1363 * If the enum does have specialized enum constants, it is 1364 * <i>not</i> final. 1365 */ 1366 private long implicitEnumFinalFlag(JCTree tree) { 1367 if (!tree.hasTag(CLASSDEF)) return 0; 1368 class SpecialTreeVisitor extends JCTree.Visitor { 1369 boolean specialized; 1370 SpecialTreeVisitor() { 1371 this.specialized = false; 1372 } 1373 1374 @Override 1375 public void visitTree(JCTree tree) { /* no-op */ } 1376 1377 @Override 1378 public void visitVarDef(JCVariableDecl tree) { 1379 if ((tree.mods.flags & ENUM) != 0) { 1380 if (tree.init instanceof JCNewClass newClass && newClass.def != null) { 1381 specialized = true; 1382 } 1383 } 1384 } 1385 } 1386 1387 SpecialTreeVisitor sts = new SpecialTreeVisitor(); 1388 JCClassDecl cdef = (JCClassDecl) tree; 1389 for (JCTree defs: cdef.defs) { 1390 defs.accept(sts); 1391 if (sts.specialized) return allowSealed ? SEALED : 0; 1392 } 1393 return FINAL; 1394 } 1395 1396 /* ************************************************************************* 1397 * Type Validation 1398 **************************************************************************/ 1399 1400 /** Validate a type expression. That is, 1401 * check that all type arguments of a parametric type are within 1402 * their bounds. This must be done in a second phase after type attribution 1403 * since a class might have a subclass as type parameter bound. E.g: 1404 * 1405 * <pre>{@code 1406 * class B<A extends C> { ... } 1407 * class C extends B<C> { ... } 1408 * }</pre> 1409 * 1410 * and we can't make sure that the bound is already attributed because 1411 * of possible cycles. 1412 * 1413 * Visitor method: Validate a type expression, if it is not null, catching 1414 * and reporting any completion failures. 1415 */ 1416 void validate(JCTree tree, Env<AttrContext> env) { 1417 validate(tree, env, true); 1418 } 1419 void validate(JCTree tree, Env<AttrContext> env, boolean checkRaw) { 1420 new Validator(env).validateTree(tree, checkRaw, true); 1421 } 1422 1423 /** Visitor method: Validate a list of type expressions. 1424 */ 1425 void validate(List<? extends JCTree> trees, Env<AttrContext> env) { 1426 for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) 1427 validate(l.head, env); 1428 } 1429 1430 /** A visitor class for type validation. 1431 */ 1432 class Validator extends JCTree.Visitor { 1433 1434 boolean checkRaw; 1435 boolean isOuter; 1436 Env<AttrContext> env; 1437 1438 Validator(Env<AttrContext> env) { 1439 this.env = env; 1440 } 1441 1442 @Override 1443 public void visitTypeArray(JCArrayTypeTree tree) { 1444 validateTree(tree.elemtype, checkRaw, isOuter); 1445 } 1446 1447 @Override 1448 public void visitTypeApply(JCTypeApply tree) { 1449 if (tree.type.hasTag(CLASS)) { 1450 List<JCExpression> args = tree.arguments; 1451 List<Type> forms = tree.type.tsym.type.getTypeArguments(); 1452 1453 Type incompatibleArg = firstIncompatibleTypeArg(tree.type); 1454 if (incompatibleArg != null) { 1455 for (JCTree arg : tree.arguments) { 1456 if (arg.type == incompatibleArg) { 1457 log.error(arg, Errors.NotWithinBounds(incompatibleArg, forms.head)); 1458 } 1459 forms = forms.tail; 1460 } 1461 } 1462 1463 forms = tree.type.tsym.type.getTypeArguments(); 1464 1465 boolean is_java_lang_Class = tree.type.tsym.flatName() == names.java_lang_Class; 1466 1467 // For matching pairs of actual argument types `a' and 1468 // formal type parameters with declared bound `b' ... 1469 while (args.nonEmpty() && forms.nonEmpty()) { 1470 validateTree(args.head, 1471 !(isOuter && is_java_lang_Class), 1472 false); 1473 args = args.tail; 1474 forms = forms.tail; 1475 } 1476 1477 // Check that this type is either fully parameterized, or 1478 // not parameterized at all. 1479 if (tree.type.getEnclosingType().isRaw()) 1480 log.error(tree.pos(), Errors.ImproperlyFormedTypeInnerRawParam); 1481 if (tree.clazz.hasTag(SELECT)) 1482 visitSelectInternal((JCFieldAccess)tree.clazz); 1483 } 1484 } 1485 1486 @Override 1487 public void visitTypeParameter(JCTypeParameter tree) { 1488 validateTrees(tree.bounds, true, isOuter); 1489 checkClassBounds(tree.pos(), tree.type); 1490 } 1491 1492 @Override 1493 public void visitWildcard(JCWildcard tree) { 1494 if (tree.inner != null) 1495 validateTree(tree.inner, true, isOuter); 1496 } 1497 1498 @Override 1499 public void visitSelect(JCFieldAccess tree) { 1500 if (tree.type.hasTag(CLASS)) { 1501 visitSelectInternal(tree); 1502 1503 // Check that this type is either fully parameterized, or 1504 // not parameterized at all. 1505 if (tree.selected.type.isParameterized() && tree.type.tsym.type.getTypeArguments().nonEmpty()) 1506 log.error(tree.pos(), Errors.ImproperlyFormedTypeParamMissing); 1507 } 1508 } 1509 1510 public void visitSelectInternal(JCFieldAccess tree) { 1511 if (tree.type.tsym.isStatic() && 1512 tree.selected.type.isParameterized()) { 1513 // The enclosing type is not a class, so we are 1514 // looking at a static member type. However, the 1515 // qualifying expression is parameterized. 1516 log.error(tree.pos(), Errors.CantSelectStaticClassFromParamType); 1517 } else { 1518 // otherwise validate the rest of the expression 1519 tree.selected.accept(this); 1520 } 1521 } 1522 1523 @Override 1524 public void visitAnnotatedType(JCAnnotatedType tree) { 1525 tree.underlyingType.accept(this); 1526 } 1527 1528 @Override 1529 public void visitTypeIdent(JCPrimitiveTypeTree that) { 1530 if (that.type.hasTag(TypeTag.VOID)) { 1531 log.error(that.pos(), Errors.VoidNotAllowedHere); 1532 } 1533 super.visitTypeIdent(that); 1534 } 1535 1536 /** Default visitor method: do nothing. 1537 */ 1538 @Override 1539 public void visitTree(JCTree tree) { 1540 } 1541 1542 public void validateTree(JCTree tree, boolean checkRaw, boolean isOuter) { 1543 if (tree != null) { 1544 boolean prevCheckRaw = this.checkRaw; 1545 this.checkRaw = checkRaw; 1546 this.isOuter = isOuter; 1547 1548 try { 1549 tree.accept(this); 1550 if (checkRaw) 1551 checkRaw(tree, env); 1552 } catch (CompletionFailure ex) { 1553 completionError(tree.pos(), ex); 1554 } finally { 1555 this.checkRaw = prevCheckRaw; 1556 } 1557 } 1558 } 1559 1560 public void validateTrees(List<? extends JCTree> trees, boolean checkRaw, boolean isOuter) { 1561 for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) 1562 validateTree(l.head, checkRaw, isOuter); 1563 } 1564 } 1565 1566 void checkRaw(JCTree tree, Env<AttrContext> env) { 1567 if (lint.isEnabled(LintCategory.RAW) && 1568 tree.type.hasTag(CLASS) && 1569 !TreeInfo.isDiamond(tree) && 1570 !withinAnonConstr(env) && 1571 tree.type.isRaw()) { 1572 log.warning(LintCategory.RAW, 1573 tree.pos(), Warnings.RawClassUse(tree.type, tree.type.tsym.type)); 1574 } 1575 } 1576 //where 1577 private boolean withinAnonConstr(Env<AttrContext> env) { 1578 return env.enclClass.name.isEmpty() && 1579 env.enclMethod != null && env.enclMethod.name == names.init; 1580 } 1581 1582 /* ************************************************************************* 1583 * Exception checking 1584 **************************************************************************/ 1585 1586 /* The following methods treat classes as sets that contain 1587 * the class itself and all their subclasses 1588 */ 1589 1590 /** Is given type a subtype of some of the types in given list? 1591 */ 1592 boolean subset(Type t, List<Type> ts) { 1593 for (List<Type> l = ts; l.nonEmpty(); l = l.tail) 1594 if (types.isSubtype(t, l.head)) return true; 1595 return false; 1596 } 1597 1598 /** Is given type a subtype or supertype of 1599 * some of the types in given list? 1600 */ 1601 boolean intersects(Type t, List<Type> ts) { 1602 for (List<Type> l = ts; l.nonEmpty(); l = l.tail) 1603 if (types.isSubtype(t, l.head) || types.isSubtype(l.head, t)) return true; 1604 return false; 1605 } 1606 1607 /** Add type set to given type list, unless it is a subclass of some class 1608 * in the list. 1609 */ 1610 List<Type> incl(Type t, List<Type> ts) { 1611 return subset(t, ts) ? ts : excl(t, ts).prepend(t); 1612 } 1613 1614 /** Remove type set from type set list. 1615 */ 1616 List<Type> excl(Type t, List<Type> ts) { 1617 if (ts.isEmpty()) { 1618 return ts; 1619 } else { 1620 List<Type> ts1 = excl(t, ts.tail); 1621 if (types.isSubtype(ts.head, t)) return ts1; 1622 else if (ts1 == ts.tail) return ts; 1623 else return ts1.prepend(ts.head); 1624 } 1625 } 1626 1627 /** Form the union of two type set lists. 1628 */ 1629 List<Type> union(List<Type> ts1, List<Type> ts2) { 1630 List<Type> ts = ts1; 1631 for (List<Type> l = ts2; l.nonEmpty(); l = l.tail) 1632 ts = incl(l.head, ts); 1633 return ts; 1634 } 1635 1636 /** Form the difference of two type lists. 1637 */ 1638 List<Type> diff(List<Type> ts1, List<Type> ts2) { 1639 List<Type> ts = ts1; 1640 for (List<Type> l = ts2; l.nonEmpty(); l = l.tail) 1641 ts = excl(l.head, ts); 1642 return ts; 1643 } 1644 1645 /** Form the intersection of two type lists. 1646 */ 1647 public List<Type> intersect(List<Type> ts1, List<Type> ts2) { 1648 List<Type> ts = List.nil(); 1649 for (List<Type> l = ts1; l.nonEmpty(); l = l.tail) 1650 if (subset(l.head, ts2)) ts = incl(l.head, ts); 1651 for (List<Type> l = ts2; l.nonEmpty(); l = l.tail) 1652 if (subset(l.head, ts1)) ts = incl(l.head, ts); 1653 return ts; 1654 } 1655 1656 /** Is exc an exception symbol that need not be declared? 1657 */ 1658 boolean isUnchecked(ClassSymbol exc) { 1659 return 1660 exc.kind == ERR || 1661 exc.isSubClass(syms.errorType.tsym, types) || 1662 exc.isSubClass(syms.runtimeExceptionType.tsym, types); 1663 } 1664 1665 /** Is exc an exception type that need not be declared? 1666 */ 1667 boolean isUnchecked(Type exc) { 1668 return 1669 (exc.hasTag(TYPEVAR)) ? isUnchecked(types.supertype(exc)) : 1670 (exc.hasTag(CLASS)) ? isUnchecked((ClassSymbol)exc.tsym) : 1671 exc.hasTag(BOT); 1672 } 1673 1674 boolean isChecked(Type exc) { 1675 return !isUnchecked(exc); 1676 } 1677 1678 /** Same, but handling completion failures. 1679 */ 1680 boolean isUnchecked(DiagnosticPosition pos, Type exc) { 1681 try { 1682 return isUnchecked(exc); 1683 } catch (CompletionFailure ex) { 1684 completionError(pos, ex); 1685 return true; 1686 } 1687 } 1688 1689 /** Is exc handled by given exception list? 1690 */ 1691 boolean isHandled(Type exc, List<Type> handled) { 1692 return isUnchecked(exc) || subset(exc, handled); 1693 } 1694 1695 /** Return all exceptions in thrown list that are not in handled list. 1696 * @param thrown The list of thrown exceptions. 1697 * @param handled The list of handled exceptions. 1698 */ 1699 List<Type> unhandled(List<Type> thrown, List<Type> handled) { 1700 List<Type> unhandled = List.nil(); 1701 for (List<Type> l = thrown; l.nonEmpty(); l = l.tail) 1702 if (!isHandled(l.head, handled)) unhandled = unhandled.prepend(l.head); 1703 return unhandled; 1704 } 1705 1706 /* ************************************************************************* 1707 * Overriding/Implementation checking 1708 **************************************************************************/ 1709 1710 /** The level of access protection given by a flag set, 1711 * where PRIVATE is highest and PUBLIC is lowest. 1712 */ 1713 static int protection(long flags) { 1714 switch ((short)(flags & AccessFlags)) { 1715 case PRIVATE: return 3; 1716 case PROTECTED: return 1; 1717 default: 1718 case PUBLIC: return 0; 1719 case 0: return 2; 1720 } 1721 } 1722 1723 /** A customized "cannot override" error message. 1724 * @param m The overriding method. 1725 * @param other The overridden method. 1726 * @return An internationalized string. 1727 */ 1728 Fragment cannotOverride(MethodSymbol m, MethodSymbol other) { 1729 Symbol mloc = m.location(); 1730 Symbol oloc = other.location(); 1731 1732 if ((other.owner.flags() & INTERFACE) == 0) 1733 return Fragments.CantOverride(m, mloc, other, oloc); 1734 else if ((m.owner.flags() & INTERFACE) == 0) 1735 return Fragments.CantImplement(m, mloc, other, oloc); 1736 else 1737 return Fragments.ClashesWith(m, mloc, other, oloc); 1738 } 1739 1740 /** A customized "override" warning message. 1741 * @param m The overriding method. 1742 * @param other The overridden method. 1743 * @return An internationalized string. 1744 */ 1745 Fragment uncheckedOverrides(MethodSymbol m, MethodSymbol other) { 1746 Symbol mloc = m.location(); 1747 Symbol oloc = other.location(); 1748 1749 if ((other.owner.flags() & INTERFACE) == 0) 1750 return Fragments.UncheckedOverride(m, mloc, other, oloc); 1751 else if ((m.owner.flags() & INTERFACE) == 0) 1752 return Fragments.UncheckedImplement(m, mloc, other, oloc); 1753 else 1754 return Fragments.UncheckedClashWith(m, mloc, other, oloc); 1755 } 1756 1757 /** A customized "override" warning message. 1758 * @param m The overriding method. 1759 * @param other The overridden method. 1760 * @return An internationalized string. 1761 */ 1762 Fragment varargsOverrides(MethodSymbol m, MethodSymbol other) { 1763 Symbol mloc = m.location(); 1764 Symbol oloc = other.location(); 1765 1766 if ((other.owner.flags() & INTERFACE) == 0) 1767 return Fragments.VarargsOverride(m, mloc, other, oloc); 1768 else if ((m.owner.flags() & INTERFACE) == 0) 1769 return Fragments.VarargsImplement(m, mloc, other, oloc); 1770 else 1771 return Fragments.VarargsClashWith(m, mloc, other, oloc); 1772 } 1773 1774 /** Check that this method conforms with overridden method 'other'. 1775 * where `origin' is the class where checking started. 1776 * Complications: 1777 * (1) Do not check overriding of synthetic methods 1778 * (reason: they might be final). 1779 * todo: check whether this is still necessary. 1780 * (2) Admit the case where an interface proxy throws fewer exceptions 1781 * than the method it implements. Augment the proxy methods with the 1782 * undeclared exceptions in this case. 1783 * (3) When generics are enabled, admit the case where an interface proxy 1784 * has a result type 1785 * extended by the result type of the method it implements. 1786 * Change the proxies result type to the smaller type in this case. 1787 * 1788 * @param tree The tree from which positions 1789 * are extracted for errors. 1790 * @param m The overriding method. 1791 * @param other The overridden method. 1792 * @param origin The class of which the overriding method 1793 * is a member. 1794 */ 1795 void checkOverride(JCTree tree, 1796 MethodSymbol m, 1797 MethodSymbol other, 1798 ClassSymbol origin) { 1799 // Don't check overriding of synthetic methods or by bridge methods. 1800 if ((m.flags() & (SYNTHETIC|BRIDGE)) != 0 || (other.flags() & SYNTHETIC) != 0) { 1801 return; 1802 } 1803 1804 // Error if static method overrides instance method (JLS 8.4.8.2). 1805 if ((m.flags() & STATIC) != 0 && 1806 (other.flags() & STATIC) == 0) { 1807 log.error(TreeInfo.diagnosticPositionFor(m, tree), 1808 Errors.OverrideStatic(cannotOverride(m, other))); 1809 m.flags_field |= BAD_OVERRIDE; 1810 return; 1811 } 1812 1813 // Error if instance method overrides static or final 1814 // method (JLS 8.4.8.1). 1815 if ((other.flags() & FINAL) != 0 || 1816 (m.flags() & STATIC) == 0 && 1817 (other.flags() & STATIC) != 0) { 1818 log.error(TreeInfo.diagnosticPositionFor(m, tree), 1819 Errors.OverrideMeth(cannotOverride(m, other), 1820 asFlagSet(other.flags() & (FINAL | STATIC)))); 1821 m.flags_field |= BAD_OVERRIDE; 1822 return; 1823 } 1824 1825 if ((m.owner.flags() & ANNOTATION) != 0) { 1826 // handled in validateAnnotationMethod 1827 return; 1828 } 1829 1830 // Error if overriding method has weaker access (JLS 8.4.8.3). 1831 if (protection(m.flags()) > protection(other.flags())) { 1832 log.error(TreeInfo.diagnosticPositionFor(m, tree), 1833 (other.flags() & AccessFlags) == 0 ? 1834 Errors.OverrideWeakerAccess(cannotOverride(m, other), 1835 "package") : 1836 Errors.OverrideWeakerAccess(cannotOverride(m, other), 1837 asFlagSet(other.flags() & AccessFlags))); 1838 m.flags_field |= BAD_OVERRIDE; 1839 return; 1840 } 1841 1842 if (shouldCheckPreview(m, other, origin)) { 1843 checkPreview(tree.pos(), m, other); 1844 } 1845 1846 Type mt = types.memberType(origin.type, m); 1847 Type ot = types.memberType(origin.type, other); 1848 // Error if overriding result type is different 1849 // (or, in the case of generics mode, not a subtype) of 1850 // overridden result type. We have to rename any type parameters 1851 // before comparing types. 1852 List<Type> mtvars = mt.getTypeArguments(); 1853 List<Type> otvars = ot.getTypeArguments(); 1854 Type mtres = mt.getReturnType(); 1855 Type otres = types.subst(ot.getReturnType(), otvars, mtvars); 1856 1857 overrideWarner.clear(); 1858 boolean resultTypesOK = 1859 types.returnTypeSubstitutable(mt, ot, otres, overrideWarner); 1860 if (!resultTypesOK) { 1861 if ((m.flags() & STATIC) != 0 && (other.flags() & STATIC) != 0) { 1862 log.error(TreeInfo.diagnosticPositionFor(m, tree), 1863 Errors.OverrideIncompatibleRet(Fragments.CantHide(m, m.location(), other, 1864 other.location()), mtres, otres)); 1865 m.flags_field |= BAD_OVERRIDE; 1866 } else { 1867 log.error(TreeInfo.diagnosticPositionFor(m, tree), 1868 Errors.OverrideIncompatibleRet(cannotOverride(m, other), mtres, otres)); 1869 m.flags_field |= BAD_OVERRIDE; 1870 } 1871 return; 1872 } else if (overrideWarner.hasNonSilentLint(LintCategory.UNCHECKED)) { 1873 warnUnchecked(TreeInfo.diagnosticPositionFor(m, tree), 1874 Warnings.OverrideUncheckedRet(uncheckedOverrides(m, other), mtres, otres)); 1875 } 1876 1877 // Error if overriding method throws an exception not reported 1878 // by overridden method. 1879 List<Type> otthrown = types.subst(ot.getThrownTypes(), otvars, mtvars); 1880 List<Type> unhandledErased = unhandled(mt.getThrownTypes(), types.erasure(otthrown)); 1881 List<Type> unhandledUnerased = unhandled(mt.getThrownTypes(), otthrown); 1882 if (unhandledErased.nonEmpty()) { 1883 log.error(TreeInfo.diagnosticPositionFor(m, tree), 1884 Errors.OverrideMethDoesntThrow(cannotOverride(m, other), unhandledUnerased.head)); 1885 m.flags_field |= BAD_OVERRIDE; 1886 return; 1887 } 1888 else if (unhandledUnerased.nonEmpty()) { 1889 warnUnchecked(TreeInfo.diagnosticPositionFor(m, tree), 1890 Warnings.OverrideUncheckedThrown(cannotOverride(m, other), unhandledUnerased.head)); 1891 return; 1892 } 1893 1894 // Optional warning if varargs don't agree 1895 if ((((m.flags() ^ other.flags()) & Flags.VARARGS) != 0) 1896 && lint.isEnabled(LintCategory.OVERRIDES)) { 1897 log.warning(TreeInfo.diagnosticPositionFor(m, tree), 1898 ((m.flags() & Flags.VARARGS) != 0) 1899 ? Warnings.OverrideVarargsMissing(varargsOverrides(m, other)) 1900 : Warnings.OverrideVarargsExtra(varargsOverrides(m, other))); 1901 } 1902 1903 // Warn if instance method overrides bridge method (compiler spec ??) 1904 if ((other.flags() & BRIDGE) != 0) { 1905 log.warning(TreeInfo.diagnosticPositionFor(m, tree), 1906 Warnings.OverrideBridge(uncheckedOverrides(m, other))); 1907 } 1908 1909 // Warn if a deprecated method overridden by a non-deprecated one. 1910 if (!isDeprecatedOverrideIgnorable(other, origin)) { 1911 Lint prevLint = setLint(lint.augment(m)); 1912 try { 1913 checkDeprecated(() -> TreeInfo.diagnosticPositionFor(m, tree), m, other); 1914 } finally { 1915 setLint(prevLint); 1916 } 1917 } 1918 } 1919 // where 1920 private boolean shouldCheckPreview(MethodSymbol m, MethodSymbol other, ClassSymbol origin) { 1921 if (m.owner != origin || 1922 //performance - only do the expensive checks when the overridden method is a Preview API: 1923 (other.flags() & PREVIEW_API) == 0) { 1924 return false; 1925 } 1926 1927 for (Symbol s : types.membersClosure(origin.type, false).getSymbolsByName(m.name)) { 1928 if (m != s && m.overrides(s, origin, types, false)) { 1929 //only produce preview warnings or errors if "m" immediatelly overrides "other" 1930 //without intermediate overriding methods: 1931 return s == other; 1932 } 1933 } 1934 1935 return false; 1936 } 1937 private boolean isDeprecatedOverrideIgnorable(MethodSymbol m, ClassSymbol origin) { 1938 // If the method, m, is defined in an interface, then ignore the issue if the method 1939 // is only inherited via a supertype and also implemented in the supertype, 1940 // because in that case, we will rediscover the issue when examining the method 1941 // in the supertype. 1942 // If the method, m, is not defined in an interface, then the only time we need to 1943 // address the issue is when the method is the supertype implementation: any other 1944 // case, we will have dealt with when examining the supertype classes 1945 ClassSymbol mc = m.enclClass(); 1946 Type st = types.supertype(origin.type); 1947 if (!st.hasTag(CLASS)) 1948 return true; 1949 MethodSymbol stimpl = m.implementation((ClassSymbol)st.tsym, types, false); 1950 1951 if (mc != null && ((mc.flags() & INTERFACE) != 0)) { 1952 List<Type> intfs = types.interfaces(origin.type); 1953 return (intfs.contains(mc.type) ? false : (stimpl != null)); 1954 } 1955 else 1956 return (stimpl != m); 1957 } 1958 1959 1960 // used to check if there were any unchecked conversions 1961 Warner overrideWarner = new Warner(); 1962 1963 /** Check that a class does not inherit two concrete methods 1964 * with the same signature. 1965 * @param pos Position to be used for error reporting. 1966 * @param site The class type to be checked. 1967 */ 1968 public void checkCompatibleConcretes(DiagnosticPosition pos, Type site) { 1969 Type sup = types.supertype(site); 1970 if (!sup.hasTag(CLASS)) return; 1971 1972 for (Type t1 = sup; 1973 t1.hasTag(CLASS) && t1.tsym.type.isParameterized(); 1974 t1 = types.supertype(t1)) { 1975 for (Symbol s1 : t1.tsym.members().getSymbols(NON_RECURSIVE)) { 1976 if (s1.kind != MTH || 1977 (s1.flags() & (STATIC|SYNTHETIC|BRIDGE)) != 0 || 1978 !s1.isInheritedIn(site.tsym, types) || 1979 ((MethodSymbol)s1).implementation(site.tsym, 1980 types, 1981 true) != s1) 1982 continue; 1983 Type st1 = types.memberType(t1, s1); 1984 int s1ArgsLength = st1.getParameterTypes().length(); 1985 if (st1 == s1.type) continue; 1986 1987 for (Type t2 = sup; 1988 t2.hasTag(CLASS); 1989 t2 = types.supertype(t2)) { 1990 for (Symbol s2 : t2.tsym.members().getSymbolsByName(s1.name)) { 1991 if (s2 == s1 || 1992 s2.kind != MTH || 1993 (s2.flags() & (STATIC|SYNTHETIC|BRIDGE)) != 0 || 1994 s2.type.getParameterTypes().length() != s1ArgsLength || 1995 !s2.isInheritedIn(site.tsym, types) || 1996 ((MethodSymbol)s2).implementation(site.tsym, 1997 types, 1998 true) != s2) 1999 continue; 2000 Type st2 = types.memberType(t2, s2); 2001 if (types.overrideEquivalent(st1, st2)) 2002 log.error(pos, 2003 Errors.ConcreteInheritanceConflict(s1, t1, s2, t2, sup)); 2004 } 2005 } 2006 } 2007 } 2008 } 2009 2010 /** Check that classes (or interfaces) do not each define an abstract 2011 * method with same name and arguments but incompatible return types. 2012 * @param pos Position to be used for error reporting. 2013 * @param t1 The first argument type. 2014 * @param t2 The second argument type. 2015 */ 2016 public boolean checkCompatibleAbstracts(DiagnosticPosition pos, 2017 Type t1, 2018 Type t2, 2019 Type site) { 2020 if ((site.tsym.flags() & COMPOUND) != 0) { 2021 // special case for intersections: need to eliminate wildcards in supertypes 2022 t1 = types.capture(t1); 2023 t2 = types.capture(t2); 2024 } 2025 return firstIncompatibility(pos, t1, t2, site) == null; 2026 } 2027 2028 /** Return the first method which is defined with same args 2029 * but different return types in two given interfaces, or null if none 2030 * exists. 2031 * @param t1 The first type. 2032 * @param t2 The second type. 2033 * @param site The most derived type. 2034 * @return symbol from t2 that conflicts with one in t1. 2035 */ 2036 private Symbol firstIncompatibility(DiagnosticPosition pos, Type t1, Type t2, Type site) { 2037 Map<TypeSymbol,Type> interfaces1 = new HashMap<>(); 2038 closure(t1, interfaces1); 2039 Map<TypeSymbol,Type> interfaces2; 2040 if (t1 == t2) 2041 interfaces2 = interfaces1; 2042 else 2043 closure(t2, interfaces1, interfaces2 = new HashMap<>()); 2044 2045 for (Type t3 : interfaces1.values()) { 2046 for (Type t4 : interfaces2.values()) { 2047 Symbol s = firstDirectIncompatibility(pos, t3, t4, site); 2048 if (s != null) return s; 2049 } 2050 } 2051 return null; 2052 } 2053 2054 /** Compute all the supertypes of t, indexed by type symbol. */ 2055 private void closure(Type t, Map<TypeSymbol,Type> typeMap) { 2056 if (!t.hasTag(CLASS)) return; 2057 if (typeMap.put(t.tsym, t) == null) { 2058 closure(types.supertype(t), typeMap); 2059 for (Type i : types.interfaces(t)) 2060 closure(i, typeMap); 2061 } 2062 } 2063 2064 /** Compute all the supertypes of t, indexed by type symbol (except those in typesSkip). */ 2065 private void closure(Type t, Map<TypeSymbol,Type> typesSkip, Map<TypeSymbol,Type> typeMap) { 2066 if (!t.hasTag(CLASS)) return; 2067 if (typesSkip.get(t.tsym) != null) return; 2068 if (typeMap.put(t.tsym, t) == null) { 2069 closure(types.supertype(t), typesSkip, typeMap); 2070 for (Type i : types.interfaces(t)) 2071 closure(i, typesSkip, typeMap); 2072 } 2073 } 2074 2075 /** Return the first method in t2 that conflicts with a method from t1. */ 2076 private Symbol firstDirectIncompatibility(DiagnosticPosition pos, Type t1, Type t2, Type site) { 2077 for (Symbol s1 : t1.tsym.members().getSymbols(NON_RECURSIVE)) { 2078 Type st1 = null; 2079 if (s1.kind != MTH || !s1.isInheritedIn(site.tsym, types) || 2080 (s1.flags() & SYNTHETIC) != 0) continue; 2081 Symbol impl = ((MethodSymbol)s1).implementation(site.tsym, types, false); 2082 if (impl != null && (impl.flags() & ABSTRACT) == 0) continue; 2083 for (Symbol s2 : t2.tsym.members().getSymbolsByName(s1.name)) { 2084 if (s1 == s2) continue; 2085 if (s2.kind != MTH || !s2.isInheritedIn(site.tsym, types) || 2086 (s2.flags() & SYNTHETIC) != 0) continue; 2087 if (st1 == null) st1 = types.memberType(t1, s1); 2088 Type st2 = types.memberType(t2, s2); 2089 if (types.overrideEquivalent(st1, st2)) { 2090 List<Type> tvars1 = st1.getTypeArguments(); 2091 List<Type> tvars2 = st2.getTypeArguments(); 2092 Type rt1 = st1.getReturnType(); 2093 Type rt2 = types.subst(st2.getReturnType(), tvars2, tvars1); 2094 boolean compat = 2095 types.isSameType(rt1, rt2) || 2096 !rt1.isPrimitiveOrVoid() && 2097 !rt2.isPrimitiveOrVoid() && 2098 (types.covariantReturnType(rt1, rt2, types.noWarnings) || 2099 types.covariantReturnType(rt2, rt1, types.noWarnings)) || 2100 checkCommonOverriderIn(s1,s2,site); 2101 if (!compat) { 2102 if (types.isSameType(t1, t2)) { 2103 log.error(pos, Errors.IncompatibleDiffRetSameType(t1, 2104 s2.name, types.memberType(t2, s2).getParameterTypes())); 2105 } else { 2106 log.error(pos, Errors.TypesIncompatible(t1, t2, 2107 Fragments.IncompatibleDiffRet(s2.name, types.memberType(t2, s2).getParameterTypes()))); 2108 } 2109 return s2; 2110 } 2111 } else if (checkNameClash((ClassSymbol)site.tsym, s1, s2) && 2112 !checkCommonOverriderIn(s1, s2, site)) { 2113 log.error(pos, Errors.NameClashSameErasureNoOverride( 2114 s1.name, types.memberType(site, s1).asMethodType().getParameterTypes(), s1.location(), 2115 s2.name, types.memberType(site, s2).asMethodType().getParameterTypes(), s2.location())); 2116 return s2; 2117 } 2118 } 2119 } 2120 return null; 2121 } 2122 //WHERE 2123 boolean checkCommonOverriderIn(Symbol s1, Symbol s2, Type site) { 2124 Map<TypeSymbol,Type> supertypes = new HashMap<>(); 2125 Type st1 = types.memberType(site, s1); 2126 Type st2 = types.memberType(site, s2); 2127 closure(site, supertypes); 2128 for (Type t : supertypes.values()) { 2129 for (Symbol s3 : t.tsym.members().getSymbolsByName(s1.name)) { 2130 if (s3 == s1 || s3 == s2 || s3.kind != MTH || (s3.flags() & (BRIDGE|SYNTHETIC)) != 0) continue; 2131 Type st3 = types.memberType(site,s3); 2132 if (types.overrideEquivalent(st3, st1) && 2133 types.overrideEquivalent(st3, st2) && 2134 types.returnTypeSubstitutable(st3, st1) && 2135 types.returnTypeSubstitutable(st3, st2)) { 2136 return true; 2137 } 2138 } 2139 } 2140 return false; 2141 } 2142 2143 /** Check that a given method conforms with any method it overrides. 2144 * @param tree The tree from which positions are extracted 2145 * for errors. 2146 * @param m The overriding method. 2147 */ 2148 void checkOverride(Env<AttrContext> env, JCMethodDecl tree, MethodSymbol m) { 2149 ClassSymbol origin = (ClassSymbol)m.owner; 2150 if ((origin.flags() & ENUM) != 0 && names.finalize.equals(m.name)) { 2151 if (m.overrides(syms.enumFinalFinalize, origin, types, false)) { 2152 log.error(tree.pos(), Errors.EnumNoFinalize); 2153 return; 2154 } 2155 } 2156 if (allowRecords && origin.isRecord()) { 2157 // let's find out if this is a user defined accessor in which case the @Override annotation is acceptable 2158 Optional<? extends RecordComponent> recordComponent = origin.getRecordComponents().stream() 2159 .filter(rc -> rc.accessor == tree.sym && (rc.accessor.flags_field & GENERATED_MEMBER) == 0).findFirst(); 2160 if (recordComponent.isPresent()) { 2161 return; 2162 } 2163 } 2164 2165 for (Type t = origin.type; t.hasTag(CLASS); 2166 t = types.supertype(t)) { 2167 if (t != origin.type) { 2168 checkOverride(tree, t, origin, m); 2169 } 2170 for (Type t2 : types.interfaces(t)) { 2171 checkOverride(tree, t2, origin, m); 2172 } 2173 } 2174 2175 final boolean explicitOverride = m.attribute(syms.overrideType.tsym) != null; 2176 // Check if this method must override a super method due to being annotated with @Override 2177 // or by virtue of being a member of a diamond inferred anonymous class. Latter case is to 2178 // be treated "as if as they were annotated" with @Override. 2179 boolean mustOverride = explicitOverride || 2180 (env.info.isAnonymousDiamond && !m.isConstructor() && !m.isPrivate()); 2181 if (mustOverride && !isOverrider(m)) { 2182 DiagnosticPosition pos = tree.pos(); 2183 for (JCAnnotation a : tree.getModifiers().annotations) { 2184 if (a.annotationType.type.tsym == syms.overrideType.tsym) { 2185 pos = a.pos(); 2186 break; 2187 } 2188 } 2189 log.error(pos, 2190 explicitOverride ? (m.isStatic() ? Errors.StaticMethodsCannotBeAnnotatedWithOverride : Errors.MethodDoesNotOverrideSuperclass) : 2191 Errors.AnonymousDiamondMethodDoesNotOverrideSuperclass(Fragments.DiamondAnonymousMethodsImplicitlyOverride)); 2192 } 2193 } 2194 2195 void checkOverride(JCTree tree, Type site, ClassSymbol origin, MethodSymbol m) { 2196 TypeSymbol c = site.tsym; 2197 for (Symbol sym : c.members().getSymbolsByName(m.name)) { 2198 if (m.overrides(sym, origin, types, false)) { 2199 if ((sym.flags() & ABSTRACT) == 0) { 2200 checkOverride(tree, m, (MethodSymbol)sym, origin); 2201 } 2202 } 2203 } 2204 } 2205 2206 private Predicate<Symbol> equalsHasCodeFilter = s -> MethodSymbol.implementation_filter.test(s) && 2207 (s.flags() & BAD_OVERRIDE) == 0; 2208 2209 public void checkClassOverrideEqualsAndHashIfNeeded(DiagnosticPosition pos, 2210 ClassSymbol someClass) { 2211 /* At present, annotations cannot possibly have a method that is override 2212 * equivalent with Object.equals(Object) but in any case the condition is 2213 * fine for completeness. 2214 */ 2215 if (someClass == (ClassSymbol)syms.objectType.tsym || 2216 someClass.isInterface() || someClass.isEnum() || 2217 (someClass.flags() & ANNOTATION) != 0 || 2218 (someClass.flags() & ABSTRACT) != 0) return; 2219 //anonymous inner classes implementing interfaces need especial treatment 2220 if (someClass.isAnonymous()) { 2221 List<Type> interfaces = types.interfaces(someClass.type); 2222 if (interfaces != null && !interfaces.isEmpty() && 2223 interfaces.head.tsym == syms.comparatorType.tsym) return; 2224 } 2225 checkClassOverrideEqualsAndHash(pos, someClass); 2226 } 2227 2228 private void checkClassOverrideEqualsAndHash(DiagnosticPosition pos, 2229 ClassSymbol someClass) { 2230 if (lint.isEnabled(LintCategory.OVERRIDES)) { 2231 MethodSymbol equalsAtObject = (MethodSymbol)syms.objectType 2232 .tsym.members().findFirst(names.equals); 2233 MethodSymbol hashCodeAtObject = (MethodSymbol)syms.objectType 2234 .tsym.members().findFirst(names.hashCode); 2235 MethodSymbol equalsImpl = types.implementation(equalsAtObject, 2236 someClass, false, equalsHasCodeFilter); 2237 boolean overridesEquals = equalsImpl != null && 2238 equalsImpl.owner == someClass; 2239 boolean overridesHashCode = types.implementation(hashCodeAtObject, 2240 someClass, false, equalsHasCodeFilter) != hashCodeAtObject; 2241 2242 if (overridesEquals && !overridesHashCode) { 2243 log.warning(LintCategory.OVERRIDES, pos, 2244 Warnings.OverrideEqualsButNotHashcode(someClass)); 2245 } 2246 } 2247 } 2248 2249 public void checkModuleName (JCModuleDecl tree) { 2250 Name moduleName = tree.sym.name; 2251 Assert.checkNonNull(moduleName); 2252 if (lint.isEnabled(LintCategory.MODULE)) { 2253 JCExpression qualId = tree.qualId; 2254 while (qualId != null) { 2255 Name componentName; 2256 DiagnosticPosition pos; 2257 switch (qualId.getTag()) { 2258 case SELECT: 2259 JCFieldAccess selectNode = ((JCFieldAccess) qualId); 2260 componentName = selectNode.name; 2261 pos = selectNode.pos(); 2262 qualId = selectNode.selected; 2263 break; 2264 case IDENT: 2265 componentName = ((JCIdent) qualId).name; 2266 pos = qualId.pos(); 2267 qualId = null; 2268 break; 2269 default: 2270 throw new AssertionError("Unexpected qualified identifier: " + qualId.toString()); 2271 } 2272 if (componentName != null) { 2273 String moduleNameComponentString = componentName.toString(); 2274 int nameLength = moduleNameComponentString.length(); 2275 if (nameLength > 0 && Character.isDigit(moduleNameComponentString.charAt(nameLength - 1))) { 2276 log.warning(Lint.LintCategory.MODULE, pos, Warnings.PoorChoiceForModuleName(componentName)); 2277 } 2278 } 2279 } 2280 } 2281 } 2282 2283 private boolean checkNameClash(ClassSymbol origin, Symbol s1, Symbol s2) { 2284 ClashFilter cf = new ClashFilter(origin.type); 2285 return (cf.test(s1) && 2286 cf.test(s2) && 2287 types.hasSameArgs(s1.erasure(types), s2.erasure(types))); 2288 } 2289 2290 2291 /** Check that all abstract members of given class have definitions. 2292 * @param pos Position to be used for error reporting. 2293 * @param c The class. 2294 */ 2295 void checkAllDefined(DiagnosticPosition pos, ClassSymbol c) { 2296 MethodSymbol undef = types.firstUnimplementedAbstract(c); 2297 if (undef != null) { 2298 MethodSymbol undef1 = 2299 new MethodSymbol(undef.flags(), undef.name, 2300 types.memberType(c.type, undef), undef.owner); 2301 log.error(pos, 2302 Errors.DoesNotOverrideAbstract(c, undef1, undef1.location())); 2303 } 2304 } 2305 2306 void checkNonCyclicDecl(JCClassDecl tree) { 2307 CycleChecker cc = new CycleChecker(); 2308 cc.scan(tree); 2309 if (!cc.errorFound && !cc.partialCheck) { 2310 tree.sym.flags_field |= ACYCLIC; 2311 } 2312 } 2313 2314 class CycleChecker extends TreeScanner { 2315 2316 Set<Symbol> seenClasses = new HashSet<>(); 2317 boolean errorFound = false; 2318 boolean partialCheck = false; 2319 2320 private void checkSymbol(DiagnosticPosition pos, Symbol sym) { 2321 if (sym != null && sym.kind == TYP) { 2322 Env<AttrContext> classEnv = enter.getEnv((TypeSymbol)sym); 2323 if (classEnv != null) { 2324 DiagnosticSource prevSource = log.currentSource(); 2325 try { 2326 log.useSource(classEnv.toplevel.sourcefile); 2327 scan(classEnv.tree); 2328 } 2329 finally { 2330 log.useSource(prevSource.getFile()); 2331 } 2332 } else if (sym.kind == TYP) { 2333 checkClass(pos, sym, List.nil()); 2334 } 2335 } else if (sym == null || sym.kind != PCK) { 2336 //not completed yet 2337 partialCheck = true; 2338 } 2339 } 2340 2341 @Override 2342 public void visitSelect(JCFieldAccess tree) { 2343 super.visitSelect(tree); 2344 checkSymbol(tree.pos(), tree.sym); 2345 } 2346 2347 @Override 2348 public void visitIdent(JCIdent tree) { 2349 checkSymbol(tree.pos(), tree.sym); 2350 } 2351 2352 @Override 2353 public void visitTypeApply(JCTypeApply tree) { 2354 scan(tree.clazz); 2355 } 2356 2357 @Override 2358 public void visitTypeArray(JCArrayTypeTree tree) { 2359 scan(tree.elemtype); 2360 } 2361 2362 @Override 2363 public void visitClassDef(JCClassDecl tree) { 2364 List<JCTree> supertypes = List.nil(); 2365 if (tree.getExtendsClause() != null) { 2366 supertypes = supertypes.prepend(tree.getExtendsClause()); 2367 } 2368 if (tree.getImplementsClause() != null) { 2369 for (JCTree intf : tree.getImplementsClause()) { 2370 supertypes = supertypes.prepend(intf); 2371 } 2372 } 2373 checkClass(tree.pos(), tree.sym, supertypes); 2374 } 2375 2376 void checkClass(DiagnosticPosition pos, Symbol c, List<JCTree> supertypes) { 2377 if ((c.flags_field & ACYCLIC) != 0) 2378 return; 2379 if (seenClasses.contains(c)) { 2380 errorFound = true; 2381 noteCyclic(pos, (ClassSymbol)c); 2382 } else if (!c.type.isErroneous()) { 2383 try { 2384 seenClasses.add(c); 2385 if (c.type.hasTag(CLASS)) { 2386 if (supertypes.nonEmpty()) { 2387 scan(supertypes); 2388 } 2389 else { 2390 ClassType ct = (ClassType)c.type; 2391 if (ct.supertype_field == null || 2392 ct.interfaces_field == null) { 2393 //not completed yet 2394 partialCheck = true; 2395 return; 2396 } 2397 checkSymbol(pos, ct.supertype_field.tsym); 2398 for (Type intf : ct.interfaces_field) { 2399 checkSymbol(pos, intf.tsym); 2400 } 2401 } 2402 if (c.owner.kind == TYP) { 2403 checkSymbol(pos, c.owner); 2404 } 2405 } 2406 } finally { 2407 seenClasses.remove(c); 2408 } 2409 } 2410 } 2411 } 2412 2413 /** Check for cyclic references. Issue an error if the 2414 * symbol of the type referred to has a LOCKED flag set. 2415 * 2416 * @param pos Position to be used for error reporting. 2417 * @param t The type referred to. 2418 */ 2419 void checkNonCyclic(DiagnosticPosition pos, Type t) { 2420 checkNonCyclicInternal(pos, t); 2421 } 2422 2423 2424 void checkNonCyclic(DiagnosticPosition pos, TypeVar t) { 2425 checkNonCyclic1(pos, t, List.nil()); 2426 } 2427 2428 private void checkNonCyclic1(DiagnosticPosition pos, Type t, List<TypeVar> seen) { 2429 final TypeVar tv; 2430 if (t.hasTag(TYPEVAR) && (t.tsym.flags() & UNATTRIBUTED) != 0) 2431 return; 2432 if (seen.contains(t)) { 2433 tv = (TypeVar)t; 2434 tv.setUpperBound(types.createErrorType(t)); 2435 log.error(pos, Errors.CyclicInheritance(t)); 2436 } else if (t.hasTag(TYPEVAR)) { 2437 tv = (TypeVar)t; 2438 seen = seen.prepend(tv); 2439 for (Type b : types.getBounds(tv)) 2440 checkNonCyclic1(pos, b, seen); 2441 } 2442 } 2443 2444 /** Check for cyclic references. Issue an error if the 2445 * symbol of the type referred to has a LOCKED flag set. 2446 * 2447 * @param pos Position to be used for error reporting. 2448 * @param t The type referred to. 2449 * @return True if the check completed on all attributed classes 2450 */ 2451 private boolean checkNonCyclicInternal(DiagnosticPosition pos, Type t) { 2452 boolean complete = true; // was the check complete? 2453 //- System.err.println("checkNonCyclicInternal("+t+");");//DEBUG 2454 Symbol c = t.tsym; 2455 if ((c.flags_field & ACYCLIC) != 0) return true; 2456 2457 if ((c.flags_field & LOCKED) != 0) { 2458 noteCyclic(pos, (ClassSymbol)c); 2459 } else if (!c.type.isErroneous()) { 2460 try { 2461 c.flags_field |= LOCKED; 2462 if (c.type.hasTag(CLASS)) { 2463 ClassType clazz = (ClassType)c.type; 2464 if (clazz.interfaces_field != null) 2465 for (List<Type> l=clazz.interfaces_field; l.nonEmpty(); l=l.tail) 2466 complete &= checkNonCyclicInternal(pos, l.head); 2467 if (clazz.supertype_field != null) { 2468 Type st = clazz.supertype_field; 2469 if (st != null && st.hasTag(CLASS)) 2470 complete &= checkNonCyclicInternal(pos, st); 2471 } 2472 if (c.owner.kind == TYP) 2473 complete &= checkNonCyclicInternal(pos, c.owner.type); 2474 } 2475 } finally { 2476 c.flags_field &= ~LOCKED; 2477 } 2478 } 2479 if (complete) 2480 complete = ((c.flags_field & UNATTRIBUTED) == 0) && c.isCompleted(); 2481 if (complete) c.flags_field |= ACYCLIC; 2482 return complete; 2483 } 2484 2485 /** Note that we found an inheritance cycle. */ 2486 private void noteCyclic(DiagnosticPosition pos, ClassSymbol c) { 2487 log.error(pos, Errors.CyclicInheritance(c)); 2488 for (List<Type> l=types.interfaces(c.type); l.nonEmpty(); l=l.tail) 2489 l.head = types.createErrorType((ClassSymbol)l.head.tsym, Type.noType); 2490 Type st = types.supertype(c.type); 2491 if (st.hasTag(CLASS)) 2492 ((ClassType)c.type).supertype_field = types.createErrorType((ClassSymbol)st.tsym, Type.noType); 2493 c.type = types.createErrorType(c, c.type); 2494 c.flags_field |= ACYCLIC; 2495 } 2496 2497 /** Check that all methods which implement some 2498 * method conform to the method they implement. 2499 * @param tree The class definition whose members are checked. 2500 */ 2501 void checkImplementations(JCClassDecl tree) { 2502 checkImplementations(tree, tree.sym, tree.sym); 2503 } 2504 //where 2505 /** Check that all methods which implement some 2506 * method in `ic' conform to the method they implement. 2507 */ 2508 void checkImplementations(JCTree tree, ClassSymbol origin, ClassSymbol ic) { 2509 for (List<Type> l = types.closure(ic.type); l.nonEmpty(); l = l.tail) { 2510 ClassSymbol lc = (ClassSymbol)l.head.tsym; 2511 if ((lc.flags() & ABSTRACT) != 0) { 2512 for (Symbol sym : lc.members().getSymbols(NON_RECURSIVE)) { 2513 if (sym.kind == MTH && 2514 (sym.flags() & (STATIC|ABSTRACT)) == ABSTRACT) { 2515 MethodSymbol absmeth = (MethodSymbol)sym; 2516 MethodSymbol implmeth = absmeth.implementation(origin, types, false); 2517 if (implmeth != null && implmeth != absmeth && 2518 (implmeth.owner.flags() & INTERFACE) == 2519 (origin.flags() & INTERFACE)) { 2520 // don't check if implmeth is in a class, yet 2521 // origin is an interface. This case arises only 2522 // if implmeth is declared in Object. The reason is 2523 // that interfaces really don't inherit from 2524 // Object it's just that the compiler represents 2525 // things that way. 2526 checkOverride(tree, implmeth, absmeth, origin); 2527 } 2528 } 2529 } 2530 } 2531 } 2532 } 2533 2534 /** Check that all abstract methods implemented by a class are 2535 * mutually compatible. 2536 * @param pos Position to be used for error reporting. 2537 * @param c The class whose interfaces are checked. 2538 */ 2539 void checkCompatibleSupertypes(DiagnosticPosition pos, Type c) { 2540 List<Type> supertypes = types.interfaces(c); 2541 Type supertype = types.supertype(c); 2542 if (supertype.hasTag(CLASS) && 2543 (supertype.tsym.flags() & ABSTRACT) != 0) 2544 supertypes = supertypes.prepend(supertype); 2545 for (List<Type> l = supertypes; l.nonEmpty(); l = l.tail) { 2546 if (!l.head.getTypeArguments().isEmpty() && 2547 !checkCompatibleAbstracts(pos, l.head, l.head, c)) 2548 return; 2549 for (List<Type> m = supertypes; m != l; m = m.tail) 2550 if (!checkCompatibleAbstracts(pos, l.head, m.head, c)) 2551 return; 2552 } 2553 checkCompatibleConcretes(pos, c); 2554 } 2555 2556 /** Check that all non-override equivalent methods accessible from 'site' 2557 * are mutually compatible (JLS 8.4.8/9.4.1). 2558 * 2559 * @param pos Position to be used for error reporting. 2560 * @param site The class whose methods are checked. 2561 * @param sym The method symbol to be checked. 2562 */ 2563 void checkOverrideClashes(DiagnosticPosition pos, Type site, MethodSymbol sym) { 2564 ClashFilter cf = new ClashFilter(site); 2565 //for each method m1 that is overridden (directly or indirectly) 2566 //by method 'sym' in 'site'... 2567 2568 ArrayList<Symbol> symbolsByName = new ArrayList<>(); 2569 types.membersClosure(site, false).getSymbolsByName(sym.name, cf).forEach(symbolsByName::add); 2570 for (Symbol m1 : symbolsByName) { 2571 if (!sym.overrides(m1, site.tsym, types, false)) { 2572 continue; 2573 } 2574 2575 //...check each method m2 that is a member of 'site' 2576 for (Symbol m2 : symbolsByName) { 2577 if (m2 == m1) continue; 2578 //if (i) the signature of 'sym' is not a subsignature of m1 (seen as 2579 //a member of 'site') and (ii) m1 has the same erasure as m2, issue an error 2580 if (!types.isSubSignature(sym.type, types.memberType(site, m2)) && 2581 types.hasSameArgs(m2.erasure(types), m1.erasure(types))) { 2582 sym.flags_field |= CLASH; 2583 if (m1 == sym) { 2584 log.error(pos, Errors.NameClashSameErasureNoOverride( 2585 m1.name, types.memberType(site, m1).asMethodType().getParameterTypes(), m1.location(), 2586 m2.name, types.memberType(site, m2).asMethodType().getParameterTypes(), m2.location())); 2587 } else { 2588 ClassType ct = (ClassType)site; 2589 String kind = ct.isInterface() ? "interface" : "class"; 2590 log.error(pos, Errors.NameClashSameErasureNoOverride1( 2591 kind, 2592 ct.tsym.name, 2593 m1.name, 2594 types.memberType(site, m1).asMethodType().getParameterTypes(), 2595 m1.location(), 2596 m2.name, 2597 types.memberType(site, m2).asMethodType().getParameterTypes(), 2598 m2.location())); 2599 } 2600 return; 2601 } 2602 } 2603 } 2604 } 2605 2606 /** Check that all static methods accessible from 'site' are 2607 * mutually compatible (JLS 8.4.8). 2608 * 2609 * @param pos Position to be used for error reporting. 2610 * @param site The class whose methods are checked. 2611 * @param sym The method symbol to be checked. 2612 */ 2613 void checkHideClashes(DiagnosticPosition pos, Type site, MethodSymbol sym) { 2614 ClashFilter cf = new ClashFilter(site); 2615 //for each method m1 that is a member of 'site'... 2616 for (Symbol s : types.membersClosure(site, true).getSymbolsByName(sym.name, cf)) { 2617 //if (i) the signature of 'sym' is not a subsignature of m1 (seen as 2618 //a member of 'site') and (ii) 'sym' has the same erasure as m1, issue an error 2619 if (!types.isSubSignature(sym.type, types.memberType(site, s))) { 2620 if (types.hasSameArgs(s.erasure(types), sym.erasure(types))) { 2621 log.error(pos, 2622 Errors.NameClashSameErasureNoHide(sym, sym.location(), s, s.location())); 2623 return; 2624 } 2625 } 2626 } 2627 } 2628 2629 //where 2630 private class ClashFilter implements Predicate<Symbol> { 2631 2632 Type site; 2633 2634 ClashFilter(Type site) { 2635 this.site = site; 2636 } 2637 2638 boolean shouldSkip(Symbol s) { 2639 return (s.flags() & CLASH) != 0 && 2640 s.owner == site.tsym; 2641 } 2642 2643 @Override 2644 public boolean test(Symbol s) { 2645 return s.kind == MTH && 2646 (s.flags() & SYNTHETIC) == 0 && 2647 !shouldSkip(s) && 2648 s.isInheritedIn(site.tsym, types) && 2649 !s.isConstructor(); 2650 } 2651 } 2652 2653 void checkDefaultMethodClashes(DiagnosticPosition pos, Type site) { 2654 DefaultMethodClashFilter dcf = new DefaultMethodClashFilter(site); 2655 for (Symbol m : types.membersClosure(site, false).getSymbols(dcf)) { 2656 Assert.check(m.kind == MTH); 2657 List<MethodSymbol> prov = types.interfaceCandidates(site, (MethodSymbol)m); 2658 if (prov.size() > 1) { 2659 ListBuffer<Symbol> abstracts = new ListBuffer<>(); 2660 ListBuffer<Symbol> defaults = new ListBuffer<>(); 2661 for (MethodSymbol provSym : prov) { 2662 if ((provSym.flags() & DEFAULT) != 0) { 2663 defaults = defaults.append(provSym); 2664 } else if ((provSym.flags() & ABSTRACT) != 0) { 2665 abstracts = abstracts.append(provSym); 2666 } 2667 if (defaults.nonEmpty() && defaults.size() + abstracts.size() >= 2) { 2668 //strong semantics - issue an error if two sibling interfaces 2669 //have two override-equivalent defaults - or if one is abstract 2670 //and the other is default 2671 Fragment diagKey; 2672 Symbol s1 = defaults.first(); 2673 Symbol s2; 2674 if (defaults.size() > 1) { 2675 s2 = defaults.toList().tail.head; 2676 diagKey = Fragments.IncompatibleUnrelatedDefaults(Kinds.kindName(site.tsym), site, 2677 m.name, types.memberType(site, m).getParameterTypes(), 2678 s1.location(), s2.location()); 2679 2680 } else { 2681 s2 = abstracts.first(); 2682 diagKey = Fragments.IncompatibleAbstractDefault(Kinds.kindName(site.tsym), site, 2683 m.name, types.memberType(site, m).getParameterTypes(), 2684 s1.location(), s2.location()); 2685 } 2686 log.error(pos, Errors.TypesIncompatible(s1.location().type, s2.location().type, diagKey)); 2687 break; 2688 } 2689 } 2690 } 2691 } 2692 } 2693 2694 //where 2695 private class DefaultMethodClashFilter implements Predicate<Symbol> { 2696 2697 Type site; 2698 2699 DefaultMethodClashFilter(Type site) { 2700 this.site = site; 2701 } 2702 2703 @Override 2704 public boolean test(Symbol s) { 2705 return s.kind == MTH && 2706 (s.flags() & DEFAULT) != 0 && 2707 s.isInheritedIn(site.tsym, types) && 2708 !s.isConstructor(); 2709 } 2710 } 2711 2712 /** Report warnings for potentially ambiguous method declarations in the given site. */ 2713 void checkPotentiallyAmbiguousOverloads(JCClassDecl tree, Type site) { 2714 2715 // Skip if warning not enabled 2716 if (!lint.isEnabled(LintCategory.OVERLOADS)) 2717 return; 2718 2719 // Gather all of site's methods, including overridden methods, grouped by name (except Object methods) 2720 List<java.util.List<MethodSymbol>> methodGroups = methodsGroupedByName(site, 2721 new PotentiallyAmbiguousFilter(site), ArrayList::new); 2722 2723 // Build the predicate that determines if site is responsible for an ambiguity 2724 BiPredicate<MethodSymbol, MethodSymbol> responsible = buildResponsiblePredicate(site, methodGroups); 2725 2726 // Now remove overridden methods from each group, leaving only site's actual members 2727 methodGroups.forEach(list -> removePreempted(list, (m1, m2) -> m1.overrides(m2, site.tsym, types, false))); 2728 2729 // Allow site's own declared methods (only) to apply @SuppressWarnings("overloads") 2730 methodGroups.forEach(list -> list.removeIf( 2731 m -> m.owner == site.tsym && !lint.augment(m).isEnabled(LintCategory.OVERLOADS))); 2732 2733 // Warn about ambiguous overload method pairs for which site is responsible 2734 methodGroups.forEach(list -> compareAndRemove(list, (m1, m2) -> { 2735 2736 // See if this is an ambiguous overload for which "site" is responsible 2737 if (!potentiallyAmbiguousOverload(site, m1, m2) || !responsible.test(m1, m2)) 2738 return 0; 2739 2740 // Locate the warning at one of the methods, if possible 2741 DiagnosticPosition pos = 2742 m1.owner == site.tsym ? TreeInfo.diagnosticPositionFor(m1, tree) : 2743 m2.owner == site.tsym ? TreeInfo.diagnosticPositionFor(m2, tree) : 2744 tree.pos(); 2745 2746 // Log the warning 2747 log.warning(LintCategory.OVERLOADS, pos, 2748 Warnings.PotentiallyAmbiguousOverload( 2749 m1.asMemberOf(site, types), m1.location(), 2750 m2.asMemberOf(site, types), m2.location())); 2751 2752 // Don't warn again for either of these two methods 2753 return FIRST | SECOND; 2754 })); 2755 } 2756 2757 /** Build a predicate that determines, given two methods that are members of the given class, 2758 * whether the class should be held "responsible" if the methods are potentially ambiguous. 2759 * 2760 * Sometimes ambiguous methods are unavoidable because they're inherited from a supertype. 2761 * For example, any subtype of Spliterator.OfInt will have ambiguities for both 2762 * forEachRemaining() and tryAdvance() (in both cases the overloads are IntConsumer and 2763 * Consumer<? super Integer>). So we only want to "blame" a class when that class is 2764 * itself responsible for creating the ambiguity. We declare that a class C is "responsible" 2765 * for the ambiguity between two methods m1 and m2 if there is no direct supertype T of C 2766 * such that m1 and m2, or some overrides thereof, both exist in T and are ambiguous in T. 2767 * As an optimization, we first check if either method is declared in C and does not override 2768 * any other methods; in this case the class is definitely responsible. 2769 */ 2770 BiPredicate<MethodSymbol, MethodSymbol> buildResponsiblePredicate(Type site, 2771 List<? extends Collection<MethodSymbol>> methodGroups) { 2772 2773 // Define the "overrides" predicate 2774 BiPredicate<MethodSymbol, MethodSymbol> overrides = (m1, m2) -> m1.overrides(m2, site.tsym, types, false); 2775 2776 // Map each method declared in site to a list of the supertype method(s) it directly overrides 2777 HashMap<MethodSymbol, ArrayList<MethodSymbol>> overriddenMethodsMap = new HashMap<>(); 2778 methodGroups.forEach(list -> { 2779 for (MethodSymbol m : list) { 2780 2781 // Skip methods not declared in site 2782 if (m.owner != site.tsym) 2783 continue; 2784 2785 // Gather all supertype methods overridden by m, directly or indirectly 2786 ArrayList<MethodSymbol> overriddenMethods = list.stream() 2787 .filter(m2 -> m2 != m && overrides.test(m, m2)) 2788 .collect(Collectors.toCollection(ArrayList::new)); 2789 2790 // Eliminate non-direct overrides 2791 removePreempted(overriddenMethods, overrides); 2792 2793 // Add to map 2794 overriddenMethodsMap.put(m, overriddenMethods); 2795 } 2796 }); 2797 2798 // Build the predicate 2799 return (m1, m2) -> { 2800 2801 // Get corresponding supertype methods (if declared in site) 2802 java.util.List<MethodSymbol> overriddenMethods1 = overriddenMethodsMap.get(m1); 2803 java.util.List<MethodSymbol> overriddenMethods2 = overriddenMethodsMap.get(m2); 2804 2805 // Quick check for the case where a method was added by site itself 2806 if (overriddenMethods1 != null && overriddenMethods1.isEmpty()) 2807 return true; 2808 if (overriddenMethods2 != null && overriddenMethods2.isEmpty()) 2809 return true; 2810 2811 // Get each method's corresponding method(s) from supertypes of site 2812 java.util.List<MethodSymbol> supertypeMethods1 = overriddenMethods1 != null ? 2813 overriddenMethods1 : Collections.singletonList(m1); 2814 java.util.List<MethodSymbol> supertypeMethods2 = overriddenMethods2 != null ? 2815 overriddenMethods2 : Collections.singletonList(m2); 2816 2817 // See if we can blame some direct supertype instead 2818 return types.directSupertypes(site).stream() 2819 .filter(stype -> stype != syms.objectType) 2820 .map(stype -> stype.tsym.type) // view supertype in its original form 2821 .noneMatch(stype -> { 2822 for (MethodSymbol sm1 : supertypeMethods1) { 2823 if (!types.isSubtype(types.erasure(stype), types.erasure(sm1.owner.type))) 2824 continue; 2825 for (MethodSymbol sm2 : supertypeMethods2) { 2826 if (!types.isSubtype(types.erasure(stype), types.erasure(sm2.owner.type))) 2827 continue; 2828 if (potentiallyAmbiguousOverload(stype, sm1, sm2)) 2829 return true; 2830 } 2831 } 2832 return false; 2833 }); 2834 }; 2835 } 2836 2837 /** Gather all of site's methods, including overridden methods, grouped and sorted by name, 2838 * after applying the given filter. 2839 */ 2840 <C extends Collection<MethodSymbol>> List<C> methodsGroupedByName(Type site, 2841 Predicate<Symbol> filter, Supplier<? extends C> groupMaker) { 2842 Iterable<Symbol> symbols = types.membersClosure(site, false).getSymbols(filter, RECURSIVE); 2843 return StreamSupport.stream(symbols.spliterator(), false) 2844 .map(MethodSymbol.class::cast) 2845 .collect(Collectors.groupingBy(m -> m.name, Collectors.toCollection(groupMaker))) 2846 .entrySet() 2847 .stream() 2848 .sorted(Comparator.comparing(e -> e.getKey().toString())) 2849 .map(Map.Entry::getValue) 2850 .collect(List.collector()); 2851 } 2852 2853 /** Compare elements in a list pair-wise in order to remove some of them. 2854 * @param list mutable list of items 2855 * @param comparer returns flag bit(s) to remove FIRST and/or SECOND 2856 */ 2857 <T> void compareAndRemove(java.util.List<T> list, ToIntBiFunction<? super T, ? super T> comparer) { 2858 for (int index1 = 0; index1 < list.size() - 1; index1++) { 2859 T item1 = list.get(index1); 2860 for (int index2 = index1 + 1; index2 < list.size(); index2++) { 2861 T item2 = list.get(index2); 2862 int flags = comparer.applyAsInt(item1, item2); 2863 if ((flags & SECOND) != 0) 2864 list.remove(index2--); // remove item2 2865 if ((flags & FIRST) != 0) { 2866 list.remove(index1--); // remove item1 2867 break; 2868 } 2869 } 2870 } 2871 } 2872 2873 /** Remove elements in a list that are preempted by some other element in the list. 2874 * @param list mutable list of items 2875 * @param preempts decides if one item preempts another, causing the second one to be removed 2876 */ 2877 <T> void removePreempted(java.util.List<T> list, BiPredicate<? super T, ? super T> preempts) { 2878 compareAndRemove(list, (item1, item2) -> { 2879 int flags = 0; 2880 if (preempts.test(item1, item2)) 2881 flags |= SECOND; 2882 if (preempts.test(item2, item1)) 2883 flags |= FIRST; 2884 return flags; 2885 }); 2886 } 2887 2888 /** Filters method candidates for the "potentially ambiguous method" check */ 2889 class PotentiallyAmbiguousFilter extends ClashFilter { 2890 2891 PotentiallyAmbiguousFilter(Type site) { 2892 super(site); 2893 } 2894 2895 @Override 2896 boolean shouldSkip(Symbol s) { 2897 return s.owner.type.tsym == syms.objectType.tsym || super.shouldSkip(s); 2898 } 2899 } 2900 2901 /** 2902 * Report warnings for potentially ambiguous method declarations. Two declarations 2903 * are potentially ambiguous if they feature two unrelated functional interface 2904 * in same argument position (in which case, a call site passing an implicit 2905 * lambda would be ambiguous). This assumes they already have the same name. 2906 */ 2907 boolean potentiallyAmbiguousOverload(Type site, MethodSymbol msym1, MethodSymbol msym2) { 2908 Assert.check(msym1.name == msym2.name); 2909 if (msym1 == msym2) 2910 return false; 2911 Type mt1 = types.memberType(site, msym1); 2912 Type mt2 = types.memberType(site, msym2); 2913 //if both generic methods, adjust type variables 2914 if (mt1.hasTag(FORALL) && mt2.hasTag(FORALL) && 2915 types.hasSameBounds((ForAll)mt1, (ForAll)mt2)) { 2916 mt2 = types.subst(mt2, ((ForAll)mt2).tvars, ((ForAll)mt1).tvars); 2917 } 2918 //expand varargs methods if needed 2919 int maxLength = Math.max(mt1.getParameterTypes().length(), mt2.getParameterTypes().length()); 2920 List<Type> args1 = rs.adjustArgs(mt1.getParameterTypes(), msym1, maxLength, true); 2921 List<Type> args2 = rs.adjustArgs(mt2.getParameterTypes(), msym2, maxLength, true); 2922 //if arities don't match, exit 2923 if (args1.length() != args2.length()) 2924 return false; 2925 boolean potentiallyAmbiguous = false; 2926 while (args1.nonEmpty() && args2.nonEmpty()) { 2927 Type s = args1.head; 2928 Type t = args2.head; 2929 if (!types.isSubtype(t, s) && !types.isSubtype(s, t)) { 2930 if (types.isFunctionalInterface(s) && types.isFunctionalInterface(t) && 2931 types.findDescriptorType(s).getParameterTypes().length() > 0 && 2932 types.findDescriptorType(s).getParameterTypes().length() == 2933 types.findDescriptorType(t).getParameterTypes().length()) { 2934 potentiallyAmbiguous = true; 2935 } else { 2936 return false; 2937 } 2938 } 2939 args1 = args1.tail; 2940 args2 = args2.tail; 2941 } 2942 return potentiallyAmbiguous; 2943 } 2944 2945 void checkAccessFromSerializableElement(final JCTree tree, boolean isLambda) { 2946 if (warnOnAnyAccessToMembers || 2947 (lint.isEnabled(LintCategory.SERIAL) && 2948 !lint.isSuppressed(LintCategory.SERIAL) && 2949 isLambda)) { 2950 Symbol sym = TreeInfo.symbol(tree); 2951 if (!sym.kind.matches(KindSelector.VAL_MTH)) { 2952 return; 2953 } 2954 2955 if (sym.kind == VAR) { 2956 if ((sym.flags() & PARAMETER) != 0 || 2957 sym.isDirectlyOrIndirectlyLocal() || 2958 sym.name == names._this || 2959 sym.name == names._super) { 2960 return; 2961 } 2962 } 2963 2964 if (!types.isSubtype(sym.owner.type, syms.serializableType) && 2965 isEffectivelyNonPublic(sym)) { 2966 if (isLambda) { 2967 if (belongsToRestrictedPackage(sym)) { 2968 log.warning(LintCategory.SERIAL, tree.pos(), 2969 Warnings.AccessToMemberFromSerializableLambda(sym)); 2970 } 2971 } else { 2972 log.warning(tree.pos(), 2973 Warnings.AccessToMemberFromSerializableElement(sym)); 2974 } 2975 } 2976 } 2977 } 2978 2979 private boolean isEffectivelyNonPublic(Symbol sym) { 2980 if (sym.packge() == syms.rootPackage) { 2981 return false; 2982 } 2983 2984 while (sym.kind != PCK) { 2985 if ((sym.flags() & PUBLIC) == 0) { 2986 return true; 2987 } 2988 sym = sym.owner; 2989 } 2990 return false; 2991 } 2992 2993 private boolean belongsToRestrictedPackage(Symbol sym) { 2994 String fullName = sym.packge().fullname.toString(); 2995 return fullName.startsWith("java.") || 2996 fullName.startsWith("javax.") || 2997 fullName.startsWith("sun.") || 2998 fullName.contains(".internal."); 2999 } 3000 3001 /** Check that class c does not implement directly or indirectly 3002 * the same parameterized interface with two different argument lists. 3003 * @param pos Position to be used for error reporting. 3004 * @param type The type whose interfaces are checked. 3005 */ 3006 void checkClassBounds(DiagnosticPosition pos, Type type) { 3007 checkClassBounds(pos, new HashMap<TypeSymbol,Type>(), type); 3008 } 3009 //where 3010 /** Enter all interfaces of type `type' into the hash table `seensofar' 3011 * with their class symbol as key and their type as value. Make 3012 * sure no class is entered with two different types. 3013 */ 3014 void checkClassBounds(DiagnosticPosition pos, 3015 Map<TypeSymbol,Type> seensofar, 3016 Type type) { 3017 if (type.isErroneous()) return; 3018 for (List<Type> l = types.interfaces(type); l.nonEmpty(); l = l.tail) { 3019 Type it = l.head; 3020 if (type.hasTag(CLASS) && !it.hasTag(CLASS)) continue; // JLS 8.1.5 3021 3022 Type oldit = seensofar.put(it.tsym, it); 3023 if (oldit != null) { 3024 List<Type> oldparams = oldit.allparams(); 3025 List<Type> newparams = it.allparams(); 3026 if (!types.containsTypeEquivalent(oldparams, newparams)) 3027 log.error(pos, 3028 Errors.CantInheritDiffArg(it.tsym, 3029 Type.toString(oldparams), 3030 Type.toString(newparams))); 3031 } 3032 checkClassBounds(pos, seensofar, it); 3033 } 3034 Type st = types.supertype(type); 3035 if (type.hasTag(CLASS) && !st.hasTag(CLASS)) return; // JLS 8.1.4 3036 if (st != Type.noType) checkClassBounds(pos, seensofar, st); 3037 } 3038 3039 /** Enter interface into into set. 3040 * If it existed already, issue a "repeated interface" error. 3041 */ 3042 void checkNotRepeated(DiagnosticPosition pos, Type it, Set<Symbol> its) { 3043 if (its.contains(it.tsym)) 3044 log.error(pos, Errors.RepeatedInterface); 3045 else { 3046 its.add(it.tsym); 3047 } 3048 } 3049 3050 /* ************************************************************************* 3051 * Check annotations 3052 **************************************************************************/ 3053 3054 /** 3055 * Recursively validate annotations values 3056 */ 3057 void validateAnnotationTree(JCTree tree) { 3058 class AnnotationValidator extends TreeScanner { 3059 @Override 3060 public void visitAnnotation(JCAnnotation tree) { 3061 if (!tree.type.isErroneous() && tree.type.tsym.isAnnotationType()) { 3062 super.visitAnnotation(tree); 3063 validateAnnotation(tree); 3064 } 3065 } 3066 } 3067 tree.accept(new AnnotationValidator()); 3068 } 3069 3070 /** 3071 * {@literal 3072 * Annotation types are restricted to primitives, String, an 3073 * enum, an annotation, Class, Class<?>, Class<? extends 3074 * Anything>, arrays of the preceding. 3075 * } 3076 */ 3077 void validateAnnotationType(JCTree restype) { 3078 // restype may be null if an error occurred, so don't bother validating it 3079 if (restype != null) { 3080 validateAnnotationType(restype.pos(), restype.type); 3081 } 3082 } 3083 3084 void validateAnnotationType(DiagnosticPosition pos, Type type) { 3085 if (type.isPrimitive()) return; 3086 if (types.isSameType(type, syms.stringType)) return; 3087 if ((type.tsym.flags() & Flags.ENUM) != 0) return; 3088 if ((type.tsym.flags() & Flags.ANNOTATION) != 0) return; 3089 if (types.cvarLowerBound(type).tsym == syms.classType.tsym) return; 3090 if (types.isArray(type) && !types.isArray(types.elemtype(type))) { 3091 validateAnnotationType(pos, types.elemtype(type)); 3092 return; 3093 } 3094 log.error(pos, Errors.InvalidAnnotationMemberType); 3095 } 3096 3097 /** 3098 * "It is also a compile-time error if any method declared in an 3099 * annotation type has a signature that is override-equivalent to 3100 * that of any public or protected method declared in class Object 3101 * or in the interface annotation.Annotation." 3102 * 3103 * @jls 9.6 Annotation Types 3104 */ 3105 void validateAnnotationMethod(DiagnosticPosition pos, MethodSymbol m) { 3106 for (Type sup = syms.annotationType; sup.hasTag(CLASS); sup = types.supertype(sup)) { 3107 Scope s = sup.tsym.members(); 3108 for (Symbol sym : s.getSymbolsByName(m.name)) { 3109 if (sym.kind == MTH && 3110 (sym.flags() & (PUBLIC | PROTECTED)) != 0 && 3111 types.overrideEquivalent(m.type, sym.type)) 3112 log.error(pos, Errors.IntfAnnotationMemberClash(sym, sup)); 3113 } 3114 } 3115 } 3116 3117 /** Check the annotations of a symbol. 3118 */ 3119 public void validateAnnotations(List<JCAnnotation> annotations, JCTree declarationTree, Symbol s) { 3120 for (JCAnnotation a : annotations) 3121 validateAnnotation(a, declarationTree, s); 3122 } 3123 3124 /** Check the type annotations. 3125 */ 3126 public void validateTypeAnnotations(List<JCAnnotation> annotations, Symbol s, boolean isTypeParameter) { 3127 for (JCAnnotation a : annotations) 3128 validateTypeAnnotation(a, s, isTypeParameter); 3129 } 3130 3131 /** Check an annotation of a symbol. 3132 */ 3133 private void validateAnnotation(JCAnnotation a, JCTree declarationTree, Symbol s) { 3134 /** NOTE: if annotation processors are present, annotation processing rounds can happen after this method, 3135 * this can impact in particular records for which annotations are forcibly propagated. 3136 */ 3137 validateAnnotationTree(a); 3138 boolean isRecordMember = ((s.flags_field & RECORD) != 0 || s.enclClass() != null && s.enclClass().isRecord()); 3139 3140 boolean isRecordField = (s.flags_field & RECORD) != 0 && 3141 declarationTree.hasTag(VARDEF) && 3142 s.owner.kind == TYP; 3143 3144 if (isRecordField) { 3145 // first we need to check if the annotation is applicable to records 3146 Name[] targets = getTargetNames(a); 3147 boolean appliesToRecords = false; 3148 for (Name target : targets) { 3149 appliesToRecords = 3150 target == names.FIELD || 3151 target == names.PARAMETER || 3152 target == names.METHOD || 3153 target == names.TYPE_USE || 3154 target == names.RECORD_COMPONENT; 3155 if (appliesToRecords) { 3156 break; 3157 } 3158 } 3159 if (!appliesToRecords) { 3160 log.error(a.pos(), Errors.AnnotationTypeNotApplicable); 3161 } else { 3162 /* lets now find the annotations in the field that are targeted to record components and append them to 3163 * the corresponding record component 3164 */ 3165 ClassSymbol recordClass = (ClassSymbol) s.owner; 3166 RecordComponent rc = recordClass.getRecordComponent((VarSymbol)s); 3167 SymbolMetadata metadata = rc.getMetadata(); 3168 if (metadata == null || metadata.isEmpty()) { 3169 /* if not is empty then we have already been here, which is the case if multiple annotations are applied 3170 * to the record component declaration 3171 */ 3172 rc.appendAttributes(s.getRawAttributes().stream().filter(anno -> 3173 Arrays.stream(getTargetNames(anno.type.tsym)).anyMatch(name -> name == names.RECORD_COMPONENT) 3174 ).collect(List.collector())); 3175 3176 JCVariableDecl fieldAST = (JCVariableDecl) declarationTree; 3177 for (JCAnnotation fieldAnnot : fieldAST.mods.annotations) { 3178 for (JCAnnotation rcAnnot : rc.declarationFor().mods.annotations) { 3179 if (rcAnnot.pos == fieldAnnot.pos) { 3180 rcAnnot.setType(fieldAnnot.type); 3181 break; 3182 } 3183 } 3184 } 3185 3186 /* At this point, we used to carry over any type annotations from the VARDEF to the record component, but 3187 * that is problematic, since we get here only when *some* annotation is applied to the SE5 (declaration) 3188 * annotation location, inadvertently failing to carry over the type annotations when the VarDef has no 3189 * annotations in the SE5 annotation location. 3190 * 3191 * Now type annotations are assigned to record components in a method that would execute irrespective of 3192 * whether there are SE5 annotations on a VarDef viz com.sun.tools.javac.code.TypeAnnotations.TypeAnnotationPositions.visitVarDef 3193 */ 3194 } 3195 } 3196 } 3197 3198 /* the section below is tricky. Annotations applied to record components are propagated to the corresponding 3199 * record member so if an annotation has target: FIELD, it is propagated to the corresponding FIELD, if it has 3200 * target METHOD, it is propagated to the accessor and so on. But at the moment when method members are generated 3201 * there is no enough information to propagate only the right annotations. So all the annotations are propagated 3202 * to all the possible locations. 3203 * 3204 * At this point we need to remove all the annotations that are not in place before going on with the annotation 3205 * party. On top of the above there is the issue that there is no AST representing record components, just symbols 3206 * so the corresponding field has been holding all the annotations and it's metadata has been modified as if it 3207 * was both a field and a record component. 3208 * 3209 * So there are two places where we need to trim annotations from: the metadata of the symbol and / or the modifiers 3210 * in the AST. Whatever is in the metadata will be written to the class file, whatever is in the modifiers could 3211 * be see by annotation processors. 3212 * 3213 * The metadata contains both type annotations and declaration annotations. At this point of the game we don't 3214 * need to care about type annotations, they are all in the right place. But we could need to remove declaration 3215 * annotations. So for declaration annotations if they are not applicable to the record member, excluding type 3216 * annotations which are already correct, then we will remove it. For the AST modifiers if the annotation is not 3217 * applicable either as type annotation and or declaration annotation, only in that case it will be removed. 3218 * 3219 * So it could be that annotation is removed as a declaration annotation but it is kept in the AST modifier for 3220 * further inspection by annotation processors. 3221 * 3222 * For example: 3223 * 3224 * import java.lang.annotation.*; 3225 * 3226 * @Target({ElementType.TYPE_USE, ElementType.RECORD_COMPONENT}) 3227 * @Retention(RetentionPolicy.RUNTIME) 3228 * @interface Anno { } 3229 * 3230 * record R(@Anno String s) {} 3231 * 3232 * at this point we will have for the case of the generated field: 3233 * - @Anno in the modifier 3234 * - @Anno as a type annotation 3235 * - @Anno as a declaration annotation 3236 * 3237 * the last one should be removed because the annotation has not FIELD as target but it was applied as a 3238 * declaration annotation because the field was being treated both as a field and as a record component 3239 * as we have already copied the annotations to the record component, now the field doesn't need to hold 3240 * annotations that are not intended for it anymore. Still @Anno has to be kept in the AST's modifiers as it 3241 * is applicable as a type annotation to the type of the field. 3242 */ 3243 3244 if (a.type.tsym.isAnnotationType()) { 3245 Optional<Set<Name>> applicableTargetsOp = getApplicableTargets(a, s); 3246 if (!applicableTargetsOp.isEmpty()) { 3247 Set<Name> applicableTargets = applicableTargetsOp.get(); 3248 boolean notApplicableOrIsTypeUseOnly = applicableTargets.isEmpty() || 3249 applicableTargets.size() == 1 && applicableTargets.contains(names.TYPE_USE); 3250 boolean isCompGeneratedRecordElement = isRecordMember && (s.flags_field & Flags.GENERATED_MEMBER) != 0; 3251 boolean isCompRecordElementWithNonApplicableDeclAnno = isCompGeneratedRecordElement && notApplicableOrIsTypeUseOnly; 3252 3253 if (applicableTargets.isEmpty() || isCompRecordElementWithNonApplicableDeclAnno) { 3254 if (isCompRecordElementWithNonApplicableDeclAnno) { 3255 /* so we have found an annotation that is not applicable to a record member that was generated by the 3256 * compiler. This was intentionally done at TypeEnter, now is the moment strip away the annotations 3257 * that are not applicable to the given record member 3258 */ 3259 JCModifiers modifiers = TreeInfo.getModifiers(declarationTree); 3260 /* lets first remove the annotation from the modifier if it is not applicable, we have to check again as 3261 * it could be a type annotation 3262 */ 3263 if (modifiers != null && applicableTargets.isEmpty()) { 3264 ListBuffer<JCAnnotation> newAnnotations = new ListBuffer<>(); 3265 for (JCAnnotation anno : modifiers.annotations) { 3266 if (anno != a) { 3267 newAnnotations.add(anno); 3268 } 3269 } 3270 modifiers.annotations = newAnnotations.toList(); 3271 } 3272 // now lets remove it from the symbol 3273 s.getMetadata().removeDeclarationMetadata(a.attribute); 3274 } else { 3275 log.error(a.pos(), Errors.AnnotationTypeNotApplicable); 3276 } 3277 } 3278 /* if we are seeing the @SafeVarargs annotation applied to a compiler generated accessor, 3279 * then this is an error as we know that no compiler generated accessor will be a varargs 3280 * method, better to fail asap 3281 */ 3282 if (isCompGeneratedRecordElement && !isRecordField && a.type.tsym == syms.trustMeType.tsym && declarationTree.hasTag(METHODDEF)) { 3283 log.error(a.pos(), Errors.VarargsInvalidTrustmeAnno(syms.trustMeType.tsym, Fragments.VarargsTrustmeOnNonVarargsAccessor(s))); 3284 } 3285 } 3286 } 3287 3288 if (a.annotationType.type.tsym == syms.functionalInterfaceType.tsym) { 3289 if (s.kind != TYP) { 3290 log.error(a.pos(), Errors.BadFunctionalIntfAnno); 3291 } else if (!s.isInterface() || (s.flags() & ANNOTATION) != 0) { 3292 log.error(a.pos(), Errors.BadFunctionalIntfAnno1(Fragments.NotAFunctionalIntf(s))); 3293 } 3294 } 3295 } 3296 3297 public void validateTypeAnnotation(JCAnnotation a, Symbol s, boolean isTypeParameter) { 3298 Assert.checkNonNull(a.type); 3299 // we just want to validate that the anotation doesn't have any wrong target 3300 if (s != null) getApplicableTargets(a, s); 3301 validateAnnotationTree(a); 3302 3303 if (a.hasTag(TYPE_ANNOTATION) && 3304 !a.annotationType.type.isErroneous() && 3305 !isTypeAnnotation(a, isTypeParameter)) { 3306 log.error(a.pos(), Errors.AnnotationTypeNotApplicableToType(a.type)); 3307 } 3308 } 3309 3310 /** 3311 * Validate the proposed container 'repeatable' on the 3312 * annotation type symbol 's'. Report errors at position 3313 * 'pos'. 3314 * 3315 * @param s The (annotation)type declaration annotated with a @Repeatable 3316 * @param repeatable the @Repeatable on 's' 3317 * @param pos where to report errors 3318 */ 3319 public void validateRepeatable(TypeSymbol s, Attribute.Compound repeatable, DiagnosticPosition pos) { 3320 Assert.check(types.isSameType(repeatable.type, syms.repeatableType)); 3321 3322 Type t = null; 3323 List<Pair<MethodSymbol,Attribute>> l = repeatable.values; 3324 if (!l.isEmpty()) { 3325 Assert.check(l.head.fst.name == names.value); 3326 if (l.head.snd instanceof Attribute.Class) { 3327 t = ((Attribute.Class)l.head.snd).getValue(); 3328 } 3329 } 3330 3331 if (t == null) { 3332 // errors should already have been reported during Annotate 3333 return; 3334 } 3335 3336 validateValue(t.tsym, s, pos); 3337 validateRetention(t.tsym, s, pos); 3338 validateDocumented(t.tsym, s, pos); 3339 validateInherited(t.tsym, s, pos); 3340 validateTarget(t.tsym, s, pos); 3341 validateDefault(t.tsym, pos); 3342 } 3343 3344 private void validateValue(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) { 3345 Symbol sym = container.members().findFirst(names.value); 3346 if (sym != null && sym.kind == MTH) { 3347 MethodSymbol m = (MethodSymbol) sym; 3348 Type ret = m.getReturnType(); 3349 if (!(ret.hasTag(ARRAY) && types.isSameType(((ArrayType)ret).elemtype, contained.type))) { 3350 log.error(pos, 3351 Errors.InvalidRepeatableAnnotationValueReturn(container, 3352 ret, 3353 types.makeArrayType(contained.type))); 3354 } 3355 } else { 3356 log.error(pos, Errors.InvalidRepeatableAnnotationNoValue(container)); 3357 } 3358 } 3359 3360 private void validateRetention(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) { 3361 Attribute.RetentionPolicy containerRetention = types.getRetention(container); 3362 Attribute.RetentionPolicy containedRetention = types.getRetention(contained); 3363 3364 boolean error = false; 3365 switch (containedRetention) { 3366 case RUNTIME: 3367 if (containerRetention != Attribute.RetentionPolicy.RUNTIME) { 3368 error = true; 3369 } 3370 break; 3371 case CLASS: 3372 if (containerRetention == Attribute.RetentionPolicy.SOURCE) { 3373 error = true; 3374 } 3375 } 3376 if (error ) { 3377 log.error(pos, 3378 Errors.InvalidRepeatableAnnotationRetention(container, 3379 containerRetention.name(), 3380 contained, 3381 containedRetention.name())); 3382 } 3383 } 3384 3385 private void validateDocumented(Symbol container, Symbol contained, DiagnosticPosition pos) { 3386 if (contained.attribute(syms.documentedType.tsym) != null) { 3387 if (container.attribute(syms.documentedType.tsym) == null) { 3388 log.error(pos, Errors.InvalidRepeatableAnnotationNotDocumented(container, contained)); 3389 } 3390 } 3391 } 3392 3393 private void validateInherited(Symbol container, Symbol contained, DiagnosticPosition pos) { 3394 if (contained.attribute(syms.inheritedType.tsym) != null) { 3395 if (container.attribute(syms.inheritedType.tsym) == null) { 3396 log.error(pos, Errors.InvalidRepeatableAnnotationNotInherited(container, contained)); 3397 } 3398 } 3399 } 3400 3401 private void validateTarget(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) { 3402 // The set of targets the container is applicable to must be a subset 3403 // (with respect to annotation target semantics) of the set of targets 3404 // the contained is applicable to. The target sets may be implicit or 3405 // explicit. 3406 3407 Set<Name> containerTargets; 3408 Attribute.Array containerTarget = getAttributeTargetAttribute(container); 3409 if (containerTarget == null) { 3410 containerTargets = getDefaultTargetSet(); 3411 } else { 3412 containerTargets = new HashSet<>(); 3413 for (Attribute app : containerTarget.values) { 3414 if (!(app instanceof Attribute.Enum attributeEnum)) { 3415 continue; // recovery 3416 } 3417 containerTargets.add(attributeEnum.value.name); 3418 } 3419 } 3420 3421 Set<Name> containedTargets; 3422 Attribute.Array containedTarget = getAttributeTargetAttribute(contained); 3423 if (containedTarget == null) { 3424 containedTargets = getDefaultTargetSet(); 3425 } else { 3426 containedTargets = new HashSet<>(); 3427 for (Attribute app : containedTarget.values) { 3428 if (!(app instanceof Attribute.Enum attributeEnum)) { 3429 continue; // recovery 3430 } 3431 containedTargets.add(attributeEnum.value.name); 3432 } 3433 } 3434 3435 if (!isTargetSubsetOf(containerTargets, containedTargets)) { 3436 log.error(pos, Errors.InvalidRepeatableAnnotationIncompatibleTarget(container, contained)); 3437 } 3438 } 3439 3440 /* get a set of names for the default target */ 3441 private Set<Name> getDefaultTargetSet() { 3442 if (defaultTargets == null) { 3443 defaultTargets = Set.of(defaultTargetMetaInfo()); 3444 } 3445 3446 return defaultTargets; 3447 } 3448 private Set<Name> defaultTargets; 3449 3450 3451 /** Checks that s is a subset of t, with respect to ElementType 3452 * semantics, specifically {ANNOTATION_TYPE} is a subset of {TYPE}, 3453 * and {TYPE_USE} covers the set {ANNOTATION_TYPE, TYPE, TYPE_USE, 3454 * TYPE_PARAMETER}. 3455 */ 3456 private boolean isTargetSubsetOf(Set<Name> s, Set<Name> t) { 3457 // Check that all elements in s are present in t 3458 for (Name n2 : s) { 3459 boolean currentElementOk = false; 3460 for (Name n1 : t) { 3461 if (n1 == n2) { 3462 currentElementOk = true; 3463 break; 3464 } else if (n1 == names.TYPE && n2 == names.ANNOTATION_TYPE) { 3465 currentElementOk = true; 3466 break; 3467 } else if (n1 == names.TYPE_USE && 3468 (n2 == names.TYPE || 3469 n2 == names.ANNOTATION_TYPE || 3470 n2 == names.TYPE_PARAMETER)) { 3471 currentElementOk = true; 3472 break; 3473 } 3474 } 3475 if (!currentElementOk) 3476 return false; 3477 } 3478 return true; 3479 } 3480 3481 private void validateDefault(Symbol container, DiagnosticPosition pos) { 3482 // validate that all other elements of containing type has defaults 3483 Scope scope = container.members(); 3484 for(Symbol elm : scope.getSymbols()) { 3485 if (elm.name != names.value && 3486 elm.kind == MTH && 3487 ((MethodSymbol)elm).defaultValue == null) { 3488 log.error(pos, 3489 Errors.InvalidRepeatableAnnotationElemNondefault(container, elm)); 3490 } 3491 } 3492 } 3493 3494 /** Is s a method symbol that overrides a method in a superclass? */ 3495 boolean isOverrider(Symbol s) { 3496 if (s.kind != MTH || s.isStatic()) 3497 return false; 3498 MethodSymbol m = (MethodSymbol)s; 3499 TypeSymbol owner = (TypeSymbol)m.owner; 3500 for (Type sup : types.closure(owner.type)) { 3501 if (sup == owner.type) 3502 continue; // skip "this" 3503 Scope scope = sup.tsym.members(); 3504 for (Symbol sym : scope.getSymbolsByName(m.name)) { 3505 if (!sym.isStatic() && m.overrides(sym, owner, types, true)) 3506 return true; 3507 } 3508 } 3509 return false; 3510 } 3511 3512 /** Is the annotation applicable to types? */ 3513 protected boolean isTypeAnnotation(JCAnnotation a, boolean isTypeParameter) { 3514 List<Attribute> targets = typeAnnotations.annotationTargets(a.annotationType.type.tsym); 3515 return (targets == null) ? 3516 false : 3517 targets.stream() 3518 .anyMatch(attr -> isTypeAnnotation(attr, isTypeParameter)); 3519 } 3520 //where 3521 boolean isTypeAnnotation(Attribute a, boolean isTypeParameter) { 3522 Attribute.Enum e = (Attribute.Enum)a; 3523 return (e.value.name == names.TYPE_USE || 3524 (isTypeParameter && e.value.name == names.TYPE_PARAMETER)); 3525 } 3526 3527 /** Is the annotation applicable to the symbol? */ 3528 Name[] getTargetNames(JCAnnotation a) { 3529 return getTargetNames(a.annotationType.type.tsym); 3530 } 3531 3532 public Name[] getTargetNames(TypeSymbol annoSym) { 3533 Attribute.Array arr = getAttributeTargetAttribute(annoSym); 3534 Name[] targets; 3535 if (arr == null) { 3536 targets = defaultTargetMetaInfo(); 3537 } else { 3538 // TODO: can we optimize this? 3539 targets = new Name[arr.values.length]; 3540 for (int i=0; i<arr.values.length; ++i) { 3541 Attribute app = arr.values[i]; 3542 if (!(app instanceof Attribute.Enum attributeEnum)) { 3543 return new Name[0]; 3544 } 3545 targets[i] = attributeEnum.value.name; 3546 } 3547 } 3548 return targets; 3549 } 3550 3551 boolean annotationApplicable(JCAnnotation a, Symbol s) { 3552 Optional<Set<Name>> targets = getApplicableTargets(a, s); 3553 /* the optional could be empty if the annotation is unknown in that case 3554 * we return that it is applicable and if it is erroneous that should imply 3555 * an error at the declaration site 3556 */ 3557 return targets.isEmpty() || targets.isPresent() && !targets.get().isEmpty(); 3558 } 3559 3560 Optional<Set<Name>> getApplicableTargets(JCAnnotation a, Symbol s) { 3561 Attribute.Array arr = getAttributeTargetAttribute(a.annotationType.type.tsym); 3562 Name[] targets; 3563 Set<Name> applicableTargets = new HashSet<>(); 3564 3565 if (arr == null) { 3566 targets = defaultTargetMetaInfo(); 3567 } else { 3568 // TODO: can we optimize this? 3569 targets = new Name[arr.values.length]; 3570 for (int i=0; i<arr.values.length; ++i) { 3571 Attribute app = arr.values[i]; 3572 if (!(app instanceof Attribute.Enum attributeEnum)) { 3573 // recovery 3574 return Optional.empty(); 3575 } 3576 targets[i] = attributeEnum.value.name; 3577 } 3578 } 3579 for (Name target : targets) { 3580 if (target == names.TYPE) { 3581 if (s.kind == TYP) 3582 applicableTargets.add(names.TYPE); 3583 } else if (target == names.FIELD) { 3584 if (s.kind == VAR && s.owner.kind != MTH) 3585 applicableTargets.add(names.FIELD); 3586 } else if (target == names.RECORD_COMPONENT) { 3587 if (s.getKind() == ElementKind.RECORD_COMPONENT) { 3588 applicableTargets.add(names.RECORD_COMPONENT); 3589 } 3590 } else if (target == names.METHOD) { 3591 if (s.kind == MTH && !s.isConstructor()) 3592 applicableTargets.add(names.METHOD); 3593 } else if (target == names.PARAMETER) { 3594 if (s.kind == VAR && 3595 (s.owner.kind == MTH && (s.flags() & PARAMETER) != 0)) { 3596 applicableTargets.add(names.PARAMETER); 3597 } 3598 } else if (target == names.CONSTRUCTOR) { 3599 if (s.kind == MTH && s.isConstructor()) 3600 applicableTargets.add(names.CONSTRUCTOR); 3601 } else if (target == names.LOCAL_VARIABLE) { 3602 if (s.kind == VAR && s.owner.kind == MTH && 3603 (s.flags() & PARAMETER) == 0) { 3604 applicableTargets.add(names.LOCAL_VARIABLE); 3605 } 3606 } else if (target == names.ANNOTATION_TYPE) { 3607 if (s.kind == TYP && (s.flags() & ANNOTATION) != 0) { 3608 applicableTargets.add(names.ANNOTATION_TYPE); 3609 } 3610 } else if (target == names.PACKAGE) { 3611 if (s.kind == PCK) 3612 applicableTargets.add(names.PACKAGE); 3613 } else if (target == names.TYPE_USE) { 3614 if (s.kind == VAR && s.owner.kind == MTH && s.type.hasTag(NONE)) { 3615 //cannot type annotate implicitly typed locals 3616 continue; 3617 } else if (s.kind == TYP || s.kind == VAR || 3618 (s.kind == MTH && !s.isConstructor() && 3619 !s.type.getReturnType().hasTag(VOID)) || 3620 (s.kind == MTH && s.isConstructor())) { 3621 applicableTargets.add(names.TYPE_USE); 3622 } 3623 } else if (target == names.TYPE_PARAMETER) { 3624 if (s.kind == TYP && s.type.hasTag(TYPEVAR)) 3625 applicableTargets.add(names.TYPE_PARAMETER); 3626 } else if (target == names.MODULE) { 3627 if (s.kind == MDL) 3628 applicableTargets.add(names.MODULE); 3629 } else { 3630 log.error(a, Errors.AnnotationUnrecognizedAttributeName(a.type, target)); 3631 return Optional.empty(); // Unknown ElementType 3632 } 3633 } 3634 return Optional.of(applicableTargets); 3635 } 3636 3637 Attribute.Array getAttributeTargetAttribute(TypeSymbol s) { 3638 Attribute.Compound atTarget = s.getAnnotationTypeMetadata().getTarget(); 3639 if (atTarget == null) return null; // ok, is applicable 3640 Attribute atValue = atTarget.member(names.value); 3641 return (atValue instanceof Attribute.Array attributeArray) ? attributeArray : null; 3642 } 3643 3644 private Name[] dfltTargetMeta; 3645 private Name[] defaultTargetMetaInfo() { 3646 if (dfltTargetMeta == null) { 3647 ArrayList<Name> defaultTargets = new ArrayList<>(); 3648 defaultTargets.add(names.PACKAGE); 3649 defaultTargets.add(names.TYPE); 3650 defaultTargets.add(names.FIELD); 3651 defaultTargets.add(names.METHOD); 3652 defaultTargets.add(names.CONSTRUCTOR); 3653 defaultTargets.add(names.ANNOTATION_TYPE); 3654 defaultTargets.add(names.LOCAL_VARIABLE); 3655 defaultTargets.add(names.PARAMETER); 3656 if (allowRecords) { 3657 defaultTargets.add(names.RECORD_COMPONENT); 3658 } 3659 if (allowModules) { 3660 defaultTargets.add(names.MODULE); 3661 } 3662 dfltTargetMeta = defaultTargets.toArray(new Name[0]); 3663 } 3664 return dfltTargetMeta; 3665 } 3666 3667 /** Check an annotation value. 3668 * 3669 * @param a The annotation tree to check 3670 * @return true if this annotation tree is valid, otherwise false 3671 */ 3672 public boolean validateAnnotationDeferErrors(JCAnnotation a) { 3673 boolean res = false; 3674 final Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log); 3675 try { 3676 res = validateAnnotation(a); 3677 } finally { 3678 log.popDiagnosticHandler(diagHandler); 3679 } 3680 return res; 3681 } 3682 3683 private boolean validateAnnotation(JCAnnotation a) { 3684 boolean isValid = true; 3685 AnnotationTypeMetadata metadata = a.annotationType.type.tsym.getAnnotationTypeMetadata(); 3686 3687 // collect an inventory of the annotation elements 3688 Set<MethodSymbol> elements = metadata.getAnnotationElements(); 3689 3690 // remove the ones that are assigned values 3691 for (JCTree arg : a.args) { 3692 if (!arg.hasTag(ASSIGN)) continue; // recovery 3693 JCAssign assign = (JCAssign)arg; 3694 Symbol m = TreeInfo.symbol(assign.lhs); 3695 if (m == null || m.type.isErroneous()) continue; 3696 if (!elements.remove(m)) { 3697 isValid = false; 3698 log.error(assign.lhs.pos(), 3699 Errors.DuplicateAnnotationMemberValue(m.name, a.type)); 3700 } 3701 } 3702 3703 // all the remaining ones better have default values 3704 List<Name> missingDefaults = List.nil(); 3705 Set<MethodSymbol> membersWithDefault = metadata.getAnnotationElementsWithDefault(); 3706 for (MethodSymbol m : elements) { 3707 if (m.type.isErroneous()) 3708 continue; 3709 3710 if (!membersWithDefault.contains(m)) 3711 missingDefaults = missingDefaults.append(m.name); 3712 } 3713 missingDefaults = missingDefaults.reverse(); 3714 if (missingDefaults.nonEmpty()) { 3715 isValid = false; 3716 Error errorKey = (missingDefaults.size() > 1) 3717 ? Errors.AnnotationMissingDefaultValue1(a.type, missingDefaults) 3718 : Errors.AnnotationMissingDefaultValue(a.type, missingDefaults); 3719 log.error(a.pos(), errorKey); 3720 } 3721 3722 return isValid && validateTargetAnnotationValue(a); 3723 } 3724 3725 /* Validate the special java.lang.annotation.Target annotation */ 3726 boolean validateTargetAnnotationValue(JCAnnotation a) { 3727 // special case: java.lang.annotation.Target must not have 3728 // repeated values in its value member 3729 if (a.annotationType.type.tsym != syms.annotationTargetType.tsym || 3730 a.args.tail == null) 3731 return true; 3732 3733 boolean isValid = true; 3734 if (!a.args.head.hasTag(ASSIGN)) return false; // error recovery 3735 JCAssign assign = (JCAssign) a.args.head; 3736 Symbol m = TreeInfo.symbol(assign.lhs); 3737 if (m.name != names.value) return false; 3738 JCTree rhs = assign.rhs; 3739 if (!rhs.hasTag(NEWARRAY)) return false; 3740 JCNewArray na = (JCNewArray) rhs; 3741 Set<Symbol> targets = new HashSet<>(); 3742 for (JCTree elem : na.elems) { 3743 if (!targets.add(TreeInfo.symbol(elem))) { 3744 isValid = false; 3745 log.error(elem.pos(), Errors.RepeatedAnnotationTarget); 3746 } 3747 } 3748 return isValid; 3749 } 3750 3751 void checkDeprecatedAnnotation(DiagnosticPosition pos, Symbol s) { 3752 if (lint.isEnabled(LintCategory.DEP_ANN) && s.isDeprecatableViaAnnotation() && 3753 (s.flags() & DEPRECATED) != 0 && 3754 !syms.deprecatedType.isErroneous() && 3755 s.attribute(syms.deprecatedType.tsym) == null) { 3756 log.warning(LintCategory.DEP_ANN, 3757 pos, Warnings.MissingDeprecatedAnnotation); 3758 } 3759 // Note: @Deprecated has no effect on local variables, parameters and package decls. 3760 if (lint.isEnabled(LintCategory.DEPRECATION) && !s.isDeprecatableViaAnnotation()) { 3761 if (!syms.deprecatedType.isErroneous() && s.attribute(syms.deprecatedType.tsym) != null) { 3762 log.warning(LintCategory.DEPRECATION, pos, 3763 Warnings.DeprecatedAnnotationHasNoEffect(Kinds.kindName(s))); 3764 } 3765 } 3766 } 3767 3768 void checkDeprecated(final DiagnosticPosition pos, final Symbol other, final Symbol s) { 3769 checkDeprecated(() -> pos, other, s); 3770 } 3771 3772 void checkDeprecated(Supplier<DiagnosticPosition> pos, final Symbol other, final Symbol s) { 3773 if ( (s.isDeprecatedForRemoval() 3774 || s.isDeprecated() && !other.isDeprecated()) 3775 && (s.outermostClass() != other.outermostClass() || s.outermostClass() == null) 3776 && s.kind != Kind.PCK) { 3777 deferredLintHandler.report(() -> warnDeprecated(pos.get(), s)); 3778 } 3779 } 3780 3781 void checkSunAPI(final DiagnosticPosition pos, final Symbol s) { 3782 if ((s.flags() & PROPRIETARY) != 0) { 3783 deferredLintHandler.report(() -> { 3784 log.mandatoryWarning(pos, Warnings.SunProprietary(s)); 3785 }); 3786 } 3787 } 3788 3789 void checkProfile(final DiagnosticPosition pos, final Symbol s) { 3790 if (profile != Profile.DEFAULT && (s.flags() & NOT_IN_PROFILE) != 0) { 3791 log.error(pos, Errors.NotInProfile(s, profile)); 3792 } 3793 } 3794 3795 void checkPreview(DiagnosticPosition pos, Symbol other, Symbol s) { 3796 if ((s.flags() & PREVIEW_API) != 0 && !preview.participatesInPreview(syms, other, s)) { 3797 if ((s.flags() & PREVIEW_REFLECTIVE) == 0) { 3798 if (!preview.isEnabled()) { 3799 log.error(pos, Errors.IsPreview(s)); 3800 } else { 3801 preview.markUsesPreview(pos); 3802 deferredLintHandler.report(() -> warnPreviewAPI(pos, Warnings.IsPreview(s))); 3803 } 3804 } else { 3805 deferredLintHandler.report(() -> warnPreviewAPI(pos, Warnings.IsPreviewReflective(s))); 3806 } 3807 } 3808 if (preview.declaredUsingPreviewFeature(s)) { 3809 if (preview.isEnabled()) { 3810 //for preview disabled do presumably so not need to do anything? 3811 //If "s" is compiled from source, then there was an error for it already; 3812 //if "s" is from classfile, there already was an error for the classfile. 3813 preview.markUsesPreview(pos); 3814 deferredLintHandler.report(() -> warnDeclaredUsingPreview(pos, s)); 3815 } 3816 } 3817 } 3818 3819 /* ************************************************************************* 3820 * Check for recursive annotation elements. 3821 **************************************************************************/ 3822 3823 /** Check for cycles in the graph of annotation elements. 3824 */ 3825 void checkNonCyclicElements(JCClassDecl tree) { 3826 if ((tree.sym.flags_field & ANNOTATION) == 0) return; 3827 Assert.check((tree.sym.flags_field & LOCKED) == 0); 3828 try { 3829 tree.sym.flags_field |= LOCKED; 3830 for (JCTree def : tree.defs) { 3831 if (!def.hasTag(METHODDEF)) continue; 3832 JCMethodDecl meth = (JCMethodDecl)def; 3833 checkAnnotationResType(meth.pos(), meth.restype.type); 3834 } 3835 } finally { 3836 tree.sym.flags_field &= ~LOCKED; 3837 tree.sym.flags_field |= ACYCLIC_ANN; 3838 } 3839 } 3840 3841 void checkNonCyclicElementsInternal(DiagnosticPosition pos, TypeSymbol tsym) { 3842 if ((tsym.flags_field & ACYCLIC_ANN) != 0) 3843 return; 3844 if ((tsym.flags_field & LOCKED) != 0) { 3845 log.error(pos, Errors.CyclicAnnotationElement(tsym)); 3846 return; 3847 } 3848 try { 3849 tsym.flags_field |= LOCKED; 3850 for (Symbol s : tsym.members().getSymbols(NON_RECURSIVE)) { 3851 if (s.kind != MTH) 3852 continue; 3853 checkAnnotationResType(pos, ((MethodSymbol)s).type.getReturnType()); 3854 } 3855 } finally { 3856 tsym.flags_field &= ~LOCKED; 3857 tsym.flags_field |= ACYCLIC_ANN; 3858 } 3859 } 3860 3861 void checkAnnotationResType(DiagnosticPosition pos, Type type) { 3862 switch (type.getTag()) { 3863 case CLASS: 3864 if ((type.tsym.flags() & ANNOTATION) != 0) 3865 checkNonCyclicElementsInternal(pos, type.tsym); 3866 break; 3867 case ARRAY: 3868 checkAnnotationResType(pos, types.elemtype(type)); 3869 break; 3870 default: 3871 break; // int etc 3872 } 3873 } 3874 3875 /* ************************************************************************* 3876 * Check for cycles in the constructor call graph. 3877 **************************************************************************/ 3878 3879 /** Check for cycles in the graph of constructors calling other 3880 * constructors. 3881 */ 3882 void checkCyclicConstructors(JCClassDecl tree) { 3883 // use LinkedHashMap so we generate errors deterministically 3884 Map<Symbol,Symbol> callMap = new LinkedHashMap<>(); 3885 3886 // enter each constructor this-call into the map 3887 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { 3888 JCMethodInvocation app = TreeInfo.firstConstructorCall(l.head); 3889 if (app == null) continue; 3890 JCMethodDecl meth = (JCMethodDecl) l.head; 3891 if (TreeInfo.name(app.meth) == names._this) { 3892 callMap.put(meth.sym, TreeInfo.symbol(app.meth)); 3893 } else { 3894 meth.sym.flags_field |= ACYCLIC; 3895 } 3896 } 3897 3898 // Check for cycles in the map 3899 Symbol[] ctors = new Symbol[0]; 3900 ctors = callMap.keySet().toArray(ctors); 3901 for (Symbol caller : ctors) { 3902 checkCyclicConstructor(tree, caller, callMap); 3903 } 3904 } 3905 3906 /** Look in the map to see if the given constructor is part of a 3907 * call cycle. 3908 */ 3909 private void checkCyclicConstructor(JCClassDecl tree, Symbol ctor, 3910 Map<Symbol,Symbol> callMap) { 3911 if (ctor != null && (ctor.flags_field & ACYCLIC) == 0) { 3912 if ((ctor.flags_field & LOCKED) != 0) { 3913 log.error(TreeInfo.diagnosticPositionFor(ctor, tree, false, t -> t.hasTag(IDENT)), 3914 Errors.RecursiveCtorInvocation); 3915 } else { 3916 ctor.flags_field |= LOCKED; 3917 checkCyclicConstructor(tree, callMap.remove(ctor), callMap); 3918 ctor.flags_field &= ~LOCKED; 3919 } 3920 ctor.flags_field |= ACYCLIC; 3921 } 3922 } 3923 3924 /* ************************************************************************* 3925 * Miscellaneous 3926 **************************************************************************/ 3927 3928 /** 3929 * Check for division by integer constant zero 3930 * @param pos Position for error reporting. 3931 * @param operator The operator for the expression 3932 * @param operand The right hand operand for the expression 3933 */ 3934 void checkDivZero(final DiagnosticPosition pos, Symbol operator, Type operand) { 3935 if (operand.constValue() != null 3936 && operand.getTag().isSubRangeOf(LONG) 3937 && ((Number) (operand.constValue())).longValue() == 0) { 3938 int opc = ((OperatorSymbol)operator).opcode; 3939 if (opc == ByteCodes.idiv || opc == ByteCodes.imod 3940 || opc == ByteCodes.ldiv || opc == ByteCodes.lmod) { 3941 deferredLintHandler.report(() -> warnDivZero(pos)); 3942 } 3943 } 3944 } 3945 3946 /** 3947 * Check for possible loss of precission 3948 * @param pos Position for error reporting. 3949 * @param found The computed type of the tree 3950 * @param req The computed type of the tree 3951 */ 3952 void checkLossOfPrecision(final DiagnosticPosition pos, Type found, Type req) { 3953 if (found.isNumeric() && req.isNumeric() && !types.isAssignable(found, req)) { 3954 deferredLintHandler.report(() -> { 3955 if (lint.isEnabled(LintCategory.LOSSY_CONVERSIONS)) 3956 log.warning(LintCategory.LOSSY_CONVERSIONS, 3957 pos, Warnings.PossibleLossOfPrecision(found, req)); 3958 }); 3959 } 3960 } 3961 3962 /** 3963 * Check for empty statements after if 3964 */ 3965 void checkEmptyIf(JCIf tree) { 3966 if (tree.thenpart.hasTag(SKIP) && tree.elsepart == null && 3967 lint.isEnabled(LintCategory.EMPTY)) 3968 log.warning(LintCategory.EMPTY, tree.thenpart.pos(), Warnings.EmptyIf); 3969 } 3970 3971 /** Check that symbol is unique in given scope. 3972 * @param pos Position for error reporting. 3973 * @param sym The symbol. 3974 * @param s The scope. 3975 */ 3976 boolean checkUnique(DiagnosticPosition pos, Symbol sym, Scope s) { 3977 if (sym.type.isErroneous()) 3978 return true; 3979 if (sym.owner.name == names.any) return false; 3980 for (Symbol byName : s.getSymbolsByName(sym.name, NON_RECURSIVE)) { 3981 if (sym != byName && 3982 (byName.flags() & CLASH) == 0 && 3983 sym.kind == byName.kind && 3984 sym.name != names.error && 3985 (sym.kind != MTH || 3986 types.hasSameArgs(sym.type, byName.type) || 3987 types.hasSameArgs(types.erasure(sym.type), types.erasure(byName.type)))) { 3988 if ((sym.flags() & VARARGS) != (byName.flags() & VARARGS)) { 3989 sym.flags_field |= CLASH; 3990 varargsDuplicateError(pos, sym, byName); 3991 return true; 3992 } else if (sym.kind == MTH && !types.hasSameArgs(sym.type, byName.type, false)) { 3993 duplicateErasureError(pos, sym, byName); 3994 sym.flags_field |= CLASH; 3995 return true; 3996 } else if ((sym.flags() & MATCH_BINDING) != 0 && 3997 (byName.flags() & MATCH_BINDING) != 0 && 3998 (byName.flags() & MATCH_BINDING_TO_OUTER) == 0) { 3999 if (!sym.type.isErroneous()) { 4000 log.error(pos, Errors.MatchBindingExists); 4001 sym.flags_field |= CLASH; 4002 } 4003 return false; 4004 } else { 4005 duplicateError(pos, byName); 4006 return false; 4007 } 4008 } 4009 } 4010 return true; 4011 } 4012 4013 /** Report duplicate declaration error. 4014 */ 4015 void duplicateErasureError(DiagnosticPosition pos, Symbol sym1, Symbol sym2) { 4016 if (!sym1.type.isErroneous() && !sym2.type.isErroneous()) { 4017 log.error(pos, Errors.NameClashSameErasure(sym1, sym2)); 4018 } 4019 } 4020 4021 /**Check that types imported through the ordinary imports don't clash with types imported 4022 * by other (static or ordinary) imports. Note that two static imports may import two clashing 4023 * types without an error on the imports. 4024 * @param toplevel The toplevel tree for which the test should be performed. 4025 */ 4026 void checkImportsUnique(JCCompilationUnit toplevel) { 4027 WriteableScope ordinallyImportedSoFar = WriteableScope.create(toplevel.packge); 4028 WriteableScope staticallyImportedSoFar = WriteableScope.create(toplevel.packge); 4029 WriteableScope topLevelScope = toplevel.toplevelScope; 4030 4031 for (JCTree def : toplevel.defs) { 4032 if (!def.hasTag(IMPORT)) 4033 continue; 4034 4035 JCImport imp = (JCImport) def; 4036 4037 if (imp.importScope == null) 4038 continue; 4039 4040 for (Symbol sym : imp.importScope.getSymbols(sym -> sym.kind == TYP)) { 4041 if (imp.isStatic()) { 4042 checkUniqueImport(imp.pos(), ordinallyImportedSoFar, staticallyImportedSoFar, topLevelScope, sym, true); 4043 staticallyImportedSoFar.enter(sym); 4044 } else { 4045 checkUniqueImport(imp.pos(), ordinallyImportedSoFar, staticallyImportedSoFar, topLevelScope, sym, false); 4046 ordinallyImportedSoFar.enter(sym); 4047 } 4048 } 4049 4050 imp.importScope = null; 4051 } 4052 } 4053 4054 /** Check that single-type import is not already imported or top-level defined, 4055 * but make an exception for two single-type imports which denote the same type. 4056 * @param pos Position for error reporting. 4057 * @param ordinallyImportedSoFar A Scope containing types imported so far through 4058 * ordinary imports. 4059 * @param staticallyImportedSoFar A Scope containing types imported so far through 4060 * static imports. 4061 * @param topLevelScope The current file's top-level Scope 4062 * @param sym The symbol. 4063 * @param staticImport Whether or not this was a static import 4064 */ 4065 private boolean checkUniqueImport(DiagnosticPosition pos, Scope ordinallyImportedSoFar, 4066 Scope staticallyImportedSoFar, Scope topLevelScope, 4067 Symbol sym, boolean staticImport) { 4068 Predicate<Symbol> duplicates = candidate -> candidate != sym && !candidate.type.isErroneous(); 4069 Symbol ordinaryClashing = ordinallyImportedSoFar.findFirst(sym.name, duplicates); 4070 Symbol staticClashing = null; 4071 if (ordinaryClashing == null && !staticImport) { 4072 staticClashing = staticallyImportedSoFar.findFirst(sym.name, duplicates); 4073 } 4074 if (ordinaryClashing != null || staticClashing != null) { 4075 if (ordinaryClashing != null) 4076 log.error(pos, Errors.AlreadyDefinedSingleImport(ordinaryClashing)); 4077 else 4078 log.error(pos, Errors.AlreadyDefinedStaticSingleImport(staticClashing)); 4079 return false; 4080 } 4081 Symbol clashing = topLevelScope.findFirst(sym.name, duplicates); 4082 if (clashing != null) { 4083 log.error(pos, Errors.AlreadyDefinedThisUnit(clashing)); 4084 return false; 4085 } 4086 return true; 4087 } 4088 4089 /** Check that a qualified name is in canonical form (for import decls). 4090 */ 4091 public void checkCanonical(JCTree tree) { 4092 if (!isCanonical(tree)) 4093 log.error(tree.pos(), 4094 Errors.ImportRequiresCanonical(TreeInfo.symbol(tree))); 4095 } 4096 // where 4097 private boolean isCanonical(JCTree tree) { 4098 while (tree.hasTag(SELECT)) { 4099 JCFieldAccess s = (JCFieldAccess) tree; 4100 if (s.sym.owner.getQualifiedName() != TreeInfo.symbol(s.selected).getQualifiedName()) 4101 return false; 4102 tree = s.selected; 4103 } 4104 return true; 4105 } 4106 4107 /** Check that an auxiliary class is not accessed from any other file than its own. 4108 */ 4109 void checkForBadAuxiliaryClassAccess(DiagnosticPosition pos, Env<AttrContext> env, ClassSymbol c) { 4110 if (lint.isEnabled(Lint.LintCategory.AUXILIARYCLASS) && 4111 (c.flags() & AUXILIARY) != 0 && 4112 rs.isAccessible(env, c) && 4113 !fileManager.isSameFile(c.sourcefile, env.toplevel.sourcefile)) 4114 { 4115 log.warning(pos, 4116 Warnings.AuxiliaryClassAccessedFromOutsideOfItsSourceFile(c, c.sourcefile)); 4117 } 4118 } 4119 4120 /** 4121 * Check for a default constructor in an exported package. 4122 */ 4123 void checkDefaultConstructor(ClassSymbol c, DiagnosticPosition pos) { 4124 if (lint.isEnabled(LintCategory.MISSING_EXPLICIT_CTOR) && 4125 ((c.flags() & (ENUM | RECORD)) == 0) && 4126 !c.isAnonymous() && 4127 ((c.flags() & (PUBLIC | PROTECTED)) != 0) && 4128 Feature.MODULES.allowedInSource(source)) { 4129 NestingKind nestingKind = c.getNestingKind(); 4130 switch (nestingKind) { 4131 case ANONYMOUS, 4132 LOCAL -> {return;} 4133 case TOP_LEVEL -> {;} // No additional checks needed 4134 case MEMBER -> { 4135 // For nested member classes, all the enclosing 4136 // classes must be public or protected. 4137 Symbol owner = c.owner; 4138 while (owner != null && owner.kind == TYP) { 4139 if ((owner.flags() & (PUBLIC | PROTECTED)) == 0) 4140 return; 4141 owner = owner.owner; 4142 } 4143 } 4144 } 4145 4146 // Only check classes in named packages exported by its module 4147 PackageSymbol pkg = c.packge(); 4148 if (!pkg.isUnnamed()) { 4149 ModuleSymbol modle = pkg.modle; 4150 for (ExportsDirective exportDir : modle.exports) { 4151 // Report warning only if the containing 4152 // package is unconditionally exported 4153 if (exportDir.packge.equals(pkg)) { 4154 if (exportDir.modules == null || exportDir.modules.isEmpty()) { 4155 // Warning may be suppressed by 4156 // annotations; check again for being 4157 // enabled in the deferred context. 4158 deferredLintHandler.report(() -> { 4159 if (lint.isEnabled(LintCategory.MISSING_EXPLICIT_CTOR)) 4160 log.warning(LintCategory.MISSING_EXPLICIT_CTOR, 4161 pos, Warnings.MissingExplicitCtor(c, pkg, modle)); 4162 }); 4163 } else { 4164 return; 4165 } 4166 } 4167 } 4168 } 4169 } 4170 return; 4171 } 4172 4173 private class ConversionWarner extends Warner { 4174 final String uncheckedKey; 4175 final Type found; 4176 final Type expected; 4177 public ConversionWarner(DiagnosticPosition pos, String uncheckedKey, Type found, Type expected) { 4178 super(pos); 4179 this.uncheckedKey = uncheckedKey; 4180 this.found = found; 4181 this.expected = expected; 4182 } 4183 4184 @Override 4185 public void warn(LintCategory lint) { 4186 boolean warned = this.warned; 4187 super.warn(lint); 4188 if (warned) return; // suppress redundant diagnostics 4189 switch (lint) { 4190 case UNCHECKED: 4191 Check.this.warnUnchecked(pos(), Warnings.ProbFoundReq(diags.fragment(uncheckedKey), found, expected)); 4192 break; 4193 case VARARGS: 4194 if (method != null && 4195 method.attribute(syms.trustMeType.tsym) != null && 4196 isTrustMeAllowedOnMethod(method) && 4197 !types.isReifiable(method.type.getParameterTypes().last())) { 4198 Check.this.warnUnsafeVararg(pos(), Warnings.VarargsUnsafeUseVarargsParam(method.params.last())); 4199 } 4200 break; 4201 default: 4202 throw new AssertionError("Unexpected lint: " + lint); 4203 } 4204 } 4205 } 4206 4207 public Warner castWarner(DiagnosticPosition pos, Type found, Type expected) { 4208 return new ConversionWarner(pos, "unchecked.cast.to.type", found, expected); 4209 } 4210 4211 public Warner convertWarner(DiagnosticPosition pos, Type found, Type expected) { 4212 return new ConversionWarner(pos, "unchecked.assign", found, expected); 4213 } 4214 4215 public void checkFunctionalInterface(JCClassDecl tree, ClassSymbol cs) { 4216 Compound functionalType = cs.attribute(syms.functionalInterfaceType.tsym); 4217 4218 if (functionalType != null) { 4219 try { 4220 types.findDescriptorSymbol((TypeSymbol)cs); 4221 } catch (Types.FunctionDescriptorLookupError ex) { 4222 DiagnosticPosition pos = tree.pos(); 4223 for (JCAnnotation a : tree.getModifiers().annotations) { 4224 if (a.annotationType.type.tsym == syms.functionalInterfaceType.tsym) { 4225 pos = a.pos(); 4226 break; 4227 } 4228 } 4229 log.error(pos, Errors.BadFunctionalIntfAnno1(ex.getDiagnostic())); 4230 } 4231 } 4232 } 4233 4234 public void checkImportsResolvable(final JCCompilationUnit toplevel) { 4235 for (final JCImport imp : toplevel.getImports()) { 4236 if (!imp.staticImport || !imp.qualid.hasTag(SELECT)) 4237 continue; 4238 final JCFieldAccess select = imp.qualid; 4239 final Symbol origin; 4240 if (select.name == names.asterisk || (origin = TreeInfo.symbol(select.selected)) == null || origin.kind != TYP) 4241 continue; 4242 4243 TypeSymbol site = (TypeSymbol) TreeInfo.symbol(select.selected); 4244 if (!checkTypeContainsImportableElement(site, site, toplevel.packge, select.name, new HashSet<Symbol>())) { 4245 log.error(imp.pos(), 4246 Errors.CantResolveLocation(KindName.STATIC, 4247 select.name, 4248 null, 4249 null, 4250 Fragments.Location(kindName(site), 4251 site, 4252 null))); 4253 } 4254 } 4255 } 4256 4257 // Check that packages imported are in scope (JLS 7.4.3, 6.3, 6.5.3.1, 6.5.3.2) 4258 public void checkImportedPackagesObservable(final JCCompilationUnit toplevel) { 4259 OUTER: for (JCImport imp : toplevel.getImports()) { 4260 if (!imp.staticImport && TreeInfo.name(imp.qualid) == names.asterisk) { 4261 TypeSymbol tsym = imp.qualid.selected.type.tsym; 4262 if (tsym.kind == PCK && tsym.members().isEmpty() && 4263 !(Feature.IMPORT_ON_DEMAND_OBSERVABLE_PACKAGES.allowedInSource(source) && tsym.exists())) { 4264 log.error(DiagnosticFlag.RESOLVE_ERROR, imp.pos, Errors.DoesntExist(tsym)); 4265 } 4266 } 4267 } 4268 } 4269 4270 private boolean checkTypeContainsImportableElement(TypeSymbol tsym, TypeSymbol origin, PackageSymbol packge, Name name, Set<Symbol> processed) { 4271 if (tsym == null || !processed.add(tsym)) 4272 return false; 4273 4274 // also search through inherited names 4275 if (checkTypeContainsImportableElement(types.supertype(tsym.type).tsym, origin, packge, name, processed)) 4276 return true; 4277 4278 for (Type t : types.interfaces(tsym.type)) 4279 if (checkTypeContainsImportableElement(t.tsym, origin, packge, name, processed)) 4280 return true; 4281 4282 for (Symbol sym : tsym.members().getSymbolsByName(name)) { 4283 if (sym.isStatic() && 4284 importAccessible(sym, packge) && 4285 sym.isMemberOf(origin, types)) { 4286 return true; 4287 } 4288 } 4289 4290 return false; 4291 } 4292 4293 // is the sym accessible everywhere in packge? 4294 public boolean importAccessible(Symbol sym, PackageSymbol packge) { 4295 try { 4296 int flags = (int)(sym.flags() & AccessFlags); 4297 switch (flags) { 4298 default: 4299 case PUBLIC: 4300 return true; 4301 case PRIVATE: 4302 return false; 4303 case 0: 4304 case PROTECTED: 4305 return sym.packge() == packge; 4306 } 4307 } catch (ClassFinder.BadClassFile err) { 4308 throw err; 4309 } catch (CompletionFailure ex) { 4310 return false; 4311 } 4312 } 4313 4314 public void checkLeaksNotAccessible(Env<AttrContext> env, JCClassDecl check) { 4315 JCCompilationUnit toplevel = env.toplevel; 4316 4317 if ( toplevel.modle == syms.unnamedModule 4318 || toplevel.modle == syms.noModule 4319 || (check.sym.flags() & COMPOUND) != 0) { 4320 return ; 4321 } 4322 4323 ExportsDirective currentExport = findExport(toplevel.packge); 4324 4325 if ( currentExport == null //not exported 4326 || currentExport.modules != null) //don't check classes in qualified export 4327 return ; 4328 4329 new TreeScanner() { 4330 Lint lint = env.info.lint; 4331 boolean inSuperType; 4332 4333 @Override 4334 public void visitBlock(JCBlock tree) { 4335 } 4336 @Override 4337 public void visitMethodDef(JCMethodDecl tree) { 4338 if (!isAPISymbol(tree.sym)) 4339 return; 4340 Lint prevLint = lint; 4341 try { 4342 lint = lint.augment(tree.sym); 4343 if (lint.isEnabled(LintCategory.EXPORTS)) { 4344 super.visitMethodDef(tree); 4345 } 4346 } finally { 4347 lint = prevLint; 4348 } 4349 } 4350 @Override 4351 public void visitVarDef(JCVariableDecl tree) { 4352 if (!isAPISymbol(tree.sym) && tree.sym.owner.kind != MTH) 4353 return; 4354 Lint prevLint = lint; 4355 try { 4356 lint = lint.augment(tree.sym); 4357 if (lint.isEnabled(LintCategory.EXPORTS)) { 4358 scan(tree.mods); 4359 scan(tree.vartype); 4360 } 4361 } finally { 4362 lint = prevLint; 4363 } 4364 } 4365 @Override 4366 public void visitClassDef(JCClassDecl tree) { 4367 if (tree != check) 4368 return ; 4369 4370 if (!isAPISymbol(tree.sym)) 4371 return ; 4372 4373 Lint prevLint = lint; 4374 try { 4375 lint = lint.augment(tree.sym); 4376 if (lint.isEnabled(LintCategory.EXPORTS)) { 4377 scan(tree.mods); 4378 scan(tree.typarams); 4379 try { 4380 inSuperType = true; 4381 scan(tree.extending); 4382 scan(tree.implementing); 4383 } finally { 4384 inSuperType = false; 4385 } 4386 scan(tree.defs); 4387 } 4388 } finally { 4389 lint = prevLint; 4390 } 4391 } 4392 @Override 4393 public void visitTypeApply(JCTypeApply tree) { 4394 scan(tree.clazz); 4395 boolean oldInSuperType = inSuperType; 4396 try { 4397 inSuperType = false; 4398 scan(tree.arguments); 4399 } finally { 4400 inSuperType = oldInSuperType; 4401 } 4402 } 4403 @Override 4404 public void visitIdent(JCIdent tree) { 4405 Symbol sym = TreeInfo.symbol(tree); 4406 if (sym.kind == TYP && !sym.type.hasTag(TYPEVAR)) { 4407 checkVisible(tree.pos(), sym, toplevel.packge, inSuperType); 4408 } 4409 } 4410 4411 @Override 4412 public void visitSelect(JCFieldAccess tree) { 4413 Symbol sym = TreeInfo.symbol(tree); 4414 Symbol sitesym = TreeInfo.symbol(tree.selected); 4415 if (sym.kind == TYP && sitesym.kind == PCK) { 4416 checkVisible(tree.pos(), sym, toplevel.packge, inSuperType); 4417 } else { 4418 super.visitSelect(tree); 4419 } 4420 } 4421 4422 @Override 4423 public void visitAnnotation(JCAnnotation tree) { 4424 if (tree.attribute.type.tsym.getAnnotation(java.lang.annotation.Documented.class) != null) 4425 super.visitAnnotation(tree); 4426 } 4427 4428 }.scan(check); 4429 } 4430 //where: 4431 private ExportsDirective findExport(PackageSymbol pack) { 4432 for (ExportsDirective d : pack.modle.exports) { 4433 if (d.packge == pack) 4434 return d; 4435 } 4436 4437 return null; 4438 } 4439 private boolean isAPISymbol(Symbol sym) { 4440 while (sym.kind != PCK) { 4441 if ((sym.flags() & Flags.PUBLIC) == 0 && (sym.flags() & Flags.PROTECTED) == 0) { 4442 return false; 4443 } 4444 sym = sym.owner; 4445 } 4446 return true; 4447 } 4448 private void checkVisible(DiagnosticPosition pos, Symbol what, PackageSymbol inPackage, boolean inSuperType) { 4449 if (!isAPISymbol(what) && !inSuperType) { //package private/private element 4450 log.warning(LintCategory.EXPORTS, pos, Warnings.LeaksNotAccessible(kindName(what), what, what.packge().modle)); 4451 return ; 4452 } 4453 4454 PackageSymbol whatPackage = what.packge(); 4455 ExportsDirective whatExport = findExport(whatPackage); 4456 ExportsDirective inExport = findExport(inPackage); 4457 4458 if (whatExport == null) { //package not exported: 4459 log.warning(LintCategory.EXPORTS, pos, Warnings.LeaksNotAccessibleUnexported(kindName(what), what, what.packge().modle)); 4460 return ; 4461 } 4462 4463 if (whatExport.modules != null) { 4464 if (inExport.modules == null || !whatExport.modules.containsAll(inExport.modules)) { 4465 log.warning(LintCategory.EXPORTS, pos, Warnings.LeaksNotAccessibleUnexportedQualified(kindName(what), what, what.packge().modle)); 4466 } 4467 } 4468 4469 if (whatPackage.modle != inPackage.modle && whatPackage.modle != syms.java_base) { 4470 //check that relativeTo.modle requires transitive what.modle, somehow: 4471 List<ModuleSymbol> todo = List.of(inPackage.modle); 4472 4473 while (todo.nonEmpty()) { 4474 ModuleSymbol current = todo.head; 4475 todo = todo.tail; 4476 if (current == whatPackage.modle) 4477 return ; //OK 4478 if ((current.flags() & Flags.AUTOMATIC_MODULE) != 0) 4479 continue; //for automatic modules, don't look into their dependencies 4480 for (RequiresDirective req : current.requires) { 4481 if (req.isTransitive()) { 4482 todo = todo.prepend(req.module); 4483 } 4484 } 4485 } 4486 4487 log.warning(LintCategory.EXPORTS, pos, Warnings.LeaksNotAccessibleNotRequiredTransitive(kindName(what), what, what.packge().modle)); 4488 } 4489 } 4490 4491 void checkModuleExists(final DiagnosticPosition pos, ModuleSymbol msym) { 4492 if (msym.kind != MDL) { 4493 deferredLintHandler.report(() -> { 4494 if (lint.isEnabled(LintCategory.MODULE)) 4495 log.warning(LintCategory.MODULE, pos, Warnings.ModuleNotFound(msym)); 4496 }); 4497 } 4498 } 4499 4500 void checkPackageExistsForOpens(final DiagnosticPosition pos, PackageSymbol packge) { 4501 if (packge.members().isEmpty() && 4502 ((packge.flags() & Flags.HAS_RESOURCE) == 0)) { 4503 deferredLintHandler.report(() -> { 4504 if (lint.isEnabled(LintCategory.OPENS)) 4505 log.warning(pos, Warnings.PackageEmptyOrNotFound(packge)); 4506 }); 4507 } 4508 } 4509 4510 void checkModuleRequires(final DiagnosticPosition pos, final RequiresDirective rd) { 4511 if ((rd.module.flags() & Flags.AUTOMATIC_MODULE) != 0) { 4512 deferredLintHandler.report(() -> { 4513 if (rd.isTransitive() && lint.isEnabled(LintCategory.REQUIRES_TRANSITIVE_AUTOMATIC)) { 4514 log.warning(pos, Warnings.RequiresTransitiveAutomatic); 4515 } else if (lint.isEnabled(LintCategory.REQUIRES_AUTOMATIC)) { 4516 log.warning(pos, Warnings.RequiresAutomatic); 4517 } 4518 }); 4519 } 4520 } 4521 4522 /** 4523 * Verify the case labels conform to the constraints. Checks constraints related 4524 * combinations of patterns and other labels. 4525 * 4526 * @param cases the cases that should be checked. 4527 */ 4528 void checkSwitchCaseStructure(List<JCCase> cases) { 4529 for (List<JCCase> l = cases; l.nonEmpty(); l = l.tail) { 4530 JCCase c = l.head; 4531 if (c.labels.head instanceof JCConstantCaseLabel constLabel) { 4532 if (TreeInfo.isNull(constLabel.expr)) { 4533 if (c.labels.tail.nonEmpty()) { 4534 if (c.labels.tail.head instanceof JCDefaultCaseLabel defLabel) { 4535 if (c.labels.tail.tail.nonEmpty()) { 4536 log.error(c.labels.tail.tail.head.pos(), Errors.InvalidCaseLabelCombination); 4537 } 4538 } else { 4539 log.error(c.labels.tail.head.pos(), Errors.InvalidCaseLabelCombination); 4540 } 4541 } 4542 } else { 4543 for (JCCaseLabel label : c.labels.tail) { 4544 if (!(label instanceof JCConstantCaseLabel) || TreeInfo.isNullCaseLabel(label)) { 4545 log.error(label.pos(), Errors.InvalidCaseLabelCombination); 4546 break; 4547 } 4548 } 4549 } 4550 } else { 4551 if (c.labels.tail.nonEmpty()) { 4552 log.error(c.labels.tail.head.pos(), Errors.FlowsThroughFromPattern); 4553 } 4554 } 4555 } 4556 4557 boolean isCaseStatementGroup = cases.nonEmpty() && 4558 cases.head.caseKind == CaseTree.CaseKind.STATEMENT; 4559 4560 if (isCaseStatementGroup) { 4561 boolean previousCompletessNormally = false; 4562 for (List<JCCase> l = cases; l.nonEmpty(); l = l.tail) { 4563 JCCase c = l.head; 4564 if (previousCompletessNormally && 4565 c.stats.nonEmpty() && 4566 c.labels.head instanceof JCPatternCaseLabel patternLabel && 4567 hasBindings(patternLabel.pat)) { 4568 log.error(c.labels.head.pos(), Errors.FlowsThroughToPattern); 4569 } else if (c.stats.isEmpty() && 4570 c.labels.head instanceof JCPatternCaseLabel patternLabel && 4571 hasBindings(patternLabel.pat) && 4572 hasStatements(l.tail)) { 4573 log.error(c.labels.head.pos(), Errors.FlowsThroughFromPattern); 4574 } 4575 previousCompletessNormally = c.completesNormally; 4576 } 4577 } 4578 } 4579 4580 boolean hasBindings(JCPattern p) { 4581 boolean[] bindings = new boolean[1]; 4582 4583 new TreeScanner() { 4584 @Override 4585 public void visitBindingPattern(JCBindingPattern tree) { 4586 bindings[0] = true; 4587 super.visitBindingPattern(tree); 4588 } 4589 }.scan(p); 4590 4591 return bindings[0]; 4592 } 4593 4594 boolean hasStatements(List<JCCase> cases) { 4595 for (List<JCCase> l = cases; l.nonEmpty(); l = l.tail) { 4596 if (l.head.stats.nonEmpty()) { 4597 return true; 4598 } 4599 } 4600 4601 return false; 4602 } 4603 void checkSwitchCaseLabelDominated(List<JCCase> cases) { 4604 List<JCCaseLabel> caseLabels = List.nil(); 4605 boolean seenDefault = false; 4606 boolean seenDefaultLabel = false; 4607 boolean warnDominatedByDefault = false; 4608 for (List<JCCase> l = cases; l.nonEmpty(); l = l.tail) { 4609 JCCase c = l.head; 4610 for (JCCaseLabel label : c.labels) { 4611 if (label.hasTag(DEFAULTCASELABEL)) { 4612 seenDefault = true; 4613 seenDefaultLabel |= 4614 TreeInfo.isNullCaseLabel(c.labels.head); 4615 continue; 4616 } 4617 if (TreeInfo.isNullCaseLabel(label)) { 4618 if (seenDefault) { 4619 log.error(label.pos(), Errors.PatternDominated); 4620 } 4621 continue; 4622 } 4623 if (seenDefault && !warnDominatedByDefault) { 4624 if (label.hasTag(PATTERNCASELABEL) || 4625 (label instanceof JCConstantCaseLabel && seenDefaultLabel)) { 4626 log.error(label.pos(), Errors.PatternDominated); 4627 warnDominatedByDefault = true; 4628 } 4629 } 4630 Type currentType = labelType(label); 4631 for (JCCaseLabel testCaseLabel : caseLabels) { 4632 Type testType = labelType(testCaseLabel); 4633 if (types.isSubtype(currentType, testType) && 4634 !currentType.hasTag(ERROR) && !testType.hasTag(ERROR)) { 4635 //the current label is potentially dominated by the existing (test) label, check: 4636 boolean dominated = false; 4637 if (label instanceof JCConstantCaseLabel) { 4638 dominated |= !(testCaseLabel instanceof JCConstantCaseLabel); 4639 } else if (label instanceof JCPatternCaseLabel patternCL && 4640 testCaseLabel instanceof JCPatternCaseLabel testPatternCaseLabel && 4641 TreeInfo.unguardedCaseLabel(testCaseLabel)) { 4642 dominated = patternDominated(testPatternCaseLabel.pat, 4643 patternCL.pat); 4644 } 4645 if (dominated) { 4646 log.error(label.pos(), Errors.PatternDominated); 4647 } 4648 } 4649 } 4650 caseLabels = caseLabels.prepend(label); 4651 } 4652 } 4653 } 4654 //where: 4655 private Type labelType(JCCaseLabel label) { 4656 return types.erasure(switch (label.getTag()) { 4657 case PATTERNCASELABEL -> ((JCPatternCaseLabel) label).pat.type; 4658 case CONSTANTCASELABEL -> types.boxedTypeOrType(((JCConstantCaseLabel) label).expr.type); 4659 default -> throw Assert.error("Unexpected tree kind: " + label.getTag()); 4660 }); 4661 } 4662 private boolean patternDominated(JCPattern existingPattern, JCPattern currentPattern) { 4663 Type existingPatternType = types.erasure(existingPattern.type); 4664 Type currentPatternType = types.erasure(currentPattern.type); 4665 if (existingPatternType.isPrimitive() ^ currentPatternType.isPrimitive()) { 4666 return false; 4667 } 4668 if (existingPatternType.isPrimitive()) { 4669 return types.isSameType(existingPatternType, currentPatternType); 4670 } else { 4671 if (!types.isSubtype(currentPatternType, existingPatternType)) { 4672 return false; 4673 } 4674 } 4675 while (existingPattern instanceof JCParenthesizedPattern parenthesized) { 4676 existingPattern = parenthesized.pattern; 4677 } 4678 while (currentPattern instanceof JCParenthesizedPattern parenthesized) { 4679 currentPattern = parenthesized.pattern; 4680 } 4681 if (currentPattern instanceof JCBindingPattern) { 4682 return existingPattern instanceof JCBindingPattern; 4683 } else if (currentPattern instanceof JCRecordPattern currentRecordPattern) { 4684 if (existingPattern instanceof JCBindingPattern) { 4685 return true; 4686 } else if (existingPattern instanceof JCRecordPattern existingRecordPattern) { 4687 List<JCPattern> existingNested = existingRecordPattern.nested; 4688 List<JCPattern> currentNested = currentRecordPattern.nested; 4689 if (existingNested.size() != currentNested.size()) { 4690 return false; 4691 } 4692 while (existingNested.nonEmpty()) { 4693 if (!patternDominated(existingNested.head, currentNested.head)) { 4694 return false; 4695 } 4696 existingNested = existingNested.tail; 4697 currentNested = currentNested.tail; 4698 } 4699 return true; 4700 } else { 4701 Assert.error("Unknown pattern: " + existingPattern.getTag()); 4702 } 4703 } else { 4704 Assert.error("Unknown pattern: " + currentPattern.getTag()); 4705 } 4706 return false; 4707 } 4708 4709 /** check if a type is a subtype of Externalizable, if that is available. */ 4710 boolean isExternalizable(Type t) { 4711 try { 4712 syms.externalizableType.complete(); 4713 } 4714 catch (CompletionFailure e) { 4715 return false; 4716 } 4717 return types.isSubtype(t, syms.externalizableType); 4718 } 4719 4720 /** 4721 * Check structure of serialization declarations. 4722 */ 4723 public void checkSerialStructure(JCClassDecl tree, ClassSymbol c) { 4724 (new SerialTypeVisitor()).visit(c, tree); 4725 } 4726 4727 /** 4728 * This visitor will warn if a serialization-related field or 4729 * method is declared in a suspicious or incorrect way. In 4730 * particular, it will warn for cases where the runtime 4731 * serialization mechanism will silently ignore a mis-declared 4732 * entity. 4733 * 4734 * Distinguished serialization-related fields and methods: 4735 * 4736 * Methods: 4737 * 4738 * private void writeObject(ObjectOutputStream stream) throws IOException 4739 * ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException 4740 * 4741 * private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException 4742 * private void readObjectNoData() throws ObjectStreamException 4743 * ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException 4744 * 4745 * Fields: 4746 * 4747 * private static final long serialVersionUID 4748 * private static final ObjectStreamField[] serialPersistentFields 4749 * 4750 * Externalizable: methods defined on the interface 4751 * public void writeExternal(ObjectOutput) throws IOException 4752 * public void readExternal(ObjectInput) throws IOException 4753 */ 4754 private class SerialTypeVisitor extends ElementKindVisitor14<Void, JCClassDecl> { 4755 SerialTypeVisitor() { 4756 this.lint = Check.this.lint; 4757 } 4758 4759 private static final Set<String> serialMethodNames = 4760 Set.of("writeObject", "writeReplace", 4761 "readObject", "readObjectNoData", 4762 "readResolve"); 4763 4764 private static final Set<String> serialFieldNames = 4765 Set.of("serialVersionUID", "serialPersistentFields"); 4766 4767 // Type of serialPersistentFields 4768 private final Type OSF_TYPE = new Type.ArrayType(syms.objectStreamFieldType, syms.arrayClass); 4769 4770 Lint lint; 4771 4772 @Override 4773 public Void defaultAction(Element e, JCClassDecl p) { 4774 throw new IllegalArgumentException(Objects.requireNonNullElse(e.toString(), "")); 4775 } 4776 4777 @Override 4778 public Void visitType(TypeElement e, JCClassDecl p) { 4779 runUnderLint(e, p, (symbol, param) -> super.visitType(symbol, param)); 4780 return null; 4781 } 4782 4783 @Override 4784 public Void visitTypeAsClass(TypeElement e, 4785 JCClassDecl p) { 4786 // Anonymous classes filtered out by caller. 4787 4788 ClassSymbol c = (ClassSymbol)e; 4789 4790 checkCtorAccess(p, c); 4791 4792 // Check for missing serialVersionUID; check *not* done 4793 // for enums or records. 4794 VarSymbol svuidSym = null; 4795 for (Symbol sym : c.members().getSymbolsByName(names.serialVersionUID)) { 4796 if (sym.kind == VAR) { 4797 svuidSym = (VarSymbol)sym; 4798 break; 4799 } 4800 } 4801 4802 if (svuidSym == null) { 4803 log.warning(LintCategory.SERIAL, p.pos(), Warnings.MissingSVUID(c)); 4804 } 4805 4806 // Check for serialPersistentFields to gate checks for 4807 // non-serializable non-transient instance fields 4808 boolean serialPersistentFieldsPresent = 4809 c.members() 4810 .getSymbolsByName(names.serialPersistentFields, sym -> sym.kind == VAR) 4811 .iterator() 4812 .hasNext(); 4813 4814 // Check declarations of serialization-related methods and 4815 // fields 4816 for(Symbol el : c.getEnclosedElements()) { 4817 runUnderLint(el, p, (enclosed, tree) -> { 4818 String name = null; 4819 switch(enclosed.getKind()) { 4820 case FIELD -> { 4821 if (!serialPersistentFieldsPresent) { 4822 var flags = enclosed.flags(); 4823 if ( ((flags & TRANSIENT) == 0) && 4824 ((flags & STATIC) == 0)) { 4825 Type varType = enclosed.asType(); 4826 if (!canBeSerialized(varType)) { 4827 // Note per JLS arrays are 4828 // serializable even if the 4829 // component type is not. 4830 log.warning(LintCategory.SERIAL, 4831 TreeInfo.diagnosticPositionFor(enclosed, tree), 4832 Warnings.NonSerializableInstanceField); 4833 } else if (varType.hasTag(ARRAY)) { 4834 ArrayType arrayType = (ArrayType)varType; 4835 Type elementType = arrayType.elemtype; 4836 while (elementType.hasTag(ARRAY)) { 4837 arrayType = (ArrayType)elementType; 4838 elementType = arrayType.elemtype; 4839 } 4840 if (!canBeSerialized(elementType)) { 4841 log.warning(LintCategory.SERIAL, 4842 TreeInfo.diagnosticPositionFor(enclosed, tree), 4843 Warnings.NonSerializableInstanceFieldArray(elementType)); 4844 } 4845 } 4846 } 4847 } 4848 4849 name = enclosed.getSimpleName().toString(); 4850 if (serialFieldNames.contains(name)) { 4851 VarSymbol field = (VarSymbol)enclosed; 4852 switch (name) { 4853 case "serialVersionUID" -> checkSerialVersionUID(tree, e, field); 4854 case "serialPersistentFields" -> checkSerialPersistentFields(tree, e, field); 4855 default -> throw new AssertionError(); 4856 } 4857 } 4858 } 4859 4860 // Correctly checking the serialization-related 4861 // methods is subtle. For the methods declared to be 4862 // private or directly declared in the class, the 4863 // enclosed elements of the class can be checked in 4864 // turn. However, writeReplace and readResolve can be 4865 // declared in a superclass and inherited. Note that 4866 // the runtime lookup walks the superclass chain 4867 // looking for writeReplace/readResolve via 4868 // Class.getDeclaredMethod. This differs from calling 4869 // Elements.getAllMembers(TypeElement) as the latter 4870 // will also pull in default methods from 4871 // superinterfaces. In other words, the runtime checks 4872 // (which long predate default methods on interfaces) 4873 // do not admit the possibility of inheriting methods 4874 // this way, a difference from general inheritance. 4875 4876 // The current implementation just checks the enclosed 4877 // elements and does not directly check the inherited 4878 // methods. If all the types are being checked this is 4879 // less of a concern; however, there are cases that 4880 // could be missed. In particular, readResolve and 4881 // writeReplace could, in principle, by inherited from 4882 // a non-serializable superclass and thus not checked 4883 // even if compiled with a serializable child class. 4884 case METHOD -> { 4885 var method = (MethodSymbol)enclosed; 4886 name = method.getSimpleName().toString(); 4887 if (serialMethodNames.contains(name)) { 4888 switch (name) { 4889 case "writeObject" -> checkWriteObject(tree, e, method); 4890 case "writeReplace" -> checkWriteReplace(tree,e, method); 4891 case "readObject" -> checkReadObject(tree,e, method); 4892 case "readObjectNoData" -> checkReadObjectNoData(tree, e, method); 4893 case "readResolve" -> checkReadResolve(tree, e, method); 4894 default -> throw new AssertionError(); 4895 } 4896 } 4897 } 4898 } 4899 }); 4900 } 4901 4902 return null; 4903 } 4904 4905 boolean canBeSerialized(Type type) { 4906 return type.isPrimitive() || rs.isSerializable(type); 4907 } 4908 4909 /** 4910 * Check that Externalizable class needs a public no-arg 4911 * constructor. 4912 * 4913 * Check that a Serializable class has access to the no-arg 4914 * constructor of its first nonserializable superclass. 4915 */ 4916 private void checkCtorAccess(JCClassDecl tree, ClassSymbol c) { 4917 if (isExternalizable(c.type)) { 4918 for(var sym : c.getEnclosedElements()) { 4919 if (sym.isConstructor() && 4920 ((sym.flags() & PUBLIC) == PUBLIC)) { 4921 if (((MethodSymbol)sym).getParameters().isEmpty()) { 4922 return; 4923 } 4924 } 4925 } 4926 log.warning(LintCategory.SERIAL, tree.pos(), 4927 Warnings.ExternalizableMissingPublicNoArgCtor); 4928 } else { 4929 // Approximate access to the no-arg constructor up in 4930 // the superclass chain by checking that the 4931 // constructor is not private. This may not handle 4932 // some cross-package situations correctly. 4933 Type superClass = c.getSuperclass(); 4934 // java.lang.Object is *not* Serializable so this loop 4935 // should terminate. 4936 while (rs.isSerializable(superClass) ) { 4937 try { 4938 superClass = (Type)((TypeElement)(((DeclaredType)superClass)).asElement()).getSuperclass(); 4939 } catch(ClassCastException cce) { 4940 return ; // Don't try to recover 4941 } 4942 } 4943 // Non-Serializable superclass 4944 try { 4945 ClassSymbol supertype = ((ClassSymbol)(((DeclaredType)superClass).asElement())); 4946 for(var sym : supertype.getEnclosedElements()) { 4947 if (sym.isConstructor()) { 4948 MethodSymbol ctor = (MethodSymbol)sym; 4949 if (ctor.getParameters().isEmpty()) { 4950 if (((ctor.flags() & PRIVATE) == PRIVATE) || 4951 // Handle nested classes and implicit this$0 4952 (supertype.getNestingKind() == NestingKind.MEMBER && 4953 ((supertype.flags() & STATIC) == 0))) 4954 log.warning(LintCategory.SERIAL, tree.pos(), 4955 Warnings.SerializableMissingAccessNoArgCtor(supertype.getQualifiedName())); 4956 } 4957 } 4958 } 4959 } catch (ClassCastException cce) { 4960 return ; // Don't try to recover 4961 } 4962 return; 4963 } 4964 } 4965 4966 private void checkSerialVersionUID(JCClassDecl tree, Element e, VarSymbol svuid) { 4967 // To be effective, serialVersionUID must be marked static 4968 // and final, but private is recommended. But alas, in 4969 // practice there are many non-private serialVersionUID 4970 // fields. 4971 if ((svuid.flags() & (STATIC | FINAL)) != 4972 (STATIC | FINAL)) { 4973 log.warning(LintCategory.SERIAL, 4974 TreeInfo.diagnosticPositionFor(svuid, tree), 4975 Warnings.ImproperSVUID((Symbol)e)); 4976 } 4977 4978 // check svuid has type long 4979 if (!svuid.type.hasTag(LONG)) { 4980 log.warning(LintCategory.SERIAL, 4981 TreeInfo.diagnosticPositionFor(svuid, tree), 4982 Warnings.LongSVUID((Symbol)e)); 4983 } 4984 4985 if (svuid.getConstValue() == null) 4986 log.warning(LintCategory.SERIAL, 4987 TreeInfo.diagnosticPositionFor(svuid, tree), 4988 Warnings.ConstantSVUID((Symbol)e)); 4989 } 4990 4991 private void checkSerialPersistentFields(JCClassDecl tree, Element e, VarSymbol spf) { 4992 // To be effective, serialPersisentFields must be private, static, and final. 4993 if ((spf.flags() & (PRIVATE | STATIC | FINAL)) != 4994 (PRIVATE | STATIC | FINAL)) { 4995 log.warning(LintCategory.SERIAL, 4996 TreeInfo.diagnosticPositionFor(spf, tree), Warnings.ImproperSPF); 4997 } 4998 4999 if (!types.isSameType(spf.type, OSF_TYPE)) { 5000 log.warning(LintCategory.SERIAL, 5001 TreeInfo.diagnosticPositionFor(spf, tree), Warnings.OSFArraySPF); 5002 } 5003 5004 if (isExternalizable((Type)(e.asType()))) { 5005 log.warning(LintCategory.SERIAL, tree.pos(), 5006 Warnings.IneffectualSerialFieldExternalizable); 5007 } 5008 5009 // Warn if serialPersistentFields is initialized to a 5010 // literal null. 5011 JCTree spfDecl = TreeInfo.declarationFor(spf, tree); 5012 if (spfDecl != null && spfDecl.getTag() == VARDEF) { 5013 JCVariableDecl variableDef = (JCVariableDecl) spfDecl; 5014 JCExpression initExpr = variableDef.init; 5015 if (initExpr != null && TreeInfo.isNull(initExpr)) { 5016 log.warning(LintCategory.SERIAL, initExpr.pos(), 5017 Warnings.SPFNullInit); 5018 } 5019 } 5020 } 5021 5022 private void checkWriteObject(JCClassDecl tree, Element e, MethodSymbol method) { 5023 // The "synchronized" modifier is seen in the wild on 5024 // readObject and writeObject methods and is generally 5025 // innocuous. 5026 5027 // private void writeObject(ObjectOutputStream stream) throws IOException 5028 checkPrivateNonStaticMethod(tree, method); 5029 checkReturnType(tree, e, method, syms.voidType); 5030 checkOneArg(tree, e, method, syms.objectOutputStreamType); 5031 checkExceptions(tree, e, method, syms.ioExceptionType); 5032 checkExternalizable(tree, e, method); 5033 } 5034 5035 private void checkWriteReplace(JCClassDecl tree, Element e, MethodSymbol method) { 5036 // ANY-ACCESS-MODIFIER Object writeReplace() throws 5037 // ObjectStreamException 5038 5039 // Excluding abstract, could have a more complicated 5040 // rule based on abstract-ness of the class 5041 checkConcreteInstanceMethod(tree, e, method); 5042 checkReturnType(tree, e, method, syms.objectType); 5043 checkNoArgs(tree, e, method); 5044 checkExceptions(tree, e, method, syms.objectStreamExceptionType); 5045 } 5046 5047 private void checkReadObject(JCClassDecl tree, Element e, MethodSymbol method) { 5048 // The "synchronized" modifier is seen in the wild on 5049 // readObject and writeObject methods and is generally 5050 // innocuous. 5051 5052 // private void readObject(ObjectInputStream stream) 5053 // throws IOException, ClassNotFoundException 5054 checkPrivateNonStaticMethod(tree, method); 5055 checkReturnType(tree, e, method, syms.voidType); 5056 checkOneArg(tree, e, method, syms.objectInputStreamType); 5057 checkExceptions(tree, e, method, syms.ioExceptionType, syms.classNotFoundExceptionType); 5058 checkExternalizable(tree, e, method); 5059 } 5060 5061 private void checkReadObjectNoData(JCClassDecl tree, Element e, MethodSymbol method) { 5062 // private void readObjectNoData() throws ObjectStreamException 5063 checkPrivateNonStaticMethod(tree, method); 5064 checkReturnType(tree, e, method, syms.voidType); 5065 checkNoArgs(tree, e, method); 5066 checkExceptions(tree, e, method, syms.objectStreamExceptionType); 5067 checkExternalizable(tree, e, method); 5068 } 5069 5070 private void checkReadResolve(JCClassDecl tree, Element e, MethodSymbol method) { 5071 // ANY-ACCESS-MODIFIER Object readResolve() 5072 // throws ObjectStreamException 5073 5074 // Excluding abstract, could have a more complicated 5075 // rule based on abstract-ness of the class 5076 checkConcreteInstanceMethod(tree, e, method); 5077 checkReturnType(tree,e, method, syms.objectType); 5078 checkNoArgs(tree, e, method); 5079 checkExceptions(tree, e, method, syms.objectStreamExceptionType); 5080 } 5081 5082 void checkPrivateNonStaticMethod(JCClassDecl tree, MethodSymbol method) { 5083 var flags = method.flags(); 5084 if ((flags & PRIVATE) == 0) { 5085 log.warning(LintCategory.SERIAL, 5086 TreeInfo.diagnosticPositionFor(method, tree), 5087 Warnings.SerialMethodNotPrivate(method.getSimpleName())); 5088 } 5089 5090 if ((flags & STATIC) != 0) { 5091 log.warning(LintCategory.SERIAL, 5092 TreeInfo.diagnosticPositionFor(method, tree), 5093 Warnings.SerialMethodStatic(method.getSimpleName())); 5094 } 5095 } 5096 5097 /** 5098 * Per section 1.12 "Serialization of Enum Constants" of 5099 * the serialization specification, due to the special 5100 * serialization handling of enums, any writeObject, 5101 * readObject, writeReplace, and readResolve methods are 5102 * ignored as are serialPersistentFields and 5103 * serialVersionUID fields. 5104 */ 5105 @Override 5106 public Void visitTypeAsEnum(TypeElement e, 5107 JCClassDecl p) { 5108 for(Element el : e.getEnclosedElements()) { 5109 runUnderLint(el, p, (enclosed, tree) -> { 5110 String name = enclosed.getSimpleName().toString(); 5111 switch(enclosed.getKind()) { 5112 case FIELD -> { 5113 if (serialFieldNames.contains(name)) { 5114 log.warning(LintCategory.SERIAL, tree.pos(), 5115 Warnings.IneffectualSerialFieldEnum(name)); 5116 } 5117 } 5118 5119 case METHOD -> { 5120 if (serialMethodNames.contains(name)) { 5121 log.warning(LintCategory.SERIAL, tree.pos(), 5122 Warnings.IneffectualSerialMethodEnum(name)); 5123 } 5124 } 5125 } 5126 }); 5127 } 5128 return null; 5129 } 5130 5131 /** 5132 * Most serialization-related fields and methods on interfaces 5133 * are ineffectual or problematic. 5134 */ 5135 @Override 5136 public Void visitTypeAsInterface(TypeElement e, 5137 JCClassDecl p) { 5138 for(Element el : e.getEnclosedElements()) { 5139 runUnderLint(el, p, (enclosed, tree) -> { 5140 String name = null; 5141 switch(enclosed.getKind()) { 5142 case FIELD -> { 5143 var field = (VarSymbol)enclosed; 5144 name = field.getSimpleName().toString(); 5145 switch(name) { 5146 case "serialPersistentFields" -> { 5147 log.warning(LintCategory.SERIAL, 5148 TreeInfo.diagnosticPositionFor(field, tree), 5149 Warnings.IneffectualSerialFieldInterface); 5150 } 5151 5152 case "serialVersionUID" -> { 5153 checkSerialVersionUID(tree, e, field); 5154 } 5155 } 5156 } 5157 5158 case METHOD -> { 5159 var method = (MethodSymbol)enclosed; 5160 name = enclosed.getSimpleName().toString(); 5161 if (serialMethodNames.contains(name)) { 5162 switch (name) { 5163 case 5164 "readObject", 5165 "readObjectNoData", 5166 "writeObject" -> checkPrivateMethod(tree, e, method); 5167 5168 case 5169 "writeReplace", 5170 "readResolve" -> checkDefaultIneffective(tree, e, method); 5171 5172 default -> throw new AssertionError(); 5173 } 5174 5175 } 5176 } 5177 } 5178 }); 5179 } 5180 5181 return null; 5182 } 5183 5184 private void checkPrivateMethod(JCClassDecl tree, 5185 Element e, 5186 MethodSymbol method) { 5187 if ((method.flags() & PRIVATE) == 0) { 5188 log.warning(LintCategory.SERIAL, 5189 TreeInfo.diagnosticPositionFor(method, tree), 5190 Warnings.NonPrivateMethodWeakerAccess); 5191 } 5192 } 5193 5194 private void checkDefaultIneffective(JCClassDecl tree, 5195 Element e, 5196 MethodSymbol method) { 5197 if ((method.flags() & DEFAULT) == DEFAULT) { 5198 log.warning(LintCategory.SERIAL, 5199 TreeInfo.diagnosticPositionFor(method, tree), 5200 Warnings.DefaultIneffective); 5201 5202 } 5203 } 5204 5205 @Override 5206 public Void visitTypeAsAnnotationType(TypeElement e, 5207 JCClassDecl p) { 5208 // Per the JLS, annotation types are not serializeable 5209 return null; 5210 } 5211 5212 /** 5213 * From the Java Object Serialization Specification, 1.13 5214 * Serialization of Records: 5215 * 5216 * "The process by which record objects are serialized or 5217 * externalized cannot be customized; any class-specific 5218 * writeObject, readObject, readObjectNoData, writeExternal, 5219 * and readExternal methods defined by record classes are 5220 * ignored during serialization and deserialization. However, 5221 * a substitute object to be serialized or a designate 5222 * replacement may be specified, by the writeReplace and 5223 * readResolve methods, respectively. Any 5224 * serialPersistentFields field declaration is 5225 * ignored. Documenting serializable fields and data for 5226 * record classes is unnecessary, since there is no variation 5227 * in the serial form, other than whether a substitute or 5228 * replacement object is used. The serialVersionUID of a 5229 * record class is 0L unless explicitly declared. The 5230 * requirement for matching serialVersionUID values is waived 5231 * for record classes." 5232 */ 5233 @Override 5234 public Void visitTypeAsRecord(TypeElement e, 5235 JCClassDecl p) { 5236 for(Element el : e.getEnclosedElements()) { 5237 runUnderLint(el, p, (enclosed, tree) -> { 5238 String name = enclosed.getSimpleName().toString(); 5239 switch(enclosed.getKind()) { 5240 case FIELD -> { 5241 switch(name) { 5242 case "serialPersistentFields" -> { 5243 log.warning(LintCategory.SERIAL, tree.pos(), 5244 Warnings.IneffectualSerialFieldRecord); 5245 } 5246 5247 case "serialVersionUID" -> { 5248 // Could generate additional warning that 5249 // svuid value is not checked to match for 5250 // records. 5251 checkSerialVersionUID(tree, e, (VarSymbol)enclosed); 5252 } 5253 5254 } 5255 } 5256 5257 case METHOD -> { 5258 var method = (MethodSymbol)enclosed; 5259 switch(name) { 5260 case "writeReplace" -> checkWriteReplace(tree, e, method); 5261 case "readResolve" -> checkReadResolve(tree, e, method); 5262 default -> { 5263 if (serialMethodNames.contains(name)) { 5264 log.warning(LintCategory.SERIAL, tree.pos(), 5265 Warnings.IneffectualSerialMethodRecord(name)); 5266 } 5267 } 5268 } 5269 5270 } 5271 } 5272 }); 5273 } 5274 return null; 5275 } 5276 5277 void checkConcreteInstanceMethod(JCClassDecl tree, 5278 Element enclosing, 5279 MethodSymbol method) { 5280 if ((method.flags() & (STATIC | ABSTRACT)) != 0) { 5281 log.warning(LintCategory.SERIAL, 5282 TreeInfo.diagnosticPositionFor(method, tree), 5283 Warnings.SerialConcreteInstanceMethod(method.getSimpleName())); 5284 } 5285 } 5286 5287 private void checkReturnType(JCClassDecl tree, 5288 Element enclosing, 5289 MethodSymbol method, 5290 Type expectedReturnType) { 5291 // Note: there may be complications checking writeReplace 5292 // and readResolve since they return Object and could, in 5293 // principle, have covariant overrides and any synthetic 5294 // bridge method would not be represented here for 5295 // checking. 5296 Type rtype = method.getReturnType(); 5297 if (!types.isSameType(expectedReturnType, rtype)) { 5298 log.warning(LintCategory.SERIAL, 5299 TreeInfo.diagnosticPositionFor(method, tree), 5300 Warnings.SerialMethodUnexpectedReturnType(method.getSimpleName(), 5301 rtype, expectedReturnType)); 5302 } 5303 } 5304 5305 private void checkOneArg(JCClassDecl tree, 5306 Element enclosing, 5307 MethodSymbol method, 5308 Type expectedType) { 5309 String name = method.getSimpleName().toString(); 5310 5311 var parameters= method.getParameters(); 5312 5313 if (parameters.size() != 1) { 5314 log.warning(LintCategory.SERIAL, 5315 TreeInfo.diagnosticPositionFor(method, tree), 5316 Warnings.SerialMethodOneArg(method.getSimpleName(), parameters.size())); 5317 return; 5318 } 5319 5320 Type parameterType = parameters.get(0).asType(); 5321 if (!types.isSameType(parameterType, expectedType)) { 5322 log.warning(LintCategory.SERIAL, 5323 TreeInfo.diagnosticPositionFor(method, tree), 5324 Warnings.SerialMethodParameterType(method.getSimpleName(), 5325 expectedType, 5326 parameterType)); 5327 } 5328 } 5329 5330 private void checkNoArgs(JCClassDecl tree, Element enclosing, MethodSymbol method) { 5331 var parameters = method.getParameters(); 5332 if (!parameters.isEmpty()) { 5333 log.warning(LintCategory.SERIAL, 5334 TreeInfo.diagnosticPositionFor(parameters.get(0), tree), 5335 Warnings.SerialMethodNoArgs(method.getSimpleName())); 5336 } 5337 } 5338 5339 private void checkExternalizable(JCClassDecl tree, Element enclosing, MethodSymbol method) { 5340 // If the enclosing class is externalizable, warn for the method 5341 if (isExternalizable((Type)enclosing.asType())) { 5342 log.warning(LintCategory.SERIAL, tree.pos(), 5343 Warnings.IneffectualSerialMethodExternalizable(method.getSimpleName())); 5344 } 5345 return; 5346 } 5347 5348 private void checkExceptions(JCClassDecl tree, 5349 Element enclosing, 5350 MethodSymbol method, 5351 Type... declaredExceptions) { 5352 for (Type thrownType: method.getThrownTypes()) { 5353 // For each exception in the throws clause of the 5354 // method, if not an Error and not a RuntimeException, 5355 // check if the exception is a subtype of a declared 5356 // exception from the throws clause of the 5357 // serialization method in question. 5358 if (types.isSubtype(thrownType, syms.runtimeExceptionType) || 5359 types.isSubtype(thrownType, syms.errorType) ) { 5360 continue; 5361 } else { 5362 boolean declared = false; 5363 for (Type declaredException : declaredExceptions) { 5364 if (types.isSubtype(thrownType, declaredException)) { 5365 declared = true; 5366 continue; 5367 } 5368 } 5369 if (!declared) { 5370 log.warning(LintCategory.SERIAL, 5371 TreeInfo.diagnosticPositionFor(method, tree), 5372 Warnings.SerialMethodUnexpectedException(method.getSimpleName(), 5373 thrownType)); 5374 } 5375 } 5376 } 5377 return; 5378 } 5379 5380 private <E extends Element> Void runUnderLint(E symbol, JCClassDecl p, BiConsumer<E, JCClassDecl> task) { 5381 Lint prevLint = lint; 5382 try { 5383 lint = lint.augment((Symbol) symbol); 5384 5385 if (lint.isEnabled(LintCategory.SERIAL)) { 5386 task.accept(symbol, p); 5387 } 5388 5389 return null; 5390 } finally { 5391 lint = prevLint; 5392 } 5393 } 5394 5395 } 5396 5397 }