1 /* 2 * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.tools.javac.comp; 27 28 import java.util.*; 29 import java.util.Set; 30 31 import com.sun.tools.javac.code.*; 32 import com.sun.tools.javac.jvm.*; 33 import com.sun.tools.javac.tree.*; 34 import com.sun.tools.javac.util.*; 35 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 36 import com.sun.tools.javac.util.List; 37 38 import com.sun.tools.javac.tree.JCTree.*; 39 import com.sun.tools.javac.code.Lint; 40 import com.sun.tools.javac.code.Lint.LintCategory; 41 import com.sun.tools.javac.code.Type.*; 42 import com.sun.tools.javac.code.Symbol.*; 43 44 import static com.sun.tools.javac.code.Flags.*; 45 import static com.sun.tools.javac.code.Kinds.*; 46 import static com.sun.tools.javac.code.TypeTags.*; 47 48 import static com.sun.tools.javac.main.OptionName.*; 49 50 /** Type checking helper class for the attribution phase. 51 * 52 * <p><b>This is NOT part of any supported API. 53 * If you write code that depends on this, you do so at your own risk. 54 * This code and its internal interfaces are subject to change or 55 * deletion without notice.</b> 56 */ 57 public class Check { 58 protected static final Context.Key<Check> checkKey = 59 new Context.Key<Check>(); 60 61 private final Names names; 62 private final Log log; 63 private final Symtab syms; 64 private final Enter enter; 65 private final Infer infer; 66 private final Types types; 67 private final JCDiagnostic.Factory diags; 68 private final boolean skipAnnotations; 69 private boolean warnOnSyntheticConflicts; 70 private boolean suppressAbortOnBadClassFile; 71 private boolean enableSunApiLintControl; 72 private final TreeInfo treeinfo; 73 74 // The set of lint options currently in effect. It is initialized 75 // from the context, and then is set/reset as needed by Attr as it 76 // visits all the various parts of the trees during attribution. 77 private Lint lint; 78 79 // The method being analyzed in Attr - it is set/reset as needed by 80 // Attr as it visits new method declarations. 81 private MethodSymbol method; 82 83 public static Check instance(Context context) { 84 Check instance = context.get(checkKey); 85 if (instance == null) 86 instance = new Check(context); 87 return instance; 88 } 89 90 protected Check(Context context) { 91 context.put(checkKey, this); 92 93 names = Names.instance(context); 94 log = Log.instance(context); 95 syms = Symtab.instance(context); 96 enter = Enter.instance(context); 97 infer = Infer.instance(context); 98 this.types = Types.instance(context); 99 diags = JCDiagnostic.Factory.instance(context); 100 Options options = Options.instance(context); 101 lint = Lint.instance(context); 102 treeinfo = TreeInfo.instance(context); 103 104 Source source = Source.instance(context); 105 allowGenerics = source.allowGenerics(); 106 allowAnnotations = source.allowAnnotations(); 107 allowCovariantReturns = source.allowCovariantReturns(); 108 allowSimplifiedVarargs = source.allowSimplifiedVarargs(); 109 complexInference = options.isSet(COMPLEXINFERENCE); 110 skipAnnotations = options.isSet("skipAnnotations"); 111 warnOnSyntheticConflicts = options.isSet("warnOnSyntheticConflicts"); 112 suppressAbortOnBadClassFile = options.isSet("suppressAbortOnBadClassFile"); 113 enableSunApiLintControl = options.isSet("enableSunApiLintControl"); 114 115 Target target = Target.instance(context); 116 syntheticNameChar = target.syntheticNameChar(); 117 118 boolean verboseDeprecated = lint.isEnabled(LintCategory.DEPRECATION); 119 boolean verboseUnchecked = lint.isEnabled(LintCategory.UNCHECKED); 120 boolean verboseSunApi = lint.isEnabled(LintCategory.SUNAPI); 121 boolean enforceMandatoryWarnings = source.enforceMandatoryWarnings(); 122 123 deprecationHandler = new MandatoryWarningHandler(log, verboseDeprecated, 124 enforceMandatoryWarnings, "deprecated", LintCategory.DEPRECATION); 125 uncheckedHandler = new MandatoryWarningHandler(log, verboseUnchecked, 126 enforceMandatoryWarnings, "unchecked", LintCategory.UNCHECKED); 127 sunApiHandler = new MandatoryWarningHandler(log, verboseSunApi, 128 enforceMandatoryWarnings, "sunapi", null); 129 130 deferredLintHandler = DeferredLintHandler.immediateHandler; 131 } 132 133 /** Switch: generics enabled? 134 */ 135 boolean allowGenerics; 136 137 /** Switch: annotations enabled? 138 */ 139 boolean allowAnnotations; 140 141 /** Switch: covariant returns enabled? 142 */ 143 boolean allowCovariantReturns; 144 145 /** Switch: simplified varargs enabled? 146 */ 147 boolean allowSimplifiedVarargs; 148 149 /** Switch: -complexinference option set? 150 */ 151 boolean complexInference; 152 153 /** Character for synthetic names 154 */ 155 char syntheticNameChar; 156 157 /** A table mapping flat names of all compiled classes in this run to their 158 * symbols; maintained from outside. 159 */ 160 public Map<Name,ClassSymbol> compiled = new HashMap<Name, ClassSymbol>(); 161 162 /** A handler for messages about deprecated usage. 163 */ 164 private MandatoryWarningHandler deprecationHandler; 165 166 /** A handler for messages about unchecked or unsafe usage. 167 */ 168 private MandatoryWarningHandler uncheckedHandler; 169 170 /** A handler for messages about using proprietary API. 171 */ 172 private MandatoryWarningHandler sunApiHandler; 173 174 /** A handler for deferred lint warnings. 175 */ 176 private DeferredLintHandler deferredLintHandler; 177 178 /* ************************************************************************* 179 * Errors and Warnings 180 **************************************************************************/ 181 182 Lint setLint(Lint newLint) { 183 Lint prev = lint; 184 lint = newLint; 185 return prev; 186 } 187 188 DeferredLintHandler setDeferredLintHandler(DeferredLintHandler newDeferredLintHandler) { 189 DeferredLintHandler prev = deferredLintHandler; 190 deferredLintHandler = newDeferredLintHandler; 191 return prev; 192 } 193 194 MethodSymbol setMethod(MethodSymbol newMethod) { 195 MethodSymbol prev = method; 196 method = newMethod; 197 return prev; 198 } 199 200 /** Warn about deprecated symbol. 201 * @param pos Position to be used for error reporting. 202 * @param sym The deprecated symbol. 203 */ 204 void warnDeprecated(DiagnosticPosition pos, Symbol sym) { 205 if (!lint.isSuppressed(LintCategory.DEPRECATION)) 206 deprecationHandler.report(pos, "has.been.deprecated", sym, sym.location()); 207 } 208 209 /** Warn about unchecked operation. 210 * @param pos Position to be used for error reporting. 211 * @param msg A string describing the problem. 212 */ 213 public void warnUnchecked(DiagnosticPosition pos, String msg, Object... args) { 214 if (!lint.isSuppressed(LintCategory.UNCHECKED)) 215 uncheckedHandler.report(pos, msg, args); 216 } 217 218 /** Warn about unsafe vararg method decl. 219 * @param pos Position to be used for error reporting. 220 * @param sym The deprecated symbol. 221 */ 222 void warnUnsafeVararg(DiagnosticPosition pos, String key, Object... args) { 223 if (lint.isEnabled(LintCategory.VARARGS) && allowSimplifiedVarargs) 224 log.warning(LintCategory.VARARGS, pos, key, args); 225 } 226 227 /** Warn about using proprietary API. 228 * @param pos Position to be used for error reporting. 229 * @param msg A string describing the problem. 230 */ 231 public void warnSunApi(DiagnosticPosition pos, String msg, Object... args) { 232 if (!lint.isSuppressed(LintCategory.SUNAPI)) 233 sunApiHandler.report(pos, msg, args); 234 } 235 236 public void warnStatic(DiagnosticPosition pos, String msg, Object... args) { 237 if (lint.isEnabled(LintCategory.STATIC)) 238 log.warning(LintCategory.STATIC, pos, msg, args); 239 } 240 241 /** 242 * Report any deferred diagnostics. 243 */ 244 public void reportDeferredDiagnostics() { 245 deprecationHandler.reportDeferredDiagnostic(); 246 uncheckedHandler.reportDeferredDiagnostic(); 247 sunApiHandler.reportDeferredDiagnostic(); 248 } 249 250 251 /** Report a failure to complete a class. 252 * @param pos Position to be used for error reporting. 253 * @param ex The failure to report. 254 */ 255 public Type completionError(DiagnosticPosition pos, CompletionFailure ex) { 256 log.error(pos, "cant.access", ex.sym, ex.getDetailValue()); 257 if (ex instanceof ClassReader.BadClassFile 258 && !suppressAbortOnBadClassFile) throw new Abort(); 259 else return syms.errType; 260 } 261 262 /** Report a type error. 263 * @param pos Position to be used for error reporting. 264 * @param problem A string describing the error. 265 * @param found The type that was found. 266 * @param req The type that was required. 267 */ 268 Type typeError(DiagnosticPosition pos, Object problem, Type found, Type req) { 269 log.error(pos, "prob.found.req", 270 problem, found, req); 271 return types.createErrorType(found); 272 } 273 274 Type typeError(DiagnosticPosition pos, String problem, Type found, Type req, Object explanation) { 275 log.error(pos, "prob.found.req.1", problem, found, req, explanation); 276 return types.createErrorType(found); 277 } 278 279 /** Report an error that wrong type tag was found. 280 * @param pos Position to be used for error reporting. 281 * @param required An internationalized string describing the type tag 282 * required. 283 * @param found The type that was found. 284 */ 285 Type typeTagError(DiagnosticPosition pos, Object required, Object found) { 286 // this error used to be raised by the parser, 287 // but has been delayed to this point: 288 if (found instanceof Type && ((Type)found).tag == VOID) { 289 log.error(pos, "illegal.start.of.type"); 290 return syms.errType; 291 } 292 log.error(pos, "type.found.req", found, required); 293 return types.createErrorType(found instanceof Type ? (Type)found : syms.errType); 294 } 295 296 /** Report an error that symbol cannot be referenced before super 297 * has been called. 298 * @param pos Position to be used for error reporting. 299 * @param sym The referenced symbol. 300 */ 301 void earlyRefError(DiagnosticPosition pos, Symbol sym) { 302 log.error(pos, "cant.ref.before.ctor.called", sym); 303 } 304 305 /** Report duplicate declaration error. 306 */ 307 void duplicateError(DiagnosticPosition pos, Symbol sym) { 308 if (!sym.type.isErroneous()) { 309 Symbol location = sym.location(); 310 if (location.kind == MTH && 311 ((MethodSymbol)location).isStaticOrInstanceInit()) { 312 log.error(pos, "already.defined.in.clinit", kindName(sym), sym, 313 kindName(sym.location()), kindName(sym.location().enclClass()), 314 sym.location().enclClass()); 315 } else { 316 log.error(pos, "already.defined", kindName(sym), sym, 317 kindName(sym.location()), sym.location()); 318 } 319 } 320 } 321 322 /** Report array/varargs duplicate declaration 323 */ 324 void varargsDuplicateError(DiagnosticPosition pos, Symbol sym1, Symbol sym2) { 325 if (!sym1.type.isErroneous() && !sym2.type.isErroneous()) { 326 log.error(pos, "array.and.varargs", sym1, sym2, sym2.location()); 327 } 328 } 329 330 /* ************************************************************************ 331 * duplicate declaration checking 332 *************************************************************************/ 333 334 /** Check that variable does not hide variable with same name in 335 * immediately enclosing local scope. 336 * @param pos Position for error reporting. 337 * @param v The symbol. 338 * @param s The scope. 339 */ 340 void checkTransparentVar(DiagnosticPosition pos, VarSymbol v, Scope s) { 341 if (s.next != null) { 342 for (Scope.Entry e = s.next.lookup(v.name); 343 e.scope != null && e.sym.owner == v.owner; 344 e = e.next()) { 345 if (e.sym.kind == VAR && 346 (e.sym.owner.kind & (VAR | MTH)) != 0 && 347 v.name != names.error) { 348 duplicateError(pos, e.sym); 349 return; 350 } 351 } 352 } 353 } 354 355 /** Check that a class or interface does not hide a class or 356 * interface with same name in immediately enclosing local scope. 357 * @param pos Position for error reporting. 358 * @param c The symbol. 359 * @param s The scope. 360 */ 361 void checkTransparentClass(DiagnosticPosition pos, ClassSymbol c, Scope s) { 362 if (s.next != null) { 363 for (Scope.Entry e = s.next.lookup(c.name); 364 e.scope != null && e.sym.owner == c.owner; 365 e = e.next()) { 366 if (e.sym.kind == TYP && e.sym.type.tag != TYPEVAR && 367 (e.sym.owner.kind & (VAR | MTH)) != 0 && 368 c.name != names.error) { 369 duplicateError(pos, e.sym); 370 return; 371 } 372 } 373 } 374 } 375 376 /** Check that class does not have the same name as one of 377 * its enclosing classes, or as a class defined in its enclosing scope. 378 * return true if class is unique in its enclosing scope. 379 * @param pos Position for error reporting. 380 * @param name The class name. 381 * @param s The enclosing scope. 382 */ 383 boolean checkUniqueClassName(DiagnosticPosition pos, Name name, Scope s) { 384 for (Scope.Entry e = s.lookup(name); e.scope == s; e = e.next()) { 385 if (e.sym.kind == TYP && e.sym.name != names.error) { 386 duplicateError(pos, e.sym); 387 return false; 388 } 389 } 390 for (Symbol sym = s.owner; sym != null; sym = sym.owner) { 391 if (sym.kind == TYP && sym.name == name && sym.name != names.error) { 392 duplicateError(pos, sym); 393 return true; 394 } 395 } 396 return true; 397 } 398 399 /* ************************************************************************* 400 * Class name generation 401 **************************************************************************/ 402 403 /** Return name of local class. 404 * This is of the form <enclClass> $ n <classname> 405 * where 406 * enclClass is the flat name of the enclosing class, 407 * classname is the simple name of the local class 408 */ 409 Name localClassName(ClassSymbol c) { 410 for (int i=1; ; i++) { 411 Name flatname = names. 412 fromString("" + c.owner.enclClass().flatname + 413 syntheticNameChar + i + 414 c.name); 415 if (compiled.get(flatname) == null) return flatname; 416 } 417 } 418 419 /* ************************************************************************* 420 * Type Checking 421 **************************************************************************/ 422 423 /** Check that a given type is assignable to a given proto-type. 424 * If it is, return the type, otherwise return errType. 425 * @param pos Position to be used for error reporting. 426 * @param found The type that was found. 427 * @param req The type that was required. 428 */ 429 Type checkType(DiagnosticPosition pos, Type found, Type req) { 430 return checkType(pos, found, req, "incompatible.types"); 431 } 432 433 Type checkType(DiagnosticPosition pos, Type found, Type req, String errKey) { 434 if (req.tag == ERROR) 435 return req; 436 if (found.tag == FORALL) 437 return instantiatePoly(pos, (ForAll)found, req, convertWarner(pos, found, req)); 438 if (req.tag == NONE) 439 return found; 440 if (types.isAssignable(found, req, convertWarner(pos, found, req))) 441 return found; 442 if (found.tag <= DOUBLE && req.tag <= DOUBLE) 443 return typeError(pos, diags.fragment("possible.loss.of.precision"), found, req); 444 if (found.isSuperBound()) { 445 log.error(pos, "assignment.from.super-bound", found); 446 return types.createErrorType(found); 447 } 448 if (req.isExtendsBound()) { 449 log.error(pos, "assignment.to.extends-bound", req); 450 return types.createErrorType(found); 451 } 452 return typeError(pos, diags.fragment(errKey), found, req); 453 } 454 455 /** Instantiate polymorphic type to some prototype, unless 456 * prototype is `anyPoly' in which case polymorphic type 457 * is returned unchanged. 458 */ 459 Type instantiatePoly(DiagnosticPosition pos, ForAll t, Type pt, Warner warn) throws Infer.NoInstanceException { 460 if (pt == Infer.anyPoly && complexInference) { 461 return t; 462 } else if (pt == Infer.anyPoly || pt.tag == NONE) { 463 Type newpt = t.qtype.tag <= VOID ? t.qtype : syms.objectType; 464 return instantiatePoly(pos, t, newpt, warn); 465 } else if (pt.tag == ERROR) { 466 return pt; 467 } else { 468 try { 469 return infer.instantiateExpr(t, pt, warn); 470 } catch (Infer.NoInstanceException ex) { 471 if (ex.isAmbiguous) { 472 JCDiagnostic d = ex.getDiagnostic(); 473 log.error(pos, 474 "undetermined.type" + (d!=null ? ".1" : ""), 475 t, d); 476 return types.createErrorType(pt); 477 } else { 478 JCDiagnostic d = ex.getDiagnostic(); 479 return typeError(pos, 480 diags.fragment("incompatible.types" + (d!=null ? ".1" : ""), d), 481 t, pt); 482 } 483 } catch (Infer.InvalidInstanceException ex) { 484 JCDiagnostic d = ex.getDiagnostic(); 485 log.error(pos, "invalid.inferred.types", t.tvars, d); 486 return types.createErrorType(pt); 487 } 488 } 489 } 490 491 /** Check that a given type can be cast to a given target type. 492 * Return the result of the cast. 493 * @param pos Position to be used for error reporting. 494 * @param found The type that is being cast. 495 * @param req The target type of the cast. 496 */ 497 Type checkCastable(DiagnosticPosition pos, Type found, Type req) { 498 if (found.tag == FORALL) { 499 instantiatePoly(pos, (ForAll) found, req, castWarner(pos, found, req)); 500 return req; 501 } else if (types.isCastable(found, req, castWarner(pos, found, req))) { 502 return req; 503 } else { 504 return typeError(pos, 505 diags.fragment("inconvertible.types"), 506 found, req); 507 } 508 } 509 //where 510 /** Is type a type variable, or a (possibly multi-dimensional) array of 511 * type variables? 512 */ 513 boolean isTypeVar(Type t) { 514 return t.tag == TYPEVAR || t.tag == ARRAY && isTypeVar(types.elemtype(t)); 515 } 516 517 /** Check that a type is within some bounds. 518 * 519 * Used in TypeApply to verify that, e.g., X in V<X> is a valid 520 * type argument. 521 * @param pos Position to be used for error reporting. 522 * @param a The type that should be bounded by bs. 523 * @param bs The bound. 524 */ 525 private boolean checkExtends(Type a, TypeVar bs) { 526 if (a.isUnbound()) { 527 return true; 528 } else if (a.tag != WILDCARD) { 529 a = types.upperBound(a); 530 return types.isSubtype(a, bs.bound); 531 } else if (a.isExtendsBound()) { 532 return types.isCastable(bs.getUpperBound(), types.upperBound(a), Warner.noWarnings); 533 } else if (a.isSuperBound()) { 534 return !types.notSoftSubtype(types.lowerBound(a), bs.getUpperBound()); 535 } 536 return true; 537 } 538 539 /** Check that type is different from 'void'. 540 * @param pos Position to be used for error reporting. 541 * @param t The type to be checked. 542 */ 543 Type checkNonVoid(DiagnosticPosition pos, Type t) { 544 if (t.tag == VOID) { 545 log.error(pos, "void.not.allowed.here"); 546 return types.createErrorType(t); 547 } else { 548 return t; 549 } 550 } 551 552 /** Check that type is a class or interface type. 553 * @param pos Position to be used for error reporting. 554 * @param t The type to be checked. 555 */ 556 Type checkClassType(DiagnosticPosition pos, Type t) { 557 if (t.tag != CLASS && t.tag != ERROR) 558 return typeTagError(pos, 559 diags.fragment("type.req.class"), 560 (t.tag == TYPEVAR) 561 ? diags.fragment("type.parameter", t) 562 : t); 563 else 564 return t; 565 } 566 567 /** Check that type is a class or interface type. 568 * @param pos Position to be used for error reporting. 569 * @param t The type to be checked. 570 * @param noBounds True if type bounds are illegal here. 571 */ 572 Type checkClassType(DiagnosticPosition pos, Type t, boolean noBounds) { 573 t = checkClassType(pos, t); 574 if (noBounds && t.isParameterized()) { 575 List<Type> args = t.getTypeArguments(); 576 while (args.nonEmpty()) { 577 if (args.head.tag == WILDCARD) 578 return typeTagError(pos, 579 diags.fragment("type.req.exact"), 580 args.head); 581 args = args.tail; 582 } 583 } 584 return t; 585 } 586 587 /** Check that type is a reifiable class, interface or array type. 588 * @param pos Position to be used for error reporting. 589 * @param t The type to be checked. 590 */ 591 Type checkReifiableReferenceType(DiagnosticPosition pos, Type t) { 592 if (t.tag != CLASS && t.tag != ARRAY && t.tag != ERROR) { 593 return typeTagError(pos, 594 diags.fragment("type.req.class.array"), 595 t); 596 } else if (!types.isReifiable(t)) { 597 log.error(pos, "illegal.generic.type.for.instof"); 598 return types.createErrorType(t); 599 } else { 600 return t; 601 } 602 } 603 604 /** Check that type is a reference type, i.e. a class, interface or array type 605 * or a type variable. 606 * @param pos Position to be used for error reporting. 607 * @param t The type to be checked. 608 */ 609 Type checkRefType(DiagnosticPosition pos, Type t) { 610 switch (t.tag) { 611 case CLASS: 612 case ARRAY: 613 case TYPEVAR: 614 case WILDCARD: 615 case ERROR: 616 return t; 617 default: 618 return typeTagError(pos, 619 diags.fragment("type.req.ref"), 620 t); 621 } 622 } 623 624 /** Check that each type is a reference type, i.e. a class, interface or array type 625 * or a type variable. 626 * @param trees Original trees, used for error reporting. 627 * @param types The types to be checked. 628 */ 629 List<Type> checkRefTypes(List<JCExpression> trees, List<Type> types) { 630 List<JCExpression> tl = trees; 631 for (List<Type> l = types; l.nonEmpty(); l = l.tail) { 632 l.head = checkRefType(tl.head.pos(), l.head); 633 tl = tl.tail; 634 } 635 return types; 636 } 637 638 /** Check that type is a null or reference type. 639 * @param pos Position to be used for error reporting. 640 * @param t The type to be checked. 641 */ 642 Type checkNullOrRefType(DiagnosticPosition pos, Type t) { 643 switch (t.tag) { 644 case CLASS: 645 case ARRAY: 646 case TYPEVAR: 647 case WILDCARD: 648 case BOT: 649 case ERROR: 650 return t; 651 default: 652 return typeTagError(pos, 653 diags.fragment("type.req.ref"), 654 t); 655 } 656 } 657 658 /** Check that flag set does not contain elements of two conflicting sets. s 659 * Return true if it doesn't. 660 * @param pos Position to be used for error reporting. 661 * @param flags The set of flags to be checked. 662 * @param set1 Conflicting flags set #1. 663 * @param set2 Conflicting flags set #2. 664 */ 665 boolean checkDisjoint(DiagnosticPosition pos, long flags, long set1, long set2) { 666 if ((flags & set1) != 0 && (flags & set2) != 0) { 667 log.error(pos, 668 "illegal.combination.of.modifiers", 669 asFlagSet(TreeInfo.firstFlag(flags & set1)), 670 asFlagSet(TreeInfo.firstFlag(flags & set2))); 671 return false; 672 } else 673 return true; 674 } 675 676 /** Check that usage of diamond operator is correct (i.e. diamond should not 677 * be used with non-generic classes or in anonymous class creation expressions) 678 */ 679 Type checkDiamond(JCNewClass tree, Type t) { 680 if (!TreeInfo.isDiamond(tree) || 681 t.isErroneous()) { 682 return checkClassType(tree.clazz.pos(), t, true); 683 } else if (tree.def != null) { 684 log.error(tree.clazz.pos(), 685 "cant.apply.diamond.1", 686 t, diags.fragment("diamond.and.anon.class", t)); 687 return types.createErrorType(t); 688 } else if (t.tsym.type.getTypeArguments().isEmpty()) { 689 log.error(tree.clazz.pos(), 690 "cant.apply.diamond.1", 691 t, diags.fragment("diamond.non.generic", t)); 692 return types.createErrorType(t); 693 } else if (tree.typeargs != null && 694 tree.typeargs.nonEmpty()) { 695 log.error(tree.clazz.pos(), 696 "cant.apply.diamond.1", 697 t, diags.fragment("diamond.and.explicit.params", t)); 698 return types.createErrorType(t); 699 } else { 700 return t; 701 } 702 } 703 704 void checkVarargsMethodDecl(Env<AttrContext> env, JCMethodDecl tree) { 705 MethodSymbol m = tree.sym; 706 if (!allowSimplifiedVarargs) return; 707 boolean hasTrustMeAnno = m.attribute(syms.trustMeType.tsym) != null; 708 Type varargElemType = null; 709 if (m.isVarArgs()) { 710 varargElemType = types.elemtype(tree.params.last().type); 711 } 712 if (hasTrustMeAnno && !isTrustMeAllowedOnMethod(m)) { 713 if (varargElemType != null) { 714 log.error(tree, 715 "varargs.invalid.trustme.anno", 716 syms.trustMeType.tsym, 717 diags.fragment("varargs.trustme.on.virtual.varargs", m)); 718 } else { 719 log.error(tree, 720 "varargs.invalid.trustme.anno", 721 syms.trustMeType.tsym, 722 diags.fragment("varargs.trustme.on.non.varargs.meth", m)); 723 } 724 } else if (hasTrustMeAnno && varargElemType != null && 725 types.isReifiable(varargElemType)) { 726 warnUnsafeVararg(tree, 727 "varargs.redundant.trustme.anno", 728 syms.trustMeType.tsym, 729 diags.fragment("varargs.trustme.on.reifiable.varargs", varargElemType)); 730 } 731 else if (!hasTrustMeAnno && varargElemType != null && 732 !types.isReifiable(varargElemType)) { 733 warnUnchecked(tree.params.head.pos(), "unchecked.varargs.non.reifiable.type", varargElemType); 734 } 735 } 736 //where 737 private boolean isTrustMeAllowedOnMethod(Symbol s) { 738 return (s.flags() & VARARGS) != 0 && 739 (s.isConstructor() || 740 (s.flags() & (STATIC | FINAL)) != 0); 741 } 742 743 /** 744 * Check that vararg method call is sound 745 * @param pos Position to be used for error reporting. 746 * @param argtypes Actual arguments supplied to vararg method. 747 */ 748 void checkVararg(DiagnosticPosition pos, List<Type> argtypes, Symbol msym) { 749 Type argtype = argtypes.last(); 750 if (!types.isReifiable(argtype) && 751 (!allowSimplifiedVarargs || 752 msym.attribute(syms.trustMeType.tsym) == null || 753 !isTrustMeAllowedOnMethod(msym))) { 754 warnUnchecked(pos, 755 "unchecked.generic.array.creation", 756 argtype); 757 } 758 } 759 760 /** 761 * Check that type 't' is a valid instantiation of a generic class 762 * (see JLS 4.5) 763 * 764 * @param t class type to be checked 765 * @return true if 't' is well-formed 766 */ 767 public boolean checkValidGenericType(Type t) { 768 return firstIncompatibleTypeArg(t) == null; 769 } 770 //WHERE 771 private Type firstIncompatibleTypeArg(Type type) { 772 List<Type> formals = type.tsym.type.allparams(); 773 List<Type> actuals = type.allparams(); 774 List<Type> args = type.getTypeArguments(); 775 List<Type> forms = type.tsym.type.getTypeArguments(); 776 ListBuffer<Type> tvars_buf = new ListBuffer<Type>(); 777 778 // For matching pairs of actual argument types `a' and 779 // formal type parameters with declared bound `b' ... 780 while (args.nonEmpty() && forms.nonEmpty()) { 781 // exact type arguments needs to know their 782 // bounds (for upper and lower bound 783 // calculations). So we create new TypeVars with 784 // bounds substed with actuals. 785 tvars_buf.append(types.substBound(((TypeVar)forms.head), 786 formals, 787 actuals)); 788 args = args.tail; 789 forms = forms.tail; 790 } 791 792 args = type.getTypeArguments(); 793 List<Type> tvars_cap = types.substBounds(formals, 794 formals, 795 types.capture(type).allparams()); 796 while (args.nonEmpty() && tvars_cap.nonEmpty()) { 797 // Let the actual arguments know their bound 798 args.head.withTypeVar((TypeVar)tvars_cap.head); 799 args = args.tail; 800 tvars_cap = tvars_cap.tail; 801 } 802 803 args = type.getTypeArguments(); 804 List<Type> tvars = tvars_buf.toList(); 805 806 while (args.nonEmpty() && tvars.nonEmpty()) { 807 Type actual = types.subst(args.head, 808 type.tsym.type.getTypeArguments(), 809 tvars_buf.toList()); 810 if (!isTypeArgErroneous(actual) && 811 !tvars.head.getUpperBound().isErroneous() && 812 !checkExtends(actual, (TypeVar)tvars.head)) { 813 return args.head; 814 } 815 args = args.tail; 816 tvars = tvars.tail; 817 } 818 819 args = type.getTypeArguments(); 820 tvars = tvars_buf.toList(); 821 822 for (Type arg : types.capture(type).getTypeArguments()) { 823 if (arg.tag == TYPEVAR && 824 arg.getUpperBound().isErroneous() && 825 !tvars.head.getUpperBound().isErroneous() && 826 !isTypeArgErroneous(args.head)) { 827 return args.head; 828 } 829 tvars = tvars.tail; 830 args = args.tail; 831 } 832 833 return null; 834 } 835 //where 836 boolean isTypeArgErroneous(Type t) { 837 return isTypeArgErroneous.visit(t); 838 } 839 840 Types.UnaryVisitor<Boolean> isTypeArgErroneous = new Types.UnaryVisitor<Boolean>() { 841 public Boolean visitType(Type t, Void s) { 842 return t.isErroneous(); 843 } 844 @Override 845 public Boolean visitTypeVar(TypeVar t, Void s) { 846 return visit(t.getUpperBound()); 847 } 848 @Override 849 public Boolean visitCapturedType(CapturedType t, Void s) { 850 return visit(t.getUpperBound()) || 851 visit(t.getLowerBound()); 852 } 853 @Override 854 public Boolean visitWildcardType(WildcardType t, Void s) { 855 return visit(t.type); 856 } 857 }; 858 859 /** Check that given modifiers are legal for given symbol and 860 * return modifiers together with any implicit modififiers for that symbol. 861 * Warning: we can't use flags() here since this method 862 * is called during class enter, when flags() would cause a premature 863 * completion. 864 * @param pos Position to be used for error reporting. 865 * @param flags The set of modifiers given in a definition. 866 * @param sym The defined symbol. 867 */ 868 long checkFlags(DiagnosticPosition pos, long flags, Symbol sym, JCTree tree) { 869 long mask; 870 long implicit = 0; 871 switch (sym.kind) { 872 case VAR: 873 if (sym.owner.kind != TYP) 874 mask = LocalVarFlags; 875 else if ((sym.owner.flags_field & INTERFACE) != 0) 876 mask = implicit = InterfaceVarFlags; 877 else 878 mask = VarFlags; 879 break; 880 case MTH: 881 if (sym.name == names.init) { 882 if ((sym.owner.flags_field & ENUM) != 0) { 883 // enum constructors cannot be declared public or 884 // protected and must be implicitly or explicitly 885 // private 886 implicit = PRIVATE; 887 mask = PRIVATE; 888 } else 889 mask = ConstructorFlags; 890 } else if ((sym.owner.flags_field & INTERFACE) != 0) 891 mask = implicit = InterfaceMethodFlags; 892 else { 893 mask = MethodFlags; 894 } 895 // Imply STRICTFP if owner has STRICTFP set. 896 if (((flags|implicit) & Flags.ABSTRACT) == 0) 897 implicit |= sym.owner.flags_field & STRICTFP; 898 break; 899 case TYP: 900 if (sym.isLocal()) { 901 mask = LocalClassFlags; 902 if (sym.name.isEmpty()) { // Anonymous class 903 // Anonymous classes in static methods are themselves static; 904 // that's why we admit STATIC here. 905 mask |= STATIC; 906 // JLS: Anonymous classes are final. 907 implicit |= FINAL; 908 } 909 if ((sym.owner.flags_field & STATIC) == 0 && 910 (flags & ENUM) != 0) 911 log.error(pos, "enums.must.be.static"); 912 } else if (sym.owner.kind == TYP) { 913 mask = MemberClassFlags; 914 if (sym.owner.owner.kind == PCK || 915 (sym.owner.flags_field & STATIC) != 0) 916 mask |= STATIC; 917 else if ((flags & ENUM) != 0) 918 log.error(pos, "enums.must.be.static"); 919 // Nested interfaces and enums are always STATIC (Spec ???) 920 if ((flags & (INTERFACE | ENUM)) != 0 ) implicit = STATIC; 921 } else { 922 mask = ClassFlags; 923 } 924 // Interfaces are always ABSTRACT 925 if ((flags & INTERFACE) != 0) implicit |= ABSTRACT; 926 927 if ((flags & ENUM) != 0) { 928 // enums can't be declared abstract or final 929 mask &= ~(ABSTRACT | FINAL); 930 implicit |= implicitEnumFinalFlag(tree); 931 } 932 // Imply STRICTFP if owner has STRICTFP set. 933 implicit |= sym.owner.flags_field & STRICTFP; 934 break; 935 default: 936 throw new AssertionError(); 937 } 938 long illegal = flags & StandardFlags & ~mask; 939 if (illegal != 0) { 940 if ((illegal & INTERFACE) != 0) { 941 log.error(pos, "intf.not.allowed.here"); 942 mask |= INTERFACE; 943 } 944 else { 945 log.error(pos, 946 "mod.not.allowed.here", asFlagSet(illegal)); 947 } 948 } 949 else if ((sym.kind == TYP || 950 // ISSUE: Disallowing abstract&private is no longer appropriate 951 // in the presence of inner classes. Should it be deleted here? 952 checkDisjoint(pos, flags, 953 ABSTRACT, 954 PRIVATE | STATIC)) 955 && 956 checkDisjoint(pos, flags, 957 ABSTRACT | INTERFACE, 958 FINAL | NATIVE | SYNCHRONIZED) 959 && 960 checkDisjoint(pos, flags, 961 PUBLIC, 962 PRIVATE | PROTECTED) 963 && 964 checkDisjoint(pos, flags, 965 PRIVATE, 966 PUBLIC | PROTECTED) 967 && 968 checkDisjoint(pos, flags, 969 FINAL, 970 VOLATILE) 971 && 972 (sym.kind == TYP || 973 checkDisjoint(pos, flags, 974 ABSTRACT | NATIVE, 975 STRICTFP))) { 976 // skip 977 } 978 return flags & (mask | ~StandardFlags) | implicit; 979 } 980 981 982 /** Determine if this enum should be implicitly final. 983 * 984 * If the enum has no specialized enum contants, it is final. 985 * 986 * If the enum does have specialized enum contants, it is 987 * <i>not</i> final. 988 */ 989 private long implicitEnumFinalFlag(JCTree tree) { 990 if (tree.getTag() != JCTree.CLASSDEF) return 0; 991 class SpecialTreeVisitor extends JCTree.Visitor { 992 boolean specialized; 993 SpecialTreeVisitor() { 994 this.specialized = false; 995 }; 996 997 @Override 998 public void visitTree(JCTree tree) { /* no-op */ } 999 1000 @Override 1001 public void visitVarDef(JCVariableDecl tree) { 1002 if ((tree.mods.flags & ENUM) != 0) { 1003 if (tree.init instanceof JCNewClass && 1004 ((JCNewClass) tree.init).def != null) { 1005 specialized = true; 1006 } 1007 } 1008 } 1009 } 1010 1011 SpecialTreeVisitor sts = new SpecialTreeVisitor(); 1012 JCClassDecl cdef = (JCClassDecl) tree; 1013 for (JCTree defs: cdef.defs) { 1014 defs.accept(sts); 1015 if (sts.specialized) return 0; 1016 } 1017 return FINAL; 1018 } 1019 1020 /* ************************************************************************* 1021 * Type Validation 1022 **************************************************************************/ 1023 1024 /** Validate a type expression. That is, 1025 * check that all type arguments of a parametric type are within 1026 * their bounds. This must be done in a second phase after type attributon 1027 * since a class might have a subclass as type parameter bound. E.g: 1028 * 1029 * class B<A extends C> { ... } 1030 * class C extends B<C> { ... } 1031 * 1032 * and we can't make sure that the bound is already attributed because 1033 * of possible cycles. 1034 * 1035 * Visitor method: Validate a type expression, if it is not null, catching 1036 * and reporting any completion failures. 1037 */ 1038 void validate(JCTree tree, Env<AttrContext> env) { 1039 validate(tree, env, true); 1040 } 1041 void validate(JCTree tree, Env<AttrContext> env, boolean checkRaw) { 1042 new Validator(env).validateTree(tree, checkRaw, true); 1043 } 1044 1045 /** Visitor method: Validate a list of type expressions. 1046 */ 1047 void validate(List<? extends JCTree> trees, Env<AttrContext> env) { 1048 for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) 1049 validate(l.head, env); 1050 } 1051 1052 /** A visitor class for type validation. 1053 */ 1054 class Validator extends JCTree.Visitor { 1055 1056 boolean isOuter; 1057 Env<AttrContext> env; 1058 1059 Validator(Env<AttrContext> env) { 1060 this.env = env; 1061 } 1062 1063 @Override 1064 public void visitTypeArray(JCArrayTypeTree tree) { 1065 tree.elemtype.accept(this); 1066 } 1067 1068 @Override 1069 public void visitTypeApply(JCTypeApply tree) { 1070 if (tree.type.tag == CLASS) { 1071 List<JCExpression> args = tree.arguments; 1072 List<Type> forms = tree.type.tsym.type.getTypeArguments(); 1073 1074 Type incompatibleArg = firstIncompatibleTypeArg(tree.type); 1075 if (incompatibleArg != null) { 1076 for (JCTree arg : tree.arguments) { 1077 if (arg.type == incompatibleArg) { 1078 log.error(arg, "not.within.bounds", incompatibleArg, forms.head); 1079 } 1080 forms = forms.tail; 1081 } 1082 } 1083 1084 forms = tree.type.tsym.type.getTypeArguments(); 1085 1086 boolean is_java_lang_Class = tree.type.tsym.flatName() == names.java_lang_Class; 1087 1088 // For matching pairs of actual argument types `a' and 1089 // formal type parameters with declared bound `b' ... 1090 while (args.nonEmpty() && forms.nonEmpty()) { 1091 validateTree(args.head, 1092 !(isOuter && is_java_lang_Class), 1093 false); 1094 args = args.tail; 1095 forms = forms.tail; 1096 } 1097 1098 // Check that this type is either fully parameterized, or 1099 // not parameterized at all. 1100 if (tree.type.getEnclosingType().isRaw()) 1101 log.error(tree.pos(), "improperly.formed.type.inner.raw.param"); 1102 if (tree.clazz.getTag() == JCTree.SELECT) 1103 visitSelectInternal((JCFieldAccess)tree.clazz); 1104 } 1105 } 1106 1107 @Override 1108 public void visitTypeParameter(JCTypeParameter tree) { 1109 validateTrees(tree.bounds, true, isOuter); 1110 checkClassBounds(tree.pos(), tree.type); 1111 } 1112 1113 @Override 1114 public void visitWildcard(JCWildcard tree) { 1115 if (tree.inner != null) 1116 validateTree(tree.inner, true, isOuter); 1117 } 1118 1119 @Override 1120 public void visitSelect(JCFieldAccess tree) { 1121 if (tree.type.tag == CLASS) { 1122 visitSelectInternal(tree); 1123 1124 // Check that this type is either fully parameterized, or 1125 // not parameterized at all. 1126 if (tree.selected.type.isParameterized() && tree.type.tsym.type.getTypeArguments().nonEmpty()) 1127 log.error(tree.pos(), "improperly.formed.type.param.missing"); 1128 } 1129 } 1130 1131 public void visitSelectInternal(JCFieldAccess tree) { 1132 if (tree.type.tsym.isStatic() && 1133 tree.selected.type.isParameterized()) { 1134 // The enclosing type is not a class, so we are 1135 // looking at a static member type. However, the 1136 // qualifying expression is parameterized. 1137 log.error(tree.pos(), "cant.select.static.class.from.param.type"); 1138 } else { 1139 // otherwise validate the rest of the expression 1140 tree.selected.accept(this); 1141 } 1142 } 1143 1144 /** Default visitor method: do nothing. 1145 */ 1146 @Override 1147 public void visitTree(JCTree tree) { 1148 } 1149 1150 public void validateTree(JCTree tree, boolean checkRaw, boolean isOuter) { 1151 try { 1152 if (tree != null) { 1153 this.isOuter = isOuter; 1154 tree.accept(this); 1155 if (checkRaw) 1156 checkRaw(tree, env); 1157 } 1158 } catch (CompletionFailure ex) { 1159 completionError(tree.pos(), ex); 1160 } 1161 } 1162 1163 public void validateTrees(List<? extends JCTree> trees, boolean checkRaw, boolean isOuter) { 1164 for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) 1165 validateTree(l.head, checkRaw, isOuter); 1166 } 1167 1168 void checkRaw(JCTree tree, Env<AttrContext> env) { 1169 if (lint.isEnabled(LintCategory.RAW) && 1170 tree.type.tag == CLASS && 1171 !TreeInfo.isDiamond(tree) && 1172 !withinAnonConstr(env) && 1173 tree.type.isRaw()) { 1174 log.warning(LintCategory.RAW, 1175 tree.pos(), "raw.class.use", tree.type, tree.type.tsym.type); 1176 } 1177 } 1178 1179 boolean withinAnonConstr(Env<AttrContext> env) { 1180 return env.enclClass.name.isEmpty() && 1181 env.enclMethod != null && env.enclMethod.name == names.init; 1182 } 1183 } 1184 1185 /* ************************************************************************* 1186 * Exception checking 1187 **************************************************************************/ 1188 1189 /* The following methods treat classes as sets that contain 1190 * the class itself and all their subclasses 1191 */ 1192 1193 /** Is given type a subtype of some of the types in given list? 1194 */ 1195 boolean subset(Type t, List<Type> ts) { 1196 for (List<Type> l = ts; l.nonEmpty(); l = l.tail) 1197 if (types.isSubtype(t, l.head)) return true; 1198 return false; 1199 } 1200 1201 /** Is given type a subtype or supertype of 1202 * some of the types in given list? 1203 */ 1204 boolean intersects(Type t, List<Type> ts) { 1205 for (List<Type> l = ts; l.nonEmpty(); l = l.tail) 1206 if (types.isSubtype(t, l.head) || types.isSubtype(l.head, t)) return true; 1207 return false; 1208 } 1209 1210 /** Add type set to given type list, unless it is a subclass of some class 1211 * in the list. 1212 */ 1213 List<Type> incl(Type t, List<Type> ts) { 1214 return subset(t, ts) ? ts : excl(t, ts).prepend(t); 1215 } 1216 1217 /** Remove type set from type set list. 1218 */ 1219 List<Type> excl(Type t, List<Type> ts) { 1220 if (ts.isEmpty()) { 1221 return ts; 1222 } else { 1223 List<Type> ts1 = excl(t, ts.tail); 1224 if (types.isSubtype(ts.head, t)) return ts1; 1225 else if (ts1 == ts.tail) return ts; 1226 else return ts1.prepend(ts.head); 1227 } 1228 } 1229 1230 /** Form the union of two type set lists. 1231 */ 1232 List<Type> union(List<Type> ts1, List<Type> ts2) { 1233 List<Type> ts = ts1; 1234 for (List<Type> l = ts2; l.nonEmpty(); l = l.tail) 1235 ts = incl(l.head, ts); 1236 return ts; 1237 } 1238 1239 /** Form the difference of two type lists. 1240 */ 1241 List<Type> diff(List<Type> ts1, List<Type> ts2) { 1242 List<Type> ts = ts1; 1243 for (List<Type> l = ts2; l.nonEmpty(); l = l.tail) 1244 ts = excl(l.head, ts); 1245 return ts; 1246 } 1247 1248 /** Form the intersection of two type lists. 1249 */ 1250 public List<Type> intersect(List<Type> ts1, List<Type> ts2) { 1251 List<Type> ts = List.nil(); 1252 for (List<Type> l = ts1; l.nonEmpty(); l = l.tail) 1253 if (subset(l.head, ts2)) ts = incl(l.head, ts); 1254 for (List<Type> l = ts2; l.nonEmpty(); l = l.tail) 1255 if (subset(l.head, ts1)) ts = incl(l.head, ts); 1256 return ts; 1257 } 1258 1259 /** Is exc an exception symbol that need not be declared? 1260 */ 1261 boolean isUnchecked(ClassSymbol exc) { 1262 return 1263 exc.kind == ERR || 1264 exc.isSubClass(syms.errorType.tsym, types) || 1265 exc.isSubClass(syms.runtimeExceptionType.tsym, types); 1266 } 1267 1268 /** Is exc an exception type that need not be declared? 1269 */ 1270 boolean isUnchecked(Type exc) { 1271 return 1272 (exc.tag == TYPEVAR) ? isUnchecked(types.supertype(exc)) : 1273 (exc.tag == CLASS) ? isUnchecked((ClassSymbol)exc.tsym) : 1274 exc.tag == BOT; 1275 } 1276 1277 /** Same, but handling completion failures. 1278 */ 1279 boolean isUnchecked(DiagnosticPosition pos, Type exc) { 1280 try { 1281 return isUnchecked(exc); 1282 } catch (CompletionFailure ex) { 1283 completionError(pos, ex); 1284 return true; 1285 } 1286 } 1287 1288 /** Is exc handled by given exception list? 1289 */ 1290 boolean isHandled(Type exc, List<Type> handled) { 1291 return isUnchecked(exc) || subset(exc, handled); 1292 } 1293 1294 /** Return all exceptions in thrown list that are not in handled list. 1295 * @param thrown The list of thrown exceptions. 1296 * @param handled The list of handled exceptions. 1297 */ 1298 List<Type> unhandled(List<Type> thrown, List<Type> handled) { 1299 List<Type> unhandled = List.nil(); 1300 for (List<Type> l = thrown; l.nonEmpty(); l = l.tail) 1301 if (!isHandled(l.head, handled)) unhandled = unhandled.prepend(l.head); 1302 return unhandled; 1303 } 1304 1305 /* ************************************************************************* 1306 * Overriding/Implementation checking 1307 **************************************************************************/ 1308 1309 /** The level of access protection given by a flag set, 1310 * where PRIVATE is highest and PUBLIC is lowest. 1311 */ 1312 static int protection(long flags) { 1313 switch ((short)(flags & AccessFlags)) { 1314 case PRIVATE: return 3; 1315 case PROTECTED: return 1; 1316 default: 1317 case PUBLIC: return 0; 1318 case 0: return 2; 1319 } 1320 } 1321 1322 /** A customized "cannot override" error message. 1323 * @param m The overriding method. 1324 * @param other The overridden method. 1325 * @return An internationalized string. 1326 */ 1327 Object cannotOverride(MethodSymbol m, MethodSymbol other) { 1328 String key; 1329 if ((other.owner.flags() & INTERFACE) == 0) 1330 key = "cant.override"; 1331 else if ((m.owner.flags() & INTERFACE) == 0) 1332 key = "cant.implement"; 1333 else 1334 key = "clashes.with"; 1335 return diags.fragment(key, m, m.location(), other, other.location()); 1336 } 1337 1338 /** A customized "override" warning message. 1339 * @param m The overriding method. 1340 * @param other The overridden method. 1341 * @return An internationalized string. 1342 */ 1343 Object uncheckedOverrides(MethodSymbol m, MethodSymbol other) { 1344 String key; 1345 if ((other.owner.flags() & INTERFACE) == 0) 1346 key = "unchecked.override"; 1347 else if ((m.owner.flags() & INTERFACE) == 0) 1348 key = "unchecked.implement"; 1349 else 1350 key = "unchecked.clash.with"; 1351 return diags.fragment(key, m, m.location(), other, other.location()); 1352 } 1353 1354 /** A customized "override" warning message. 1355 * @param m The overriding method. 1356 * @param other The overridden method. 1357 * @return An internationalized string. 1358 */ 1359 Object varargsOverrides(MethodSymbol m, MethodSymbol other) { 1360 String key; 1361 if ((other.owner.flags() & INTERFACE) == 0) 1362 key = "varargs.override"; 1363 else if ((m.owner.flags() & INTERFACE) == 0) 1364 key = "varargs.implement"; 1365 else 1366 key = "varargs.clash.with"; 1367 return diags.fragment(key, m, m.location(), other, other.location()); 1368 } 1369 1370 /** Check that this method conforms with overridden method 'other'. 1371 * where `origin' is the class where checking started. 1372 * Complications: 1373 * (1) Do not check overriding of synthetic methods 1374 * (reason: they might be final). 1375 * todo: check whether this is still necessary. 1376 * (2) Admit the case where an interface proxy throws fewer exceptions 1377 * than the method it implements. Augment the proxy methods with the 1378 * undeclared exceptions in this case. 1379 * (3) When generics are enabled, admit the case where an interface proxy 1380 * has a result type 1381 * extended by the result type of the method it implements. 1382 * Change the proxies result type to the smaller type in this case. 1383 * 1384 * @param tree The tree from which positions 1385 * are extracted for errors. 1386 * @param m The overriding method. 1387 * @param other The overridden method. 1388 * @param origin The class of which the overriding method 1389 * is a member. 1390 */ 1391 void checkOverride(JCTree tree, 1392 MethodSymbol m, 1393 MethodSymbol other, 1394 ClassSymbol origin) { 1395 // Don't check overriding of synthetic methods or by bridge methods. 1396 if ((m.flags() & (SYNTHETIC|BRIDGE)) != 0 || (other.flags() & SYNTHETIC) != 0) { 1397 return; 1398 } 1399 1400 // Error if static method overrides instance method (JLS 8.4.6.2). 1401 if ((m.flags() & STATIC) != 0 && 1402 (other.flags() & STATIC) == 0) { 1403 log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.static", 1404 cannotOverride(m, other)); 1405 return; 1406 } 1407 1408 // Error if instance method overrides static or final 1409 // method (JLS 8.4.6.1). 1410 if ((other.flags() & FINAL) != 0 || 1411 (m.flags() & STATIC) == 0 && 1412 (other.flags() & STATIC) != 0) { 1413 log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.meth", 1414 cannotOverride(m, other), 1415 asFlagSet(other.flags() & (FINAL | STATIC))); 1416 return; 1417 } 1418 1419 if ((m.owner.flags() & ANNOTATION) != 0) { 1420 // handled in validateAnnotationMethod 1421 return; 1422 } 1423 1424 // Error if overriding method has weaker access (JLS 8.4.6.3). 1425 if ((origin.flags() & INTERFACE) == 0 && 1426 protection(m.flags()) > protection(other.flags())) { 1427 log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.weaker.access", 1428 cannotOverride(m, other), 1429 other.flags() == 0 ? 1430 Flag.PACKAGE : 1431 asFlagSet(other.flags() & AccessFlags)); 1432 return; 1433 } 1434 1435 Type mt = types.memberType(origin.type, m); 1436 Type ot = types.memberType(origin.type, other); 1437 // Error if overriding result type is different 1438 // (or, in the case of generics mode, not a subtype) of 1439 // overridden result type. We have to rename any type parameters 1440 // before comparing types. 1441 List<Type> mtvars = mt.getTypeArguments(); 1442 List<Type> otvars = ot.getTypeArguments(); 1443 Type mtres = mt.getReturnType(); 1444 Type otres = types.subst(ot.getReturnType(), otvars, mtvars); 1445 1446 overrideWarner.clear(); 1447 boolean resultTypesOK = 1448 types.returnTypeSubstitutable(mt, ot, otres, overrideWarner); 1449 if (!resultTypesOK) { 1450 if (!allowCovariantReturns && 1451 m.owner != origin && 1452 m.owner.isSubClass(other.owner, types)) { 1453 // allow limited interoperability with covariant returns 1454 } else { 1455 log.error(TreeInfo.diagnosticPositionFor(m, tree), 1456 "override.incompatible.ret", 1457 cannotOverride(m, other), 1458 mtres, otres); 1459 return; 1460 } 1461 } else if (overrideWarner.hasNonSilentLint(LintCategory.UNCHECKED)) { 1462 warnUnchecked(TreeInfo.diagnosticPositionFor(m, tree), 1463 "override.unchecked.ret", 1464 uncheckedOverrides(m, other), 1465 mtres, otres); 1466 } 1467 1468 // Error if overriding method throws an exception not reported 1469 // by overridden method. 1470 List<Type> otthrown = types.subst(ot.getThrownTypes(), otvars, mtvars); 1471 List<Type> unhandledErased = unhandled(mt.getThrownTypes(), types.erasure(otthrown)); 1472 List<Type> unhandledUnerased = unhandled(mt.getThrownTypes(), otthrown); 1473 if (unhandledErased.nonEmpty()) { 1474 log.error(TreeInfo.diagnosticPositionFor(m, tree), 1475 "override.meth.doesnt.throw", 1476 cannotOverride(m, other), 1477 unhandledUnerased.head); 1478 return; 1479 } 1480 else if (unhandledUnerased.nonEmpty()) { 1481 warnUnchecked(TreeInfo.diagnosticPositionFor(m, tree), 1482 "override.unchecked.thrown", 1483 cannotOverride(m, other), 1484 unhandledUnerased.head); 1485 return; 1486 } 1487 1488 // Optional warning if varargs don't agree 1489 if ((((m.flags() ^ other.flags()) & Flags.VARARGS) != 0) 1490 && lint.isEnabled(LintCategory.OVERRIDES)) { 1491 log.warning(TreeInfo.diagnosticPositionFor(m, tree), 1492 ((m.flags() & Flags.VARARGS) != 0) 1493 ? "override.varargs.missing" 1494 : "override.varargs.extra", 1495 varargsOverrides(m, other)); 1496 } 1497 1498 // Warn if instance method overrides bridge method (compiler spec ??) 1499 if ((other.flags() & BRIDGE) != 0) { 1500 log.warning(TreeInfo.diagnosticPositionFor(m, tree), "override.bridge", 1501 uncheckedOverrides(m, other)); 1502 } 1503 1504 // Warn if a deprecated method overridden by a non-deprecated one. 1505 if (!isDeprecatedOverrideIgnorable(other, origin)) { 1506 checkDeprecated(TreeInfo.diagnosticPositionFor(m, tree), m, other); 1507 } 1508 } 1509 // where 1510 private boolean isDeprecatedOverrideIgnorable(MethodSymbol m, ClassSymbol origin) { 1511 // If the method, m, is defined in an interface, then ignore the issue if the method 1512 // is only inherited via a supertype and also implemented in the supertype, 1513 // because in that case, we will rediscover the issue when examining the method 1514 // in the supertype. 1515 // If the method, m, is not defined in an interface, then the only time we need to 1516 // address the issue is when the method is the supertype implemementation: any other 1517 // case, we will have dealt with when examining the supertype classes 1518 ClassSymbol mc = m.enclClass(); 1519 Type st = types.supertype(origin.type); 1520 if (st.tag != CLASS) 1521 return true; 1522 MethodSymbol stimpl = m.implementation((ClassSymbol)st.tsym, types, false); 1523 1524 if (mc != null && ((mc.flags() & INTERFACE) != 0)) { 1525 List<Type> intfs = types.interfaces(origin.type); 1526 return (intfs.contains(mc.type) ? false : (stimpl != null)); 1527 } 1528 else 1529 return (stimpl != m); 1530 } 1531 1532 1533 // used to check if there were any unchecked conversions 1534 Warner overrideWarner = new Warner(); 1535 1536 /** Check that a class does not inherit two concrete methods 1537 * with the same signature. 1538 * @param pos Position to be used for error reporting. 1539 * @param site The class type to be checked. 1540 */ 1541 public void checkCompatibleConcretes(DiagnosticPosition pos, Type site) { 1542 Type sup = types.supertype(site); 1543 if (sup.tag != CLASS) return; 1544 1545 for (Type t1 = sup; 1546 t1.tsym.type.isParameterized(); 1547 t1 = types.supertype(t1)) { 1548 for (Scope.Entry e1 = t1.tsym.members().elems; 1549 e1 != null; 1550 e1 = e1.sibling) { 1551 Symbol s1 = e1.sym; 1552 if (s1.kind != MTH || 1553 (s1.flags() & (STATIC|SYNTHETIC|BRIDGE)) != 0 || 1554 !s1.isInheritedIn(site.tsym, types) || 1555 ((MethodSymbol)s1).implementation(site.tsym, 1556 types, 1557 true) != s1) 1558 continue; 1559 Type st1 = types.memberType(t1, s1); 1560 int s1ArgsLength = st1.getParameterTypes().length(); 1561 if (st1 == s1.type) continue; 1562 1563 for (Type t2 = sup; 1564 t2.tag == CLASS; 1565 t2 = types.supertype(t2)) { 1566 for (Scope.Entry e2 = t2.tsym.members().lookup(s1.name); 1567 e2.scope != null; 1568 e2 = e2.next()) { 1569 Symbol s2 = e2.sym; 1570 if (s2 == s1 || 1571 s2.kind != MTH || 1572 (s2.flags() & (STATIC|SYNTHETIC|BRIDGE)) != 0 || 1573 s2.type.getParameterTypes().length() != s1ArgsLength || 1574 !s2.isInheritedIn(site.tsym, types) || 1575 ((MethodSymbol)s2).implementation(site.tsym, 1576 types, 1577 true) != s2) 1578 continue; 1579 Type st2 = types.memberType(t2, s2); 1580 if (types.overrideEquivalent(st1, st2)) 1581 log.error(pos, "concrete.inheritance.conflict", 1582 s1, t1, s2, t2, sup); 1583 } 1584 } 1585 } 1586 } 1587 } 1588 1589 /** Check that classes (or interfaces) do not each define an abstract 1590 * method with same name and arguments but incompatible return types. 1591 * @param pos Position to be used for error reporting. 1592 * @param t1 The first argument type. 1593 * @param t2 The second argument type. 1594 */ 1595 public boolean checkCompatibleAbstracts(DiagnosticPosition pos, 1596 Type t1, 1597 Type t2) { 1598 return checkCompatibleAbstracts(pos, t1, t2, 1599 types.makeCompoundType(t1, t2)); 1600 } 1601 1602 public boolean checkCompatibleAbstracts(DiagnosticPosition pos, 1603 Type t1, 1604 Type t2, 1605 Type site) { 1606 return firstIncompatibility(pos, t1, t2, site) == null; 1607 } 1608 1609 /** Return the first method which is defined with same args 1610 * but different return types in two given interfaces, or null if none 1611 * exists. 1612 * @param t1 The first type. 1613 * @param t2 The second type. 1614 * @param site The most derived type. 1615 * @returns symbol from t2 that conflicts with one in t1. 1616 */ 1617 private Symbol firstIncompatibility(DiagnosticPosition pos, Type t1, Type t2, Type site) { 1618 Map<TypeSymbol,Type> interfaces1 = new HashMap<TypeSymbol,Type>(); 1619 closure(t1, interfaces1); 1620 Map<TypeSymbol,Type> interfaces2; 1621 if (t1 == t2) 1622 interfaces2 = interfaces1; 1623 else 1624 closure(t2, interfaces1, interfaces2 = new HashMap<TypeSymbol,Type>()); 1625 1626 for (Type t3 : interfaces1.values()) { 1627 for (Type t4 : interfaces2.values()) { 1628 Symbol s = firstDirectIncompatibility(pos, t3, t4, site); 1629 if (s != null) return s; 1630 } 1631 } 1632 return null; 1633 } 1634 1635 /** Compute all the supertypes of t, indexed by type symbol. */ 1636 private void closure(Type t, Map<TypeSymbol,Type> typeMap) { 1637 if (t.tag != CLASS) return; 1638 if (typeMap.put(t.tsym, t) == null) { 1639 closure(types.supertype(t), typeMap); 1640 for (Type i : types.interfaces(t)) 1641 closure(i, typeMap); 1642 } 1643 } 1644 1645 /** Compute all the supertypes of t, indexed by type symbol (except thise in typesSkip). */ 1646 private void closure(Type t, Map<TypeSymbol,Type> typesSkip, Map<TypeSymbol,Type> typeMap) { 1647 if (t.tag != CLASS) return; 1648 if (typesSkip.get(t.tsym) != null) return; 1649 if (typeMap.put(t.tsym, t) == null) { 1650 closure(types.supertype(t), typesSkip, typeMap); 1651 for (Type i : types.interfaces(t)) 1652 closure(i, typesSkip, typeMap); 1653 } 1654 } 1655 1656 /** Return the first method in t2 that conflicts with a method from t1. */ 1657 private Symbol firstDirectIncompatibility(DiagnosticPosition pos, Type t1, Type t2, Type site) { 1658 for (Scope.Entry e1 = t1.tsym.members().elems; e1 != null; e1 = e1.sibling) { 1659 Symbol s1 = e1.sym; 1660 Type st1 = null; 1661 if (s1.kind != MTH || !s1.isInheritedIn(site.tsym, types)) continue; 1662 Symbol impl = ((MethodSymbol)s1).implementation(site.tsym, types, false); 1663 if (impl != null && (impl.flags() & ABSTRACT) == 0) continue; 1664 for (Scope.Entry e2 = t2.tsym.members().lookup(s1.name); e2.scope != null; e2 = e2.next()) { 1665 Symbol s2 = e2.sym; 1666 if (s1 == s2) continue; 1667 if (s2.kind != MTH || !s2.isInheritedIn(site.tsym, types)) continue; 1668 if (st1 == null) st1 = types.memberType(t1, s1); 1669 Type st2 = types.memberType(t2, s2); 1670 if (types.overrideEquivalent(st1, st2)) { 1671 List<Type> tvars1 = st1.getTypeArguments(); 1672 List<Type> tvars2 = st2.getTypeArguments(); 1673 Type rt1 = st1.getReturnType(); 1674 Type rt2 = types.subst(st2.getReturnType(), tvars2, tvars1); 1675 boolean compat = 1676 types.isSameType(rt1, rt2) || 1677 rt1.tag >= CLASS && rt2.tag >= CLASS && 1678 (types.covariantReturnType(rt1, rt2, Warner.noWarnings) || 1679 types.covariantReturnType(rt2, rt1, Warner.noWarnings)) || 1680 checkCommonOverriderIn(s1,s2,site); 1681 if (!compat) { 1682 log.error(pos, "types.incompatible.diff.ret", 1683 t1, t2, s2.name + 1684 "(" + types.memberType(t2, s2).getParameterTypes() + ")"); 1685 return s2; 1686 } 1687 } else if (checkNameClash((ClassSymbol)site.tsym, s1, s2) && 1688 !checkCommonOverriderIn(s1, s2, site)) { 1689 log.error(pos, 1690 "name.clash.same.erasure.no.override", 1691 s1, s1.location(), 1692 s2, s2.location()); 1693 return s2; 1694 } 1695 } 1696 } 1697 return null; 1698 } 1699 //WHERE 1700 boolean checkCommonOverriderIn(Symbol s1, Symbol s2, Type site) { 1701 Map<TypeSymbol,Type> supertypes = new HashMap<TypeSymbol,Type>(); 1702 Type st1 = types.memberType(site, s1); 1703 Type st2 = types.memberType(site, s2); 1704 closure(site, supertypes); 1705 for (Type t : supertypes.values()) { 1706 for (Scope.Entry e = t.tsym.members().lookup(s1.name); e.scope != null; e = e.next()) { 1707 Symbol s3 = e.sym; 1708 if (s3 == s1 || s3 == s2 || s3.kind != MTH || (s3.flags() & (BRIDGE|SYNTHETIC)) != 0) continue; 1709 Type st3 = types.memberType(site,s3); 1710 if (types.overrideEquivalent(st3, st1) && types.overrideEquivalent(st3, st2)) { 1711 if (s3.owner == site.tsym) { 1712 return true; 1713 } 1714 List<Type> tvars1 = st1.getTypeArguments(); 1715 List<Type> tvars2 = st2.getTypeArguments(); 1716 List<Type> tvars3 = st3.getTypeArguments(); 1717 Type rt1 = st1.getReturnType(); 1718 Type rt2 = st2.getReturnType(); 1719 Type rt13 = types.subst(st3.getReturnType(), tvars3, tvars1); 1720 Type rt23 = types.subst(st3.getReturnType(), tvars3, tvars2); 1721 boolean compat = 1722 rt13.tag >= CLASS && rt23.tag >= CLASS && 1723 (types.covariantReturnType(rt13, rt1, Warner.noWarnings) && 1724 types.covariantReturnType(rt23, rt2, Warner.noWarnings)); 1725 if (compat) 1726 return true; 1727 } 1728 } 1729 } 1730 return false; 1731 } 1732 1733 /** Check that a given method conforms with any method it overrides. 1734 * @param tree The tree from which positions are extracted 1735 * for errors. 1736 * @param m The overriding method. 1737 */ 1738 void checkOverride(JCTree tree, MethodSymbol m) { 1739 ClassSymbol origin = (ClassSymbol)m.owner; 1740 if ((origin.flags() & ENUM) != 0 && names.finalize.equals(m.name)) 1741 if (m.overrides(syms.enumFinalFinalize, origin, types, false)) { 1742 log.error(tree.pos(), "enum.no.finalize"); 1743 return; 1744 } 1745 for (Type t = origin.type; t.tag == CLASS; 1746 t = types.supertype(t)) { 1747 if (t != origin.type) { 1748 checkOverride(tree, t, origin, m); 1749 } 1750 for (Type t2 : types.interfaces(t)) { 1751 checkOverride(tree, t2, origin, m); 1752 } 1753 } 1754 } 1755 1756 void checkOverride(JCTree tree, Type site, ClassSymbol origin, MethodSymbol m) { 1757 TypeSymbol c = site.tsym; 1758 Scope.Entry e = c.members().lookup(m.name); 1759 while (e.scope != null) { 1760 if (m.overrides(e.sym, origin, types, false)) { 1761 if ((e.sym.flags() & ABSTRACT) == 0) { 1762 checkOverride(tree, m, (MethodSymbol)e.sym, origin); 1763 } 1764 } 1765 e = e.next(); 1766 } 1767 } 1768 1769 private boolean checkNameClash(ClassSymbol origin, Symbol s1, Symbol s2) { 1770 ClashFilter cf = new ClashFilter(origin.type); 1771 return (cf.accepts(s1) && 1772 cf.accepts(s2) && 1773 types.hasSameArgs(s1.erasure(types), s2.erasure(types))); 1774 } 1775 1776 1777 /** Check that all abstract members of given class have definitions. 1778 * @param pos Position to be used for error reporting. 1779 * @param c The class. 1780 */ 1781 void checkAllDefined(DiagnosticPosition pos, ClassSymbol c) { 1782 try { 1783 MethodSymbol undef = firstUndef(c, c); 1784 if (undef != null) { 1785 if ((c.flags() & ENUM) != 0 && 1786 types.supertype(c.type).tsym == syms.enumSym && 1787 (c.flags() & FINAL) == 0) { 1788 // add the ABSTRACT flag to an enum 1789 c.flags_field |= ABSTRACT; 1790 } else { 1791 MethodSymbol undef1 = 1792 new MethodSymbol(undef.flags(), undef.name, 1793 types.memberType(c.type, undef), undef.owner); 1794 log.error(pos, "does.not.override.abstract", 1795 c, undef1, undef1.location()); 1796 } 1797 } 1798 } catch (CompletionFailure ex) { 1799 completionError(pos, ex); 1800 } 1801 } 1802 //where 1803 /** Return first abstract member of class `c' that is not defined 1804 * in `impl', null if there is none. 1805 */ 1806 private MethodSymbol firstUndef(ClassSymbol impl, ClassSymbol c) { 1807 MethodSymbol undef = null; 1808 // Do not bother to search in classes that are not abstract, 1809 // since they cannot have abstract members. 1810 if (c == impl || (c.flags() & (ABSTRACT | INTERFACE)) != 0) { 1811 Scope s = c.members(); 1812 for (Scope.Entry e = s.elems; 1813 undef == null && e != null; 1814 e = e.sibling) { 1815 if (e.sym.kind == MTH && 1816 (e.sym.flags() & (ABSTRACT|IPROXY)) == ABSTRACT) { 1817 MethodSymbol absmeth = (MethodSymbol)e.sym; 1818 MethodSymbol implmeth = absmeth.implementation(impl, types, true); 1819 if (implmeth == null || implmeth == absmeth) 1820 undef = absmeth; 1821 } 1822 } 1823 if (undef == null) { 1824 Type st = types.supertype(c.type); 1825 if (st.tag == CLASS) 1826 undef = firstUndef(impl, (ClassSymbol)st.tsym); 1827 } 1828 for (List<Type> l = types.interfaces(c.type); 1829 undef == null && l.nonEmpty(); 1830 l = l.tail) { 1831 undef = firstUndef(impl, (ClassSymbol)l.head.tsym); 1832 } 1833 } 1834 return undef; 1835 } 1836 1837 void checkNonCyclicDecl(JCClassDecl tree) { 1838 CycleChecker cc = new CycleChecker(); 1839 cc.scan(tree); 1840 if (!cc.errorFound && !cc.partialCheck) { 1841 tree.sym.flags_field |= ACYCLIC; 1842 } 1843 } 1844 1845 class CycleChecker extends TreeScanner { 1846 1847 List<Symbol> seenClasses = List.nil(); 1848 boolean errorFound = false; 1849 boolean partialCheck = false; 1850 1851 private void checkSymbol(DiagnosticPosition pos, Symbol sym) { 1852 if (sym != null && sym.kind == TYP) { 1853 Env<AttrContext> classEnv = enter.getEnv((TypeSymbol)sym); 1854 if (classEnv != null) { 1855 DiagnosticSource prevSource = log.currentSource(); 1856 try { 1857 log.useSource(classEnv.toplevel.sourcefile); 1858 scan(classEnv.tree); 1859 } 1860 finally { 1861 log.useSource(prevSource.getFile()); 1862 } 1863 } else if (sym.kind == TYP) { 1864 checkClass(pos, sym, List.<JCTree>nil()); 1865 } 1866 } else { 1867 //not completed yet 1868 partialCheck = true; 1869 } 1870 } 1871 1872 @Override 1873 public void visitSelect(JCFieldAccess tree) { 1874 super.visitSelect(tree); 1875 checkSymbol(tree.pos(), tree.sym); 1876 } 1877 1878 @Override 1879 public void visitIdent(JCIdent tree) { 1880 checkSymbol(tree.pos(), tree.sym); 1881 } 1882 1883 @Override 1884 public void visitTypeApply(JCTypeApply tree) { 1885 scan(tree.clazz); 1886 } 1887 1888 @Override 1889 public void visitTypeArray(JCArrayTypeTree tree) { 1890 scan(tree.elemtype); 1891 } 1892 1893 @Override 1894 public void visitClassDef(JCClassDecl tree) { 1895 List<JCTree> supertypes = List.nil(); 1896 if (tree.getExtendsClause() != null) { 1897 supertypes = supertypes.prepend(tree.getExtendsClause()); 1898 } 1899 if (tree.getImplementsClause() != null) { 1900 for (JCTree intf : tree.getImplementsClause()) { 1901 supertypes = supertypes.prepend(intf); 1902 } 1903 } 1904 checkClass(tree.pos(), tree.sym, supertypes); 1905 } 1906 1907 void checkClass(DiagnosticPosition pos, Symbol c, List<JCTree> supertypes) { 1908 if ((c.flags_field & ACYCLIC) != 0) 1909 return; 1910 if (seenClasses.contains(c)) { 1911 errorFound = true; 1912 noteCyclic(pos, (ClassSymbol)c); 1913 } else if (!c.type.isErroneous()) { 1914 try { 1915 seenClasses = seenClasses.prepend(c); 1916 if (c.type.tag == CLASS) { 1917 if (supertypes.nonEmpty()) { 1918 scan(supertypes); 1919 } 1920 else { 1921 ClassType ct = (ClassType)c.type; 1922 if (ct.supertype_field == null || 1923 ct.interfaces_field == null) { 1924 //not completed yet 1925 partialCheck = true; 1926 return; 1927 } 1928 checkSymbol(pos, ct.supertype_field.tsym); 1929 for (Type intf : ct.interfaces_field) { 1930 checkSymbol(pos, intf.tsym); 1931 } 1932 } 1933 if (c.owner.kind == TYP) { 1934 checkSymbol(pos, c.owner); 1935 } 1936 } 1937 } finally { 1938 seenClasses = seenClasses.tail; 1939 } 1940 } 1941 } 1942 } 1943 1944 /** Check for cyclic references. Issue an error if the 1945 * symbol of the type referred to has a LOCKED flag set. 1946 * 1947 * @param pos Position to be used for error reporting. 1948 * @param t The type referred to. 1949 */ 1950 void checkNonCyclic(DiagnosticPosition pos, Type t) { 1951 checkNonCyclicInternal(pos, t); 1952 } 1953 1954 1955 void checkNonCyclic(DiagnosticPosition pos, TypeVar t) { 1956 checkNonCyclic1(pos, t, List.<TypeVar>nil()); 1957 } 1958 1959 private void checkNonCyclic1(DiagnosticPosition pos, Type t, List<TypeVar> seen) { 1960 final TypeVar tv; 1961 if (t.tag == TYPEVAR && (t.tsym.flags() & UNATTRIBUTED) != 0) 1962 return; 1963 if (seen.contains(t)) { 1964 tv = (TypeVar)t; 1965 tv.bound = types.createErrorType(t); 1966 log.error(pos, "cyclic.inheritance", t); 1967 } else if (t.tag == TYPEVAR) { 1968 tv = (TypeVar)t; 1969 seen = seen.prepend(tv); 1970 for (Type b : types.getBounds(tv)) 1971 checkNonCyclic1(pos, b, seen); 1972 } 1973 } 1974 1975 /** Check for cyclic references. Issue an error if the 1976 * symbol of the type referred to has a LOCKED flag set. 1977 * 1978 * @param pos Position to be used for error reporting. 1979 * @param t The type referred to. 1980 * @returns True if the check completed on all attributed classes 1981 */ 1982 private boolean checkNonCyclicInternal(DiagnosticPosition pos, Type t) { 1983 boolean complete = true; // was the check complete? 1984 //- System.err.println("checkNonCyclicInternal("+t+");");//DEBUG 1985 Symbol c = t.tsym; 1986 if ((c.flags_field & ACYCLIC) != 0) return true; 1987 1988 if ((c.flags_field & LOCKED) != 0) { 1989 noteCyclic(pos, (ClassSymbol)c); 1990 } else if (!c.type.isErroneous()) { 1991 try { 1992 c.flags_field |= LOCKED; 1993 if (c.type.tag == CLASS) { 1994 ClassType clazz = (ClassType)c.type; 1995 if (clazz.interfaces_field != null) 1996 for (List<Type> l=clazz.interfaces_field; l.nonEmpty(); l=l.tail) 1997 complete &= checkNonCyclicInternal(pos, l.head); 1998 if (clazz.supertype_field != null) { 1999 Type st = clazz.supertype_field; 2000 if (st != null && st.tag == CLASS) 2001 complete &= checkNonCyclicInternal(pos, st); 2002 } 2003 if (c.owner.kind == TYP) 2004 complete &= checkNonCyclicInternal(pos, c.owner.type); 2005 } 2006 } finally { 2007 c.flags_field &= ~LOCKED; 2008 } 2009 } 2010 if (complete) 2011 complete = ((c.flags_field & UNATTRIBUTED) == 0) && c.completer == null; 2012 if (complete) c.flags_field |= ACYCLIC; 2013 return complete; 2014 } 2015 2016 /** Note that we found an inheritance cycle. */ 2017 private void noteCyclic(DiagnosticPosition pos, ClassSymbol c) { 2018 log.error(pos, "cyclic.inheritance", c); 2019 for (List<Type> l=types.interfaces(c.type); l.nonEmpty(); l=l.tail) 2020 l.head = types.createErrorType((ClassSymbol)l.head.tsym, Type.noType); 2021 Type st = types.supertype(c.type); 2022 if (st.tag == CLASS) 2023 ((ClassType)c.type).supertype_field = types.createErrorType((ClassSymbol)st.tsym, Type.noType); 2024 c.type = types.createErrorType(c, c.type); 2025 c.flags_field |= ACYCLIC; 2026 } 2027 2028 /** Check that all methods which implement some 2029 * method conform to the method they implement. 2030 * @param tree The class definition whose members are checked. 2031 */ 2032 void checkImplementations(JCClassDecl tree) { 2033 checkImplementations(tree, tree.sym); 2034 } 2035 //where 2036 /** Check that all methods which implement some 2037 * method in `ic' conform to the method they implement. 2038 */ 2039 void checkImplementations(JCClassDecl tree, ClassSymbol ic) { 2040 ClassSymbol origin = tree.sym; 2041 for (List<Type> l = types.closure(ic.type); l.nonEmpty(); l = l.tail) { 2042 ClassSymbol lc = (ClassSymbol)l.head.tsym; 2043 if ((allowGenerics || origin != lc) && (lc.flags() & ABSTRACT) != 0) { 2044 for (Scope.Entry e=lc.members().elems; e != null; e=e.sibling) { 2045 if (e.sym.kind == MTH && 2046 (e.sym.flags() & (STATIC|ABSTRACT)) == ABSTRACT) { 2047 MethodSymbol absmeth = (MethodSymbol)e.sym; 2048 MethodSymbol implmeth = absmeth.implementation(origin, types, false); 2049 if (implmeth != null && implmeth != absmeth && 2050 (implmeth.owner.flags() & INTERFACE) == 2051 (origin.flags() & INTERFACE)) { 2052 // don't check if implmeth is in a class, yet 2053 // origin is an interface. This case arises only 2054 // if implmeth is declared in Object. The reason is 2055 // that interfaces really don't inherit from 2056 // Object it's just that the compiler represents 2057 // things that way. 2058 checkOverride(tree, implmeth, absmeth, origin); 2059 } 2060 } 2061 } 2062 } 2063 } 2064 } 2065 2066 /** Check that all abstract methods implemented by a class are 2067 * mutually compatible. 2068 * @param pos Position to be used for error reporting. 2069 * @param c The class whose interfaces are checked. 2070 */ 2071 void checkCompatibleSupertypes(DiagnosticPosition pos, Type c) { 2072 List<Type> supertypes = types.interfaces(c); 2073 Type supertype = types.supertype(c); 2074 if (supertype.tag == CLASS && 2075 (supertype.tsym.flags() & ABSTRACT) != 0) 2076 supertypes = supertypes.prepend(supertype); 2077 for (List<Type> l = supertypes; l.nonEmpty(); l = l.tail) { 2078 if (allowGenerics && !l.head.getTypeArguments().isEmpty() && 2079 !checkCompatibleAbstracts(pos, l.head, l.head, c)) 2080 return; 2081 for (List<Type> m = supertypes; m != l; m = m.tail) 2082 if (!checkCompatibleAbstracts(pos, l.head, m.head, c)) 2083 return; 2084 } 2085 checkCompatibleConcretes(pos, c); 2086 } 2087 2088 void checkConflicts(DiagnosticPosition pos, Symbol sym, TypeSymbol c) { 2089 for (Type ct = c.type; ct != Type.noType ; ct = types.supertype(ct)) { 2090 for (Scope.Entry e = ct.tsym.members().lookup(sym.name); e.scope == ct.tsym.members(); e = e.next()) { 2091 // VM allows methods and variables with differing types 2092 if (sym.kind == e.sym.kind && 2093 types.isSameType(types.erasure(sym.type), types.erasure(e.sym.type)) && 2094 sym != e.sym && 2095 (sym.flags() & Flags.SYNTHETIC) != (e.sym.flags() & Flags.SYNTHETIC) && 2096 (sym.flags() & IPROXY) == 0 && (e.sym.flags() & IPROXY) == 0 && 2097 (sym.flags() & BRIDGE) == 0 && (e.sym.flags() & BRIDGE) == 0) { 2098 syntheticError(pos, (e.sym.flags() & SYNTHETIC) == 0 ? e.sym : sym); 2099 return; 2100 } 2101 } 2102 } 2103 } 2104 2105 /** Check that all non-override equivalent methods accessible from 'site' 2106 * are mutually compatible (JLS 8.4.8/9.4.1). 2107 * 2108 * @param pos Position to be used for error reporting. 2109 * @param site The class whose methods are checked. 2110 * @param sym The method symbol to be checked. 2111 */ 2112 void checkOverrideClashes(DiagnosticPosition pos, Type site, MethodSymbol sym) { 2113 ClashFilter cf = new ClashFilter(site); 2114 //for each method m1 that is a member of 'site'... 2115 for (Symbol s1 : types.membersClosure(site, false).getElementsByName(sym.name, cf)) { 2116 //...find another method m2 that is overridden (directly or indirectly) 2117 //by method 'sym' in 'site' 2118 for (Symbol s2 : types.membersClosure(site, false).getElementsByName(sym.name, cf)) { 2119 if (s1 == s2 || !sym.overrides(s2, site.tsym, types, false)) continue; 2120 //if (i) the signature of 'sym' is not a subsignature of m1 (seen as 2121 //a member of 'site') and (ii) m1 has the same erasure as m2, issue an error 2122 if (!types.isSubSignature(sym.type, types.memberType(site, s1), false) && 2123 types.hasSameArgs(s1.erasure(types), s2.erasure(types))) { 2124 sym.flags_field |= CLASH; 2125 String key = s2 == sym ? 2126 "name.clash.same.erasure.no.override" : 2127 "name.clash.same.erasure.no.override.1"; 2128 log.error(pos, 2129 key, 2130 sym, sym.location(), 2131 s1, s1.location(), 2132 s2, s2.location()); 2133 return; 2134 } 2135 } 2136 } 2137 } 2138 2139 2140 2141 /** Check that all static methods accessible from 'site' are 2142 * mutually compatible (JLS 8.4.8). 2143 * 2144 * @param pos Position to be used for error reporting. 2145 * @param site The class whose methods are checked. 2146 * @param sym The method symbol to be checked. 2147 */ 2148 void checkHideClashes(DiagnosticPosition pos, Type site, MethodSymbol sym) { 2149 ClashFilter cf = new ClashFilter(site); 2150 //for each method m1 that is a member of 'site'... 2151 for (Symbol s : types.membersClosure(site, true).getElementsByName(sym.name, cf)) { 2152 //if (i) the signature of 'sym' is not a subsignature of m1 (seen as 2153 //a member of 'site') and (ii) 'sym' has the same erasure as m1, issue an error 2154 if (!types.isSubSignature(sym.type, types.memberType(site, s), false) && 2155 types.hasSameArgs(s.erasure(types), sym.erasure(types))) { 2156 log.error(pos, 2157 "name.clash.same.erasure.no.hide", 2158 sym, sym.location(), 2159 s, s.location()); 2160 return; 2161 } 2162 } 2163 } 2164 2165 //where 2166 private class ClashFilter implements Filter<Symbol> { 2167 2168 Type site; 2169 2170 ClashFilter(Type site) { 2171 this.site = site; 2172 } 2173 2174 boolean shouldSkip(Symbol s) { 2175 return (s.flags() & CLASH) != 0 && 2176 s.owner == site.tsym; 2177 } 2178 2179 public boolean accepts(Symbol s) { 2180 return s.kind == MTH && 2181 (s.flags() & SYNTHETIC) == 0 && 2182 !shouldSkip(s) && 2183 s.isInheritedIn(site.tsym, types) && 2184 !s.isConstructor(); 2185 } 2186 } 2187 2188 /** Report a conflict between a user symbol and a synthetic symbol. 2189 */ 2190 private void syntheticError(DiagnosticPosition pos, Symbol sym) { 2191 if (!sym.type.isErroneous()) { 2192 if (warnOnSyntheticConflicts) { 2193 log.warning(pos, "synthetic.name.conflict", sym, sym.location()); 2194 } 2195 else { 2196 log.error(pos, "synthetic.name.conflict", sym, sym.location()); 2197 } 2198 } 2199 } 2200 2201 /** Check that class c does not implement directly or indirectly 2202 * the same parameterized interface with two different argument lists. 2203 * @param pos Position to be used for error reporting. 2204 * @param type The type whose interfaces are checked. 2205 */ 2206 void checkClassBounds(DiagnosticPosition pos, Type type) { 2207 checkClassBounds(pos, new HashMap<TypeSymbol,Type>(), type); 2208 } 2209 //where 2210 /** Enter all interfaces of type `type' into the hash table `seensofar' 2211 * with their class symbol as key and their type as value. Make 2212 * sure no class is entered with two different types. 2213 */ 2214 void checkClassBounds(DiagnosticPosition pos, 2215 Map<TypeSymbol,Type> seensofar, 2216 Type type) { 2217 if (type.isErroneous()) return; 2218 for (List<Type> l = types.interfaces(type); l.nonEmpty(); l = l.tail) { 2219 Type it = l.head; 2220 Type oldit = seensofar.put(it.tsym, it); 2221 if (oldit != null) { 2222 List<Type> oldparams = oldit.allparams(); 2223 List<Type> newparams = it.allparams(); 2224 if (!types.containsTypeEquivalent(oldparams, newparams)) 2225 log.error(pos, "cant.inherit.diff.arg", 2226 it.tsym, Type.toString(oldparams), 2227 Type.toString(newparams)); 2228 } 2229 checkClassBounds(pos, seensofar, it); 2230 } 2231 Type st = types.supertype(type); 2232 if (st != null) checkClassBounds(pos, seensofar, st); 2233 } 2234 2235 /** Enter interface into into set. 2236 * If it existed already, issue a "repeated interface" error. 2237 */ 2238 void checkNotRepeated(DiagnosticPosition pos, Type it, Set<Type> its) { 2239 if (its.contains(it)) 2240 log.error(pos, "repeated.interface"); 2241 else { 2242 its.add(it); 2243 } 2244 } 2245 2246 /* ************************************************************************* 2247 * Check annotations 2248 **************************************************************************/ 2249 2250 /** 2251 * Recursively validate annotations values 2252 */ 2253 void validateAnnotationTree(JCTree tree) { 2254 class AnnotationValidator extends TreeScanner { 2255 @Override 2256 public void visitAnnotation(JCAnnotation tree) { 2257 if (!tree.type.isErroneous()) { 2258 super.visitAnnotation(tree); 2259 validateAnnotation(tree); 2260 } 2261 } 2262 } 2263 tree.accept(new AnnotationValidator()); 2264 } 2265 2266 /** Annotation types are restricted to primitives, String, an 2267 * enum, an annotation, Class, Class<?>, Class<? extends 2268 * Anything>, arrays of the preceding. 2269 */ 2270 void validateAnnotationType(JCTree restype) { 2271 // restype may be null if an error occurred, so don't bother validating it 2272 if (restype != null) { 2273 validateAnnotationType(restype.pos(), restype.type); 2274 } 2275 } 2276 2277 void validateAnnotationType(DiagnosticPosition pos, Type type) { 2278 if (type.isPrimitive()) return; 2279 if (types.isSameType(type, syms.stringType)) return; 2280 if ((type.tsym.flags() & Flags.ENUM) != 0) return; 2281 if ((type.tsym.flags() & Flags.ANNOTATION) != 0) return; 2282 if (types.lowerBound(type).tsym == syms.classType.tsym) return; 2283 if (types.isArray(type) && !types.isArray(types.elemtype(type))) { 2284 validateAnnotationType(pos, types.elemtype(type)); 2285 return; 2286 } 2287 log.error(pos, "invalid.annotation.member.type"); 2288 } 2289 2290 /** 2291 * "It is also a compile-time error if any method declared in an 2292 * annotation type has a signature that is override-equivalent to 2293 * that of any public or protected method declared in class Object 2294 * or in the interface annotation.Annotation." 2295 * 2296 * @jls 9.6 Annotation Types 2297 */ 2298 void validateAnnotationMethod(DiagnosticPosition pos, MethodSymbol m) { 2299 for (Type sup = syms.annotationType; sup.tag == CLASS; sup = types.supertype(sup)) { 2300 Scope s = sup.tsym.members(); 2301 for (Scope.Entry e = s.lookup(m.name); e.scope != null; e = e.next()) { 2302 if (e.sym.kind == MTH && 2303 (e.sym.flags() & (PUBLIC | PROTECTED)) != 0 && 2304 types.overrideEquivalent(m.type, e.sym.type)) 2305 log.error(pos, "intf.annotation.member.clash", e.sym, sup); 2306 } 2307 } 2308 } 2309 2310 /** Check the annotations of a symbol. 2311 */ 2312 public void validateAnnotations(List<JCAnnotation> annotations, Symbol s) { 2313 if (skipAnnotations) return; 2314 for (JCAnnotation a : annotations) 2315 validateAnnotation(a, s); 2316 } 2317 2318 /** Check an annotation of a symbol. 2319 */ 2320 public void validateAnnotation(JCAnnotation a, Symbol s) { 2321 validateAnnotationTree(a); 2322 2323 if (!annotationApplicable(a, s)) 2324 log.error(a.pos(), "annotation.type.not.applicable"); 2325 2326 if (a.annotationType.type.tsym == syms.overrideType.tsym) { 2327 if (!isOverrider(s)) 2328 log.error(a.pos(), "method.does.not.override.superclass"); 2329 } 2330 } 2331 2332 /** Is s a method symbol that overrides a method in a superclass? */ 2333 boolean isOverrider(Symbol s) { 2334 if (s.kind != MTH || s.isStatic()) 2335 return false; 2336 MethodSymbol m = (MethodSymbol)s; 2337 TypeSymbol owner = (TypeSymbol)m.owner; 2338 for (Type sup : types.closure(owner.type)) { 2339 if (sup == owner.type) 2340 continue; // skip "this" 2341 Scope scope = sup.tsym.members(); 2342 for (Scope.Entry e = scope.lookup(m.name); e.scope != null; e = e.next()) { 2343 if (!e.sym.isStatic() && m.overrides(e.sym, owner, types, true)) 2344 return true; 2345 } 2346 } 2347 return false; 2348 } 2349 2350 /** Is the annotation applicable to the symbol? */ 2351 boolean annotationApplicable(JCAnnotation a, Symbol s) { 2352 Attribute.Compound atTarget = 2353 a.annotationType.type.tsym.attribute(syms.annotationTargetType.tsym); 2354 if (atTarget == null) return true; 2355 Attribute atValue = atTarget.member(names.value); 2356 if (!(atValue instanceof Attribute.Array)) return true; // error recovery 2357 Attribute.Array arr = (Attribute.Array) atValue; 2358 for (Attribute app : arr.values) { 2359 if (!(app instanceof Attribute.Enum)) return true; // recovery 2360 Attribute.Enum e = (Attribute.Enum) app; 2361 if (e.value.name == names.TYPE) 2362 { if (s.kind == TYP) return true; } 2363 else if (e.value.name == names.FIELD) 2364 { if (s.kind == VAR && s.owner.kind != MTH) return true; } 2365 else if (e.value.name == names.METHOD) 2366 { if (s.kind == MTH && !s.isConstructor()) return true; } 2367 else if (e.value.name == names.PARAMETER) 2368 { if (s.kind == VAR && 2369 s.owner.kind == MTH && 2370 (s.flags() & PARAMETER) != 0) 2371 return true; 2372 } 2373 else if (e.value.name == names.CONSTRUCTOR) 2374 { if (s.kind == MTH && s.isConstructor()) return true; } 2375 else if (e.value.name == names.LOCAL_VARIABLE) 2376 { if (s.kind == VAR && s.owner.kind == MTH && 2377 (s.flags() & PARAMETER) == 0) 2378 return true; 2379 } 2380 else if (e.value.name == names.ANNOTATION_TYPE) 2381 { if (s.kind == TYP && (s.flags() & ANNOTATION) != 0) 2382 return true; 2383 } 2384 else if (e.value.name == names.PACKAGE) 2385 { if (s.kind == PCK) return true; } 2386 else if (e.value.name == names.TYPE_USE) 2387 { if (s.kind == TYP || 2388 s.kind == VAR || 2389 (s.kind == MTH && !s.isConstructor() && 2390 s.type.getReturnType().tag != VOID)) 2391 return true; 2392 } 2393 else 2394 return true; // recovery 2395 } 2396 return false; 2397 } 2398 2399 /** Check an annotation value. 2400 */ 2401 public void validateAnnotation(JCAnnotation a) { 2402 // collect an inventory of the members (sorted alphabetically) 2403 Set<MethodSymbol> members = new TreeSet<MethodSymbol>(new Comparator<Symbol>() { 2404 public int compare(Symbol t, Symbol t1) { 2405 return t.name.compareTo(t1.name); 2406 } 2407 }); 2408 for (Scope.Entry e = a.annotationType.type.tsym.members().elems; 2409 e != null; 2410 e = e.sibling) 2411 if (e.sym.kind == MTH) 2412 members.add((MethodSymbol) e.sym); 2413 2414 // count them off as they're annotated 2415 for (JCTree arg : a.args) { 2416 if (arg.getTag() != JCTree.ASSIGN) continue; // recovery 2417 JCAssign assign = (JCAssign) arg; 2418 Symbol m = TreeInfo.symbol(assign.lhs); 2419 if (m == null || m.type.isErroneous()) continue; 2420 if (!members.remove(m)) 2421 log.error(assign.lhs.pos(), "duplicate.annotation.member.value", 2422 m.name, a.type); 2423 } 2424 2425 // all the remaining ones better have default values 2426 ListBuffer<Name> missingDefaults = ListBuffer.lb(); 2427 for (MethodSymbol m : members) { 2428 if (m.defaultValue == null && !m.type.isErroneous()) { 2429 missingDefaults.append(m.name); 2430 } 2431 } 2432 if (missingDefaults.nonEmpty()) { 2433 String key = (missingDefaults.size() > 1) 2434 ? "annotation.missing.default.value.1" 2435 : "annotation.missing.default.value"; 2436 log.error(a.pos(), key, a.type, missingDefaults); 2437 } 2438 2439 // special case: java.lang.annotation.Target must not have 2440 // repeated values in its value member 2441 if (a.annotationType.type.tsym != syms.annotationTargetType.tsym || 2442 a.args.tail == null) 2443 return; 2444 2445 if (a.args.head.getTag() != JCTree.ASSIGN) return; // error recovery 2446 JCAssign assign = (JCAssign) a.args.head; 2447 Symbol m = TreeInfo.symbol(assign.lhs); 2448 if (m.name != names.value) return; 2449 JCTree rhs = assign.rhs; 2450 if (rhs.getTag() != JCTree.NEWARRAY) return; 2451 JCNewArray na = (JCNewArray) rhs; 2452 Set<Symbol> targets = new HashSet<Symbol>(); 2453 for (JCTree elem : na.elems) { 2454 if (!targets.add(TreeInfo.symbol(elem))) { 2455 log.error(elem.pos(), "repeated.annotation.target"); 2456 } 2457 } 2458 } 2459 2460 void checkDeprecatedAnnotation(DiagnosticPosition pos, Symbol s) { 2461 if (allowAnnotations && 2462 lint.isEnabled(LintCategory.DEP_ANN) && 2463 (s.flags() & DEPRECATED) != 0 && 2464 !syms.deprecatedType.isErroneous() && 2465 s.attribute(syms.deprecatedType.tsym) == null) { 2466 log.warning(LintCategory.DEP_ANN, 2467 pos, "missing.deprecated.annotation"); 2468 } 2469 } 2470 2471 void checkDeprecated(final DiagnosticPosition pos, final Symbol other, final Symbol s) { 2472 if ((s.flags() & DEPRECATED) != 0 && 2473 (other.flags() & DEPRECATED) == 0 && 2474 s.outermostClass() != other.outermostClass()) { 2475 deferredLintHandler.report(new DeferredLintHandler.LintLogger() { 2476 @Override 2477 public void report() { 2478 warnDeprecated(pos, s); 2479 } 2480 }); 2481 }; 2482 } 2483 2484 void checkSunAPI(final DiagnosticPosition pos, final Symbol s) { 2485 if ((s.flags() & PROPRIETARY) != 0) { 2486 deferredLintHandler.report(new DeferredLintHandler.LintLogger() { 2487 public void report() { 2488 if (enableSunApiLintControl) 2489 warnSunApi(pos, "sun.proprietary", s); 2490 else 2491 log.strictWarning(pos, "sun.proprietary", s); 2492 } 2493 }); 2494 } 2495 } 2496 2497 /* ************************************************************************* 2498 * Check for recursive annotation elements. 2499 **************************************************************************/ 2500 2501 /** Check for cycles in the graph of annotation elements. 2502 */ 2503 void checkNonCyclicElements(JCClassDecl tree) { 2504 if ((tree.sym.flags_field & ANNOTATION) == 0) return; 2505 Assert.check((tree.sym.flags_field & LOCKED) == 0); 2506 try { 2507 tree.sym.flags_field |= LOCKED; 2508 for (JCTree def : tree.defs) { 2509 if (def.getTag() != JCTree.METHODDEF) continue; 2510 JCMethodDecl meth = (JCMethodDecl)def; 2511 checkAnnotationResType(meth.pos(), meth.restype.type); 2512 } 2513 } finally { 2514 tree.sym.flags_field &= ~LOCKED; 2515 tree.sym.flags_field |= ACYCLIC_ANN; 2516 } 2517 } 2518 2519 void checkNonCyclicElementsInternal(DiagnosticPosition pos, TypeSymbol tsym) { 2520 if ((tsym.flags_field & ACYCLIC_ANN) != 0) 2521 return; 2522 if ((tsym.flags_field & LOCKED) != 0) { 2523 log.error(pos, "cyclic.annotation.element"); 2524 return; 2525 } 2526 try { 2527 tsym.flags_field |= LOCKED; 2528 for (Scope.Entry e = tsym.members().elems; e != null; e = e.sibling) { 2529 Symbol s = e.sym; 2530 if (s.kind != Kinds.MTH) 2531 continue; 2532 checkAnnotationResType(pos, ((MethodSymbol)s).type.getReturnType()); 2533 } 2534 } finally { 2535 tsym.flags_field &= ~LOCKED; 2536 tsym.flags_field |= ACYCLIC_ANN; 2537 } 2538 } 2539 2540 void checkAnnotationResType(DiagnosticPosition pos, Type type) { 2541 switch (type.tag) { 2542 case TypeTags.CLASS: 2543 if ((type.tsym.flags() & ANNOTATION) != 0) 2544 checkNonCyclicElementsInternal(pos, type.tsym); 2545 break; 2546 case TypeTags.ARRAY: 2547 checkAnnotationResType(pos, types.elemtype(type)); 2548 break; 2549 default: 2550 break; // int etc 2551 } 2552 } 2553 2554 /* ************************************************************************* 2555 * Check for cycles in the constructor call graph. 2556 **************************************************************************/ 2557 2558 /** Check for cycles in the graph of constructors calling other 2559 * constructors. 2560 */ 2561 void checkCyclicConstructors(JCClassDecl tree) { 2562 Map<Symbol,Symbol> callMap = new HashMap<Symbol, Symbol>(); 2563 2564 // enter each constructor this-call into the map 2565 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { 2566 JCMethodInvocation app = TreeInfo.firstConstructorCall(l.head); 2567 if (app == null) continue; 2568 JCMethodDecl meth = (JCMethodDecl) l.head; 2569 if (TreeInfo.name(app.meth) == names._this) { 2570 callMap.put(meth.sym, TreeInfo.symbol(app.meth)); 2571 } else { 2572 meth.sym.flags_field |= ACYCLIC; 2573 } 2574 } 2575 2576 // Check for cycles in the map 2577 Symbol[] ctors = new Symbol[0]; 2578 ctors = callMap.keySet().toArray(ctors); 2579 for (Symbol caller : ctors) { 2580 checkCyclicConstructor(tree, caller, callMap); 2581 } 2582 } 2583 2584 /** Look in the map to see if the given constructor is part of a 2585 * call cycle. 2586 */ 2587 private void checkCyclicConstructor(JCClassDecl tree, Symbol ctor, 2588 Map<Symbol,Symbol> callMap) { 2589 if (ctor != null && (ctor.flags_field & ACYCLIC) == 0) { 2590 if ((ctor.flags_field & LOCKED) != 0) { 2591 log.error(TreeInfo.diagnosticPositionFor(ctor, tree), 2592 "recursive.ctor.invocation"); 2593 } else { 2594 ctor.flags_field |= LOCKED; 2595 checkCyclicConstructor(tree, callMap.remove(ctor), callMap); 2596 ctor.flags_field &= ~LOCKED; 2597 } 2598 ctor.flags_field |= ACYCLIC; 2599 } 2600 } 2601 2602 /* ************************************************************************* 2603 * Miscellaneous 2604 **************************************************************************/ 2605 2606 /** 2607 * Return the opcode of the operator but emit an error if it is an 2608 * error. 2609 * @param pos position for error reporting. 2610 * @param operator an operator 2611 * @param tag a tree tag 2612 * @param left type of left hand side 2613 * @param right type of right hand side 2614 */ 2615 int checkOperator(DiagnosticPosition pos, 2616 OperatorSymbol operator, 2617 int tag, 2618 Type left, 2619 Type right) { 2620 if (operator.opcode == ByteCodes.error) { 2621 log.error(pos, 2622 "operator.cant.be.applied.1", 2623 treeinfo.operatorName(tag), 2624 left, right); 2625 } 2626 return operator.opcode; 2627 } 2628 2629 2630 /** 2631 * Check for division by integer constant zero 2632 * @param pos Position for error reporting. 2633 * @param operator The operator for the expression 2634 * @param operand The right hand operand for the expression 2635 */ 2636 void checkDivZero(DiagnosticPosition pos, Symbol operator, Type operand) { 2637 if (operand.constValue() != null 2638 && lint.isEnabled(LintCategory.DIVZERO) 2639 && operand.tag <= LONG 2640 && ((Number) (operand.constValue())).longValue() == 0) { 2641 int opc = ((OperatorSymbol)operator).opcode; 2642 if (opc == ByteCodes.idiv || opc == ByteCodes.imod 2643 || opc == ByteCodes.ldiv || opc == ByteCodes.lmod) { 2644 log.warning(LintCategory.DIVZERO, pos, "div.zero"); 2645 } 2646 } 2647 } 2648 2649 /** 2650 * Check for empty statements after if 2651 */ 2652 void checkEmptyIf(JCIf tree) { 2653 if (tree.thenpart.getTag() == JCTree.SKIP && tree.elsepart == null && lint.isEnabled(LintCategory.EMPTY)) 2654 log.warning(LintCategory.EMPTY, tree.thenpart.pos(), "empty.if"); 2655 } 2656 2657 /** Check that symbol is unique in given scope. 2658 * @param pos Position for error reporting. 2659 * @param sym The symbol. 2660 * @param s The scope. 2661 */ 2662 boolean checkUnique(DiagnosticPosition pos, Symbol sym, Scope s) { 2663 if (sym.type.isErroneous()) 2664 return true; 2665 if (sym.owner.name == names.any) return false; 2666 for (Scope.Entry e = s.lookup(sym.name); e.scope == s; e = e.next()) { 2667 if (sym != e.sym && 2668 (e.sym.flags() & CLASH) == 0 && 2669 sym.kind == e.sym.kind && 2670 sym.name != names.error && 2671 (sym.kind != MTH || types.hasSameArgs(types.erasure(sym.type), types.erasure(e.sym.type)))) { 2672 if ((sym.flags() & VARARGS) != (e.sym.flags() & VARARGS)) { 2673 varargsDuplicateError(pos, sym, e.sym); 2674 return true; 2675 } else if (sym.kind == MTH && !types.hasSameArgs(sym.type, e.sym.type, false)) { 2676 duplicateErasureError(pos, sym, e.sym); 2677 sym.flags_field |= CLASH; 2678 return true; 2679 } else { 2680 duplicateError(pos, e.sym); 2681 return false; 2682 } 2683 } 2684 } 2685 return true; 2686 } 2687 2688 /** Report duplicate declaration error. 2689 */ 2690 void duplicateErasureError(DiagnosticPosition pos, Symbol sym1, Symbol sym2) { 2691 if (!sym1.type.isErroneous() && !sym2.type.isErroneous()) { 2692 log.error(pos, "name.clash.same.erasure", sym1, sym2); 2693 } 2694 } 2695 2696 /** Check that single-type import is not already imported or top-level defined, 2697 * but make an exception for two single-type imports which denote the same type. 2698 * @param pos Position for error reporting. 2699 * @param sym The symbol. 2700 * @param s The scope 2701 */ 2702 boolean checkUniqueImport(DiagnosticPosition pos, Symbol sym, Scope s) { 2703 return checkUniqueImport(pos, sym, s, false); 2704 } 2705 2706 /** Check that static single-type import is not already imported or top-level defined, 2707 * but make an exception for two single-type imports which denote the same type. 2708 * @param pos Position for error reporting. 2709 * @param sym The symbol. 2710 * @param s The scope 2711 * @param staticImport Whether or not this was a static import 2712 */ 2713 boolean checkUniqueStaticImport(DiagnosticPosition pos, Symbol sym, Scope s) { 2714 return checkUniqueImport(pos, sym, s, true); 2715 } 2716 2717 /** Check that single-type import is not already imported or top-level defined, 2718 * but make an exception for two single-type imports which denote the same type. 2719 * @param pos Position for error reporting. 2720 * @param sym The symbol. 2721 * @param s The scope. 2722 * @param staticImport Whether or not this was a static import 2723 */ 2724 private boolean checkUniqueImport(DiagnosticPosition pos, Symbol sym, Scope s, boolean staticImport) { 2725 for (Scope.Entry e = s.lookup(sym.name); e.scope != null; e = e.next()) { 2726 // is encountered class entered via a class declaration? 2727 boolean isClassDecl = e.scope == s; 2728 if ((isClassDecl || sym != e.sym) && 2729 sym.kind == e.sym.kind && 2730 sym.name != names.error) { 2731 if (!e.sym.type.isErroneous()) { 2732 String what = e.sym.toString(); 2733 if (!isClassDecl) { 2734 if (staticImport) 2735 log.error(pos, "already.defined.static.single.import", what); 2736 else 2737 log.error(pos, "already.defined.single.import", what); 2738 } 2739 else if (sym != e.sym) 2740 log.error(pos, "already.defined.this.unit", what); 2741 } 2742 return false; 2743 } 2744 } 2745 return true; 2746 } 2747 2748 /** Check that a qualified name is in canonical form (for import decls). 2749 */ 2750 public void checkCanonical(JCTree tree) { 2751 if (!isCanonical(tree)) 2752 log.error(tree.pos(), "import.requires.canonical", 2753 TreeInfo.symbol(tree)); 2754 } 2755 // where 2756 private boolean isCanonical(JCTree tree) { 2757 while (tree.getTag() == JCTree.SELECT) { 2758 JCFieldAccess s = (JCFieldAccess) tree; 2759 if (s.sym.owner != TreeInfo.symbol(s.selected)) 2760 return false; 2761 tree = s.selected; 2762 } 2763 return true; 2764 } 2765 2766 private class ConversionWarner extends Warner { 2767 final String uncheckedKey; 2768 final Type found; 2769 final Type expected; 2770 public ConversionWarner(DiagnosticPosition pos, String uncheckedKey, Type found, Type expected) { 2771 super(pos); 2772 this.uncheckedKey = uncheckedKey; 2773 this.found = found; 2774 this.expected = expected; 2775 } 2776 2777 @Override 2778 public void warn(LintCategory lint) { 2779 boolean warned = this.warned; 2780 super.warn(lint); 2781 if (warned) return; // suppress redundant diagnostics 2782 switch (lint) { 2783 case UNCHECKED: 2784 Check.this.warnUnchecked(pos(), "prob.found.req", diags.fragment(uncheckedKey), found, expected); 2785 break; 2786 case VARARGS: 2787 if (method != null && 2788 method.attribute(syms.trustMeType.tsym) != null && 2789 isTrustMeAllowedOnMethod(method) && 2790 !types.isReifiable(method.type.getParameterTypes().last())) { 2791 Check.this.warnUnsafeVararg(pos(), "varargs.unsafe.use.varargs.param", method.params.last()); 2792 } 2793 break; 2794 default: 2795 throw new AssertionError("Unexpected lint: " + lint); 2796 } 2797 } 2798 } 2799 2800 public Warner castWarner(DiagnosticPosition pos, Type found, Type expected) { 2801 return new ConversionWarner(pos, "unchecked.cast.to.type", found, expected); 2802 } 2803 2804 public Warner convertWarner(DiagnosticPosition pos, Type found, Type expected) { 2805 return new ConversionWarner(pos, "unchecked.assign", found, expected); 2806 } 2807 }