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