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