1 /* 2 * Copyright (c) 1999, 2018, 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 30 import javax.tools.JavaFileManager; 31 32 import com.sun.tools.javac.code.*; 33 import com.sun.tools.javac.code.Attribute.Compound; 34 import com.sun.tools.javac.code.Directive.ExportsDirective; 35 import com.sun.tools.javac.code.Directive.RequiresDirective; 36 import com.sun.tools.javac.code.Source.Feature; 37 import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata; 38 import com.sun.tools.javac.jvm.*; 39 import com.sun.tools.javac.resources.CompilerProperties.Errors; 40 import com.sun.tools.javac.resources.CompilerProperties.Fragments; 41 import com.sun.tools.javac.resources.CompilerProperties.Warnings; 42 import com.sun.tools.javac.tree.*; 43 import com.sun.tools.javac.util.*; 44 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; 45 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 46 import com.sun.tools.javac.util.JCDiagnostic.Error; 47 import com.sun.tools.javac.util.JCDiagnostic.Fragment; 48 import com.sun.tools.javac.util.JCDiagnostic.Warning; 49 import com.sun.tools.javac.util.List; 50 51 import com.sun.tools.javac.code.Lint; 52 import com.sun.tools.javac.code.Lint.LintCategory; 53 import com.sun.tools.javac.code.Scope.WriteableScope; 54 import com.sun.tools.javac.code.Type.*; 55 import com.sun.tools.javac.code.Symbol.*; 56 import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext; 57 import com.sun.tools.javac.comp.Infer.FreeTypeListener; 58 import com.sun.tools.javac.tree.JCTree.*; 59 60 import static com.sun.tools.javac.code.Flags.*; 61 import static com.sun.tools.javac.code.Flags.ANNOTATION; 62 import static com.sun.tools.javac.code.Flags.SYNCHRONIZED; 63 import static com.sun.tools.javac.code.Kinds.*; 64 import static com.sun.tools.javac.code.Kinds.Kind.*; 65 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE; 66 import static com.sun.tools.javac.code.TypeTag.*; 67 import static com.sun.tools.javac.code.TypeTag.WILDCARD; 68 69 import static com.sun.tools.javac.tree.JCTree.Tag.*; 70 71 /** Type checking helper class for the attribution phase. 72 * 73 * <p><b>This is NOT part of any supported API. 74 * If you write code that depends on this, you do so at your own risk. 75 * This code and its internal interfaces are subject to change or 76 * deletion without notice.</b> 77 */ 78 public class Check { 79 protected static final Context.Key<Check> checkKey = new Context.Key<>(); 80 81 private final Names names; 82 private final Log log; 83 private final Resolve rs; 84 private final Symtab syms; 85 private final Enter enter; 86 private final DeferredAttr deferredAttr; 87 private final Infer infer; 88 private final Types types; 89 private final TypeAnnotations typeAnnotations; 90 private final JCDiagnostic.Factory diags; 91 private final JavaFileManager fileManager; 92 private final Source source; 93 private final Target target; 94 private final Profile profile; 95 private final boolean warnOnAnyAccessToMembers; 96 97 // The set of lint options currently in effect. It is initialized 98 // from the context, and then is set/reset as needed by Attr as it 99 // visits all the various parts of the trees during attribution. 100 private Lint lint; 101 102 // The method being analyzed in Attr - it is set/reset as needed by 103 // Attr as it visits new method declarations. 104 private MethodSymbol method; 105 instance(Context context)106 public static Check instance(Context context) { 107 Check instance = context.get(checkKey); 108 if (instance == null) 109 instance = new Check(context); 110 return instance; 111 } 112 Check(Context context)113 protected Check(Context context) { 114 context.put(checkKey, this); 115 116 names = Names.instance(context); 117 dfltTargetMeta = new Name[] { names.PACKAGE, names.TYPE, 118 names.FIELD, names.METHOD, names.CONSTRUCTOR, 119 names.ANNOTATION_TYPE, names.LOCAL_VARIABLE, names.PARAMETER}; 120 log = Log.instance(context); 121 rs = Resolve.instance(context); 122 syms = Symtab.instance(context); 123 enter = Enter.instance(context); 124 deferredAttr = DeferredAttr.instance(context); 125 infer = Infer.instance(context); 126 types = Types.instance(context); 127 typeAnnotations = TypeAnnotations.instance(context); 128 diags = JCDiagnostic.Factory.instance(context); 129 Options options = Options.instance(context); 130 lint = Lint.instance(context); 131 fileManager = context.get(JavaFileManager.class); 132 133 source = Source.instance(context); 134 target = Target.instance(context); 135 warnOnAnyAccessToMembers = options.isSet("warnOnAccessToMembers"); 136 137 Target target = Target.instance(context); 138 syntheticNameChar = target.syntheticNameChar(); 139 140 profile = Profile.instance(context); 141 142 boolean verboseDeprecated = lint.isEnabled(LintCategory.DEPRECATION); 143 boolean verboseRemoval = lint.isEnabled(LintCategory.REMOVAL); 144 boolean verboseUnchecked = lint.isEnabled(LintCategory.UNCHECKED); 145 boolean enforceMandatoryWarnings = true; 146 147 deprecationHandler = new MandatoryWarningHandler(log, verboseDeprecated, 148 enforceMandatoryWarnings, "deprecated", LintCategory.DEPRECATION); 149 removalHandler = new MandatoryWarningHandler(log, verboseRemoval, 150 enforceMandatoryWarnings, "removal", LintCategory.REMOVAL); 151 uncheckedHandler = new MandatoryWarningHandler(log, verboseUnchecked, 152 enforceMandatoryWarnings, "unchecked", LintCategory.UNCHECKED); 153 sunApiHandler = new MandatoryWarningHandler(log, false, 154 enforceMandatoryWarnings, "sunapi", null); 155 156 deferredLintHandler = DeferredLintHandler.instance(context); 157 } 158 159 /** Character for synthetic names 160 */ 161 char syntheticNameChar; 162 163 /** A table mapping flat names of all compiled classes for each module in this run 164 * to their symbols; maintained from outside. 165 */ 166 private Map<Pair<ModuleSymbol, Name>,ClassSymbol> compiled = new HashMap<>(); 167 168 /** A handler for messages about deprecated usage. 169 */ 170 private MandatoryWarningHandler deprecationHandler; 171 172 /** A handler for messages about deprecated-for-removal usage. 173 */ 174 private MandatoryWarningHandler removalHandler; 175 176 /** A handler for messages about unchecked or unsafe usage. 177 */ 178 private MandatoryWarningHandler uncheckedHandler; 179 180 /** A handler for messages about using proprietary API. 181 */ 182 private MandatoryWarningHandler sunApiHandler; 183 184 /** A handler for deferred lint warnings. 185 */ 186 private DeferredLintHandler deferredLintHandler; 187 188 /* ************************************************************************* 189 * Errors and Warnings 190 **************************************************************************/ 191 setLint(Lint newLint)192 Lint setLint(Lint newLint) { 193 Lint prev = lint; 194 lint = newLint; 195 return prev; 196 } 197 setMethod(MethodSymbol newMethod)198 MethodSymbol setMethod(MethodSymbol newMethod) { 199 MethodSymbol prev = method; 200 method = newMethod; 201 return prev; 202 } 203 204 /** Warn about deprecated symbol. 205 * @param pos Position to be used for error reporting. 206 * @param sym The deprecated symbol. 207 */ warnDeprecated(DiagnosticPosition pos, Symbol sym)208 void warnDeprecated(DiagnosticPosition pos, Symbol sym) { 209 if (sym.isDeprecatedForRemoval()) { 210 if (!lint.isSuppressed(LintCategory.REMOVAL)) { 211 if (sym.kind == MDL) { 212 removalHandler.report(pos, Warnings.HasBeenDeprecatedForRemovalModule(sym)); 213 } else { 214 removalHandler.report(pos, Warnings.HasBeenDeprecatedForRemoval(sym, sym.location())); 215 } 216 } 217 } else if (!lint.isSuppressed(LintCategory.DEPRECATION)) { 218 if (sym.kind == MDL) { 219 deprecationHandler.report(pos, Warnings.HasBeenDeprecatedModule(sym)); 220 } else { 221 deprecationHandler.report(pos, Warnings.HasBeenDeprecated(sym, sym.location())); 222 } 223 } 224 } 225 226 /** Warn about unchecked operation. 227 * @param pos Position to be used for error reporting. 228 * @param msg A string describing the problem. 229 */ warnUnchecked(DiagnosticPosition pos, Warning warnKey)230 public void warnUnchecked(DiagnosticPosition pos, Warning warnKey) { 231 if (!lint.isSuppressed(LintCategory.UNCHECKED)) 232 uncheckedHandler.report(pos, warnKey); 233 } 234 235 /** Warn about unsafe vararg method decl. 236 * @param pos Position to be used for error reporting. 237 */ warnUnsafeVararg(DiagnosticPosition pos, Warning warnKey)238 void warnUnsafeVararg(DiagnosticPosition pos, Warning warnKey) { 239 if (lint.isEnabled(LintCategory.VARARGS)) 240 log.warning(LintCategory.VARARGS, pos, warnKey); 241 } 242 warnStatic(DiagnosticPosition pos, Warning warnKey)243 public void warnStatic(DiagnosticPosition pos, Warning warnKey) { 244 if (lint.isEnabled(LintCategory.STATIC)) 245 log.warning(LintCategory.STATIC, pos, warnKey); 246 } 247 248 /** Warn about division by integer constant zero. 249 * @param pos Position to be used for error reporting. 250 */ warnDivZero(DiagnosticPosition pos)251 void warnDivZero(DiagnosticPosition pos) { 252 if (lint.isEnabled(LintCategory.DIVZERO)) 253 log.warning(LintCategory.DIVZERO, pos, Warnings.DivZero); 254 } 255 256 /** 257 * Report any deferred diagnostics. 258 */ reportDeferredDiagnostics()259 public void reportDeferredDiagnostics() { 260 deprecationHandler.reportDeferredDiagnostic(); 261 removalHandler.reportDeferredDiagnostic(); 262 uncheckedHandler.reportDeferredDiagnostic(); 263 sunApiHandler.reportDeferredDiagnostic(); 264 } 265 266 267 /** Report a failure to complete a class. 268 * @param pos Position to be used for error reporting. 269 * @param ex The failure to report. 270 */ completionError(DiagnosticPosition pos, CompletionFailure ex)271 public Type completionError(DiagnosticPosition pos, CompletionFailure ex) { 272 log.error(JCDiagnostic.DiagnosticFlag.NON_DEFERRABLE, pos, Errors.CantAccess(ex.sym, ex.getDetailValue())); 273 return syms.errType; 274 } 275 276 /** Report an error that wrong type tag was found. 277 * @param pos Position to be used for error reporting. 278 * @param required An internationalized string describing the type tag 279 * required. 280 * @param found The type that was found. 281 */ typeTagError(DiagnosticPosition pos, JCDiagnostic required, Object found)282 Type typeTagError(DiagnosticPosition pos, JCDiagnostic required, Object found) { 283 // this error used to be raised by the parser, 284 // but has been delayed to this point: 285 if (found instanceof Type && ((Type)found).hasTag(VOID)) { 286 log.error(pos, Errors.IllegalStartOfType); 287 return syms.errType; 288 } 289 log.error(pos, Errors.TypeFoundReq(found, required)); 290 return types.createErrorType(found instanceof Type ? (Type)found : syms.errType); 291 } 292 293 /** Report an error that symbol cannot be referenced before super 294 * has been called. 295 * @param pos Position to be used for error reporting. 296 * @param sym The referenced symbol. 297 */ earlyRefError(DiagnosticPosition pos, Symbol sym)298 void earlyRefError(DiagnosticPosition pos, Symbol sym) { 299 log.error(pos, Errors.CantRefBeforeCtorCalled(sym)); 300 } 301 302 /** Report duplicate declaration error. 303 */ duplicateError(DiagnosticPosition pos, Symbol sym)304 void duplicateError(DiagnosticPosition pos, Symbol sym) { 305 if (!sym.type.isErroneous()) { 306 Symbol location = sym.location(); 307 if (location.kind == MTH && 308 ((MethodSymbol)location).isStaticOrInstanceInit()) { 309 log.error(pos, 310 Errors.AlreadyDefinedInClinit(kindName(sym), 311 sym, 312 kindName(sym.location()), 313 kindName(sym.location().enclClass()), 314 sym.location().enclClass())); 315 } else { 316 log.error(pos, 317 Errors.AlreadyDefined(kindName(sym), 318 sym, 319 kindName(sym.location()), 320 sym.location())); 321 } 322 } 323 } 324 325 /** Report array/varargs duplicate declaration 326 */ varargsDuplicateError(DiagnosticPosition pos, Symbol sym1, Symbol sym2)327 void varargsDuplicateError(DiagnosticPosition pos, Symbol sym1, Symbol sym2) { 328 if (!sym1.type.isErroneous() && !sym2.type.isErroneous()) { 329 log.error(pos, Errors.ArrayAndVarargs(sym1, sym2, sym2.location())); 330 } 331 } 332 333 /* ************************************************************************ 334 * duplicate declaration checking 335 *************************************************************************/ 336 337 /** Check that variable does not hide variable with same name in 338 * immediately enclosing local scope. 339 * @param pos Position for error reporting. 340 * @param v The symbol. 341 * @param s The scope. 342 */ checkTransparentVar(DiagnosticPosition pos, VarSymbol v, Scope s)343 void checkTransparentVar(DiagnosticPosition pos, VarSymbol v, Scope s) { 344 for (Symbol sym : s.getSymbolsByName(v.name)) { 345 if (sym.owner != v.owner) break; 346 if (sym.kind == VAR && 347 sym.owner.kind.matches(KindSelector.VAL_MTH) && 348 v.name != names.error) { 349 duplicateError(pos, sym); 350 return; 351 } 352 } 353 } 354 355 /** Check that a class or interface does not hide a class or 356 * interface with same name in immediately enclosing local scope. 357 * @param pos Position for error reporting. 358 * @param c The symbol. 359 * @param s The scope. 360 */ checkTransparentClass(DiagnosticPosition pos, ClassSymbol c, Scope s)361 void checkTransparentClass(DiagnosticPosition pos, ClassSymbol c, Scope s) { 362 for (Symbol sym : s.getSymbolsByName(c.name)) { 363 if (sym.owner != c.owner) break; 364 if (sym.kind == TYP && !sym.type.hasTag(TYPEVAR) && 365 sym.owner.kind.matches(KindSelector.VAL_MTH) && 366 c.name != names.error) { 367 duplicateError(pos, sym); 368 return; 369 } 370 } 371 } 372 373 /** Check that class does not have the same name as one of 374 * its enclosing classes, or as a class defined in its enclosing scope. 375 * return true if class is unique in its enclosing scope. 376 * @param pos Position for error reporting. 377 * @param name The class name. 378 * @param s The enclosing scope. 379 */ checkUniqueClassName(DiagnosticPosition pos, Name name, Scope s)380 boolean checkUniqueClassName(DiagnosticPosition pos, Name name, Scope s) { 381 for (Symbol sym : s.getSymbolsByName(name, NON_RECURSIVE)) { 382 if (sym.kind == TYP && sym.name != names.error) { 383 duplicateError(pos, sym); 384 return false; 385 } 386 } 387 for (Symbol sym = s.owner; sym != null; sym = sym.owner) { 388 if (sym.kind == TYP && sym.name == name && sym.name != names.error) { 389 duplicateError(pos, sym); 390 return true; 391 } 392 } 393 return true; 394 } 395 396 /* ************************************************************************* 397 * Class name generation 398 **************************************************************************/ 399 400 401 private Map<Pair<Name, Name>, Integer> localClassNameIndexes = new HashMap<>(); 402 403 /** Return name of local class. 404 * This is of the form {@code <enclClass> $ n <classname> } 405 * where 406 * enclClass is the flat name of the enclosing class, 407 * classname is the simple name of the local class 408 */ localClassName(ClassSymbol c)409 Name localClassName(ClassSymbol c) { 410 Name enclFlatname = c.owner.enclClass().flatname; 411 String enclFlatnameStr = enclFlatname.toString(); 412 Pair<Name, Name> key = new Pair<>(enclFlatname, c.name); 413 Integer index = localClassNameIndexes.get(key); 414 for (int i = (index == null) ? 1 : index; ; i++) { 415 Name flatname = names.fromString(enclFlatnameStr 416 + syntheticNameChar + i + c.name); 417 if (getCompiled(c.packge().modle, flatname) == null) { 418 localClassNameIndexes.put(key, i + 1); 419 return flatname; 420 } 421 } 422 } 423 clearLocalClassNameIndexes(ClassSymbol c)424 void clearLocalClassNameIndexes(ClassSymbol c) { 425 if (c.owner != null && c.owner.kind != NIL) { 426 localClassNameIndexes.remove(new Pair<>( 427 c.owner.enclClass().flatname, c.name)); 428 } 429 } 430 newRound()431 public void newRound() { 432 compiled.clear(); 433 localClassNameIndexes.clear(); 434 } 435 putCompiled(ClassSymbol csym)436 public void putCompiled(ClassSymbol csym) { 437 compiled.put(Pair.of(csym.packge().modle, csym.flatname), csym); 438 } 439 getCompiled(ClassSymbol csym)440 public ClassSymbol getCompiled(ClassSymbol csym) { 441 return compiled.get(Pair.of(csym.packge().modle, csym.flatname)); 442 } 443 getCompiled(ModuleSymbol msym, Name flatname)444 public ClassSymbol getCompiled(ModuleSymbol msym, Name flatname) { 445 return compiled.get(Pair.of(msym, flatname)); 446 } 447 removeCompiled(ClassSymbol csym)448 public void removeCompiled(ClassSymbol csym) { 449 compiled.remove(Pair.of(csym.packge().modle, csym.flatname)); 450 } 451 452 /* ************************************************************************* 453 * Type Checking 454 **************************************************************************/ 455 456 /** 457 * A check context is an object that can be used to perform compatibility 458 * checks - depending on the check context, meaning of 'compatibility' might 459 * vary significantly. 460 */ 461 public interface CheckContext { 462 /** 463 * Is type 'found' compatible with type 'req' in given context 464 */ compatible(Type found, Type req, Warner warn)465 boolean compatible(Type found, Type req, Warner warn); 466 /** 467 * Report a check error 468 */ report(DiagnosticPosition pos, JCDiagnostic details)469 void report(DiagnosticPosition pos, JCDiagnostic details); 470 /** 471 * Obtain a warner for this check context 472 */ checkWarner(DiagnosticPosition pos, Type found, Type req)473 public Warner checkWarner(DiagnosticPosition pos, Type found, Type req); 474 inferenceContext()475 public InferenceContext inferenceContext(); 476 deferredAttrContext()477 public DeferredAttr.DeferredAttrContext deferredAttrContext(); 478 } 479 480 /** 481 * This class represent a check context that is nested within another check 482 * context - useful to check sub-expressions. The default behavior simply 483 * redirects all method calls to the enclosing check context leveraging 484 * the forwarding pattern. 485 */ 486 static class NestedCheckContext implements CheckContext { 487 CheckContext enclosingContext; 488 NestedCheckContext(CheckContext enclosingContext)489 NestedCheckContext(CheckContext enclosingContext) { 490 this.enclosingContext = enclosingContext; 491 } 492 compatible(Type found, Type req, Warner warn)493 public boolean compatible(Type found, Type req, Warner warn) { 494 return enclosingContext.compatible(found, req, warn); 495 } 496 report(DiagnosticPosition pos, JCDiagnostic details)497 public void report(DiagnosticPosition pos, JCDiagnostic details) { 498 enclosingContext.report(pos, details); 499 } 500 checkWarner(DiagnosticPosition pos, Type found, Type req)501 public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) { 502 return enclosingContext.checkWarner(pos, found, req); 503 } 504 inferenceContext()505 public InferenceContext inferenceContext() { 506 return enclosingContext.inferenceContext(); 507 } 508 deferredAttrContext()509 public DeferredAttrContext deferredAttrContext() { 510 return enclosingContext.deferredAttrContext(); 511 } 512 } 513 514 /** 515 * Check context to be used when evaluating assignment/return statements 516 */ 517 CheckContext basicHandler = new CheckContext() { 518 public void report(DiagnosticPosition pos, JCDiagnostic details) { 519 log.error(pos, Errors.ProbFoundReq(details)); 520 } 521 public boolean compatible(Type found, Type req, Warner warn) { 522 return types.isAssignable(found, req, warn); 523 } 524 525 public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) { 526 return convertWarner(pos, found, req); 527 } 528 529 public InferenceContext inferenceContext() { 530 return infer.emptyContext; 531 } 532 533 public DeferredAttrContext deferredAttrContext() { 534 return deferredAttr.emptyDeferredAttrContext; 535 } 536 537 @Override 538 public String toString() { 539 return "CheckContext: basicHandler"; 540 } 541 }; 542 543 /** Check that a given type is assignable to a given proto-type. 544 * If it is, return the type, otherwise return errType. 545 * @param pos Position to be used for error reporting. 546 * @param found The type that was found. 547 * @param req The type that was required. 548 */ checkType(DiagnosticPosition pos, Type found, Type req)549 public Type checkType(DiagnosticPosition pos, Type found, Type req) { 550 return checkType(pos, found, req, basicHandler); 551 } 552 checkType(final DiagnosticPosition pos, final Type found, final Type req, final CheckContext checkContext)553 Type checkType(final DiagnosticPosition pos, final Type found, final Type req, final CheckContext checkContext) { 554 final InferenceContext inferenceContext = checkContext.inferenceContext(); 555 if (inferenceContext.free(req) || inferenceContext.free(found)) { 556 inferenceContext.addFreeTypeListener(List.of(req, found), 557 solvedContext -> checkType(pos, solvedContext.asInstType(found), solvedContext.asInstType(req), checkContext)); 558 } 559 if (req.hasTag(ERROR)) 560 return req; 561 if (req.hasTag(NONE)) 562 return found; 563 if (checkContext.compatible(found, req, checkContext.checkWarner(pos, found, req))) { 564 return found; 565 } else { 566 if (found.isNumeric() && req.isNumeric()) { 567 checkContext.report(pos, diags.fragment(Fragments.PossibleLossOfPrecision(found, req))); 568 return types.createErrorType(found); 569 } 570 checkContext.report(pos, diags.fragment(Fragments.InconvertibleTypes(found, req))); 571 return types.createErrorType(found); 572 } 573 } 574 575 /** Check that a given type can be cast to a given target type. 576 * Return the result of the cast. 577 * @param pos Position to be used for error reporting. 578 * @param found The type that is being cast. 579 * @param req The target type of the cast. 580 */ checkCastable(DiagnosticPosition pos, Type found, Type req)581 Type checkCastable(DiagnosticPosition pos, Type found, Type req) { 582 return checkCastable(pos, found, req, basicHandler); 583 } checkCastable(DiagnosticPosition pos, Type found, Type req, CheckContext checkContext)584 Type checkCastable(DiagnosticPosition pos, Type found, Type req, CheckContext checkContext) { 585 if (types.isCastable(found, req, castWarner(pos, found, req))) { 586 return req; 587 } else { 588 checkContext.report(pos, diags.fragment(Fragments.InconvertibleTypes(found, req))); 589 return types.createErrorType(found); 590 } 591 } 592 593 /** Check for redundant casts (i.e. where source type is a subtype of target type) 594 * The problem should only be reported for non-292 cast 595 */ checkRedundantCast(Env<AttrContext> env, final JCTypeCast tree)596 public void checkRedundantCast(Env<AttrContext> env, final JCTypeCast tree) { 597 if (!tree.type.isErroneous() 598 && types.isSameType(tree.expr.type, tree.clazz.type) 599 && !(ignoreAnnotatedCasts && TreeInfo.containsTypeAnnotation(tree.clazz)) 600 && !is292targetTypeCast(tree)) { 601 deferredLintHandler.report(() -> { 602 if (lint.isEnabled(LintCategory.CAST)) 603 log.warning(LintCategory.CAST, 604 tree.pos(), Warnings.RedundantCast(tree.clazz.type)); 605 }); 606 } 607 } 608 //where is292targetTypeCast(JCTypeCast tree)609 private boolean is292targetTypeCast(JCTypeCast tree) { 610 boolean is292targetTypeCast = false; 611 JCExpression expr = TreeInfo.skipParens(tree.expr); 612 if (expr.hasTag(APPLY)) { 613 JCMethodInvocation apply = (JCMethodInvocation)expr; 614 Symbol sym = TreeInfo.symbol(apply.meth); 615 is292targetTypeCast = sym != null && 616 sym.kind == MTH && 617 (sym.flags() & HYPOTHETICAL) != 0; 618 } 619 return is292targetTypeCast; 620 } 621 622 private static final boolean ignoreAnnotatedCasts = true; 623 624 /** Check that a type is within some bounds. 625 * 626 * Used in TypeApply to verify that, e.g., X in {@code V<X>} is a valid 627 * type argument. 628 * @param a The type that should be bounded by bs. 629 * @param bound The bound. 630 */ checkExtends(Type a, Type bound)631 private boolean checkExtends(Type a, Type bound) { 632 if (a.isUnbound()) { 633 return true; 634 } else if (!a.hasTag(WILDCARD)) { 635 a = types.cvarUpperBound(a); 636 return types.isSubtype(a, bound); 637 } else if (a.isExtendsBound()) { 638 return types.isCastable(bound, types.wildUpperBound(a), types.noWarnings); 639 } else if (a.isSuperBound()) { 640 return !types.notSoftSubtype(types.wildLowerBound(a), bound); 641 } 642 return true; 643 } 644 645 /** Check that type is different from 'void'. 646 * @param pos Position to be used for error reporting. 647 * @param t The type to be checked. 648 */ checkNonVoid(DiagnosticPosition pos, Type t)649 Type checkNonVoid(DiagnosticPosition pos, Type t) { 650 if (t.hasTag(VOID)) { 651 log.error(pos, Errors.VoidNotAllowedHere); 652 return types.createErrorType(t); 653 } else { 654 return t; 655 } 656 } 657 checkClassOrArrayType(DiagnosticPosition pos, Type t)658 Type checkClassOrArrayType(DiagnosticPosition pos, Type t) { 659 if (!t.hasTag(CLASS) && !t.hasTag(ARRAY) && !t.hasTag(ERROR)) { 660 return typeTagError(pos, 661 diags.fragment(Fragments.TypeReqClassArray), 662 asTypeParam(t)); 663 } else { 664 return t; 665 } 666 } 667 668 /** Check that type is a class or interface type. 669 * @param pos Position to be used for error reporting. 670 * @param t The type to be checked. 671 */ checkClassType(DiagnosticPosition pos, Type t)672 Type checkClassType(DiagnosticPosition pos, Type t) { 673 if (!t.hasTag(CLASS) && !t.hasTag(ERROR)) { 674 return typeTagError(pos, 675 diags.fragment(Fragments.TypeReqClass), 676 asTypeParam(t)); 677 } else { 678 return t; 679 } 680 } 681 //where asTypeParam(Type t)682 private Object asTypeParam(Type t) { 683 return (t.hasTag(TYPEVAR)) 684 ? diags.fragment(Fragments.TypeParameter(t)) 685 : t; 686 } 687 688 /** Check that type is a valid qualifier for a constructor reference expression 689 */ checkConstructorRefType(DiagnosticPosition pos, Type t)690 Type checkConstructorRefType(DiagnosticPosition pos, Type t) { 691 t = checkClassOrArrayType(pos, t); 692 if (t.hasTag(CLASS)) { 693 if ((t.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) { 694 log.error(pos, Errors.AbstractCantBeInstantiated(t.tsym)); 695 t = types.createErrorType(t); 696 } else if ((t.tsym.flags() & ENUM) != 0) { 697 log.error(pos, Errors.EnumCantBeInstantiated); 698 t = types.createErrorType(t); 699 } else { 700 t = checkClassType(pos, t, true); 701 } 702 } else if (t.hasTag(ARRAY)) { 703 if (!types.isReifiable(((ArrayType)t).elemtype)) { 704 log.error(pos, Errors.GenericArrayCreation); 705 t = types.createErrorType(t); 706 } 707 } 708 return t; 709 } 710 711 /** Check that type is a class or interface type. 712 * @param pos Position to be used for error reporting. 713 * @param t The type to be checked. 714 * @param noBounds True if type bounds are illegal here. 715 */ checkClassType(DiagnosticPosition pos, Type t, boolean noBounds)716 Type checkClassType(DiagnosticPosition pos, Type t, boolean noBounds) { 717 t = checkClassType(pos, t); 718 if (noBounds && t.isParameterized()) { 719 List<Type> args = t.getTypeArguments(); 720 while (args.nonEmpty()) { 721 if (args.head.hasTag(WILDCARD)) 722 return typeTagError(pos, 723 diags.fragment(Fragments.TypeReqExact), 724 args.head); 725 args = args.tail; 726 } 727 } 728 return t; 729 } 730 731 /** Check that type is a reference type, i.e. a class, interface or array type 732 * or a type variable. 733 * @param pos Position to be used for error reporting. 734 * @param t The type to be checked. 735 */ checkRefType(DiagnosticPosition pos, Type t)736 Type checkRefType(DiagnosticPosition pos, Type t) { 737 if (t.isReference()) 738 return t; 739 else 740 return typeTagError(pos, 741 diags.fragment(Fragments.TypeReqRef), 742 t); 743 } 744 745 /** Check that each type is a reference type, i.e. a class, interface or array type 746 * or a type variable. 747 * @param trees Original trees, used for error reporting. 748 * @param types The types to be checked. 749 */ checkRefTypes(List<JCExpression> trees, List<Type> types)750 List<Type> checkRefTypes(List<JCExpression> trees, List<Type> types) { 751 List<JCExpression> tl = trees; 752 for (List<Type> l = types; l.nonEmpty(); l = l.tail) { 753 l.head = checkRefType(tl.head.pos(), l.head); 754 tl = tl.tail; 755 } 756 return types; 757 } 758 759 /** Check that type is a null or reference type. 760 * @param pos Position to be used for error reporting. 761 * @param t The type to be checked. 762 */ checkNullOrRefType(DiagnosticPosition pos, Type t)763 Type checkNullOrRefType(DiagnosticPosition pos, Type t) { 764 if (t.isReference() || t.hasTag(BOT)) 765 return t; 766 else 767 return typeTagError(pos, 768 diags.fragment(Fragments.TypeReqRef), 769 t); 770 } 771 772 /** Check that flag set does not contain elements of two conflicting sets. s 773 * Return true if it doesn't. 774 * @param pos Position to be used for error reporting. 775 * @param flags The set of flags to be checked. 776 * @param set1 Conflicting flags set #1. 777 * @param set2 Conflicting flags set #2. 778 */ checkDisjoint(DiagnosticPosition pos, long flags, long set1, long set2)779 boolean checkDisjoint(DiagnosticPosition pos, long flags, long set1, long set2) { 780 if ((flags & set1) != 0 && (flags & set2) != 0) { 781 log.error(pos, 782 Errors.IllegalCombinationOfModifiers(asFlagSet(TreeInfo.firstFlag(flags & set1)), 783 asFlagSet(TreeInfo.firstFlag(flags & set2)))); 784 return false; 785 } else 786 return true; 787 } 788 789 /** Check that usage of diamond operator is correct (i.e. diamond should not 790 * be used with non-generic classes or in anonymous class creation expressions) 791 */ checkDiamond(JCNewClass tree, Type t)792 Type checkDiamond(JCNewClass tree, Type t) { 793 if (!TreeInfo.isDiamond(tree) || 794 t.isErroneous()) { 795 return checkClassType(tree.clazz.pos(), t, true); 796 } else { 797 if (tree.def != null && !Feature.DIAMOND_WITH_ANONYMOUS_CLASS_CREATION.allowedInSource(source)) { 798 log.error(DiagnosticFlag.SOURCE_LEVEL, tree.clazz.pos(), 799 Errors.CantApplyDiamond1(t, Feature.DIAMOND_WITH_ANONYMOUS_CLASS_CREATION.fragment(source.name))); 800 } 801 if (t.tsym.type.getTypeArguments().isEmpty()) { 802 log.error(tree.clazz.pos(), 803 Errors.CantApplyDiamond1(t, 804 Fragments.DiamondNonGeneric(t))); 805 return types.createErrorType(t); 806 } else if (tree.typeargs != null && 807 tree.typeargs.nonEmpty()) { 808 log.error(tree.clazz.pos(), 809 Errors.CantApplyDiamond1(t, 810 Fragments.DiamondAndExplicitParams(t))); 811 return types.createErrorType(t); 812 } else { 813 return t; 814 } 815 } 816 } 817 818 /** Check that the type inferred using the diamond operator does not contain 819 * non-denotable types such as captured types or intersection types. 820 * @param t the type inferred using the diamond operator 821 * @return the (possibly empty) list of non-denotable types. 822 */ checkDiamondDenotable(ClassType t)823 List<Type> checkDiamondDenotable(ClassType t) { 824 ListBuffer<Type> buf = new ListBuffer<>(); 825 for (Type arg : t.allparams()) { 826 if (!checkDenotable(arg)) { 827 buf.append(arg); 828 } 829 } 830 return buf.toList(); 831 } 832 checkDenotable(Type t)833 public boolean checkDenotable(Type t) { 834 return denotableChecker.visit(t, null); 835 } 836 // where 837 838 /** diamondTypeChecker: A type visitor that descends down the given type looking for non-denotable 839 * types. The visit methods return false as soon as a non-denotable type is encountered and true 840 * otherwise. 841 */ 842 private static final Types.SimpleVisitor<Boolean, Void> denotableChecker = new Types.SimpleVisitor<Boolean, Void>() { 843 @Override 844 public Boolean visitType(Type t, Void s) { 845 return true; 846 } 847 @Override 848 public Boolean visitClassType(ClassType t, Void s) { 849 if (t.isUnion() || t.isIntersection()) { 850 return false; 851 } 852 for (Type targ : t.allparams()) { 853 if (!visit(targ, s)) { 854 return false; 855 } 856 } 857 return true; 858 } 859 860 @Override 861 public Boolean visitTypeVar(TypeVar t, Void s) { 862 /* Any type variable mentioned in the inferred type must have been declared as a type parameter 863 (i.e cannot have been produced by inference (18.4)) 864 */ 865 return (t.tsym.flags() & SYNTHETIC) == 0; 866 } 867 868 @Override 869 public Boolean visitCapturedType(CapturedType t, Void s) { 870 /* Any type variable mentioned in the inferred type must have been declared as a type parameter 871 (i.e cannot have been produced by capture conversion (5.1.10)) 872 */ 873 return false; 874 } 875 876 @Override 877 public Boolean visitArrayType(ArrayType t, Void s) { 878 return visit(t.elemtype, s); 879 } 880 881 @Override 882 public Boolean visitWildcardType(WildcardType t, Void s) { 883 return visit(t.type, s); 884 } 885 }; 886 checkVarargsMethodDecl(Env<AttrContext> env, JCMethodDecl tree)887 void checkVarargsMethodDecl(Env<AttrContext> env, JCMethodDecl tree) { 888 MethodSymbol m = tree.sym; 889 boolean hasTrustMeAnno = m.attribute(syms.trustMeType.tsym) != null; 890 Type varargElemType = null; 891 if (m.isVarArgs()) { 892 varargElemType = types.elemtype(tree.params.last().type); 893 } 894 if (hasTrustMeAnno && !isTrustMeAllowedOnMethod(m)) { 895 if (varargElemType != null) { 896 JCDiagnostic msg = Feature.PRIVATE_SAFE_VARARGS.allowedInSource(source) ? 897 diags.fragment(Fragments.VarargsTrustmeOnVirtualVarargs(m)) : 898 diags.fragment(Fragments.VarargsTrustmeOnVirtualVarargsFinalOnly(m)); 899 log.error(tree, 900 Errors.VarargsInvalidTrustmeAnno(syms.trustMeType.tsym, 901 msg)); 902 } else { 903 log.error(tree, 904 Errors.VarargsInvalidTrustmeAnno(syms.trustMeType.tsym, 905 Fragments.VarargsTrustmeOnNonVarargsMeth(m))); 906 } 907 } else if (hasTrustMeAnno && varargElemType != null && 908 types.isReifiable(varargElemType)) { 909 warnUnsafeVararg(tree, Warnings.VarargsRedundantTrustmeAnno( 910 syms.trustMeType.tsym, 911 diags.fragment(Fragments.VarargsTrustmeOnReifiableVarargs(varargElemType)))); 912 } 913 else if (!hasTrustMeAnno && varargElemType != null && 914 !types.isReifiable(varargElemType)) { 915 warnUnchecked(tree.params.head.pos(), Warnings.UncheckedVarargsNonReifiableType(varargElemType)); 916 } 917 } 918 //where isTrustMeAllowedOnMethod(Symbol s)919 private boolean isTrustMeAllowedOnMethod(Symbol s) { 920 return (s.flags() & VARARGS) != 0 && 921 (s.isConstructor() || 922 (s.flags() & (STATIC | FINAL | 923 (Feature.PRIVATE_SAFE_VARARGS.allowedInSource(source) ? PRIVATE : 0) )) != 0); 924 } 925 checkLocalVarType(DiagnosticPosition pos, Type t, Name name)926 Type checkLocalVarType(DiagnosticPosition pos, Type t, Name name) { 927 //check that resulting type is not the null type 928 if (t.hasTag(BOT)) { 929 log.error(pos, Errors.CantInferLocalVarType(name, Fragments.LocalCantInferNull)); 930 return types.createErrorType(t); 931 } else if (t.hasTag(VOID)) { 932 log.error(pos, Errors.CantInferLocalVarType(name, Fragments.LocalCantInferVoid)); 933 return types.createErrorType(t); 934 } 935 936 //upward project the initializer type 937 return types.upward(t, types.captures(t)); 938 } 939 checkMethod(final Type mtype, final Symbol sym, final Env<AttrContext> env, final List<JCExpression> argtrees, final List<Type> argtypes, final boolean useVarargs, InferenceContext inferenceContext)940 Type checkMethod(final Type mtype, 941 final Symbol sym, 942 final Env<AttrContext> env, 943 final List<JCExpression> argtrees, 944 final List<Type> argtypes, 945 final boolean useVarargs, 946 InferenceContext inferenceContext) { 947 // System.out.println("call : " + env.tree); 948 // System.out.println("method : " + owntype); 949 // System.out.println("actuals: " + argtypes); 950 if (inferenceContext.free(mtype)) { 951 inferenceContext.addFreeTypeListener(List.of(mtype), 952 solvedContext -> checkMethod(solvedContext.asInstType(mtype), sym, env, argtrees, argtypes, useVarargs, solvedContext)); 953 return mtype; 954 } 955 Type owntype = mtype; 956 List<Type> formals = owntype.getParameterTypes(); 957 List<Type> nonInferred = sym.type.getParameterTypes(); 958 if (nonInferred.length() != formals.length()) nonInferred = formals; 959 Type last = useVarargs ? formals.last() : null; 960 if (sym.name == names.init && sym.owner == syms.enumSym) { 961 formals = formals.tail.tail; 962 nonInferred = nonInferred.tail.tail; 963 } 964 if ((sym.flags() & ANONCONSTR_BASED) != 0) { 965 formals = formals.tail; 966 nonInferred = nonInferred.tail; 967 } 968 List<JCExpression> args = argtrees; 969 if (args != null) { 970 //this is null when type-checking a method reference 971 while (formals.head != last) { 972 JCTree arg = args.head; 973 Warner warn = convertWarner(arg.pos(), arg.type, nonInferred.head); 974 assertConvertible(arg, arg.type, formals.head, warn); 975 args = args.tail; 976 formals = formals.tail; 977 nonInferred = nonInferred.tail; 978 } 979 if (useVarargs) { 980 Type varArg = types.elemtype(last); 981 while (args.tail != null) { 982 JCTree arg = args.head; 983 Warner warn = convertWarner(arg.pos(), arg.type, varArg); 984 assertConvertible(arg, arg.type, varArg, warn); 985 args = args.tail; 986 } 987 } else if ((sym.flags() & (VARARGS | SIGNATURE_POLYMORPHIC)) == VARARGS) { 988 // non-varargs call to varargs method 989 Type varParam = owntype.getParameterTypes().last(); 990 Type lastArg = argtypes.last(); 991 if (types.isSubtypeUnchecked(lastArg, types.elemtype(varParam)) && 992 !types.isSameType(types.erasure(varParam), types.erasure(lastArg))) 993 log.warning(argtrees.last().pos(), 994 Warnings.InexactNonVarargsCall(types.elemtype(varParam),varParam)); 995 } 996 } 997 if (useVarargs) { 998 Type argtype = owntype.getParameterTypes().last(); 999 if (!types.isReifiable(argtype) && 1000 (sym.baseSymbol().attribute(syms.trustMeType.tsym) == null || 1001 !isTrustMeAllowedOnMethod(sym))) { 1002 warnUnchecked(env.tree.pos(), Warnings.UncheckedGenericArrayCreation(argtype)); 1003 } 1004 TreeInfo.setVarargsElement(env.tree, types.elemtype(argtype)); 1005 } 1006 return owntype; 1007 } 1008 //where assertConvertible(JCTree tree, Type actual, Type formal, Warner warn)1009 private void assertConvertible(JCTree tree, Type actual, Type formal, Warner warn) { 1010 if (types.isConvertible(actual, formal, warn)) 1011 return; 1012 1013 if (formal.isCompound() 1014 && types.isSubtype(actual, types.supertype(formal)) 1015 && types.isSubtypeUnchecked(actual, types.interfaces(formal), warn)) 1016 return; 1017 } 1018 1019 /** 1020 * Check that type 't' is a valid instantiation of a generic class 1021 * (see JLS 4.5) 1022 * 1023 * @param t class type to be checked 1024 * @return true if 't' is well-formed 1025 */ checkValidGenericType(Type t)1026 public boolean checkValidGenericType(Type t) { 1027 return firstIncompatibleTypeArg(t) == null; 1028 } 1029 //WHERE firstIncompatibleTypeArg(Type type)1030 private Type firstIncompatibleTypeArg(Type type) { 1031 List<Type> formals = type.tsym.type.allparams(); 1032 List<Type> actuals = type.allparams(); 1033 List<Type> args = type.getTypeArguments(); 1034 List<Type> forms = type.tsym.type.getTypeArguments(); 1035 ListBuffer<Type> bounds_buf = new ListBuffer<>(); 1036 1037 // For matching pairs of actual argument types `a' and 1038 // formal type parameters with declared bound `b' ... 1039 while (args.nonEmpty() && forms.nonEmpty()) { 1040 // exact type arguments needs to know their 1041 // bounds (for upper and lower bound 1042 // calculations). So we create new bounds where 1043 // type-parameters are replaced with actuals argument types. 1044 bounds_buf.append(types.subst(forms.head.getUpperBound(), formals, actuals)); 1045 args = args.tail; 1046 forms = forms.tail; 1047 } 1048 1049 args = type.getTypeArguments(); 1050 List<Type> tvars_cap = types.substBounds(formals, 1051 formals, 1052 types.capture(type).allparams()); 1053 while (args.nonEmpty() && tvars_cap.nonEmpty()) { 1054 // Let the actual arguments know their bound 1055 args.head.withTypeVar((TypeVar)tvars_cap.head); 1056 args = args.tail; 1057 tvars_cap = tvars_cap.tail; 1058 } 1059 1060 args = type.getTypeArguments(); 1061 List<Type> bounds = bounds_buf.toList(); 1062 1063 while (args.nonEmpty() && bounds.nonEmpty()) { 1064 Type actual = args.head; 1065 if (!isTypeArgErroneous(actual) && 1066 !bounds.head.isErroneous() && 1067 !checkExtends(actual, bounds.head)) { 1068 return args.head; 1069 } 1070 args = args.tail; 1071 bounds = bounds.tail; 1072 } 1073 1074 args = type.getTypeArguments(); 1075 bounds = bounds_buf.toList(); 1076 1077 for (Type arg : types.capture(type).getTypeArguments()) { 1078 if (arg.hasTag(TYPEVAR) && 1079 arg.getUpperBound().isErroneous() && 1080 !bounds.head.isErroneous() && 1081 !isTypeArgErroneous(args.head)) { 1082 return args.head; 1083 } 1084 bounds = bounds.tail; 1085 args = args.tail; 1086 } 1087 1088 return null; 1089 } 1090 //where isTypeArgErroneous(Type t)1091 boolean isTypeArgErroneous(Type t) { 1092 return isTypeArgErroneous.visit(t); 1093 } 1094 1095 Types.UnaryVisitor<Boolean> isTypeArgErroneous = new Types.UnaryVisitor<Boolean>() { 1096 public Boolean visitType(Type t, Void s) { 1097 return t.isErroneous(); 1098 } 1099 @Override 1100 public Boolean visitTypeVar(TypeVar t, Void s) { 1101 return visit(t.getUpperBound()); 1102 } 1103 @Override 1104 public Boolean visitCapturedType(CapturedType t, Void s) { 1105 return visit(t.getUpperBound()) || 1106 visit(t.getLowerBound()); 1107 } 1108 @Override 1109 public Boolean visitWildcardType(WildcardType t, Void s) { 1110 return visit(t.type); 1111 } 1112 }; 1113 1114 /** Check that given modifiers are legal for given symbol and 1115 * return modifiers together with any implicit modifiers for that symbol. 1116 * Warning: we can't use flags() here since this method 1117 * is called during class enter, when flags() would cause a premature 1118 * completion. 1119 * @param pos Position to be used for error reporting. 1120 * @param flags The set of modifiers given in a definition. 1121 * @param sym The defined symbol. 1122 */ checkFlags(DiagnosticPosition pos, long flags, Symbol sym, JCTree tree)1123 long checkFlags(DiagnosticPosition pos, long flags, Symbol sym, JCTree tree) { 1124 long mask; 1125 long implicit = 0; 1126 1127 switch (sym.kind) { 1128 case VAR: 1129 if (TreeInfo.isReceiverParam(tree)) 1130 mask = ReceiverParamFlags; 1131 else if (sym.owner.kind != TYP) 1132 mask = LocalVarFlags; 1133 else if ((sym.owner.flags_field & INTERFACE) != 0) 1134 mask = implicit = InterfaceVarFlags; 1135 else 1136 mask = VarFlags; 1137 break; 1138 case MTH: 1139 if (sym.name == names.init) { 1140 if ((sym.owner.flags_field & ENUM) != 0) { 1141 // enum constructors cannot be declared public or 1142 // protected and must be implicitly or explicitly 1143 // private 1144 implicit = PRIVATE; 1145 mask = PRIVATE; 1146 } else 1147 mask = ConstructorFlags; 1148 } else if ((sym.owner.flags_field & INTERFACE) != 0) { 1149 if ((sym.owner.flags_field & ANNOTATION) != 0) { 1150 mask = AnnotationTypeElementMask; 1151 implicit = PUBLIC | ABSTRACT; 1152 } else if ((flags & (DEFAULT | STATIC | PRIVATE)) != 0) { 1153 mask = InterfaceMethodMask; 1154 implicit = (flags & PRIVATE) != 0 ? 0 : PUBLIC; 1155 if ((flags & DEFAULT) != 0) { 1156 implicit |= ABSTRACT; 1157 } 1158 } else { 1159 mask = implicit = InterfaceMethodFlags; 1160 } 1161 } else { 1162 mask = MethodFlags; 1163 } 1164 // Imply STRICTFP if owner has STRICTFP set. 1165 if (((flags|implicit) & Flags.ABSTRACT) == 0 || 1166 ((flags) & Flags.DEFAULT) != 0) 1167 implicit |= sym.owner.flags_field & STRICTFP; 1168 break; 1169 case TYP: 1170 if (sym.isLocal()) { 1171 mask = LocalClassFlags; 1172 if ((sym.owner.flags_field & STATIC) == 0 && 1173 (flags & ENUM) != 0) 1174 log.error(pos, Errors.EnumsMustBeStatic); 1175 } else if (sym.owner.kind == TYP) { 1176 mask = MemberClassFlags; 1177 if (sym.owner.owner.kind == PCK || 1178 (sym.owner.flags_field & STATIC) != 0) 1179 mask |= STATIC; 1180 else if ((flags & ENUM) != 0) 1181 log.error(pos, Errors.EnumsMustBeStatic); 1182 // Nested interfaces and enums are always STATIC (Spec ???) 1183 if ((flags & (INTERFACE | ENUM)) != 0 ) implicit = STATIC; 1184 } else { 1185 mask = ClassFlags; 1186 } 1187 // Interfaces are always ABSTRACT 1188 if ((flags & INTERFACE) != 0) implicit |= ABSTRACT; 1189 1190 if ((flags & ENUM) != 0) { 1191 // enums can't be declared abstract or final 1192 mask &= ~(ABSTRACT | FINAL); 1193 implicit |= implicitEnumFinalFlag(tree); 1194 } 1195 // Imply STRICTFP if owner has STRICTFP set. 1196 implicit |= sym.owner.flags_field & STRICTFP; 1197 break; 1198 default: 1199 throw new AssertionError(); 1200 } 1201 long illegal = flags & ExtendedStandardFlags & ~mask; 1202 if (illegal != 0) { 1203 if ((illegal & INTERFACE) != 0) { 1204 log.error(pos, ((flags & ANNOTATION) != 0) ? Errors.AnnotationDeclNotAllowedHere : Errors.IntfNotAllowedHere); 1205 mask |= INTERFACE; 1206 } 1207 else { 1208 log.error(pos, 1209 Errors.ModNotAllowedHere(asFlagSet(illegal))); 1210 } 1211 } 1212 else if ((sym.kind == TYP || 1213 // ISSUE: Disallowing abstract&private is no longer appropriate 1214 // in the presence of inner classes. Should it be deleted here? 1215 checkDisjoint(pos, flags, 1216 ABSTRACT, 1217 PRIVATE | STATIC | DEFAULT)) 1218 && 1219 checkDisjoint(pos, flags, 1220 STATIC | PRIVATE, 1221 DEFAULT) 1222 && 1223 checkDisjoint(pos, flags, 1224 ABSTRACT | INTERFACE, 1225 FINAL | NATIVE | SYNCHRONIZED) 1226 && 1227 checkDisjoint(pos, flags, 1228 PUBLIC, 1229 PRIVATE | PROTECTED) 1230 && 1231 checkDisjoint(pos, flags, 1232 PRIVATE, 1233 PUBLIC | PROTECTED) 1234 && 1235 checkDisjoint(pos, flags, 1236 FINAL, 1237 VOLATILE) 1238 && 1239 (sym.kind == TYP || 1240 checkDisjoint(pos, flags, 1241 ABSTRACT | NATIVE, 1242 STRICTFP))) { 1243 // skip 1244 } 1245 return flags & (mask | ~ExtendedStandardFlags) | implicit; 1246 } 1247 1248 1249 /** Determine if this enum should be implicitly final. 1250 * 1251 * If the enum has no specialized enum contants, it is final. 1252 * 1253 * If the enum does have specialized enum contants, it is 1254 * <i>not</i> final. 1255 */ implicitEnumFinalFlag(JCTree tree)1256 private long implicitEnumFinalFlag(JCTree tree) { 1257 if (!tree.hasTag(CLASSDEF)) return 0; 1258 class SpecialTreeVisitor extends JCTree.Visitor { 1259 boolean specialized; 1260 SpecialTreeVisitor() { 1261 this.specialized = false; 1262 } 1263 1264 @Override 1265 public void visitTree(JCTree tree) { /* no-op */ } 1266 1267 @Override 1268 public void visitVarDef(JCVariableDecl tree) { 1269 if ((tree.mods.flags & ENUM) != 0) { 1270 if (tree.init instanceof JCNewClass && 1271 ((JCNewClass) tree.init).def != null) { 1272 specialized = true; 1273 } 1274 } 1275 } 1276 } 1277 1278 SpecialTreeVisitor sts = new SpecialTreeVisitor(); 1279 JCClassDecl cdef = (JCClassDecl) tree; 1280 for (JCTree defs: cdef.defs) { 1281 defs.accept(sts); 1282 if (sts.specialized) return 0; 1283 } 1284 return FINAL; 1285 } 1286 1287 /* ************************************************************************* 1288 * Type Validation 1289 **************************************************************************/ 1290 1291 /** Validate a type expression. That is, 1292 * check that all type arguments of a parametric type are within 1293 * their bounds. This must be done in a second phase after type attribution 1294 * since a class might have a subclass as type parameter bound. E.g: 1295 * 1296 * <pre>{@code 1297 * class B<A extends C> { ... } 1298 * class C extends B<C> { ... } 1299 * }</pre> 1300 * 1301 * and we can't make sure that the bound is already attributed because 1302 * of possible cycles. 1303 * 1304 * Visitor method: Validate a type expression, if it is not null, catching 1305 * and reporting any completion failures. 1306 */ validate(JCTree tree, Env<AttrContext> env)1307 void validate(JCTree tree, Env<AttrContext> env) { 1308 validate(tree, env, true); 1309 } validate(JCTree tree, Env<AttrContext> env, boolean checkRaw)1310 void validate(JCTree tree, Env<AttrContext> env, boolean checkRaw) { 1311 new Validator(env).validateTree(tree, checkRaw, true); 1312 } 1313 1314 /** Visitor method: Validate a list of type expressions. 1315 */ validate(List<? extends JCTree> trees, Env<AttrContext> env)1316 void validate(List<? extends JCTree> trees, Env<AttrContext> env) { 1317 for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) 1318 validate(l.head, env); 1319 } 1320 1321 /** A visitor class for type validation. 1322 */ 1323 class Validator extends JCTree.Visitor { 1324 1325 boolean checkRaw; 1326 boolean isOuter; 1327 Env<AttrContext> env; 1328 Validator(Env<AttrContext> env)1329 Validator(Env<AttrContext> env) { 1330 this.env = env; 1331 } 1332 1333 @Override visitTypeArray(JCArrayTypeTree tree)1334 public void visitTypeArray(JCArrayTypeTree tree) { 1335 validateTree(tree.elemtype, checkRaw, isOuter); 1336 } 1337 1338 @Override visitTypeApply(JCTypeApply tree)1339 public void visitTypeApply(JCTypeApply tree) { 1340 if (tree.type.hasTag(CLASS)) { 1341 List<JCExpression> args = tree.arguments; 1342 List<Type> forms = tree.type.tsym.type.getTypeArguments(); 1343 1344 Type incompatibleArg = firstIncompatibleTypeArg(tree.type); 1345 if (incompatibleArg != null) { 1346 for (JCTree arg : tree.arguments) { 1347 if (arg.type == incompatibleArg) { 1348 log.error(arg, Errors.NotWithinBounds(incompatibleArg, forms.head)); 1349 } 1350 forms = forms.tail; 1351 } 1352 } 1353 1354 forms = tree.type.tsym.type.getTypeArguments(); 1355 1356 boolean is_java_lang_Class = tree.type.tsym.flatName() == names.java_lang_Class; 1357 1358 // For matching pairs of actual argument types `a' and 1359 // formal type parameters with declared bound `b' ... 1360 while (args.nonEmpty() && forms.nonEmpty()) { 1361 validateTree(args.head, 1362 !(isOuter && is_java_lang_Class), 1363 false); 1364 args = args.tail; 1365 forms = forms.tail; 1366 } 1367 1368 // Check that this type is either fully parameterized, or 1369 // not parameterized at all. 1370 if (tree.type.getEnclosingType().isRaw()) 1371 log.error(tree.pos(), Errors.ImproperlyFormedTypeInnerRawParam); 1372 if (tree.clazz.hasTag(SELECT)) 1373 visitSelectInternal((JCFieldAccess)tree.clazz); 1374 } 1375 } 1376 1377 @Override visitTypeParameter(JCTypeParameter tree)1378 public void visitTypeParameter(JCTypeParameter tree) { 1379 validateTrees(tree.bounds, true, isOuter); 1380 checkClassBounds(tree.pos(), tree.type); 1381 } 1382 1383 @Override visitWildcard(JCWildcard tree)1384 public void visitWildcard(JCWildcard tree) { 1385 if (tree.inner != null) 1386 validateTree(tree.inner, true, isOuter); 1387 } 1388 1389 @Override visitSelect(JCFieldAccess tree)1390 public void visitSelect(JCFieldAccess tree) { 1391 if (tree.type.hasTag(CLASS)) { 1392 visitSelectInternal(tree); 1393 1394 // Check that this type is either fully parameterized, or 1395 // not parameterized at all. 1396 if (tree.selected.type.isParameterized() && tree.type.tsym.type.getTypeArguments().nonEmpty()) 1397 log.error(tree.pos(), Errors.ImproperlyFormedTypeParamMissing); 1398 } 1399 } 1400 visitSelectInternal(JCFieldAccess tree)1401 public void visitSelectInternal(JCFieldAccess tree) { 1402 if (tree.type.tsym.isStatic() && 1403 tree.selected.type.isParameterized()) { 1404 // The enclosing type is not a class, so we are 1405 // looking at a static member type. However, the 1406 // qualifying expression is parameterized. 1407 log.error(tree.pos(), Errors.CantSelectStaticClassFromParamType); 1408 } else { 1409 // otherwise validate the rest of the expression 1410 tree.selected.accept(this); 1411 } 1412 } 1413 1414 @Override visitAnnotatedType(JCAnnotatedType tree)1415 public void visitAnnotatedType(JCAnnotatedType tree) { 1416 tree.underlyingType.accept(this); 1417 } 1418 1419 @Override visitTypeIdent(JCPrimitiveTypeTree that)1420 public void visitTypeIdent(JCPrimitiveTypeTree that) { 1421 if (that.type.hasTag(TypeTag.VOID)) { 1422 log.error(that.pos(), Errors.VoidNotAllowedHere); 1423 } 1424 super.visitTypeIdent(that); 1425 } 1426 1427 /** Default visitor method: do nothing. 1428 */ 1429 @Override visitTree(JCTree tree)1430 public void visitTree(JCTree tree) { 1431 } 1432 validateTree(JCTree tree, boolean checkRaw, boolean isOuter)1433 public void validateTree(JCTree tree, boolean checkRaw, boolean isOuter) { 1434 if (tree != null) { 1435 boolean prevCheckRaw = this.checkRaw; 1436 this.checkRaw = checkRaw; 1437 this.isOuter = isOuter; 1438 1439 try { 1440 tree.accept(this); 1441 if (checkRaw) 1442 checkRaw(tree, env); 1443 } catch (CompletionFailure ex) { 1444 completionError(tree.pos(), ex); 1445 } finally { 1446 this.checkRaw = prevCheckRaw; 1447 } 1448 } 1449 } 1450 validateTrees(List<? extends JCTree> trees, boolean checkRaw, boolean isOuter)1451 public void validateTrees(List<? extends JCTree> trees, boolean checkRaw, boolean isOuter) { 1452 for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) 1453 validateTree(l.head, checkRaw, isOuter); 1454 } 1455 } 1456 checkRaw(JCTree tree, Env<AttrContext> env)1457 void checkRaw(JCTree tree, Env<AttrContext> env) { 1458 if (lint.isEnabled(LintCategory.RAW) && 1459 tree.type.hasTag(CLASS) && 1460 !TreeInfo.isDiamond(tree) && 1461 !withinAnonConstr(env) && 1462 tree.type.isRaw()) { 1463 log.warning(LintCategory.RAW, 1464 tree.pos(), Warnings.RawClassUse(tree.type, tree.type.tsym.type)); 1465 } 1466 } 1467 //where withinAnonConstr(Env<AttrContext> env)1468 private boolean withinAnonConstr(Env<AttrContext> env) { 1469 return env.enclClass.name.isEmpty() && 1470 env.enclMethod != null && env.enclMethod.name == names.init; 1471 } 1472 1473 /* ************************************************************************* 1474 * Exception checking 1475 **************************************************************************/ 1476 1477 /* The following methods treat classes as sets that contain 1478 * the class itself and all their subclasses 1479 */ 1480 1481 /** Is given type a subtype of some of the types in given list? 1482 */ subset(Type t, List<Type> ts)1483 boolean subset(Type t, List<Type> ts) { 1484 for (List<Type> l = ts; l.nonEmpty(); l = l.tail) 1485 if (types.isSubtype(t, l.head)) return true; 1486 return false; 1487 } 1488 1489 /** Is given type a subtype or supertype of 1490 * some of the types in given list? 1491 */ intersects(Type t, List<Type> ts)1492 boolean intersects(Type t, List<Type> ts) { 1493 for (List<Type> l = ts; l.nonEmpty(); l = l.tail) 1494 if (types.isSubtype(t, l.head) || types.isSubtype(l.head, t)) return true; 1495 return false; 1496 } 1497 1498 /** Add type set to given type list, unless it is a subclass of some class 1499 * in the list. 1500 */ incl(Type t, List<Type> ts)1501 List<Type> incl(Type t, List<Type> ts) { 1502 return subset(t, ts) ? ts : excl(t, ts).prepend(t); 1503 } 1504 1505 /** Remove type set from type set list. 1506 */ excl(Type t, List<Type> ts)1507 List<Type> excl(Type t, List<Type> ts) { 1508 if (ts.isEmpty()) { 1509 return ts; 1510 } else { 1511 List<Type> ts1 = excl(t, ts.tail); 1512 if (types.isSubtype(ts.head, t)) return ts1; 1513 else if (ts1 == ts.tail) return ts; 1514 else return ts1.prepend(ts.head); 1515 } 1516 } 1517 1518 /** Form the union of two type set lists. 1519 */ union(List<Type> ts1, List<Type> ts2)1520 List<Type> union(List<Type> ts1, List<Type> ts2) { 1521 List<Type> ts = ts1; 1522 for (List<Type> l = ts2; l.nonEmpty(); l = l.tail) 1523 ts = incl(l.head, ts); 1524 return ts; 1525 } 1526 1527 /** Form the difference of two type lists. 1528 */ diff(List<Type> ts1, List<Type> ts2)1529 List<Type> diff(List<Type> ts1, List<Type> ts2) { 1530 List<Type> ts = ts1; 1531 for (List<Type> l = ts2; l.nonEmpty(); l = l.tail) 1532 ts = excl(l.head, ts); 1533 return ts; 1534 } 1535 1536 /** Form the intersection of two type lists. 1537 */ intersect(List<Type> ts1, List<Type> ts2)1538 public List<Type> intersect(List<Type> ts1, List<Type> ts2) { 1539 List<Type> ts = List.nil(); 1540 for (List<Type> l = ts1; l.nonEmpty(); l = l.tail) 1541 if (subset(l.head, ts2)) ts = incl(l.head, ts); 1542 for (List<Type> l = ts2; l.nonEmpty(); l = l.tail) 1543 if (subset(l.head, ts1)) ts = incl(l.head, ts); 1544 return ts; 1545 } 1546 1547 /** Is exc an exception symbol that need not be declared? 1548 */ isUnchecked(ClassSymbol exc)1549 boolean isUnchecked(ClassSymbol exc) { 1550 return 1551 exc.kind == ERR || 1552 exc.isSubClass(syms.errorType.tsym, types) || 1553 exc.isSubClass(syms.runtimeExceptionType.tsym, types); 1554 } 1555 1556 /** Is exc an exception type that need not be declared? 1557 */ isUnchecked(Type exc)1558 boolean isUnchecked(Type exc) { 1559 return 1560 (exc.hasTag(TYPEVAR)) ? isUnchecked(types.supertype(exc)) : 1561 (exc.hasTag(CLASS)) ? isUnchecked((ClassSymbol)exc.tsym) : 1562 exc.hasTag(BOT); 1563 } 1564 isChecked(Type exc)1565 boolean isChecked(Type exc) { 1566 return !isUnchecked(exc); 1567 } 1568 1569 /** Same, but handling completion failures. 1570 */ isUnchecked(DiagnosticPosition pos, Type exc)1571 boolean isUnchecked(DiagnosticPosition pos, Type exc) { 1572 try { 1573 return isUnchecked(exc); 1574 } catch (CompletionFailure ex) { 1575 completionError(pos, ex); 1576 return true; 1577 } 1578 } 1579 1580 /** Is exc handled by given exception list? 1581 */ isHandled(Type exc, List<Type> handled)1582 boolean isHandled(Type exc, List<Type> handled) { 1583 return isUnchecked(exc) || subset(exc, handled); 1584 } 1585 1586 /** Return all exceptions in thrown list that are not in handled list. 1587 * @param thrown The list of thrown exceptions. 1588 * @param handled The list of handled exceptions. 1589 */ unhandled(List<Type> thrown, List<Type> handled)1590 List<Type> unhandled(List<Type> thrown, List<Type> handled) { 1591 List<Type> unhandled = List.nil(); 1592 for (List<Type> l = thrown; l.nonEmpty(); l = l.tail) 1593 if (!isHandled(l.head, handled)) unhandled = unhandled.prepend(l.head); 1594 return unhandled; 1595 } 1596 1597 /* ************************************************************************* 1598 * Overriding/Implementation checking 1599 **************************************************************************/ 1600 1601 /** The level of access protection given by a flag set, 1602 * where PRIVATE is highest and PUBLIC is lowest. 1603 */ protection(long flags)1604 static int protection(long flags) { 1605 switch ((short)(flags & AccessFlags)) { 1606 case PRIVATE: return 3; 1607 case PROTECTED: return 1; 1608 default: 1609 case PUBLIC: return 0; 1610 case 0: return 2; 1611 } 1612 } 1613 1614 /** A customized "cannot override" error message. 1615 * @param m The overriding method. 1616 * @param other The overridden method. 1617 * @return An internationalized string. 1618 */ cannotOverride(MethodSymbol m, MethodSymbol other)1619 Fragment cannotOverride(MethodSymbol m, MethodSymbol other) { 1620 Symbol mloc = m.location(); 1621 Symbol oloc = other.location(); 1622 1623 if ((other.owner.flags() & INTERFACE) == 0) 1624 return Fragments.CantOverride(m, mloc, other, oloc); 1625 else if ((m.owner.flags() & INTERFACE) == 0) 1626 return Fragments.CantImplement(m, mloc, other, oloc); 1627 else 1628 return Fragments.ClashesWith(m, mloc, other, oloc); 1629 } 1630 1631 /** A customized "override" warning message. 1632 * @param m The overriding method. 1633 * @param other The overridden method. 1634 * @return An internationalized string. 1635 */ uncheckedOverrides(MethodSymbol m, MethodSymbol other)1636 Fragment uncheckedOverrides(MethodSymbol m, MethodSymbol other) { 1637 Symbol mloc = m.location(); 1638 Symbol oloc = other.location(); 1639 1640 if ((other.owner.flags() & INTERFACE) == 0) 1641 return Fragments.UncheckedOverride(m, mloc, other, oloc); 1642 else if ((m.owner.flags() & INTERFACE) == 0) 1643 return Fragments.UncheckedImplement(m, mloc, other, oloc); 1644 else 1645 return Fragments.UncheckedClashWith(m, mloc, other, oloc); 1646 } 1647 1648 /** A customized "override" warning message. 1649 * @param m The overriding method. 1650 * @param other The overridden method. 1651 * @return An internationalized string. 1652 */ varargsOverrides(MethodSymbol m, MethodSymbol other)1653 Fragment varargsOverrides(MethodSymbol m, MethodSymbol other) { 1654 Symbol mloc = m.location(); 1655 Symbol oloc = other.location(); 1656 1657 if ((other.owner.flags() & INTERFACE) == 0) 1658 return Fragments.VarargsOverride(m, mloc, other, oloc); 1659 else if ((m.owner.flags() & INTERFACE) == 0) 1660 return Fragments.VarargsImplement(m, mloc, other, oloc); 1661 else 1662 return Fragments.VarargsClashWith(m, mloc, other, oloc); 1663 } 1664 1665 /** Check that this method conforms with overridden method 'other'. 1666 * where `origin' is the class where checking started. 1667 * Complications: 1668 * (1) Do not check overriding of synthetic methods 1669 * (reason: they might be final). 1670 * todo: check whether this is still necessary. 1671 * (2) Admit the case where an interface proxy throws fewer exceptions 1672 * than the method it implements. Augment the proxy methods with the 1673 * undeclared exceptions in this case. 1674 * (3) When generics are enabled, admit the case where an interface proxy 1675 * has a result type 1676 * extended by the result type of the method it implements. 1677 * Change the proxies result type to the smaller type in this case. 1678 * 1679 * @param tree The tree from which positions 1680 * are extracted for errors. 1681 * @param m The overriding method. 1682 * @param other The overridden method. 1683 * @param origin The class of which the overriding method 1684 * is a member. 1685 */ checkOverride(JCTree tree, MethodSymbol m, MethodSymbol other, ClassSymbol origin)1686 void checkOverride(JCTree tree, 1687 MethodSymbol m, 1688 MethodSymbol other, 1689 ClassSymbol origin) { 1690 // Don't check overriding of synthetic methods or by bridge methods. 1691 if ((m.flags() & (SYNTHETIC|BRIDGE)) != 0 || (other.flags() & SYNTHETIC) != 0) { 1692 return; 1693 } 1694 1695 // Error if static method overrides instance method (JLS 8.4.6.2). 1696 if ((m.flags() & STATIC) != 0 && 1697 (other.flags() & STATIC) == 0) { 1698 log.error(TreeInfo.diagnosticPositionFor(m, tree), 1699 Errors.OverrideStatic(cannotOverride(m, other))); 1700 m.flags_field |= BAD_OVERRIDE; 1701 return; 1702 } 1703 1704 // Error if instance method overrides static or final 1705 // method (JLS 8.4.6.1). 1706 if ((other.flags() & FINAL) != 0 || 1707 (m.flags() & STATIC) == 0 && 1708 (other.flags() & STATIC) != 0) { 1709 log.error(TreeInfo.diagnosticPositionFor(m, tree), 1710 Errors.OverrideMeth(cannotOverride(m, other), 1711 asFlagSet(other.flags() & (FINAL | STATIC)))); 1712 m.flags_field |= BAD_OVERRIDE; 1713 return; 1714 } 1715 1716 if ((m.owner.flags() & ANNOTATION) != 0) { 1717 // handled in validateAnnotationMethod 1718 return; 1719 } 1720 1721 // Error if overriding method has weaker access (JLS 8.4.6.3). 1722 if (protection(m.flags()) > protection(other.flags())) { 1723 log.error(TreeInfo.diagnosticPositionFor(m, tree), 1724 (other.flags() & AccessFlags) == 0 ? 1725 Errors.OverrideWeakerAccess(cannotOverride(m, other), 1726 "package") : 1727 Errors.OverrideWeakerAccess(cannotOverride(m, other), 1728 asFlagSet(other.flags() & AccessFlags))); 1729 m.flags_field |= BAD_OVERRIDE; 1730 return; 1731 } 1732 1733 Type mt = types.memberType(origin.type, m); 1734 Type ot = types.memberType(origin.type, other); 1735 // Error if overriding result type is different 1736 // (or, in the case of generics mode, not a subtype) of 1737 // overridden result type. We have to rename any type parameters 1738 // before comparing types. 1739 List<Type> mtvars = mt.getTypeArguments(); 1740 List<Type> otvars = ot.getTypeArguments(); 1741 Type mtres = mt.getReturnType(); 1742 Type otres = types.subst(ot.getReturnType(), otvars, mtvars); 1743 1744 overrideWarner.clear(); 1745 boolean resultTypesOK = 1746 types.returnTypeSubstitutable(mt, ot, otres, overrideWarner); 1747 if (!resultTypesOK) { 1748 if ((m.flags() & STATIC) != 0 && (other.flags() & STATIC) != 0) { 1749 log.error(TreeInfo.diagnosticPositionFor(m, tree), 1750 Errors.OverrideIncompatibleRet(Fragments.CantHide(m, m.location(), other, 1751 other.location()), mtres, otres)); 1752 m.flags_field |= BAD_OVERRIDE; 1753 } else { 1754 log.error(TreeInfo.diagnosticPositionFor(m, tree), 1755 Errors.OverrideIncompatibleRet(cannotOverride(m, other), mtres, otres)); 1756 m.flags_field |= BAD_OVERRIDE; 1757 } 1758 return; 1759 } else if (overrideWarner.hasNonSilentLint(LintCategory.UNCHECKED)) { 1760 warnUnchecked(TreeInfo.diagnosticPositionFor(m, tree), 1761 Warnings.OverrideUncheckedRet(uncheckedOverrides(m, other), mtres, otres)); 1762 } 1763 1764 // Error if overriding method throws an exception not reported 1765 // by overridden method. 1766 List<Type> otthrown = types.subst(ot.getThrownTypes(), otvars, mtvars); 1767 List<Type> unhandledErased = unhandled(mt.getThrownTypes(), types.erasure(otthrown)); 1768 List<Type> unhandledUnerased = unhandled(mt.getThrownTypes(), otthrown); 1769 if (unhandledErased.nonEmpty()) { 1770 log.error(TreeInfo.diagnosticPositionFor(m, tree), 1771 Errors.OverrideMethDoesntThrow(cannotOverride(m, other), unhandledUnerased.head)); 1772 m.flags_field |= BAD_OVERRIDE; 1773 return; 1774 } 1775 else if (unhandledUnerased.nonEmpty()) { 1776 warnUnchecked(TreeInfo.diagnosticPositionFor(m, tree), 1777 Warnings.OverrideUncheckedThrown(cannotOverride(m, other), unhandledUnerased.head)); 1778 return; 1779 } 1780 1781 // Optional warning if varargs don't agree 1782 if ((((m.flags() ^ other.flags()) & Flags.VARARGS) != 0) 1783 && lint.isEnabled(LintCategory.OVERRIDES)) { 1784 log.warning(TreeInfo.diagnosticPositionFor(m, tree), 1785 ((m.flags() & Flags.VARARGS) != 0) 1786 ? Warnings.OverrideVarargsMissing(varargsOverrides(m, other)) 1787 : Warnings.OverrideVarargsExtra(varargsOverrides(m, other))); 1788 } 1789 1790 // Warn if instance method overrides bridge method (compiler spec ??) 1791 if ((other.flags() & BRIDGE) != 0) { 1792 log.warning(TreeInfo.diagnosticPositionFor(m, tree), 1793 Warnings.OverrideBridge(uncheckedOverrides(m, other))); 1794 } 1795 1796 // Warn if a deprecated method overridden by a non-deprecated one. 1797 if (!isDeprecatedOverrideIgnorable(other, origin)) { 1798 Lint prevLint = setLint(lint.augment(m)); 1799 try { 1800 checkDeprecated(TreeInfo.diagnosticPositionFor(m, tree), m, other); 1801 } finally { 1802 setLint(prevLint); 1803 } 1804 } 1805 } 1806 // where isDeprecatedOverrideIgnorable(MethodSymbol m, ClassSymbol origin)1807 private boolean isDeprecatedOverrideIgnorable(MethodSymbol m, ClassSymbol origin) { 1808 // If the method, m, is defined in an interface, then ignore the issue if the method 1809 // is only inherited via a supertype and also implemented in the supertype, 1810 // because in that case, we will rediscover the issue when examining the method 1811 // in the supertype. 1812 // If the method, m, is not defined in an interface, then the only time we need to 1813 // address the issue is when the method is the supertype implemementation: any other 1814 // case, we will have dealt with when examining the supertype classes 1815 ClassSymbol mc = m.enclClass(); 1816 Type st = types.supertype(origin.type); 1817 if (!st.hasTag(CLASS)) 1818 return true; 1819 MethodSymbol stimpl = m.implementation((ClassSymbol)st.tsym, types, false); 1820 1821 if (mc != null && ((mc.flags() & INTERFACE) != 0)) { 1822 List<Type> intfs = types.interfaces(origin.type); 1823 return (intfs.contains(mc.type) ? false : (stimpl != null)); 1824 } 1825 else 1826 return (stimpl != m); 1827 } 1828 1829 1830 // used to check if there were any unchecked conversions 1831 Warner overrideWarner = new Warner(); 1832 1833 /** Check that a class does not inherit two concrete methods 1834 * with the same signature. 1835 * @param pos Position to be used for error reporting. 1836 * @param site The class type to be checked. 1837 */ checkCompatibleConcretes(DiagnosticPosition pos, Type site)1838 public void checkCompatibleConcretes(DiagnosticPosition pos, Type site) { 1839 Type sup = types.supertype(site); 1840 if (!sup.hasTag(CLASS)) return; 1841 1842 for (Type t1 = sup; 1843 t1.hasTag(CLASS) && t1.tsym.type.isParameterized(); 1844 t1 = types.supertype(t1)) { 1845 for (Symbol s1 : t1.tsym.members().getSymbols(NON_RECURSIVE)) { 1846 if (s1.kind != MTH || 1847 (s1.flags() & (STATIC|SYNTHETIC|BRIDGE)) != 0 || 1848 !s1.isInheritedIn(site.tsym, types) || 1849 ((MethodSymbol)s1).implementation(site.tsym, 1850 types, 1851 true) != s1) 1852 continue; 1853 Type st1 = types.memberType(t1, s1); 1854 int s1ArgsLength = st1.getParameterTypes().length(); 1855 if (st1 == s1.type) continue; 1856 1857 for (Type t2 = sup; 1858 t2.hasTag(CLASS); 1859 t2 = types.supertype(t2)) { 1860 for (Symbol s2 : t2.tsym.members().getSymbolsByName(s1.name)) { 1861 if (s2 == s1 || 1862 s2.kind != MTH || 1863 (s2.flags() & (STATIC|SYNTHETIC|BRIDGE)) != 0 || 1864 s2.type.getParameterTypes().length() != s1ArgsLength || 1865 !s2.isInheritedIn(site.tsym, types) || 1866 ((MethodSymbol)s2).implementation(site.tsym, 1867 types, 1868 true) != s2) 1869 continue; 1870 Type st2 = types.memberType(t2, s2); 1871 if (types.overrideEquivalent(st1, st2)) 1872 log.error(pos, 1873 Errors.ConcreteInheritanceConflict(s1, t1, s2, t2, sup)); 1874 } 1875 } 1876 } 1877 } 1878 } 1879 1880 /** Check that classes (or interfaces) do not each define an abstract 1881 * method with same name and arguments but incompatible return types. 1882 * @param pos Position to be used for error reporting. 1883 * @param t1 The first argument type. 1884 * @param t2 The second argument type. 1885 */ checkCompatibleAbstracts(DiagnosticPosition pos, Type t1, Type t2, Type site)1886 public boolean checkCompatibleAbstracts(DiagnosticPosition pos, 1887 Type t1, 1888 Type t2, 1889 Type site) { 1890 if ((site.tsym.flags() & COMPOUND) != 0) { 1891 // special case for intersections: need to eliminate wildcards in supertypes 1892 t1 = types.capture(t1); 1893 t2 = types.capture(t2); 1894 } 1895 return firstIncompatibility(pos, t1, t2, site) == null; 1896 } 1897 1898 /** Return the first method which is defined with same args 1899 * but different return types in two given interfaces, or null if none 1900 * exists. 1901 * @param t1 The first type. 1902 * @param t2 The second type. 1903 * @param site The most derived type. 1904 * @returns symbol from t2 that conflicts with one in t1. 1905 */ firstIncompatibility(DiagnosticPosition pos, Type t1, Type t2, Type site)1906 private Symbol firstIncompatibility(DiagnosticPosition pos, Type t1, Type t2, Type site) { 1907 Map<TypeSymbol,Type> interfaces1 = new HashMap<>(); 1908 closure(t1, interfaces1); 1909 Map<TypeSymbol,Type> interfaces2; 1910 if (t1 == t2) 1911 interfaces2 = interfaces1; 1912 else 1913 closure(t2, interfaces1, interfaces2 = new HashMap<>()); 1914 1915 for (Type t3 : interfaces1.values()) { 1916 for (Type t4 : interfaces2.values()) { 1917 Symbol s = firstDirectIncompatibility(pos, t3, t4, site); 1918 if (s != null) return s; 1919 } 1920 } 1921 return null; 1922 } 1923 1924 /** Compute all the supertypes of t, indexed by type symbol. */ closure(Type t, Map<TypeSymbol,Type> typeMap)1925 private void closure(Type t, Map<TypeSymbol,Type> typeMap) { 1926 if (!t.hasTag(CLASS)) return; 1927 if (typeMap.put(t.tsym, t) == null) { 1928 closure(types.supertype(t), typeMap); 1929 for (Type i : types.interfaces(t)) 1930 closure(i, typeMap); 1931 } 1932 } 1933 1934 /** Compute all the supertypes of t, indexed by type symbol (except thise in typesSkip). */ closure(Type t, Map<TypeSymbol,Type> typesSkip, Map<TypeSymbol,Type> typeMap)1935 private void closure(Type t, Map<TypeSymbol,Type> typesSkip, Map<TypeSymbol,Type> typeMap) { 1936 if (!t.hasTag(CLASS)) return; 1937 if (typesSkip.get(t.tsym) != null) return; 1938 if (typeMap.put(t.tsym, t) == null) { 1939 closure(types.supertype(t), typesSkip, typeMap); 1940 for (Type i : types.interfaces(t)) 1941 closure(i, typesSkip, typeMap); 1942 } 1943 } 1944 1945 /** Return the first method in t2 that conflicts with a method from t1. */ firstDirectIncompatibility(DiagnosticPosition pos, Type t1, Type t2, Type site)1946 private Symbol firstDirectIncompatibility(DiagnosticPosition pos, Type t1, Type t2, Type site) { 1947 for (Symbol s1 : t1.tsym.members().getSymbols(NON_RECURSIVE)) { 1948 Type st1 = null; 1949 if (s1.kind != MTH || !s1.isInheritedIn(site.tsym, types) || 1950 (s1.flags() & SYNTHETIC) != 0) continue; 1951 Symbol impl = ((MethodSymbol)s1).implementation(site.tsym, types, false); 1952 if (impl != null && (impl.flags() & ABSTRACT) == 0) continue; 1953 for (Symbol s2 : t2.tsym.members().getSymbolsByName(s1.name)) { 1954 if (s1 == s2) continue; 1955 if (s2.kind != MTH || !s2.isInheritedIn(site.tsym, types) || 1956 (s2.flags() & SYNTHETIC) != 0) continue; 1957 if (st1 == null) st1 = types.memberType(t1, s1); 1958 Type st2 = types.memberType(t2, s2); 1959 if (types.overrideEquivalent(st1, st2)) { 1960 List<Type> tvars1 = st1.getTypeArguments(); 1961 List<Type> tvars2 = st2.getTypeArguments(); 1962 Type rt1 = st1.getReturnType(); 1963 Type rt2 = types.subst(st2.getReturnType(), tvars2, tvars1); 1964 boolean compat = 1965 types.isSameType(rt1, rt2) || 1966 !rt1.isPrimitiveOrVoid() && 1967 !rt2.isPrimitiveOrVoid() && 1968 (types.covariantReturnType(rt1, rt2, types.noWarnings) || 1969 types.covariantReturnType(rt2, rt1, types.noWarnings)) || 1970 checkCommonOverriderIn(s1,s2,site); 1971 if (!compat) { 1972 log.error(pos, Errors.TypesIncompatible(t1, t2, 1973 Fragments.IncompatibleDiffRet(s2.name, types.memberType(t2, s2).getParameterTypes()))); 1974 return s2; 1975 } 1976 } else if (checkNameClash((ClassSymbol)site.tsym, s1, s2) && 1977 !checkCommonOverriderIn(s1, s2, site)) { 1978 log.error(pos, Errors.NameClashSameErasureNoOverride( 1979 s1.name, types.memberType(site, s1).asMethodType().getParameterTypes(), s1.location(), 1980 s2.name, types.memberType(site, s2).asMethodType().getParameterTypes(), s2.location())); 1981 return s2; 1982 } 1983 } 1984 } 1985 return null; 1986 } 1987 //WHERE checkCommonOverriderIn(Symbol s1, Symbol s2, Type site)1988 boolean checkCommonOverriderIn(Symbol s1, Symbol s2, Type site) { 1989 Map<TypeSymbol,Type> supertypes = new HashMap<>(); 1990 Type st1 = types.memberType(site, s1); 1991 Type st2 = types.memberType(site, s2); 1992 closure(site, supertypes); 1993 for (Type t : supertypes.values()) { 1994 for (Symbol s3 : t.tsym.members().getSymbolsByName(s1.name)) { 1995 if (s3 == s1 || s3 == s2 || s3.kind != MTH || (s3.flags() & (BRIDGE|SYNTHETIC)) != 0) continue; 1996 Type st3 = types.memberType(site,s3); 1997 if (types.overrideEquivalent(st3, st1) && 1998 types.overrideEquivalent(st3, st2) && 1999 types.returnTypeSubstitutable(st3, st1) && 2000 types.returnTypeSubstitutable(st3, st2)) { 2001 return true; 2002 } 2003 } 2004 } 2005 return false; 2006 } 2007 2008 /** Check that a given method conforms with any method it overrides. 2009 * @param tree The tree from which positions are extracted 2010 * for errors. 2011 * @param m The overriding method. 2012 */ checkOverride(Env<AttrContext> env, JCMethodDecl tree, MethodSymbol m)2013 void checkOverride(Env<AttrContext> env, JCMethodDecl tree, MethodSymbol m) { 2014 ClassSymbol origin = (ClassSymbol)m.owner; 2015 if ((origin.flags() & ENUM) != 0 && names.finalize.equals(m.name)) 2016 if (m.overrides(syms.enumFinalFinalize, origin, types, false)) { 2017 log.error(tree.pos(), Errors.EnumNoFinalize); 2018 return; 2019 } 2020 for (Type t = origin.type; t.hasTag(CLASS); 2021 t = types.supertype(t)) { 2022 if (t != origin.type) { 2023 checkOverride(tree, t, origin, m); 2024 } 2025 for (Type t2 : types.interfaces(t)) { 2026 checkOverride(tree, t2, origin, m); 2027 } 2028 } 2029 2030 final boolean explicitOverride = m.attribute(syms.overrideType.tsym) != null; 2031 // Check if this method must override a super method due to being annotated with @Override 2032 // or by virtue of being a member of a diamond inferred anonymous class. Latter case is to 2033 // be treated "as if as they were annotated" with @Override. 2034 boolean mustOverride = explicitOverride || 2035 (env.info.isAnonymousDiamond && !m.isConstructor() && !m.isPrivate()); 2036 if (mustOverride && !isOverrider(m)) { 2037 DiagnosticPosition pos = tree.pos(); 2038 for (JCAnnotation a : tree.getModifiers().annotations) { 2039 if (a.annotationType.type.tsym == syms.overrideType.tsym) { 2040 pos = a.pos(); 2041 break; 2042 } 2043 } 2044 log.error(pos, 2045 explicitOverride ? (m.isStatic() ? Errors.StaticMethodsCannotBeAnnotatedWithOverride : Errors.MethodDoesNotOverrideSuperclass) : 2046 Errors.AnonymousDiamondMethodDoesNotOverrideSuperclass(Fragments.DiamondAnonymousMethodsImplicitlyOverride)); 2047 } 2048 } 2049 checkOverride(JCTree tree, Type site, ClassSymbol origin, MethodSymbol m)2050 void checkOverride(JCTree tree, Type site, ClassSymbol origin, MethodSymbol m) { 2051 TypeSymbol c = site.tsym; 2052 for (Symbol sym : c.members().getSymbolsByName(m.name)) { 2053 if (m.overrides(sym, origin, types, false)) { 2054 if ((sym.flags() & ABSTRACT) == 0) { 2055 checkOverride(tree, m, (MethodSymbol)sym, origin); 2056 } 2057 } 2058 } 2059 } 2060 2061 private Filter<Symbol> equalsHasCodeFilter = s -> MethodSymbol.implementation_filter.accepts(s) && 2062 (s.flags() & BAD_OVERRIDE) == 0; 2063 checkClassOverrideEqualsAndHashIfNeeded(DiagnosticPosition pos, ClassSymbol someClass)2064 public void checkClassOverrideEqualsAndHashIfNeeded(DiagnosticPosition pos, 2065 ClassSymbol someClass) { 2066 /* At present, annotations cannot possibly have a method that is override 2067 * equivalent with Object.equals(Object) but in any case the condition is 2068 * fine for completeness. 2069 */ 2070 if (someClass == (ClassSymbol)syms.objectType.tsym || 2071 someClass.isInterface() || someClass.isEnum() || 2072 (someClass.flags() & ANNOTATION) != 0 || 2073 (someClass.flags() & ABSTRACT) != 0) return; 2074 //anonymous inner classes implementing interfaces need especial treatment 2075 if (someClass.isAnonymous()) { 2076 List<Type> interfaces = types.interfaces(someClass.type); 2077 if (interfaces != null && !interfaces.isEmpty() && 2078 interfaces.head.tsym == syms.comparatorType.tsym) return; 2079 } 2080 checkClassOverrideEqualsAndHash(pos, someClass); 2081 } 2082 checkClassOverrideEqualsAndHash(DiagnosticPosition pos, ClassSymbol someClass)2083 private void checkClassOverrideEqualsAndHash(DiagnosticPosition pos, 2084 ClassSymbol someClass) { 2085 if (lint.isEnabled(LintCategory.OVERRIDES)) { 2086 MethodSymbol equalsAtObject = (MethodSymbol)syms.objectType 2087 .tsym.members().findFirst(names.equals); 2088 MethodSymbol hashCodeAtObject = (MethodSymbol)syms.objectType 2089 .tsym.members().findFirst(names.hashCode); 2090 boolean overridesEquals = types.implementation(equalsAtObject, 2091 someClass, false, equalsHasCodeFilter).owner == someClass; 2092 boolean overridesHashCode = types.implementation(hashCodeAtObject, 2093 someClass, false, equalsHasCodeFilter) != hashCodeAtObject; 2094 2095 if (overridesEquals && !overridesHashCode) { 2096 log.warning(LintCategory.OVERRIDES, pos, 2097 Warnings.OverrideEqualsButNotHashcode(someClass)); 2098 } 2099 } 2100 } 2101 checkModuleName(JCModuleDecl tree)2102 public void checkModuleName (JCModuleDecl tree) { 2103 Name moduleName = tree.sym.name; 2104 Assert.checkNonNull(moduleName); 2105 if (lint.isEnabled(LintCategory.MODULE)) { 2106 JCExpression qualId = tree.qualId; 2107 while (qualId != null) { 2108 Name componentName; 2109 DiagnosticPosition pos; 2110 switch (qualId.getTag()) { 2111 case SELECT: 2112 JCFieldAccess selectNode = ((JCFieldAccess) qualId); 2113 componentName = selectNode.name; 2114 pos = selectNode.pos(); 2115 qualId = selectNode.selected; 2116 break; 2117 case IDENT: 2118 componentName = ((JCIdent) qualId).name; 2119 pos = qualId.pos(); 2120 qualId = null; 2121 break; 2122 default: 2123 throw new AssertionError("Unexpected qualified identifier: " + qualId.toString()); 2124 } 2125 if (componentName != null) { 2126 String moduleNameComponentString = componentName.toString(); 2127 int nameLength = moduleNameComponentString.length(); 2128 if (nameLength > 0 && Character.isDigit(moduleNameComponentString.charAt(nameLength - 1))) { 2129 log.warning(Lint.LintCategory.MODULE, pos, Warnings.PoorChoiceForModuleName(componentName)); 2130 } 2131 } 2132 } 2133 } 2134 } 2135 checkNameClash(ClassSymbol origin, Symbol s1, Symbol s2)2136 private boolean checkNameClash(ClassSymbol origin, Symbol s1, Symbol s2) { 2137 ClashFilter cf = new ClashFilter(origin.type); 2138 return (cf.accepts(s1) && 2139 cf.accepts(s2) && 2140 types.hasSameArgs(s1.erasure(types), s2.erasure(types))); 2141 } 2142 2143 2144 /** Check that all abstract members of given class have definitions. 2145 * @param pos Position to be used for error reporting. 2146 * @param c The class. 2147 */ checkAllDefined(DiagnosticPosition pos, ClassSymbol c)2148 void checkAllDefined(DiagnosticPosition pos, ClassSymbol c) { 2149 MethodSymbol undef = types.firstUnimplementedAbstract(c); 2150 if (undef != null) { 2151 MethodSymbol undef1 = 2152 new MethodSymbol(undef.flags(), undef.name, 2153 types.memberType(c.type, undef), undef.owner); 2154 log.error(pos, 2155 Errors.DoesNotOverrideAbstract(c, undef1, undef1.location())); 2156 } 2157 } 2158 checkNonCyclicDecl(JCClassDecl tree)2159 void checkNonCyclicDecl(JCClassDecl tree) { 2160 CycleChecker cc = new CycleChecker(); 2161 cc.scan(tree); 2162 if (!cc.errorFound && !cc.partialCheck) { 2163 tree.sym.flags_field |= ACYCLIC; 2164 } 2165 } 2166 2167 class CycleChecker extends TreeScanner { 2168 2169 List<Symbol> seenClasses = List.nil(); 2170 boolean errorFound = false; 2171 boolean partialCheck = false; 2172 checkSymbol(DiagnosticPosition pos, Symbol sym)2173 private void checkSymbol(DiagnosticPosition pos, Symbol sym) { 2174 if (sym != null && sym.kind == TYP) { 2175 Env<AttrContext> classEnv = enter.getEnv((TypeSymbol)sym); 2176 if (classEnv != null) { 2177 DiagnosticSource prevSource = log.currentSource(); 2178 try { 2179 log.useSource(classEnv.toplevel.sourcefile); 2180 scan(classEnv.tree); 2181 } 2182 finally { 2183 log.useSource(prevSource.getFile()); 2184 } 2185 } else if (sym.kind == TYP) { 2186 checkClass(pos, sym, List.nil()); 2187 } 2188 } else { 2189 //not completed yet 2190 partialCheck = true; 2191 } 2192 } 2193 2194 @Override visitSelect(JCFieldAccess tree)2195 public void visitSelect(JCFieldAccess tree) { 2196 super.visitSelect(tree); 2197 checkSymbol(tree.pos(), tree.sym); 2198 } 2199 2200 @Override visitIdent(JCIdent tree)2201 public void visitIdent(JCIdent tree) { 2202 checkSymbol(tree.pos(), tree.sym); 2203 } 2204 2205 @Override visitTypeApply(JCTypeApply tree)2206 public void visitTypeApply(JCTypeApply tree) { 2207 scan(tree.clazz); 2208 } 2209 2210 @Override visitTypeArray(JCArrayTypeTree tree)2211 public void visitTypeArray(JCArrayTypeTree tree) { 2212 scan(tree.elemtype); 2213 } 2214 2215 @Override visitClassDef(JCClassDecl tree)2216 public void visitClassDef(JCClassDecl tree) { 2217 List<JCTree> supertypes = List.nil(); 2218 if (tree.getExtendsClause() != null) { 2219 supertypes = supertypes.prepend(tree.getExtendsClause()); 2220 } 2221 if (tree.getImplementsClause() != null) { 2222 for (JCTree intf : tree.getImplementsClause()) { 2223 supertypes = supertypes.prepend(intf); 2224 } 2225 } 2226 checkClass(tree.pos(), tree.sym, supertypes); 2227 } 2228 checkClass(DiagnosticPosition pos, Symbol c, List<JCTree> supertypes)2229 void checkClass(DiagnosticPosition pos, Symbol c, List<JCTree> supertypes) { 2230 if ((c.flags_field & ACYCLIC) != 0) 2231 return; 2232 if (seenClasses.contains(c)) { 2233 errorFound = true; 2234 noteCyclic(pos, (ClassSymbol)c); 2235 } else if (!c.type.isErroneous()) { 2236 try { 2237 seenClasses = seenClasses.prepend(c); 2238 if (c.type.hasTag(CLASS)) { 2239 if (supertypes.nonEmpty()) { 2240 scan(supertypes); 2241 } 2242 else { 2243 ClassType ct = (ClassType)c.type; 2244 if (ct.supertype_field == null || 2245 ct.interfaces_field == null) { 2246 //not completed yet 2247 partialCheck = true; 2248 return; 2249 } 2250 checkSymbol(pos, ct.supertype_field.tsym); 2251 for (Type intf : ct.interfaces_field) { 2252 checkSymbol(pos, intf.tsym); 2253 } 2254 } 2255 if (c.owner.kind == TYP) { 2256 checkSymbol(pos, c.owner); 2257 } 2258 } 2259 } finally { 2260 seenClasses = seenClasses.tail; 2261 } 2262 } 2263 } 2264 } 2265 2266 /** Check for cyclic references. Issue an error if the 2267 * symbol of the type referred to has a LOCKED flag set. 2268 * 2269 * @param pos Position to be used for error reporting. 2270 * @param t The type referred to. 2271 */ checkNonCyclic(DiagnosticPosition pos, Type t)2272 void checkNonCyclic(DiagnosticPosition pos, Type t) { 2273 checkNonCyclicInternal(pos, t); 2274 } 2275 2276 checkNonCyclic(DiagnosticPosition pos, TypeVar t)2277 void checkNonCyclic(DiagnosticPosition pos, TypeVar t) { 2278 checkNonCyclic1(pos, t, List.nil()); 2279 } 2280 checkNonCyclic1(DiagnosticPosition pos, Type t, List<TypeVar> seen)2281 private void checkNonCyclic1(DiagnosticPosition pos, Type t, List<TypeVar> seen) { 2282 final TypeVar tv; 2283 if (t.hasTag(TYPEVAR) && (t.tsym.flags() & UNATTRIBUTED) != 0) 2284 return; 2285 if (seen.contains(t)) { 2286 tv = (TypeVar)t; 2287 tv.bound = types.createErrorType(t); 2288 log.error(pos, Errors.CyclicInheritance(t)); 2289 } else if (t.hasTag(TYPEVAR)) { 2290 tv = (TypeVar)t; 2291 seen = seen.prepend(tv); 2292 for (Type b : types.getBounds(tv)) 2293 checkNonCyclic1(pos, b, seen); 2294 } 2295 } 2296 2297 /** Check for cyclic references. Issue an error if the 2298 * symbol of the type referred to has a LOCKED flag set. 2299 * 2300 * @param pos Position to be used for error reporting. 2301 * @param t The type referred to. 2302 * @returns True if the check completed on all attributed classes 2303 */ checkNonCyclicInternal(DiagnosticPosition pos, Type t)2304 private boolean checkNonCyclicInternal(DiagnosticPosition pos, Type t) { 2305 boolean complete = true; // was the check complete? 2306 //- System.err.println("checkNonCyclicInternal("+t+");");//DEBUG 2307 Symbol c = t.tsym; 2308 if ((c.flags_field & ACYCLIC) != 0) return true; 2309 2310 if ((c.flags_field & LOCKED) != 0) { 2311 noteCyclic(pos, (ClassSymbol)c); 2312 } else if (!c.type.isErroneous()) { 2313 try { 2314 c.flags_field |= LOCKED; 2315 if (c.type.hasTag(CLASS)) { 2316 ClassType clazz = (ClassType)c.type; 2317 if (clazz.interfaces_field != null) 2318 for (List<Type> l=clazz.interfaces_field; l.nonEmpty(); l=l.tail) 2319 complete &= checkNonCyclicInternal(pos, l.head); 2320 if (clazz.supertype_field != null) { 2321 Type st = clazz.supertype_field; 2322 if (st != null && st.hasTag(CLASS)) 2323 complete &= checkNonCyclicInternal(pos, st); 2324 } 2325 if (c.owner.kind == TYP) 2326 complete &= checkNonCyclicInternal(pos, c.owner.type); 2327 } 2328 } finally { 2329 c.flags_field &= ~LOCKED; 2330 } 2331 } 2332 if (complete) 2333 complete = ((c.flags_field & UNATTRIBUTED) == 0) && c.isCompleted(); 2334 if (complete) c.flags_field |= ACYCLIC; 2335 return complete; 2336 } 2337 2338 /** Note that we found an inheritance cycle. */ noteCyclic(DiagnosticPosition pos, ClassSymbol c)2339 private void noteCyclic(DiagnosticPosition pos, ClassSymbol c) { 2340 log.error(pos, Errors.CyclicInheritance(c)); 2341 for (List<Type> l=types.interfaces(c.type); l.nonEmpty(); l=l.tail) 2342 l.head = types.createErrorType((ClassSymbol)l.head.tsym, Type.noType); 2343 Type st = types.supertype(c.type); 2344 if (st.hasTag(CLASS)) 2345 ((ClassType)c.type).supertype_field = types.createErrorType((ClassSymbol)st.tsym, Type.noType); 2346 c.type = types.createErrorType(c, c.type); 2347 c.flags_field |= ACYCLIC; 2348 } 2349 2350 /** Check that all methods which implement some 2351 * method conform to the method they implement. 2352 * @param tree The class definition whose members are checked. 2353 */ checkImplementations(JCClassDecl tree)2354 void checkImplementations(JCClassDecl tree) { 2355 checkImplementations(tree, tree.sym, tree.sym); 2356 } 2357 //where 2358 /** Check that all methods which implement some 2359 * method in `ic' conform to the method they implement. 2360 */ checkImplementations(JCTree tree, ClassSymbol origin, ClassSymbol ic)2361 void checkImplementations(JCTree tree, ClassSymbol origin, ClassSymbol ic) { 2362 for (List<Type> l = types.closure(ic.type); l.nonEmpty(); l = l.tail) { 2363 ClassSymbol lc = (ClassSymbol)l.head.tsym; 2364 if ((lc.flags() & ABSTRACT) != 0) { 2365 for (Symbol sym : lc.members().getSymbols(NON_RECURSIVE)) { 2366 if (sym.kind == MTH && 2367 (sym.flags() & (STATIC|ABSTRACT)) == ABSTRACT) { 2368 MethodSymbol absmeth = (MethodSymbol)sym; 2369 MethodSymbol implmeth = absmeth.implementation(origin, types, false); 2370 if (implmeth != null && implmeth != absmeth && 2371 (implmeth.owner.flags() & INTERFACE) == 2372 (origin.flags() & INTERFACE)) { 2373 // don't check if implmeth is in a class, yet 2374 // origin is an interface. This case arises only 2375 // if implmeth is declared in Object. The reason is 2376 // that interfaces really don't inherit from 2377 // Object it's just that the compiler represents 2378 // things that way. 2379 checkOverride(tree, implmeth, absmeth, origin); 2380 } 2381 } 2382 } 2383 } 2384 } 2385 } 2386 2387 /** Check that all abstract methods implemented by a class are 2388 * mutually compatible. 2389 * @param pos Position to be used for error reporting. 2390 * @param c The class whose interfaces are checked. 2391 */ checkCompatibleSupertypes(DiagnosticPosition pos, Type c)2392 void checkCompatibleSupertypes(DiagnosticPosition pos, Type c) { 2393 List<Type> supertypes = types.interfaces(c); 2394 Type supertype = types.supertype(c); 2395 if (supertype.hasTag(CLASS) && 2396 (supertype.tsym.flags() & ABSTRACT) != 0) 2397 supertypes = supertypes.prepend(supertype); 2398 for (List<Type> l = supertypes; l.nonEmpty(); l = l.tail) { 2399 if (!l.head.getTypeArguments().isEmpty() && 2400 !checkCompatibleAbstracts(pos, l.head, l.head, c)) 2401 return; 2402 for (List<Type> m = supertypes; m != l; m = m.tail) 2403 if (!checkCompatibleAbstracts(pos, l.head, m.head, c)) 2404 return; 2405 } 2406 checkCompatibleConcretes(pos, c); 2407 } 2408 2409 /** Check that all non-override equivalent methods accessible from 'site' 2410 * are mutually compatible (JLS 8.4.8/9.4.1). 2411 * 2412 * @param pos Position to be used for error reporting. 2413 * @param site The class whose methods are checked. 2414 * @param sym The method symbol to be checked. 2415 */ checkOverrideClashes(DiagnosticPosition pos, Type site, MethodSymbol sym)2416 void checkOverrideClashes(DiagnosticPosition pos, Type site, MethodSymbol sym) { 2417 ClashFilter cf = new ClashFilter(site); 2418 //for each method m1 that is overridden (directly or indirectly) 2419 //by method 'sym' in 'site'... 2420 2421 List<MethodSymbol> potentiallyAmbiguousList = List.nil(); 2422 boolean overridesAny = false; 2423 for (Symbol m1 : types.membersClosure(site, false).getSymbolsByName(sym.name, cf)) { 2424 if (!sym.overrides(m1, site.tsym, types, false)) { 2425 if (m1 == sym) { 2426 continue; 2427 } 2428 2429 if (!overridesAny) { 2430 potentiallyAmbiguousList = potentiallyAmbiguousList.prepend((MethodSymbol)m1); 2431 } 2432 continue; 2433 } 2434 2435 if (m1 != sym) { 2436 overridesAny = true; 2437 potentiallyAmbiguousList = List.nil(); 2438 } 2439 2440 //...check each method m2 that is a member of 'site' 2441 for (Symbol m2 : types.membersClosure(site, false).getSymbolsByName(sym.name, cf)) { 2442 if (m2 == m1) continue; 2443 //if (i) the signature of 'sym' is not a subsignature of m1 (seen as 2444 //a member of 'site') and (ii) m1 has the same erasure as m2, issue an error 2445 if (!types.isSubSignature(sym.type, types.memberType(site, m2), Feature.STRICT_METHOD_CLASH_CHECK.allowedInSource(source)) && 2446 types.hasSameArgs(m2.erasure(types), m1.erasure(types))) { 2447 sym.flags_field |= CLASH; 2448 if (m1 == sym) { 2449 log.error(pos, Errors.NameClashSameErasureNoOverride( 2450 m1.name, types.memberType(site, m1).asMethodType().getParameterTypes(), m1.location(), 2451 m2.name, types.memberType(site, m2).asMethodType().getParameterTypes(), m2.location())); 2452 } else { 2453 ClassType ct = (ClassType)site; 2454 String kind = ct.isInterface() ? "interface" : "class"; 2455 log.error(pos, Errors.NameClashSameErasureNoOverride1( 2456 kind, 2457 ct.tsym.name, 2458 m1.name, 2459 types.memberType(site, m1).asMethodType().getParameterTypes(), 2460 m1.location(), 2461 m2.name, 2462 types.memberType(site, m2).asMethodType().getParameterTypes(), 2463 m2.location())); 2464 } 2465 return; 2466 } 2467 } 2468 } 2469 2470 if (!overridesAny) { 2471 for (MethodSymbol m: potentiallyAmbiguousList) { 2472 checkPotentiallyAmbiguousOverloads(pos, site, sym, m); 2473 } 2474 } 2475 } 2476 2477 /** Check that all static methods accessible from 'site' are 2478 * mutually compatible (JLS 8.4.8). 2479 * 2480 * @param pos Position to be used for error reporting. 2481 * @param site The class whose methods are checked. 2482 * @param sym The method symbol to be checked. 2483 */ checkHideClashes(DiagnosticPosition pos, Type site, MethodSymbol sym)2484 void checkHideClashes(DiagnosticPosition pos, Type site, MethodSymbol sym) { 2485 ClashFilter cf = new ClashFilter(site); 2486 //for each method m1 that is a member of 'site'... 2487 for (Symbol s : types.membersClosure(site, true).getSymbolsByName(sym.name, cf)) { 2488 //if (i) the signature of 'sym' is not a subsignature of m1 (seen as 2489 //a member of 'site') and (ii) 'sym' has the same erasure as m1, issue an error 2490 if (!types.isSubSignature(sym.type, types.memberType(site, s), Feature.STRICT_METHOD_CLASH_CHECK.allowedInSource(source))) { 2491 if (types.hasSameArgs(s.erasure(types), sym.erasure(types))) { 2492 log.error(pos, 2493 Errors.NameClashSameErasureNoHide(sym, sym.location(), s, s.location())); 2494 return; 2495 } else { 2496 checkPotentiallyAmbiguousOverloads(pos, site, sym, (MethodSymbol)s); 2497 } 2498 } 2499 } 2500 } 2501 2502 //where 2503 private class ClashFilter implements Filter<Symbol> { 2504 2505 Type site; 2506 ClashFilter(Type site)2507 ClashFilter(Type site) { 2508 this.site = site; 2509 } 2510 shouldSkip(Symbol s)2511 boolean shouldSkip(Symbol s) { 2512 return (s.flags() & CLASH) != 0 && 2513 s.owner == site.tsym; 2514 } 2515 accepts(Symbol s)2516 public boolean accepts(Symbol s) { 2517 return s.kind == MTH && 2518 (s.flags() & SYNTHETIC) == 0 && 2519 !shouldSkip(s) && 2520 s.isInheritedIn(site.tsym, types) && 2521 !s.isConstructor(); 2522 } 2523 } 2524 checkDefaultMethodClashes(DiagnosticPosition pos, Type site)2525 void checkDefaultMethodClashes(DiagnosticPosition pos, Type site) { 2526 DefaultMethodClashFilter dcf = new DefaultMethodClashFilter(site); 2527 for (Symbol m : types.membersClosure(site, false).getSymbols(dcf)) { 2528 Assert.check(m.kind == MTH); 2529 List<MethodSymbol> prov = types.interfaceCandidates(site, (MethodSymbol)m); 2530 if (prov.size() > 1) { 2531 ListBuffer<Symbol> abstracts = new ListBuffer<>(); 2532 ListBuffer<Symbol> defaults = new ListBuffer<>(); 2533 for (MethodSymbol provSym : prov) { 2534 if ((provSym.flags() & DEFAULT) != 0) { 2535 defaults = defaults.append(provSym); 2536 } else if ((provSym.flags() & ABSTRACT) != 0) { 2537 abstracts = abstracts.append(provSym); 2538 } 2539 if (defaults.nonEmpty() && defaults.size() + abstracts.size() >= 2) { 2540 //strong semantics - issue an error if two sibling interfaces 2541 //have two override-equivalent defaults - or if one is abstract 2542 //and the other is default 2543 Fragment diagKey; 2544 Symbol s1 = defaults.first(); 2545 Symbol s2; 2546 if (defaults.size() > 1) { 2547 s2 = defaults.toList().tail.head; 2548 diagKey = Fragments.IncompatibleUnrelatedDefaults(Kinds.kindName(site.tsym), site, 2549 m.name, types.memberType(site, m).getParameterTypes(), 2550 s1.location(), s2.location()); 2551 2552 } else { 2553 s2 = abstracts.first(); 2554 diagKey = Fragments.IncompatibleAbstractDefault(Kinds.kindName(site.tsym), site, 2555 m.name, types.memberType(site, m).getParameterTypes(), 2556 s1.location(), s2.location()); 2557 } 2558 log.error(pos, Errors.TypesIncompatible(s1.location().type, s2.location().type, diagKey)); 2559 break; 2560 } 2561 } 2562 } 2563 } 2564 } 2565 2566 //where 2567 private class DefaultMethodClashFilter implements Filter<Symbol> { 2568 2569 Type site; 2570 DefaultMethodClashFilter(Type site)2571 DefaultMethodClashFilter(Type site) { 2572 this.site = site; 2573 } 2574 accepts(Symbol s)2575 public boolean accepts(Symbol s) { 2576 return s.kind == MTH && 2577 (s.flags() & DEFAULT) != 0 && 2578 s.isInheritedIn(site.tsym, types) && 2579 !s.isConstructor(); 2580 } 2581 } 2582 2583 /** 2584 * Report warnings for potentially ambiguous method declarations. Two declarations 2585 * are potentially ambiguous if they feature two unrelated functional interface 2586 * in same argument position (in which case, a call site passing an implicit 2587 * lambda would be ambiguous). 2588 */ checkPotentiallyAmbiguousOverloads(DiagnosticPosition pos, Type site, MethodSymbol msym1, MethodSymbol msym2)2589 void checkPotentiallyAmbiguousOverloads(DiagnosticPosition pos, Type site, 2590 MethodSymbol msym1, MethodSymbol msym2) { 2591 if (msym1 != msym2 && 2592 Feature.DEFAULT_METHODS.allowedInSource(source) && 2593 lint.isEnabled(LintCategory.OVERLOADS) && 2594 (msym1.flags() & POTENTIALLY_AMBIGUOUS) == 0 && 2595 (msym2.flags() & POTENTIALLY_AMBIGUOUS) == 0) { 2596 Type mt1 = types.memberType(site, msym1); 2597 Type mt2 = types.memberType(site, msym2); 2598 //if both generic methods, adjust type variables 2599 if (mt1.hasTag(FORALL) && mt2.hasTag(FORALL) && 2600 types.hasSameBounds((ForAll)mt1, (ForAll)mt2)) { 2601 mt2 = types.subst(mt2, ((ForAll)mt2).tvars, ((ForAll)mt1).tvars); 2602 } 2603 //expand varargs methods if needed 2604 int maxLength = Math.max(mt1.getParameterTypes().length(), mt2.getParameterTypes().length()); 2605 List<Type> args1 = rs.adjustArgs(mt1.getParameterTypes(), msym1, maxLength, true); 2606 List<Type> args2 = rs.adjustArgs(mt2.getParameterTypes(), msym2, maxLength, true); 2607 //if arities don't match, exit 2608 if (args1.length() != args2.length()) return; 2609 boolean potentiallyAmbiguous = false; 2610 while (args1.nonEmpty() && args2.nonEmpty()) { 2611 Type s = args1.head; 2612 Type t = args2.head; 2613 if (!types.isSubtype(t, s) && !types.isSubtype(s, t)) { 2614 if (types.isFunctionalInterface(s) && types.isFunctionalInterface(t) && 2615 types.findDescriptorType(s).getParameterTypes().length() > 0 && 2616 types.findDescriptorType(s).getParameterTypes().length() == 2617 types.findDescriptorType(t).getParameterTypes().length()) { 2618 potentiallyAmbiguous = true; 2619 } else { 2620 break; 2621 } 2622 } 2623 args1 = args1.tail; 2624 args2 = args2.tail; 2625 } 2626 if (potentiallyAmbiguous) { 2627 //we found two incompatible functional interfaces with same arity 2628 //this means a call site passing an implicit lambda would be ambigiuous 2629 msym1.flags_field |= POTENTIALLY_AMBIGUOUS; 2630 msym2.flags_field |= POTENTIALLY_AMBIGUOUS; 2631 log.warning(LintCategory.OVERLOADS, pos, 2632 Warnings.PotentiallyAmbiguousOverload(msym1, msym1.location(), 2633 msym2, msym2.location())); 2634 return; 2635 } 2636 } 2637 } 2638 checkAccessFromSerializableElement(final JCTree tree, boolean isLambda)2639 void checkAccessFromSerializableElement(final JCTree tree, boolean isLambda) { 2640 if (warnOnAnyAccessToMembers || 2641 (lint.isEnabled(LintCategory.SERIAL) && 2642 !lint.isSuppressed(LintCategory.SERIAL) && 2643 isLambda)) { 2644 Symbol sym = TreeInfo.symbol(tree); 2645 if (!sym.kind.matches(KindSelector.VAL_MTH)) { 2646 return; 2647 } 2648 2649 if (sym.kind == VAR) { 2650 if ((sym.flags() & PARAMETER) != 0 || 2651 sym.isLocal() || 2652 sym.name == names._this || 2653 sym.name == names._super) { 2654 return; 2655 } 2656 } 2657 2658 if (!types.isSubtype(sym.owner.type, syms.serializableType) && 2659 isEffectivelyNonPublic(sym)) { 2660 if (isLambda) { 2661 if (belongsToRestrictedPackage(sym)) { 2662 log.warning(LintCategory.SERIAL, tree.pos(), 2663 Warnings.AccessToMemberFromSerializableLambda(sym)); 2664 } 2665 } else { 2666 log.warning(tree.pos(), 2667 Warnings.AccessToMemberFromSerializableElement(sym)); 2668 } 2669 } 2670 } 2671 } 2672 isEffectivelyNonPublic(Symbol sym)2673 private boolean isEffectivelyNonPublic(Symbol sym) { 2674 if (sym.packge() == syms.rootPackage) { 2675 return false; 2676 } 2677 2678 while (sym.kind != PCK) { 2679 if ((sym.flags() & PUBLIC) == 0) { 2680 return true; 2681 } 2682 sym = sym.owner; 2683 } 2684 return false; 2685 } 2686 belongsToRestrictedPackage(Symbol sym)2687 private boolean belongsToRestrictedPackage(Symbol sym) { 2688 String fullName = sym.packge().fullname.toString(); 2689 return fullName.startsWith("java.") || 2690 fullName.startsWith("javax.") || 2691 fullName.startsWith("sun.") || 2692 fullName.contains(".internal."); 2693 } 2694 2695 /** Check that class c does not implement directly or indirectly 2696 * the same parameterized interface with two different argument lists. 2697 * @param pos Position to be used for error reporting. 2698 * @param type The type whose interfaces are checked. 2699 */ checkClassBounds(DiagnosticPosition pos, Type type)2700 void checkClassBounds(DiagnosticPosition pos, Type type) { 2701 checkClassBounds(pos, new HashMap<TypeSymbol,Type>(), type); 2702 } 2703 //where 2704 /** Enter all interfaces of type `type' into the hash table `seensofar' 2705 * with their class symbol as key and their type as value. Make 2706 * sure no class is entered with two different types. 2707 */ checkClassBounds(DiagnosticPosition pos, Map<TypeSymbol,Type> seensofar, Type type)2708 void checkClassBounds(DiagnosticPosition pos, 2709 Map<TypeSymbol,Type> seensofar, 2710 Type type) { 2711 if (type.isErroneous()) return; 2712 for (List<Type> l = types.interfaces(type); l.nonEmpty(); l = l.tail) { 2713 Type it = l.head; 2714 Type oldit = seensofar.put(it.tsym, it); 2715 if (oldit != null) { 2716 List<Type> oldparams = oldit.allparams(); 2717 List<Type> newparams = it.allparams(); 2718 if (!types.containsTypeEquivalent(oldparams, newparams)) 2719 log.error(pos, 2720 Errors.CantInheritDiffArg(it.tsym, 2721 Type.toString(oldparams), 2722 Type.toString(newparams))); 2723 } 2724 checkClassBounds(pos, seensofar, it); 2725 } 2726 Type st = types.supertype(type); 2727 if (st != Type.noType) checkClassBounds(pos, seensofar, st); 2728 } 2729 2730 /** Enter interface into into set. 2731 * If it existed already, issue a "repeated interface" error. 2732 */ checkNotRepeated(DiagnosticPosition pos, Type it, Set<Type> its)2733 void checkNotRepeated(DiagnosticPosition pos, Type it, Set<Type> its) { 2734 if (its.contains(it)) 2735 log.error(pos, Errors.RepeatedInterface); 2736 else { 2737 its.add(it); 2738 } 2739 } 2740 2741 /* ************************************************************************* 2742 * Check annotations 2743 **************************************************************************/ 2744 2745 /** 2746 * Recursively validate annotations values 2747 */ validateAnnotationTree(JCTree tree)2748 void validateAnnotationTree(JCTree tree) { 2749 class AnnotationValidator extends TreeScanner { 2750 @Override 2751 public void visitAnnotation(JCAnnotation tree) { 2752 if (!tree.type.isErroneous() && tree.type.tsym.isAnnotationType()) { 2753 super.visitAnnotation(tree); 2754 validateAnnotation(tree); 2755 } 2756 } 2757 } 2758 tree.accept(new AnnotationValidator()); 2759 } 2760 2761 /** 2762 * {@literal 2763 * Annotation types are restricted to primitives, String, an 2764 * enum, an annotation, Class, Class<?>, Class<? extends 2765 * Anything>, arrays of the preceding. 2766 * } 2767 */ validateAnnotationType(JCTree restype)2768 void validateAnnotationType(JCTree restype) { 2769 // restype may be null if an error occurred, so don't bother validating it 2770 if (restype != null) { 2771 validateAnnotationType(restype.pos(), restype.type); 2772 } 2773 } 2774 validateAnnotationType(DiagnosticPosition pos, Type type)2775 void validateAnnotationType(DiagnosticPosition pos, Type type) { 2776 if (type.isPrimitive()) return; 2777 if (types.isSameType(type, syms.stringType)) return; 2778 if ((type.tsym.flags() & Flags.ENUM) != 0) return; 2779 if ((type.tsym.flags() & Flags.ANNOTATION) != 0) return; 2780 if (types.cvarLowerBound(type).tsym == syms.classType.tsym) return; 2781 if (types.isArray(type) && !types.isArray(types.elemtype(type))) { 2782 validateAnnotationType(pos, types.elemtype(type)); 2783 return; 2784 } 2785 log.error(pos, Errors.InvalidAnnotationMemberType); 2786 } 2787 2788 /** 2789 * "It is also a compile-time error if any method declared in an 2790 * annotation type has a signature that is override-equivalent to 2791 * that of any public or protected method declared in class Object 2792 * or in the interface annotation.Annotation." 2793 * 2794 * @jls 9.6 Annotation Types 2795 */ validateAnnotationMethod(DiagnosticPosition pos, MethodSymbol m)2796 void validateAnnotationMethod(DiagnosticPosition pos, MethodSymbol m) { 2797 for (Type sup = syms.annotationType; sup.hasTag(CLASS); sup = types.supertype(sup)) { 2798 Scope s = sup.tsym.members(); 2799 for (Symbol sym : s.getSymbolsByName(m.name)) { 2800 if (sym.kind == MTH && 2801 (sym.flags() & (PUBLIC | PROTECTED)) != 0 && 2802 types.overrideEquivalent(m.type, sym.type)) 2803 log.error(pos, Errors.IntfAnnotationMemberClash(sym, sup)); 2804 } 2805 } 2806 } 2807 2808 /** Check the annotations of a symbol. 2809 */ validateAnnotations(List<JCAnnotation> annotations, Symbol s)2810 public void validateAnnotations(List<JCAnnotation> annotations, Symbol s) { 2811 for (JCAnnotation a : annotations) 2812 validateAnnotation(a, s); 2813 } 2814 2815 /** Check the type annotations. 2816 */ validateTypeAnnotations(List<JCAnnotation> annotations, boolean isTypeParameter)2817 public void validateTypeAnnotations(List<JCAnnotation> annotations, boolean isTypeParameter) { 2818 for (JCAnnotation a : annotations) 2819 validateTypeAnnotation(a, isTypeParameter); 2820 } 2821 2822 /** Check an annotation of a symbol. 2823 */ validateAnnotation(JCAnnotation a, Symbol s)2824 private void validateAnnotation(JCAnnotation a, Symbol s) { 2825 validateAnnotationTree(a); 2826 2827 if (a.type.tsym.isAnnotationType() && !annotationApplicable(a, s)) 2828 log.error(a.pos(), Errors.AnnotationTypeNotApplicable); 2829 2830 if (a.annotationType.type.tsym == syms.functionalInterfaceType.tsym) { 2831 if (s.kind != TYP) { 2832 log.error(a.pos(), Errors.BadFunctionalIntfAnno); 2833 } else if (!s.isInterface() || (s.flags() & ANNOTATION) != 0) { 2834 log.error(a.pos(), Errors.BadFunctionalIntfAnno1(Fragments.NotAFunctionalIntf(s))); 2835 } 2836 } 2837 } 2838 validateTypeAnnotation(JCAnnotation a, boolean isTypeParameter)2839 public void validateTypeAnnotation(JCAnnotation a, boolean isTypeParameter) { 2840 Assert.checkNonNull(a.type); 2841 validateAnnotationTree(a); 2842 2843 if (a.hasTag(TYPE_ANNOTATION) && 2844 !a.annotationType.type.isErroneous() && 2845 !isTypeAnnotation(a, isTypeParameter)) { 2846 log.error(a.pos(), Errors.AnnotationTypeNotApplicableToType(a.type)); 2847 } 2848 } 2849 2850 /** 2851 * Validate the proposed container 'repeatable' on the 2852 * annotation type symbol 's'. Report errors at position 2853 * 'pos'. 2854 * 2855 * @param s The (annotation)type declaration annotated with a @Repeatable 2856 * @param repeatable the @Repeatable on 's' 2857 * @param pos where to report errors 2858 */ validateRepeatable(TypeSymbol s, Attribute.Compound repeatable, DiagnosticPosition pos)2859 public void validateRepeatable(TypeSymbol s, Attribute.Compound repeatable, DiagnosticPosition pos) { 2860 Assert.check(types.isSameType(repeatable.type, syms.repeatableType)); 2861 2862 Type t = null; 2863 List<Pair<MethodSymbol,Attribute>> l = repeatable.values; 2864 if (!l.isEmpty()) { 2865 Assert.check(l.head.fst.name == names.value); 2866 t = ((Attribute.Class)l.head.snd).getValue(); 2867 } 2868 2869 if (t == null) { 2870 // errors should already have been reported during Annotate 2871 return; 2872 } 2873 2874 validateValue(t.tsym, s, pos); 2875 validateRetention(t.tsym, s, pos); 2876 validateDocumented(t.tsym, s, pos); 2877 validateInherited(t.tsym, s, pos); 2878 validateTarget(t.tsym, s, pos); 2879 validateDefault(t.tsym, pos); 2880 } 2881 validateValue(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos)2882 private void validateValue(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) { 2883 Symbol sym = container.members().findFirst(names.value); 2884 if (sym != null && sym.kind == MTH) { 2885 MethodSymbol m = (MethodSymbol) sym; 2886 Type ret = m.getReturnType(); 2887 if (!(ret.hasTag(ARRAY) && types.isSameType(((ArrayType)ret).elemtype, contained.type))) { 2888 log.error(pos, 2889 Errors.InvalidRepeatableAnnotationValueReturn(container, 2890 ret, 2891 types.makeArrayType(contained.type))); 2892 } 2893 } else { 2894 log.error(pos, Errors.InvalidRepeatableAnnotationNoValue(container)); 2895 } 2896 } 2897 validateRetention(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos)2898 private void validateRetention(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) { 2899 Attribute.RetentionPolicy containerRetention = types.getRetention(container); 2900 Attribute.RetentionPolicy containedRetention = types.getRetention(contained); 2901 2902 boolean error = false; 2903 switch (containedRetention) { 2904 case RUNTIME: 2905 if (containerRetention != Attribute.RetentionPolicy.RUNTIME) { 2906 error = true; 2907 } 2908 break; 2909 case CLASS: 2910 if (containerRetention == Attribute.RetentionPolicy.SOURCE) { 2911 error = true; 2912 } 2913 } 2914 if (error ) { 2915 log.error(pos, 2916 Errors.InvalidRepeatableAnnotationRetention(container, 2917 containerRetention.name(), 2918 contained, 2919 containedRetention.name())); 2920 } 2921 } 2922 validateDocumented(Symbol container, Symbol contained, DiagnosticPosition pos)2923 private void validateDocumented(Symbol container, Symbol contained, DiagnosticPosition pos) { 2924 if (contained.attribute(syms.documentedType.tsym) != null) { 2925 if (container.attribute(syms.documentedType.tsym) == null) { 2926 log.error(pos, Errors.InvalidRepeatableAnnotationNotDocumented(container, contained)); 2927 } 2928 } 2929 } 2930 validateInherited(Symbol container, Symbol contained, DiagnosticPosition pos)2931 private void validateInherited(Symbol container, Symbol contained, DiagnosticPosition pos) { 2932 if (contained.attribute(syms.inheritedType.tsym) != null) { 2933 if (container.attribute(syms.inheritedType.tsym) == null) { 2934 log.error(pos, Errors.InvalidRepeatableAnnotationNotInherited(container, contained)); 2935 } 2936 } 2937 } 2938 validateTarget(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos)2939 private void validateTarget(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) { 2940 // The set of targets the container is applicable to must be a subset 2941 // (with respect to annotation target semantics) of the set of targets 2942 // the contained is applicable to. The target sets may be implicit or 2943 // explicit. 2944 2945 Set<Name> containerTargets; 2946 Attribute.Array containerTarget = getAttributeTargetAttribute(container); 2947 if (containerTarget == null) { 2948 containerTargets = getDefaultTargetSet(); 2949 } else { 2950 containerTargets = new HashSet<>(); 2951 for (Attribute app : containerTarget.values) { 2952 if (!(app instanceof Attribute.Enum)) { 2953 continue; // recovery 2954 } 2955 Attribute.Enum e = (Attribute.Enum)app; 2956 containerTargets.add(e.value.name); 2957 } 2958 } 2959 2960 Set<Name> containedTargets; 2961 Attribute.Array containedTarget = getAttributeTargetAttribute(contained); 2962 if (containedTarget == null) { 2963 containedTargets = getDefaultTargetSet(); 2964 } else { 2965 containedTargets = new HashSet<>(); 2966 for (Attribute app : containedTarget.values) { 2967 if (!(app instanceof Attribute.Enum)) { 2968 continue; // recovery 2969 } 2970 Attribute.Enum e = (Attribute.Enum)app; 2971 containedTargets.add(e.value.name); 2972 } 2973 } 2974 2975 if (!isTargetSubsetOf(containerTargets, containedTargets)) { 2976 log.error(pos, Errors.InvalidRepeatableAnnotationIncompatibleTarget(container, contained)); 2977 } 2978 } 2979 2980 /* get a set of names for the default target */ getDefaultTargetSet()2981 private Set<Name> getDefaultTargetSet() { 2982 if (defaultTargets == null) { 2983 Set<Name> targets = new HashSet<>(); 2984 targets.add(names.ANNOTATION_TYPE); 2985 targets.add(names.CONSTRUCTOR); 2986 targets.add(names.FIELD); 2987 targets.add(names.LOCAL_VARIABLE); 2988 targets.add(names.METHOD); 2989 targets.add(names.PACKAGE); 2990 targets.add(names.PARAMETER); 2991 targets.add(names.TYPE); 2992 2993 defaultTargets = java.util.Collections.unmodifiableSet(targets); 2994 } 2995 2996 return defaultTargets; 2997 } 2998 private Set<Name> defaultTargets; 2999 3000 3001 /** Checks that s is a subset of t, with respect to ElementType 3002 * semantics, specifically {ANNOTATION_TYPE} is a subset of {TYPE}, 3003 * and {TYPE_USE} covers the set {ANNOTATION_TYPE, TYPE, TYPE_USE, 3004 * TYPE_PARAMETER}. 3005 */ isTargetSubsetOf(Set<Name> s, Set<Name> t)3006 private boolean isTargetSubsetOf(Set<Name> s, Set<Name> t) { 3007 // Check that all elements in s are present in t 3008 for (Name n2 : s) { 3009 boolean currentElementOk = false; 3010 for (Name n1 : t) { 3011 if (n1 == n2) { 3012 currentElementOk = true; 3013 break; 3014 } else if (n1 == names.TYPE && n2 == names.ANNOTATION_TYPE) { 3015 currentElementOk = true; 3016 break; 3017 } else if (n1 == names.TYPE_USE && 3018 (n2 == names.TYPE || 3019 n2 == names.ANNOTATION_TYPE || 3020 n2 == names.TYPE_PARAMETER)) { 3021 currentElementOk = true; 3022 break; 3023 } 3024 } 3025 if (!currentElementOk) 3026 return false; 3027 } 3028 return true; 3029 } 3030 validateDefault(Symbol container, DiagnosticPosition pos)3031 private void validateDefault(Symbol container, DiagnosticPosition pos) { 3032 // validate that all other elements of containing type has defaults 3033 Scope scope = container.members(); 3034 for(Symbol elm : scope.getSymbols()) { 3035 if (elm.name != names.value && 3036 elm.kind == MTH && 3037 ((MethodSymbol)elm).defaultValue == null) { 3038 log.error(pos, 3039 Errors.InvalidRepeatableAnnotationElemNondefault(container, elm)); 3040 } 3041 } 3042 } 3043 3044 /** Is s a method symbol that overrides a method in a superclass? */ isOverrider(Symbol s)3045 boolean isOverrider(Symbol s) { 3046 if (s.kind != MTH || s.isStatic()) 3047 return false; 3048 MethodSymbol m = (MethodSymbol)s; 3049 TypeSymbol owner = (TypeSymbol)m.owner; 3050 for (Type sup : types.closure(owner.type)) { 3051 if (sup == owner.type) 3052 continue; // skip "this" 3053 Scope scope = sup.tsym.members(); 3054 for (Symbol sym : scope.getSymbolsByName(m.name)) { 3055 if (!sym.isStatic() && m.overrides(sym, owner, types, true)) 3056 return true; 3057 } 3058 } 3059 return false; 3060 } 3061 3062 /** Is the annotation applicable to types? */ isTypeAnnotation(JCAnnotation a, boolean isTypeParameter)3063 protected boolean isTypeAnnotation(JCAnnotation a, boolean isTypeParameter) { 3064 List<Attribute> targets = typeAnnotations.annotationTargets(a.annotationType.type.tsym); 3065 return (targets == null) ? 3066 false : 3067 targets.stream() 3068 .anyMatch(attr -> isTypeAnnotation(attr, isTypeParameter)); 3069 } 3070 //where isTypeAnnotation(Attribute a, boolean isTypeParameter)3071 boolean isTypeAnnotation(Attribute a, boolean isTypeParameter) { 3072 Attribute.Enum e = (Attribute.Enum)a; 3073 return (e.value.name == names.TYPE_USE || 3074 (isTypeParameter && e.value.name == names.TYPE_PARAMETER)); 3075 } 3076 3077 /** Is the annotation applicable to the symbol? */ annotationApplicable(JCAnnotation a, Symbol s)3078 boolean annotationApplicable(JCAnnotation a, Symbol s) { 3079 Attribute.Array arr = getAttributeTargetAttribute(a.annotationType.type.tsym); 3080 Name[] targets; 3081 3082 if (arr == null) { 3083 targets = defaultTargetMetaInfo(a, s); 3084 } else { 3085 // TODO: can we optimize this? 3086 targets = new Name[arr.values.length]; 3087 for (int i=0; i<arr.values.length; ++i) { 3088 Attribute app = arr.values[i]; 3089 if (!(app instanceof Attribute.Enum)) { 3090 return true; // recovery 3091 } 3092 Attribute.Enum e = (Attribute.Enum) app; 3093 targets[i] = e.value.name; 3094 } 3095 } 3096 for (Name target : targets) { 3097 if (target == names.TYPE) { 3098 if (s.kind == TYP) 3099 return true; 3100 } else if (target == names.FIELD) { 3101 if (s.kind == VAR && s.owner.kind != MTH) 3102 return true; 3103 } else if (target == names.METHOD) { 3104 if (s.kind == MTH && !s.isConstructor()) 3105 return true; 3106 } else if (target == names.PARAMETER) { 3107 if (s.kind == VAR && s.owner.kind == MTH && 3108 (s.flags() & PARAMETER) != 0) { 3109 return true; 3110 } 3111 } else if (target == names.CONSTRUCTOR) { 3112 if (s.kind == MTH && s.isConstructor()) 3113 return true; 3114 } else if (target == names.LOCAL_VARIABLE) { 3115 if (s.kind == VAR && s.owner.kind == MTH && 3116 (s.flags() & PARAMETER) == 0) { 3117 return true; 3118 } 3119 } else if (target == names.ANNOTATION_TYPE) { 3120 if (s.kind == TYP && (s.flags() & ANNOTATION) != 0) { 3121 return true; 3122 } 3123 } else if (target == names.PACKAGE) { 3124 if (s.kind == PCK) 3125 return true; 3126 } else if (target == names.TYPE_USE) { 3127 if (s.kind == VAR && s.owner.kind == MTH && s.type.hasTag(NONE)) { 3128 //cannot type annotate implictly typed locals 3129 return false; 3130 } else if (s.kind == TYP || s.kind == VAR || 3131 (s.kind == MTH && !s.isConstructor() && 3132 !s.type.getReturnType().hasTag(VOID)) || 3133 (s.kind == MTH && s.isConstructor())) { 3134 return true; 3135 } 3136 } else if (target == names.TYPE_PARAMETER) { 3137 if (s.kind == TYP && s.type.hasTag(TYPEVAR)) 3138 return true; 3139 } else 3140 return true; // Unknown ElementType. This should be an error at declaration site, 3141 // assume applicable. 3142 } 3143 return false; 3144 } 3145 3146 getAttributeTargetAttribute(TypeSymbol s)3147 Attribute.Array getAttributeTargetAttribute(TypeSymbol s) { 3148 Attribute.Compound atTarget = s.getAnnotationTypeMetadata().getTarget(); 3149 if (atTarget == null) return null; // ok, is applicable 3150 Attribute atValue = atTarget.member(names.value); 3151 if (!(atValue instanceof Attribute.Array)) return null; // error recovery 3152 return (Attribute.Array) atValue; 3153 } 3154 3155 private final Name[] dfltTargetMeta; defaultTargetMetaInfo(JCAnnotation a, Symbol s)3156 private Name[] defaultTargetMetaInfo(JCAnnotation a, Symbol s) { 3157 return dfltTargetMeta; 3158 } 3159 3160 /** Check an annotation value. 3161 * 3162 * @param a The annotation tree to check 3163 * @return true if this annotation tree is valid, otherwise false 3164 */ validateAnnotationDeferErrors(JCAnnotation a)3165 public boolean validateAnnotationDeferErrors(JCAnnotation a) { 3166 boolean res = false; 3167 final Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log); 3168 try { 3169 res = validateAnnotation(a); 3170 } finally { 3171 log.popDiagnosticHandler(diagHandler); 3172 } 3173 return res; 3174 } 3175 validateAnnotation(JCAnnotation a)3176 private boolean validateAnnotation(JCAnnotation a) { 3177 boolean isValid = true; 3178 AnnotationTypeMetadata metadata = a.annotationType.type.tsym.getAnnotationTypeMetadata(); 3179 3180 // collect an inventory of the annotation elements 3181 Set<MethodSymbol> elements = metadata.getAnnotationElements(); 3182 3183 // remove the ones that are assigned values 3184 for (JCTree arg : a.args) { 3185 if (!arg.hasTag(ASSIGN)) continue; // recovery 3186 JCAssign assign = (JCAssign)arg; 3187 Symbol m = TreeInfo.symbol(assign.lhs); 3188 if (m == null || m.type.isErroneous()) continue; 3189 if (!elements.remove(m)) { 3190 isValid = false; 3191 log.error(assign.lhs.pos(), 3192 Errors.DuplicateAnnotationMemberValue(m.name, a.type)); 3193 } 3194 } 3195 3196 // all the remaining ones better have default values 3197 List<Name> missingDefaults = List.nil(); 3198 Set<MethodSymbol> membersWithDefault = metadata.getAnnotationElementsWithDefault(); 3199 for (MethodSymbol m : elements) { 3200 if (m.type.isErroneous()) 3201 continue; 3202 3203 if (!membersWithDefault.contains(m)) 3204 missingDefaults = missingDefaults.append(m.name); 3205 } 3206 missingDefaults = missingDefaults.reverse(); 3207 if (missingDefaults.nonEmpty()) { 3208 isValid = false; 3209 Error errorKey = (missingDefaults.size() > 1) 3210 ? Errors.AnnotationMissingDefaultValue1(a.type, missingDefaults) 3211 : Errors.AnnotationMissingDefaultValue(a.type, missingDefaults); 3212 log.error(a.pos(), errorKey); 3213 } 3214 3215 return isValid && validateTargetAnnotationValue(a); 3216 } 3217 3218 /* Validate the special java.lang.annotation.Target annotation */ validateTargetAnnotationValue(JCAnnotation a)3219 boolean validateTargetAnnotationValue(JCAnnotation a) { 3220 // special case: java.lang.annotation.Target must not have 3221 // repeated values in its value member 3222 if (a.annotationType.type.tsym != syms.annotationTargetType.tsym || 3223 a.args.tail == null) 3224 return true; 3225 3226 boolean isValid = true; 3227 if (!a.args.head.hasTag(ASSIGN)) return false; // error recovery 3228 JCAssign assign = (JCAssign) a.args.head; 3229 Symbol m = TreeInfo.symbol(assign.lhs); 3230 if (m.name != names.value) return false; 3231 JCTree rhs = assign.rhs; 3232 if (!rhs.hasTag(NEWARRAY)) return false; 3233 JCNewArray na = (JCNewArray) rhs; 3234 Set<Symbol> targets = new HashSet<>(); 3235 for (JCTree elem : na.elems) { 3236 if (!targets.add(TreeInfo.symbol(elem))) { 3237 isValid = false; 3238 log.error(elem.pos(), Errors.RepeatedAnnotationTarget); 3239 } 3240 } 3241 return isValid; 3242 } 3243 checkDeprecatedAnnotation(DiagnosticPosition pos, Symbol s)3244 void checkDeprecatedAnnotation(DiagnosticPosition pos, Symbol s) { 3245 if (lint.isEnabled(LintCategory.DEP_ANN) && s.isDeprecatableViaAnnotation() && 3246 (s.flags() & DEPRECATED) != 0 && 3247 !syms.deprecatedType.isErroneous() && 3248 s.attribute(syms.deprecatedType.tsym) == null) { 3249 log.warning(LintCategory.DEP_ANN, 3250 pos, Warnings.MissingDeprecatedAnnotation); 3251 } 3252 // Note: @Deprecated has no effect on local variables, parameters and package decls. 3253 if (lint.isEnabled(LintCategory.DEPRECATION) && !s.isDeprecatableViaAnnotation()) { 3254 if (!syms.deprecatedType.isErroneous() && s.attribute(syms.deprecatedType.tsym) != null) { 3255 log.warning(LintCategory.DEPRECATION, pos, 3256 Warnings.DeprecatedAnnotationHasNoEffect(Kinds.kindName(s))); 3257 } 3258 } 3259 } 3260 checkDeprecated(final DiagnosticPosition pos, final Symbol other, final Symbol s)3261 void checkDeprecated(final DiagnosticPosition pos, final Symbol other, final Symbol s) { 3262 if ( (s.isDeprecatedForRemoval() 3263 || s.isDeprecated() && !other.isDeprecated()) 3264 && (s.outermostClass() != other.outermostClass() || s.outermostClass() == null)) { 3265 deferredLintHandler.report(() -> warnDeprecated(pos, s)); 3266 } 3267 } 3268 checkSunAPI(final DiagnosticPosition pos, final Symbol s)3269 void checkSunAPI(final DiagnosticPosition pos, final Symbol s) { 3270 if ((s.flags() & PROPRIETARY) != 0) { 3271 deferredLintHandler.report(() -> { 3272 log.mandatoryWarning(pos, Warnings.SunProprietary(s)); 3273 }); 3274 } 3275 } 3276 checkProfile(final DiagnosticPosition pos, final Symbol s)3277 void checkProfile(final DiagnosticPosition pos, final Symbol s) { 3278 if (profile != Profile.DEFAULT && (s.flags() & NOT_IN_PROFILE) != 0) { 3279 log.error(pos, Errors.NotInProfile(s, profile)); 3280 } 3281 } 3282 3283 /* ************************************************************************* 3284 * Check for recursive annotation elements. 3285 **************************************************************************/ 3286 3287 /** Check for cycles in the graph of annotation elements. 3288 */ checkNonCyclicElements(JCClassDecl tree)3289 void checkNonCyclicElements(JCClassDecl tree) { 3290 if ((tree.sym.flags_field & ANNOTATION) == 0) return; 3291 Assert.check((tree.sym.flags_field & LOCKED) == 0); 3292 try { 3293 tree.sym.flags_field |= LOCKED; 3294 for (JCTree def : tree.defs) { 3295 if (!def.hasTag(METHODDEF)) continue; 3296 JCMethodDecl meth = (JCMethodDecl)def; 3297 checkAnnotationResType(meth.pos(), meth.restype.type); 3298 } 3299 } finally { 3300 tree.sym.flags_field &= ~LOCKED; 3301 tree.sym.flags_field |= ACYCLIC_ANN; 3302 } 3303 } 3304 checkNonCyclicElementsInternal(DiagnosticPosition pos, TypeSymbol tsym)3305 void checkNonCyclicElementsInternal(DiagnosticPosition pos, TypeSymbol tsym) { 3306 if ((tsym.flags_field & ACYCLIC_ANN) != 0) 3307 return; 3308 if ((tsym.flags_field & LOCKED) != 0) { 3309 log.error(pos, Errors.CyclicAnnotationElement(tsym)); 3310 return; 3311 } 3312 try { 3313 tsym.flags_field |= LOCKED; 3314 for (Symbol s : tsym.members().getSymbols(NON_RECURSIVE)) { 3315 if (s.kind != MTH) 3316 continue; 3317 checkAnnotationResType(pos, ((MethodSymbol)s).type.getReturnType()); 3318 } 3319 } finally { 3320 tsym.flags_field &= ~LOCKED; 3321 tsym.flags_field |= ACYCLIC_ANN; 3322 } 3323 } 3324 checkAnnotationResType(DiagnosticPosition pos, Type type)3325 void checkAnnotationResType(DiagnosticPosition pos, Type type) { 3326 switch (type.getTag()) { 3327 case CLASS: 3328 if ((type.tsym.flags() & ANNOTATION) != 0) 3329 checkNonCyclicElementsInternal(pos, type.tsym); 3330 break; 3331 case ARRAY: 3332 checkAnnotationResType(pos, types.elemtype(type)); 3333 break; 3334 default: 3335 break; // int etc 3336 } 3337 } 3338 3339 /* ************************************************************************* 3340 * Check for cycles in the constructor call graph. 3341 **************************************************************************/ 3342 3343 /** Check for cycles in the graph of constructors calling other 3344 * constructors. 3345 */ checkCyclicConstructors(JCClassDecl tree)3346 void checkCyclicConstructors(JCClassDecl tree) { 3347 Map<Symbol,Symbol> callMap = new HashMap<>(); 3348 3349 // enter each constructor this-call into the map 3350 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { 3351 JCMethodInvocation app = TreeInfo.firstConstructorCall(l.head); 3352 if (app == null) continue; 3353 JCMethodDecl meth = (JCMethodDecl) l.head; 3354 if (TreeInfo.name(app.meth) == names._this) { 3355 callMap.put(meth.sym, TreeInfo.symbol(app.meth)); 3356 } else { 3357 meth.sym.flags_field |= ACYCLIC; 3358 } 3359 } 3360 3361 // Check for cycles in the map 3362 Symbol[] ctors = new Symbol[0]; 3363 ctors = callMap.keySet().toArray(ctors); 3364 for (Symbol caller : ctors) { 3365 checkCyclicConstructor(tree, caller, callMap); 3366 } 3367 } 3368 3369 /** Look in the map to see if the given constructor is part of a 3370 * call cycle. 3371 */ checkCyclicConstructor(JCClassDecl tree, Symbol ctor, Map<Symbol,Symbol> callMap)3372 private void checkCyclicConstructor(JCClassDecl tree, Symbol ctor, 3373 Map<Symbol,Symbol> callMap) { 3374 if (ctor != null && (ctor.flags_field & ACYCLIC) == 0) { 3375 if ((ctor.flags_field & LOCKED) != 0) { 3376 log.error(TreeInfo.diagnosticPositionFor(ctor, tree), 3377 Errors.RecursiveCtorInvocation); 3378 } else { 3379 ctor.flags_field |= LOCKED; 3380 checkCyclicConstructor(tree, callMap.remove(ctor), callMap); 3381 ctor.flags_field &= ~LOCKED; 3382 } 3383 ctor.flags_field |= ACYCLIC; 3384 } 3385 } 3386 3387 /* ************************************************************************* 3388 * Miscellaneous 3389 **************************************************************************/ 3390 3391 /** 3392 * Check for division by integer constant zero 3393 * @param pos Position for error reporting. 3394 * @param operator The operator for the expression 3395 * @param operand The right hand operand for the expression 3396 */ checkDivZero(final DiagnosticPosition pos, Symbol operator, Type operand)3397 void checkDivZero(final DiagnosticPosition pos, Symbol operator, Type operand) { 3398 if (operand.constValue() != null 3399 && operand.getTag().isSubRangeOf(LONG) 3400 && ((Number) (operand.constValue())).longValue() == 0) { 3401 int opc = ((OperatorSymbol)operator).opcode; 3402 if (opc == ByteCodes.idiv || opc == ByteCodes.imod 3403 || opc == ByteCodes.ldiv || opc == ByteCodes.lmod) { 3404 deferredLintHandler.report(() -> warnDivZero(pos)); 3405 } 3406 } 3407 } 3408 3409 /** 3410 * Check for empty statements after if 3411 */ checkEmptyIf(JCIf tree)3412 void checkEmptyIf(JCIf tree) { 3413 if (tree.thenpart.hasTag(SKIP) && tree.elsepart == null && 3414 lint.isEnabled(LintCategory.EMPTY)) 3415 log.warning(LintCategory.EMPTY, tree.thenpart.pos(), Warnings.EmptyIf); 3416 } 3417 3418 /** Check that symbol is unique in given scope. 3419 * @param pos Position for error reporting. 3420 * @param sym The symbol. 3421 * @param s The scope. 3422 */ checkUnique(DiagnosticPosition pos, Symbol sym, Scope s)3423 boolean checkUnique(DiagnosticPosition pos, Symbol sym, Scope s) { 3424 if (sym.type.isErroneous()) 3425 return true; 3426 if (sym.owner.name == names.any) return false; 3427 for (Symbol byName : s.getSymbolsByName(sym.name, NON_RECURSIVE)) { 3428 if (sym != byName && 3429 (byName.flags() & CLASH) == 0 && 3430 sym.kind == byName.kind && 3431 sym.name != names.error && 3432 (sym.kind != MTH || 3433 types.hasSameArgs(sym.type, byName.type) || 3434 types.hasSameArgs(types.erasure(sym.type), types.erasure(byName.type)))) { 3435 if ((sym.flags() & VARARGS) != (byName.flags() & VARARGS)) { 3436 sym.flags_field |= CLASH; 3437 varargsDuplicateError(pos, sym, byName); 3438 return true; 3439 } else if (sym.kind == MTH && !types.hasSameArgs(sym.type, byName.type, false)) { 3440 duplicateErasureError(pos, sym, byName); 3441 sym.flags_field |= CLASH; 3442 return true; 3443 } else { 3444 duplicateError(pos, byName); 3445 return false; 3446 } 3447 } 3448 } 3449 return true; 3450 } 3451 3452 /** Report duplicate declaration error. 3453 */ duplicateErasureError(DiagnosticPosition pos, Symbol sym1, Symbol sym2)3454 void duplicateErasureError(DiagnosticPosition pos, Symbol sym1, Symbol sym2) { 3455 if (!sym1.type.isErroneous() && !sym2.type.isErroneous()) { 3456 log.error(pos, Errors.NameClashSameErasure(sym1, sym2)); 3457 } 3458 } 3459 3460 /**Check that types imported through the ordinary imports don't clash with types imported 3461 * by other (static or ordinary) imports. Note that two static imports may import two clashing 3462 * types without an error on the imports. 3463 * @param toplevel The toplevel tree for which the test should be performed. 3464 */ checkImportsUnique(JCCompilationUnit toplevel)3465 void checkImportsUnique(JCCompilationUnit toplevel) { 3466 WriteableScope ordinallyImportedSoFar = WriteableScope.create(toplevel.packge); 3467 WriteableScope staticallyImportedSoFar = WriteableScope.create(toplevel.packge); 3468 WriteableScope topLevelScope = toplevel.toplevelScope; 3469 3470 for (JCTree def : toplevel.defs) { 3471 if (!def.hasTag(IMPORT)) 3472 continue; 3473 3474 JCImport imp = (JCImport) def; 3475 3476 if (imp.importScope == null) 3477 continue; 3478 3479 for (Symbol sym : imp.importScope.getSymbols(sym -> sym.kind == TYP)) { 3480 if (imp.isStatic()) { 3481 checkUniqueImport(imp.pos(), ordinallyImportedSoFar, staticallyImportedSoFar, topLevelScope, sym, true); 3482 staticallyImportedSoFar.enter(sym); 3483 } else { 3484 checkUniqueImport(imp.pos(), ordinallyImportedSoFar, staticallyImportedSoFar, topLevelScope, sym, false); 3485 ordinallyImportedSoFar.enter(sym); 3486 } 3487 } 3488 3489 imp.importScope = null; 3490 } 3491 } 3492 3493 /** Check that single-type import is not already imported or top-level defined, 3494 * but make an exception for two single-type imports which denote the same type. 3495 * @param pos Position for error reporting. 3496 * @param ordinallyImportedSoFar A Scope containing types imported so far through 3497 * ordinary imports. 3498 * @param staticallyImportedSoFar A Scope containing types imported so far through 3499 * static imports. 3500 * @param topLevelScope The current file's top-level Scope 3501 * @param sym The symbol. 3502 * @param staticImport Whether or not this was a static import 3503 */ checkUniqueImport(DiagnosticPosition pos, Scope ordinallyImportedSoFar, Scope staticallyImportedSoFar, Scope topLevelScope, Symbol sym, boolean staticImport)3504 private boolean checkUniqueImport(DiagnosticPosition pos, Scope ordinallyImportedSoFar, 3505 Scope staticallyImportedSoFar, Scope topLevelScope, 3506 Symbol sym, boolean staticImport) { 3507 Filter<Symbol> duplicates = candidate -> candidate != sym && !candidate.type.isErroneous(); 3508 Symbol ordinaryClashing = ordinallyImportedSoFar.findFirst(sym.name, duplicates); 3509 Symbol staticClashing = null; 3510 if (ordinaryClashing == null && !staticImport) { 3511 staticClashing = staticallyImportedSoFar.findFirst(sym.name, duplicates); 3512 } 3513 if (ordinaryClashing != null || staticClashing != null) { 3514 if (ordinaryClashing != null) 3515 log.error(pos, Errors.AlreadyDefinedSingleImport(ordinaryClashing)); 3516 else 3517 log.error(pos, Errors.AlreadyDefinedStaticSingleImport(staticClashing)); 3518 return false; 3519 } 3520 Symbol clashing = topLevelScope.findFirst(sym.name, duplicates); 3521 if (clashing != null) { 3522 log.error(pos, Errors.AlreadyDefinedThisUnit(clashing)); 3523 return false; 3524 } 3525 return true; 3526 } 3527 3528 /** Check that a qualified name is in canonical form (for import decls). 3529 */ checkCanonical(JCTree tree)3530 public void checkCanonical(JCTree tree) { 3531 if (!isCanonical(tree)) 3532 log.error(tree.pos(), 3533 Errors.ImportRequiresCanonical(TreeInfo.symbol(tree))); 3534 } 3535 // where isCanonical(JCTree tree)3536 private boolean isCanonical(JCTree tree) { 3537 while (tree.hasTag(SELECT)) { 3538 JCFieldAccess s = (JCFieldAccess) tree; 3539 if (s.sym.owner.getQualifiedName() != TreeInfo.symbol(s.selected).getQualifiedName()) 3540 return false; 3541 tree = s.selected; 3542 } 3543 return true; 3544 } 3545 3546 /** Check that an auxiliary class is not accessed from any other file than its own. 3547 */ checkForBadAuxiliaryClassAccess(DiagnosticPosition pos, Env<AttrContext> env, ClassSymbol c)3548 void checkForBadAuxiliaryClassAccess(DiagnosticPosition pos, Env<AttrContext> env, ClassSymbol c) { 3549 if (lint.isEnabled(Lint.LintCategory.AUXILIARYCLASS) && 3550 (c.flags() & AUXILIARY) != 0 && 3551 rs.isAccessible(env, c) && 3552 !fileManager.isSameFile(c.sourcefile, env.toplevel.sourcefile)) 3553 { 3554 log.warning(pos, 3555 Warnings.AuxiliaryClassAccessedFromOutsideOfItsSourceFile(c, c.sourcefile)); 3556 } 3557 } 3558 3559 private class ConversionWarner extends Warner { 3560 final String uncheckedKey; 3561 final Type found; 3562 final Type expected; ConversionWarner(DiagnosticPosition pos, String uncheckedKey, Type found, Type expected)3563 public ConversionWarner(DiagnosticPosition pos, String uncheckedKey, Type found, Type expected) { 3564 super(pos); 3565 this.uncheckedKey = uncheckedKey; 3566 this.found = found; 3567 this.expected = expected; 3568 } 3569 3570 @Override warn(LintCategory lint)3571 public void warn(LintCategory lint) { 3572 boolean warned = this.warned; 3573 super.warn(lint); 3574 if (warned) return; // suppress redundant diagnostics 3575 switch (lint) { 3576 case UNCHECKED: 3577 Check.this.warnUnchecked(pos(), Warnings.ProbFoundReq(diags.fragment(uncheckedKey), found, expected)); 3578 break; 3579 case VARARGS: 3580 if (method != null && 3581 method.attribute(syms.trustMeType.tsym) != null && 3582 isTrustMeAllowedOnMethod(method) && 3583 !types.isReifiable(method.type.getParameterTypes().last())) { 3584 Check.this.warnUnsafeVararg(pos(), Warnings.VarargsUnsafeUseVarargsParam(method.params.last())); 3585 } 3586 break; 3587 default: 3588 throw new AssertionError("Unexpected lint: " + lint); 3589 } 3590 } 3591 } 3592 castWarner(DiagnosticPosition pos, Type found, Type expected)3593 public Warner castWarner(DiagnosticPosition pos, Type found, Type expected) { 3594 return new ConversionWarner(pos, "unchecked.cast.to.type", found, expected); 3595 } 3596 convertWarner(DiagnosticPosition pos, Type found, Type expected)3597 public Warner convertWarner(DiagnosticPosition pos, Type found, Type expected) { 3598 return new ConversionWarner(pos, "unchecked.assign", found, expected); 3599 } 3600 checkFunctionalInterface(JCClassDecl tree, ClassSymbol cs)3601 public void checkFunctionalInterface(JCClassDecl tree, ClassSymbol cs) { 3602 Compound functionalType = cs.attribute(syms.functionalInterfaceType.tsym); 3603 3604 if (functionalType != null) { 3605 try { 3606 types.findDescriptorSymbol((TypeSymbol)cs); 3607 } catch (Types.FunctionDescriptorLookupError ex) { 3608 DiagnosticPosition pos = tree.pos(); 3609 for (JCAnnotation a : tree.getModifiers().annotations) { 3610 if (a.annotationType.type.tsym == syms.functionalInterfaceType.tsym) { 3611 pos = a.pos(); 3612 break; 3613 } 3614 } 3615 log.error(pos, Errors.BadFunctionalIntfAnno1(ex.getDiagnostic())); 3616 } 3617 } 3618 } 3619 checkImportsResolvable(final JCCompilationUnit toplevel)3620 public void checkImportsResolvable(final JCCompilationUnit toplevel) { 3621 for (final JCImport imp : toplevel.getImports()) { 3622 if (!imp.staticImport || !imp.qualid.hasTag(SELECT)) 3623 continue; 3624 final JCFieldAccess select = (JCFieldAccess) imp.qualid; 3625 final Symbol origin; 3626 if (select.name == names.asterisk || (origin = TreeInfo.symbol(select.selected)) == null || origin.kind != TYP) 3627 continue; 3628 3629 TypeSymbol site = (TypeSymbol) TreeInfo.symbol(select.selected); 3630 if (!checkTypeContainsImportableElement(site, site, toplevel.packge, select.name, new HashSet<Symbol>())) { 3631 log.error(imp.pos(), 3632 Errors.CantResolveLocation(KindName.STATIC, 3633 select.name, 3634 null, 3635 null, 3636 Fragments.Location(kindName(site), 3637 site, 3638 null))); 3639 } 3640 } 3641 } 3642 3643 // Check that packages imported are in scope (JLS 7.4.3, 6.3, 6.5.3.1, 6.5.3.2) checkImportedPackagesObservable(final JCCompilationUnit toplevel)3644 public void checkImportedPackagesObservable(final JCCompilationUnit toplevel) { 3645 OUTER: for (JCImport imp : toplevel.getImports()) { 3646 if (!imp.staticImport && TreeInfo.name(imp.qualid) == names.asterisk) { 3647 TypeSymbol tsym = ((JCFieldAccess)imp.qualid).selected.type.tsym; 3648 if (tsym.kind == PCK && tsym.members().isEmpty() && 3649 !(Feature.IMPORT_ON_DEMAND_OBSERVABLE_PACKAGES.allowedInSource(source) && tsym.exists())) { 3650 log.error(DiagnosticFlag.RESOLVE_ERROR, imp.pos, Errors.DoesntExist(tsym)); 3651 } 3652 } 3653 } 3654 } 3655 checkTypeContainsImportableElement(TypeSymbol tsym, TypeSymbol origin, PackageSymbol packge, Name name, Set<Symbol> processed)3656 private boolean checkTypeContainsImportableElement(TypeSymbol tsym, TypeSymbol origin, PackageSymbol packge, Name name, Set<Symbol> processed) { 3657 if (tsym == null || !processed.add(tsym)) 3658 return false; 3659 3660 // also search through inherited names 3661 if (checkTypeContainsImportableElement(types.supertype(tsym.type).tsym, origin, packge, name, processed)) 3662 return true; 3663 3664 for (Type t : types.interfaces(tsym.type)) 3665 if (checkTypeContainsImportableElement(t.tsym, origin, packge, name, processed)) 3666 return true; 3667 3668 for (Symbol sym : tsym.members().getSymbolsByName(name)) { 3669 if (sym.isStatic() && 3670 importAccessible(sym, packge) && 3671 sym.isMemberOf(origin, types)) { 3672 return true; 3673 } 3674 } 3675 3676 return false; 3677 } 3678 3679 // is the sym accessible everywhere in packge? importAccessible(Symbol sym, PackageSymbol packge)3680 public boolean importAccessible(Symbol sym, PackageSymbol packge) { 3681 try { 3682 int flags = (int)(sym.flags() & AccessFlags); 3683 switch (flags) { 3684 default: 3685 case PUBLIC: 3686 return true; 3687 case PRIVATE: 3688 return false; 3689 case 0: 3690 case PROTECTED: 3691 return sym.packge() == packge; 3692 } 3693 } catch (ClassFinder.BadClassFile err) { 3694 throw err; 3695 } catch (CompletionFailure ex) { 3696 return false; 3697 } 3698 } 3699 checkLeaksNotAccessible(Env<AttrContext> env, JCClassDecl check)3700 public void checkLeaksNotAccessible(Env<AttrContext> env, JCClassDecl check) { 3701 JCCompilationUnit toplevel = env.toplevel; 3702 3703 if ( toplevel.modle == syms.unnamedModule 3704 || toplevel.modle == syms.noModule 3705 || (check.sym.flags() & COMPOUND) != 0) { 3706 return ; 3707 } 3708 3709 ExportsDirective currentExport = findExport(toplevel.packge); 3710 3711 if ( currentExport == null //not exported 3712 || currentExport.modules != null) //don't check classes in qualified export 3713 return ; 3714 3715 new TreeScanner() { 3716 Lint lint = env.info.lint; 3717 boolean inSuperType; 3718 3719 @Override 3720 public void visitBlock(JCBlock tree) { 3721 } 3722 @Override 3723 public void visitMethodDef(JCMethodDecl tree) { 3724 if (!isAPISymbol(tree.sym)) 3725 return; 3726 Lint prevLint = lint; 3727 try { 3728 lint = lint.augment(tree.sym); 3729 if (lint.isEnabled(LintCategory.EXPORTS)) { 3730 super.visitMethodDef(tree); 3731 } 3732 } finally { 3733 lint = prevLint; 3734 } 3735 } 3736 @Override 3737 public void visitVarDef(JCVariableDecl tree) { 3738 if (!isAPISymbol(tree.sym) && tree.sym.owner.kind != MTH) 3739 return; 3740 Lint prevLint = lint; 3741 try { 3742 lint = lint.augment(tree.sym); 3743 if (lint.isEnabled(LintCategory.EXPORTS)) { 3744 scan(tree.mods); 3745 scan(tree.vartype); 3746 } 3747 } finally { 3748 lint = prevLint; 3749 } 3750 } 3751 @Override 3752 public void visitClassDef(JCClassDecl tree) { 3753 if (tree != check) 3754 return ; 3755 3756 if (!isAPISymbol(tree.sym)) 3757 return ; 3758 3759 Lint prevLint = lint; 3760 try { 3761 lint = lint.augment(tree.sym); 3762 if (lint.isEnabled(LintCategory.EXPORTS)) { 3763 scan(tree.mods); 3764 scan(tree.typarams); 3765 try { 3766 inSuperType = true; 3767 scan(tree.extending); 3768 scan(tree.implementing); 3769 } finally { 3770 inSuperType = false; 3771 } 3772 scan(tree.defs); 3773 } 3774 } finally { 3775 lint = prevLint; 3776 } 3777 } 3778 @Override 3779 public void visitTypeApply(JCTypeApply tree) { 3780 scan(tree.clazz); 3781 boolean oldInSuperType = inSuperType; 3782 try { 3783 inSuperType = false; 3784 scan(tree.arguments); 3785 } finally { 3786 inSuperType = oldInSuperType; 3787 } 3788 } 3789 @Override 3790 public void visitIdent(JCIdent tree) { 3791 Symbol sym = TreeInfo.symbol(tree); 3792 if (sym.kind == TYP && !sym.type.hasTag(TYPEVAR)) { 3793 checkVisible(tree.pos(), sym, toplevel.packge, inSuperType); 3794 } 3795 } 3796 3797 @Override 3798 public void visitSelect(JCFieldAccess tree) { 3799 Symbol sym = TreeInfo.symbol(tree); 3800 Symbol sitesym = TreeInfo.symbol(tree.selected); 3801 if (sym.kind == TYP && sitesym.kind == PCK) { 3802 checkVisible(tree.pos(), sym, toplevel.packge, inSuperType); 3803 } else { 3804 super.visitSelect(tree); 3805 } 3806 } 3807 3808 @Override 3809 public void visitAnnotation(JCAnnotation tree) { 3810 if (tree.attribute.type.tsym.getAnnotation(java.lang.annotation.Documented.class) != null) 3811 super.visitAnnotation(tree); 3812 } 3813 3814 }.scan(check); 3815 } 3816 //where: findExport(PackageSymbol pack)3817 private ExportsDirective findExport(PackageSymbol pack) { 3818 for (ExportsDirective d : pack.modle.exports) { 3819 if (d.packge == pack) 3820 return d; 3821 } 3822 3823 return null; 3824 } isAPISymbol(Symbol sym)3825 private boolean isAPISymbol(Symbol sym) { 3826 while (sym.kind != PCK) { 3827 if ((sym.flags() & Flags.PUBLIC) == 0 && (sym.flags() & Flags.PROTECTED) == 0) { 3828 return false; 3829 } 3830 sym = sym.owner; 3831 } 3832 return true; 3833 } checkVisible(DiagnosticPosition pos, Symbol what, PackageSymbol inPackage, boolean inSuperType)3834 private void checkVisible(DiagnosticPosition pos, Symbol what, PackageSymbol inPackage, boolean inSuperType) { 3835 if (!isAPISymbol(what) && !inSuperType) { //package private/private element 3836 log.warning(LintCategory.EXPORTS, pos, Warnings.LeaksNotAccessible(kindName(what), what, what.packge().modle)); 3837 return ; 3838 } 3839 3840 PackageSymbol whatPackage = what.packge(); 3841 ExportsDirective whatExport = findExport(whatPackage); 3842 ExportsDirective inExport = findExport(inPackage); 3843 3844 if (whatExport == null) { //package not exported: 3845 log.warning(LintCategory.EXPORTS, pos, Warnings.LeaksNotAccessibleUnexported(kindName(what), what, what.packge().modle)); 3846 return ; 3847 } 3848 3849 if (whatExport.modules != null) { 3850 if (inExport.modules == null || !whatExport.modules.containsAll(inExport.modules)) { 3851 log.warning(LintCategory.EXPORTS, pos, Warnings.LeaksNotAccessibleUnexportedQualified(kindName(what), what, what.packge().modle)); 3852 } 3853 } 3854 3855 if (whatPackage.modle != inPackage.modle && whatPackage.modle != syms.java_base) { 3856 //check that relativeTo.modle requires transitive what.modle, somehow: 3857 List<ModuleSymbol> todo = List.of(inPackage.modle); 3858 3859 while (todo.nonEmpty()) { 3860 ModuleSymbol current = todo.head; 3861 todo = todo.tail; 3862 if (current == whatPackage.modle) 3863 return ; //OK 3864 if ((current.flags() & Flags.AUTOMATIC_MODULE) != 0) 3865 continue; //for automatic modules, don't look into their dependencies 3866 for (RequiresDirective req : current.requires) { 3867 if (req.isTransitive()) { 3868 todo = todo.prepend(req.module); 3869 } 3870 } 3871 } 3872 3873 log.warning(LintCategory.EXPORTS, pos, Warnings.LeaksNotAccessibleNotRequiredTransitive(kindName(what), what, what.packge().modle)); 3874 } 3875 } 3876 checkModuleExists(final DiagnosticPosition pos, ModuleSymbol msym)3877 void checkModuleExists(final DiagnosticPosition pos, ModuleSymbol msym) { 3878 if (msym.kind != MDL) { 3879 deferredLintHandler.report(() -> { 3880 if (lint.isEnabled(LintCategory.MODULE)) 3881 log.warning(LintCategory.MODULE, pos, Warnings.ModuleNotFound(msym)); 3882 }); 3883 } 3884 } 3885 checkPackageExistsForOpens(final DiagnosticPosition pos, PackageSymbol packge)3886 void checkPackageExistsForOpens(final DiagnosticPosition pos, PackageSymbol packge) { 3887 if (packge.members().isEmpty() && 3888 ((packge.flags() & Flags.HAS_RESOURCE) == 0)) { 3889 deferredLintHandler.report(() -> { 3890 if (lint.isEnabled(LintCategory.OPENS)) 3891 log.warning(pos, Warnings.PackageEmptyOrNotFound(packge)); 3892 }); 3893 } 3894 } 3895 checkModuleRequires(final DiagnosticPosition pos, final RequiresDirective rd)3896 void checkModuleRequires(final DiagnosticPosition pos, final RequiresDirective rd) { 3897 if ((rd.module.flags() & Flags.AUTOMATIC_MODULE) != 0) { 3898 deferredLintHandler.report(() -> { 3899 if (rd.isTransitive() && lint.isEnabled(LintCategory.REQUIRES_TRANSITIVE_AUTOMATIC)) { 3900 log.warning(pos, Warnings.RequiresTransitiveAutomatic); 3901 } else if (lint.isEnabled(LintCategory.REQUIRES_AUTOMATIC)) { 3902 log.warning(pos, Warnings.RequiresAutomatic); 3903 } 3904 }); 3905 } 3906 } 3907 3908 } 3909