1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,2123 @@ 1.4 +/* 1.5 + * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Sun designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Sun in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.25 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.26 + * have any questions. 1.27 + */ 1.28 + 1.29 +package com.sun.tools.javac.comp; 1.30 + 1.31 +import java.util.*; 1.32 +import java.util.Set; 1.33 + 1.34 +import com.sun.tools.javac.code.*; 1.35 +import com.sun.tools.javac.jvm.*; 1.36 +import com.sun.tools.javac.tree.*; 1.37 +import com.sun.tools.javac.util.*; 1.38 +import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 1.39 +import com.sun.tools.javac.util.List; 1.40 + 1.41 +import com.sun.tools.javac.tree.JCTree.*; 1.42 +import com.sun.tools.javac.code.Lint; 1.43 +import com.sun.tools.javac.code.Lint.LintCategory; 1.44 +import com.sun.tools.javac.code.Type.*; 1.45 +import com.sun.tools.javac.code.Symbol.*; 1.46 + 1.47 +import static com.sun.tools.javac.code.Flags.*; 1.48 +import static com.sun.tools.javac.code.Kinds.*; 1.49 +import static com.sun.tools.javac.code.TypeTags.*; 1.50 + 1.51 +/** Type checking helper class for the attribution phase. 1.52 + * 1.53 + * <p><b>This is NOT part of any API supported by Sun Microsystems. If 1.54 + * you write code that depends on this, you do so at your own risk. 1.55 + * This code and its internal interfaces are subject to change or 1.56 + * deletion without notice.</b> 1.57 + */ 1.58 +public class Check { 1.59 + protected static final Context.Key<Check> checkKey = 1.60 + new Context.Key<Check>(); 1.61 + 1.62 + private final Name.Table names; 1.63 + private final Log log; 1.64 + private final Symtab syms; 1.65 + private final Infer infer; 1.66 + private final Target target; 1.67 + private final Source source; 1.68 + private final Types types; 1.69 + private final boolean skipAnnotations; 1.70 + private final TreeInfo treeinfo; 1.71 + 1.72 + // The set of lint options currently in effect. It is initialized 1.73 + // from the context, and then is set/reset as needed by Attr as it 1.74 + // visits all the various parts of the trees during attribution. 1.75 + private Lint lint; 1.76 + 1.77 + public static Check instance(Context context) { 1.78 + Check instance = context.get(checkKey); 1.79 + if (instance == null) 1.80 + instance = new Check(context); 1.81 + return instance; 1.82 + } 1.83 + 1.84 + protected Check(Context context) { 1.85 + context.put(checkKey, this); 1.86 + 1.87 + names = Name.Table.instance(context); 1.88 + log = Log.instance(context); 1.89 + syms = Symtab.instance(context); 1.90 + infer = Infer.instance(context); 1.91 + this.types = Types.instance(context); 1.92 + Options options = Options.instance(context); 1.93 + target = Target.instance(context); 1.94 + source = Source.instance(context); 1.95 + lint = Lint.instance(context); 1.96 + treeinfo = TreeInfo.instance(context); 1.97 + 1.98 + Source source = Source.instance(context); 1.99 + allowGenerics = source.allowGenerics(); 1.100 + allowAnnotations = source.allowAnnotations(); 1.101 + complexInference = options.get("-complexinference") != null; 1.102 + skipAnnotations = options.get("skipAnnotations") != null; 1.103 + 1.104 + boolean verboseDeprecated = lint.isEnabled(LintCategory.DEPRECATION); 1.105 + boolean verboseUnchecked = lint.isEnabled(LintCategory.UNCHECKED); 1.106 + 1.107 + deprecationHandler = new MandatoryWarningHandler(log,verboseDeprecated, "deprecated"); 1.108 + uncheckedHandler = new MandatoryWarningHandler(log, verboseUnchecked, "unchecked"); 1.109 + } 1.110 + 1.111 + /** Switch: generics enabled? 1.112 + */ 1.113 + boolean allowGenerics; 1.114 + 1.115 + /** Switch: annotations enabled? 1.116 + */ 1.117 + boolean allowAnnotations; 1.118 + 1.119 + /** Switch: -complexinference option set? 1.120 + */ 1.121 + boolean complexInference; 1.122 + 1.123 + /** A table mapping flat names of all compiled classes in this run to their 1.124 + * symbols; maintained from outside. 1.125 + */ 1.126 + public Map<Name,ClassSymbol> compiled = new HashMap<Name, ClassSymbol>(); 1.127 + 1.128 + /** A handler for messages about deprecated usage. 1.129 + */ 1.130 + private MandatoryWarningHandler deprecationHandler; 1.131 + 1.132 + /** A handler for messages about unchecked or unsafe usage. 1.133 + */ 1.134 + private MandatoryWarningHandler uncheckedHandler; 1.135 + 1.136 + 1.137 +/* ************************************************************************* 1.138 + * Errors and Warnings 1.139 + **************************************************************************/ 1.140 + 1.141 + Lint setLint(Lint newLint) { 1.142 + Lint prev = lint; 1.143 + lint = newLint; 1.144 + return prev; 1.145 + } 1.146 + 1.147 + /** Warn about deprecated symbol. 1.148 + * @param pos Position to be used for error reporting. 1.149 + * @param sym The deprecated symbol. 1.150 + */ 1.151 + void warnDeprecated(DiagnosticPosition pos, Symbol sym) { 1.152 + if (!lint.isSuppressed(LintCategory.DEPRECATION)) 1.153 + deprecationHandler.report(pos, "has.been.deprecated", sym, sym.location()); 1.154 + } 1.155 + 1.156 + /** Warn about unchecked operation. 1.157 + * @param pos Position to be used for error reporting. 1.158 + * @param msg A string describing the problem. 1.159 + */ 1.160 + public void warnUnchecked(DiagnosticPosition pos, String msg, Object... args) { 1.161 + if (!lint.isSuppressed(LintCategory.UNCHECKED)) 1.162 + uncheckedHandler.report(pos, msg, args); 1.163 + } 1.164 + 1.165 + /** 1.166 + * Report any deferred diagnostics. 1.167 + */ 1.168 + public void reportDeferredDiagnostics() { 1.169 + deprecationHandler.reportDeferredDiagnostic(); 1.170 + uncheckedHandler.reportDeferredDiagnostic(); 1.171 + } 1.172 + 1.173 + 1.174 + /** Report a failure to complete a class. 1.175 + * @param pos Position to be used for error reporting. 1.176 + * @param ex The failure to report. 1.177 + */ 1.178 + public Type completionError(DiagnosticPosition pos, CompletionFailure ex) { 1.179 + log.error(pos, "cant.access", ex.sym, ex.errmsg); 1.180 + if (ex instanceof ClassReader.BadClassFile) throw new Abort(); 1.181 + else return syms.errType; 1.182 + } 1.183 + 1.184 + /** Report a type error. 1.185 + * @param pos Position to be used for error reporting. 1.186 + * @param problem A string describing the error. 1.187 + * @param found The type that was found. 1.188 + * @param req The type that was required. 1.189 + */ 1.190 + Type typeError(DiagnosticPosition pos, Object problem, Type found, Type req) { 1.191 + log.error(pos, "prob.found.req", 1.192 + problem, found, req); 1.193 + return syms.errType; 1.194 + } 1.195 + 1.196 + Type typeError(DiagnosticPosition pos, String problem, Type found, Type req, Object explanation) { 1.197 + log.error(pos, "prob.found.req.1", problem, found, req, explanation); 1.198 + return syms.errType; 1.199 + } 1.200 + 1.201 + /** Report an error that wrong type tag was found. 1.202 + * @param pos Position to be used for error reporting. 1.203 + * @param required An internationalized string describing the type tag 1.204 + * required. 1.205 + * @param found The type that was found. 1.206 + */ 1.207 + Type typeTagError(DiagnosticPosition pos, Object required, Object found) { 1.208 + log.error(pos, "type.found.req", found, required); 1.209 + return syms.errType; 1.210 + } 1.211 + 1.212 + /** Report an error that symbol cannot be referenced before super 1.213 + * has been called. 1.214 + * @param pos Position to be used for error reporting. 1.215 + * @param sym The referenced symbol. 1.216 + */ 1.217 + void earlyRefError(DiagnosticPosition pos, Symbol sym) { 1.218 + log.error(pos, "cant.ref.before.ctor.called", sym); 1.219 + } 1.220 + 1.221 + /** Report duplicate declaration error. 1.222 + */ 1.223 + void duplicateError(DiagnosticPosition pos, Symbol sym) { 1.224 + if (!sym.type.isErroneous()) { 1.225 + log.error(pos, "already.defined", sym, sym.location()); 1.226 + } 1.227 + } 1.228 + 1.229 + /** Report array/varargs duplicate declaration 1.230 + */ 1.231 + void varargsDuplicateError(DiagnosticPosition pos, Symbol sym1, Symbol sym2) { 1.232 + if (!sym1.type.isErroneous() && !sym2.type.isErroneous()) { 1.233 + log.error(pos, "array.and.varargs", sym1, sym2, sym2.location()); 1.234 + } 1.235 + } 1.236 + 1.237 +/* ************************************************************************ 1.238 + * duplicate declaration checking 1.239 + *************************************************************************/ 1.240 + 1.241 + /** Check that variable does not hide variable with same name in 1.242 + * immediately enclosing local scope. 1.243 + * @param pos Position for error reporting. 1.244 + * @param v The symbol. 1.245 + * @param s The scope. 1.246 + */ 1.247 + void checkTransparentVar(DiagnosticPosition pos, VarSymbol v, Scope s) { 1.248 + if (s.next != null) { 1.249 + for (Scope.Entry e = s.next.lookup(v.name); 1.250 + e.scope != null && e.sym.owner == v.owner; 1.251 + e = e.next()) { 1.252 + if (e.sym.kind == VAR && 1.253 + (e.sym.owner.kind & (VAR | MTH)) != 0 && 1.254 + v.name != names.error) { 1.255 + duplicateError(pos, e.sym); 1.256 + return; 1.257 + } 1.258 + } 1.259 + } 1.260 + } 1.261 + 1.262 + /** Check that a class or interface does not hide a class or 1.263 + * interface with same name in immediately enclosing local scope. 1.264 + * @param pos Position for error reporting. 1.265 + * @param c The symbol. 1.266 + * @param s The scope. 1.267 + */ 1.268 + void checkTransparentClass(DiagnosticPosition pos, ClassSymbol c, Scope s) { 1.269 + if (s.next != null) { 1.270 + for (Scope.Entry e = s.next.lookup(c.name); 1.271 + e.scope != null && e.sym.owner == c.owner; 1.272 + e = e.next()) { 1.273 + if (e.sym.kind == TYP && 1.274 + (e.sym.owner.kind & (VAR | MTH)) != 0 && 1.275 + c.name != names.error) { 1.276 + duplicateError(pos, e.sym); 1.277 + return; 1.278 + } 1.279 + } 1.280 + } 1.281 + } 1.282 + 1.283 + /** Check that class does not have the same name as one of 1.284 + * its enclosing classes, or as a class defined in its enclosing scope. 1.285 + * return true if class is unique in its enclosing scope. 1.286 + * @param pos Position for error reporting. 1.287 + * @param name The class name. 1.288 + * @param s The enclosing scope. 1.289 + */ 1.290 + boolean checkUniqueClassName(DiagnosticPosition pos, Name name, Scope s) { 1.291 + for (Scope.Entry e = s.lookup(name); e.scope == s; e = e.next()) { 1.292 + if (e.sym.kind == TYP && e.sym.name != names.error) { 1.293 + duplicateError(pos, e.sym); 1.294 + return false; 1.295 + } 1.296 + } 1.297 + for (Symbol sym = s.owner; sym != null; sym = sym.owner) { 1.298 + if (sym.kind == TYP && sym.name == name && sym.name != names.error) { 1.299 + duplicateError(pos, sym); 1.300 + return true; 1.301 + } 1.302 + } 1.303 + return true; 1.304 + } 1.305 + 1.306 +/* ************************************************************************* 1.307 + * Class name generation 1.308 + **************************************************************************/ 1.309 + 1.310 + /** Return name of local class. 1.311 + * This is of the form <enclClass> $ n <classname> 1.312 + * where 1.313 + * enclClass is the flat name of the enclosing class, 1.314 + * classname is the simple name of the local class 1.315 + */ 1.316 + Name localClassName(ClassSymbol c) { 1.317 + for (int i=1; ; i++) { 1.318 + Name flatname = names. 1.319 + fromString("" + c.owner.enclClass().flatname + 1.320 + target.syntheticNameChar() + i + 1.321 + c.name); 1.322 + if (compiled.get(flatname) == null) return flatname; 1.323 + } 1.324 + } 1.325 + 1.326 +/* ************************************************************************* 1.327 + * Type Checking 1.328 + **************************************************************************/ 1.329 + 1.330 + /** Check that a given type is assignable to a given proto-type. 1.331 + * If it is, return the type, otherwise return errType. 1.332 + * @param pos Position to be used for error reporting. 1.333 + * @param found The type that was found. 1.334 + * @param req The type that was required. 1.335 + */ 1.336 + Type checkType(DiagnosticPosition pos, Type found, Type req) { 1.337 + if (req.tag == ERROR) 1.338 + return req; 1.339 + if (found.tag == FORALL) 1.340 + return instantiatePoly(pos, (ForAll)found, req, convertWarner(pos, found, req)); 1.341 + if (req.tag == NONE) 1.342 + return found; 1.343 + if (types.isAssignable(found, req, convertWarner(pos, found, req))) 1.344 + return found; 1.345 + if (found.tag <= DOUBLE && req.tag <= DOUBLE) 1.346 + return typeError(pos, JCDiagnostic.fragment("possible.loss.of.precision"), found, req); 1.347 + if (found.isSuperBound()) { 1.348 + log.error(pos, "assignment.from.super-bound", found); 1.349 + return syms.errType; 1.350 + } 1.351 + if (req.isExtendsBound()) { 1.352 + log.error(pos, "assignment.to.extends-bound", req); 1.353 + return syms.errType; 1.354 + } 1.355 + return typeError(pos, JCDiagnostic.fragment("incompatible.types"), found, req); 1.356 + } 1.357 + 1.358 + /** Instantiate polymorphic type to some prototype, unless 1.359 + * prototype is `anyPoly' in which case polymorphic type 1.360 + * is returned unchanged. 1.361 + */ 1.362 + Type instantiatePoly(DiagnosticPosition pos, ForAll t, Type pt, Warner warn) { 1.363 + if (pt == Infer.anyPoly && complexInference) { 1.364 + return t; 1.365 + } else if (pt == Infer.anyPoly || pt.tag == NONE) { 1.366 + Type newpt = t.qtype.tag <= VOID ? t.qtype : syms.objectType; 1.367 + return instantiatePoly(pos, t, newpt, warn); 1.368 + } else if (pt.tag == ERROR) { 1.369 + return pt; 1.370 + } else { 1.371 + try { 1.372 + return infer.instantiateExpr(t, pt, warn); 1.373 + } catch (Infer.NoInstanceException ex) { 1.374 + if (ex.isAmbiguous) { 1.375 + JCDiagnostic d = ex.getDiagnostic(); 1.376 + log.error(pos, 1.377 + "undetermined.type" + (d!=null ? ".1" : ""), 1.378 + t, d); 1.379 + return syms.errType; 1.380 + } else { 1.381 + JCDiagnostic d = ex.getDiagnostic(); 1.382 + return typeError(pos, 1.383 + JCDiagnostic.fragment("incompatible.types" + (d!=null ? ".1" : ""), d), 1.384 + t, pt); 1.385 + } 1.386 + } 1.387 + } 1.388 + } 1.389 + 1.390 + /** Check that a given type can be cast to a given target type. 1.391 + * Return the result of the cast. 1.392 + * @param pos Position to be used for error reporting. 1.393 + * @param found The type that is being cast. 1.394 + * @param req The target type of the cast. 1.395 + */ 1.396 + Type checkCastable(DiagnosticPosition pos, Type found, Type req) { 1.397 + if (found.tag == FORALL) { 1.398 + instantiatePoly(pos, (ForAll) found, req, castWarner(pos, found, req)); 1.399 + return req; 1.400 + } else if (types.isCastable(found, req, castWarner(pos, found, req))) { 1.401 + return req; 1.402 + } else { 1.403 + return typeError(pos, 1.404 + JCDiagnostic.fragment("inconvertible.types"), 1.405 + found, req); 1.406 + } 1.407 + } 1.408 +//where 1.409 + /** Is type a type variable, or a (possibly multi-dimensional) array of 1.410 + * type variables? 1.411 + */ 1.412 + boolean isTypeVar(Type t) { 1.413 + return t.tag == TYPEVAR || t.tag == ARRAY && isTypeVar(types.elemtype(t)); 1.414 + } 1.415 + 1.416 + /** Check that a type is within some bounds. 1.417 + * 1.418 + * Used in TypeApply to verify that, e.g., X in V<X> is a valid 1.419 + * type argument. 1.420 + * @param pos Position to be used for error reporting. 1.421 + * @param a The type that should be bounded by bs. 1.422 + * @param bs The bound. 1.423 + */ 1.424 + private void checkExtends(DiagnosticPosition pos, Type a, TypeVar bs) { 1.425 + if (a.isUnbound()) { 1.426 + return; 1.427 + } else if (a.tag != WILDCARD) { 1.428 + a = types.upperBound(a); 1.429 + for (List<Type> l = types.getBounds(bs); l.nonEmpty(); l = l.tail) { 1.430 + if (!types.isSubtype(a, l.head)) { 1.431 + log.error(pos, "not.within.bounds", a); 1.432 + return; 1.433 + } 1.434 + } 1.435 + } else if (a.isExtendsBound()) { 1.436 + if (!types.isCastable(bs.getUpperBound(), types.upperBound(a), Warner.noWarnings)) 1.437 + log.error(pos, "not.within.bounds", a); 1.438 + } else if (a.isSuperBound()) { 1.439 + if (types.notSoftSubtype(types.lowerBound(a), bs.getUpperBound())) 1.440 + log.error(pos, "not.within.bounds", a); 1.441 + } 1.442 + } 1.443 + 1.444 + /** Check that type is different from 'void'. 1.445 + * @param pos Position to be used for error reporting. 1.446 + * @param t The type to be checked. 1.447 + */ 1.448 + Type checkNonVoid(DiagnosticPosition pos, Type t) { 1.449 + if (t.tag == VOID) { 1.450 + log.error(pos, "void.not.allowed.here"); 1.451 + return syms.errType; 1.452 + } else { 1.453 + return t; 1.454 + } 1.455 + } 1.456 + 1.457 + /** Check that type is a class or interface type. 1.458 + * @param pos Position to be used for error reporting. 1.459 + * @param t The type to be checked. 1.460 + */ 1.461 + Type checkClassType(DiagnosticPosition pos, Type t) { 1.462 + if (t.tag != CLASS && t.tag != ERROR) 1.463 + return typeTagError(pos, 1.464 + JCDiagnostic.fragment("type.req.class"), 1.465 + (t.tag == TYPEVAR) 1.466 + ? JCDiagnostic.fragment("type.parameter", t) 1.467 + : t); 1.468 + else 1.469 + return t; 1.470 + } 1.471 + 1.472 + /** Check that type is a class or interface type. 1.473 + * @param pos Position to be used for error reporting. 1.474 + * @param t The type to be checked. 1.475 + * @param noBounds True if type bounds are illegal here. 1.476 + */ 1.477 + Type checkClassType(DiagnosticPosition pos, Type t, boolean noBounds) { 1.478 + t = checkClassType(pos, t); 1.479 + if (noBounds && t.isParameterized()) { 1.480 + List<Type> args = t.getTypeArguments(); 1.481 + while (args.nonEmpty()) { 1.482 + if (args.head.tag == WILDCARD) 1.483 + return typeTagError(pos, 1.484 + log.getLocalizedString("type.req.exact"), 1.485 + args.head); 1.486 + args = args.tail; 1.487 + } 1.488 + } 1.489 + return t; 1.490 + } 1.491 + 1.492 + /** Check that type is a reifiable class, interface or array type. 1.493 + * @param pos Position to be used for error reporting. 1.494 + * @param t The type to be checked. 1.495 + */ 1.496 + Type checkReifiableReferenceType(DiagnosticPosition pos, Type t) { 1.497 + if (t.tag != CLASS && t.tag != ARRAY && t.tag != ERROR) { 1.498 + return typeTagError(pos, 1.499 + JCDiagnostic.fragment("type.req.class.array"), 1.500 + t); 1.501 + } else if (!types.isReifiable(t)) { 1.502 + log.error(pos, "illegal.generic.type.for.instof"); 1.503 + return syms.errType; 1.504 + } else { 1.505 + return t; 1.506 + } 1.507 + } 1.508 + 1.509 + /** Check that type is a reference type, i.e. a class, interface or array type 1.510 + * or a type variable. 1.511 + * @param pos Position to be used for error reporting. 1.512 + * @param t The type to be checked. 1.513 + */ 1.514 + Type checkRefType(DiagnosticPosition pos, Type t) { 1.515 + switch (t.tag) { 1.516 + case CLASS: 1.517 + case ARRAY: 1.518 + case TYPEVAR: 1.519 + case WILDCARD: 1.520 + case ERROR: 1.521 + return t; 1.522 + default: 1.523 + return typeTagError(pos, 1.524 + JCDiagnostic.fragment("type.req.ref"), 1.525 + t); 1.526 + } 1.527 + } 1.528 + 1.529 + /** Check that type is a null or reference type. 1.530 + * @param pos Position to be used for error reporting. 1.531 + * @param t The type to be checked. 1.532 + */ 1.533 + Type checkNullOrRefType(DiagnosticPosition pos, Type t) { 1.534 + switch (t.tag) { 1.535 + case CLASS: 1.536 + case ARRAY: 1.537 + case TYPEVAR: 1.538 + case WILDCARD: 1.539 + case BOT: 1.540 + case ERROR: 1.541 + return t; 1.542 + default: 1.543 + return typeTagError(pos, 1.544 + JCDiagnostic.fragment("type.req.ref"), 1.545 + t); 1.546 + } 1.547 + } 1.548 + 1.549 + /** Check that flag set does not contain elements of two conflicting sets. s 1.550 + * Return true if it doesn't. 1.551 + * @param pos Position to be used for error reporting. 1.552 + * @param flags The set of flags to be checked. 1.553 + * @param set1 Conflicting flags set #1. 1.554 + * @param set2 Conflicting flags set #2. 1.555 + */ 1.556 + boolean checkDisjoint(DiagnosticPosition pos, long flags, long set1, long set2) { 1.557 + if ((flags & set1) != 0 && (flags & set2) != 0) { 1.558 + log.error(pos, 1.559 + "illegal.combination.of.modifiers", 1.560 + TreeInfo.flagNames(TreeInfo.firstFlag(flags & set1)), 1.561 + TreeInfo.flagNames(TreeInfo.firstFlag(flags & set2))); 1.562 + return false; 1.563 + } else 1.564 + return true; 1.565 + } 1.566 + 1.567 + /** Check that given modifiers are legal for given symbol and 1.568 + * return modifiers together with any implicit modififiers for that symbol. 1.569 + * Warning: we can't use flags() here since this method 1.570 + * is called during class enter, when flags() would cause a premature 1.571 + * completion. 1.572 + * @param pos Position to be used for error reporting. 1.573 + * @param flags The set of modifiers given in a definition. 1.574 + * @param sym The defined symbol. 1.575 + */ 1.576 + long checkFlags(DiagnosticPosition pos, long flags, Symbol sym, JCTree tree) { 1.577 + long mask; 1.578 + long implicit = 0; 1.579 + switch (sym.kind) { 1.580 + case VAR: 1.581 + if (sym.owner.kind != TYP) 1.582 + mask = LocalVarFlags; 1.583 + else if ((sym.owner.flags_field & INTERFACE) != 0) 1.584 + mask = implicit = InterfaceVarFlags; 1.585 + else 1.586 + mask = VarFlags; 1.587 + break; 1.588 + case MTH: 1.589 + if (sym.name == names.init) { 1.590 + if ((sym.owner.flags_field & ENUM) != 0) { 1.591 + // enum constructors cannot be declared public or 1.592 + // protected and must be implicitly or explicitly 1.593 + // private 1.594 + implicit = PRIVATE; 1.595 + mask = PRIVATE; 1.596 + } else 1.597 + mask = ConstructorFlags; 1.598 + } else if ((sym.owner.flags_field & INTERFACE) != 0) 1.599 + mask = implicit = InterfaceMethodFlags; 1.600 + else { 1.601 + mask = MethodFlags; 1.602 + } 1.603 + // Imply STRICTFP if owner has STRICTFP set. 1.604 + if (((flags|implicit) & Flags.ABSTRACT) == 0) 1.605 + implicit |= sym.owner.flags_field & STRICTFP; 1.606 + break; 1.607 + case TYP: 1.608 + if (sym.isLocal()) { 1.609 + mask = LocalClassFlags; 1.610 + if (sym.name.len == 0) { // Anonymous class 1.611 + // Anonymous classes in static methods are themselves static; 1.612 + // that's why we admit STATIC here. 1.613 + mask |= STATIC; 1.614 + // JLS: Anonymous classes are final. 1.615 + implicit |= FINAL; 1.616 + } 1.617 + if ((sym.owner.flags_field & STATIC) == 0 && 1.618 + (flags & ENUM) != 0) 1.619 + log.error(pos, "enums.must.be.static"); 1.620 + } else if (sym.owner.kind == TYP) { 1.621 + mask = MemberClassFlags; 1.622 + if (sym.owner.owner.kind == PCK || 1.623 + (sym.owner.flags_field & STATIC) != 0) 1.624 + mask |= STATIC; 1.625 + else if ((flags & ENUM) != 0) 1.626 + log.error(pos, "enums.must.be.static"); 1.627 + // Nested interfaces and enums are always STATIC (Spec ???) 1.628 + if ((flags & (INTERFACE | ENUM)) != 0 ) implicit = STATIC; 1.629 + } else { 1.630 + mask = ClassFlags; 1.631 + } 1.632 + // Interfaces are always ABSTRACT 1.633 + if ((flags & INTERFACE) != 0) implicit |= ABSTRACT; 1.634 + 1.635 + if ((flags & ENUM) != 0) { 1.636 + // enums can't be declared abstract or final 1.637 + mask &= ~(ABSTRACT | FINAL); 1.638 + implicit |= implicitEnumFinalFlag(tree); 1.639 + } 1.640 + // Imply STRICTFP if owner has STRICTFP set. 1.641 + implicit |= sym.owner.flags_field & STRICTFP; 1.642 + break; 1.643 + default: 1.644 + throw new AssertionError(); 1.645 + } 1.646 + long illegal = flags & StandardFlags & ~mask; 1.647 + if (illegal != 0) { 1.648 + if ((illegal & INTERFACE) != 0) { 1.649 + log.error(pos, "intf.not.allowed.here"); 1.650 + mask |= INTERFACE; 1.651 + } 1.652 + else { 1.653 + log.error(pos, 1.654 + "mod.not.allowed.here", TreeInfo.flagNames(illegal)); 1.655 + } 1.656 + } 1.657 + else if ((sym.kind == TYP || 1.658 + // ISSUE: Disallowing abstract&private is no longer appropriate 1.659 + // in the presence of inner classes. Should it be deleted here? 1.660 + checkDisjoint(pos, flags, 1.661 + ABSTRACT, 1.662 + PRIVATE | STATIC)) 1.663 + && 1.664 + checkDisjoint(pos, flags, 1.665 + ABSTRACT | INTERFACE, 1.666 + FINAL | NATIVE | SYNCHRONIZED) 1.667 + && 1.668 + checkDisjoint(pos, flags, 1.669 + PUBLIC, 1.670 + PRIVATE | PROTECTED) 1.671 + && 1.672 + checkDisjoint(pos, flags, 1.673 + PRIVATE, 1.674 + PUBLIC | PROTECTED) 1.675 + && 1.676 + checkDisjoint(pos, flags, 1.677 + FINAL, 1.678 + VOLATILE) 1.679 + && 1.680 + (sym.kind == TYP || 1.681 + checkDisjoint(pos, flags, 1.682 + ABSTRACT | NATIVE, 1.683 + STRICTFP))) { 1.684 + // skip 1.685 + } 1.686 + return flags & (mask | ~StandardFlags) | implicit; 1.687 + } 1.688 + 1.689 + 1.690 + /** Determine if this enum should be implicitly final. 1.691 + * 1.692 + * If the enum has no specialized enum contants, it is final. 1.693 + * 1.694 + * If the enum does have specialized enum contants, it is 1.695 + * <i>not</i> final. 1.696 + */ 1.697 + private long implicitEnumFinalFlag(JCTree tree) { 1.698 + if (tree.getTag() != JCTree.CLASSDEF) return 0; 1.699 + class SpecialTreeVisitor extends JCTree.Visitor { 1.700 + boolean specialized; 1.701 + SpecialTreeVisitor() { 1.702 + this.specialized = false; 1.703 + }; 1.704 + 1.705 + public void visitTree(JCTree tree) { /* no-op */ } 1.706 + 1.707 + public void visitVarDef(JCVariableDecl tree) { 1.708 + if ((tree.mods.flags & ENUM) != 0) { 1.709 + if (tree.init instanceof JCNewClass && 1.710 + ((JCNewClass) tree.init).def != null) { 1.711 + specialized = true; 1.712 + } 1.713 + } 1.714 + } 1.715 + } 1.716 + 1.717 + SpecialTreeVisitor sts = new SpecialTreeVisitor(); 1.718 + JCClassDecl cdef = (JCClassDecl) tree; 1.719 + for (JCTree defs: cdef.defs) { 1.720 + defs.accept(sts); 1.721 + if (sts.specialized) return 0; 1.722 + } 1.723 + return FINAL; 1.724 + } 1.725 + 1.726 +/* ************************************************************************* 1.727 + * Type Validation 1.728 + **************************************************************************/ 1.729 + 1.730 + /** Validate a type expression. That is, 1.731 + * check that all type arguments of a parametric type are within 1.732 + * their bounds. This must be done in a second phase after type attributon 1.733 + * since a class might have a subclass as type parameter bound. E.g: 1.734 + * 1.735 + * class B<A extends C> { ... } 1.736 + * class C extends B<C> { ... } 1.737 + * 1.738 + * and we can't make sure that the bound is already attributed because 1.739 + * of possible cycles. 1.740 + */ 1.741 + private Validator validator = new Validator(); 1.742 + 1.743 + /** Visitor method: Validate a type expression, if it is not null, catching 1.744 + * and reporting any completion failures. 1.745 + */ 1.746 + void validate(JCTree tree) { 1.747 + try { 1.748 + if (tree != null) tree.accept(validator); 1.749 + } catch (CompletionFailure ex) { 1.750 + completionError(tree.pos(), ex); 1.751 + } 1.752 + } 1.753 + 1.754 + /** Visitor method: Validate a list of type expressions. 1.755 + */ 1.756 + void validate(List<? extends JCTree> trees) { 1.757 + for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) 1.758 + validate(l.head); 1.759 + } 1.760 + 1.761 + /** Visitor method: Validate a list of type parameters. 1.762 + */ 1.763 + void validateTypeParams(List<JCTypeParameter> trees) { 1.764 + for (List<JCTypeParameter> l = trees; l.nonEmpty(); l = l.tail) 1.765 + validate(l.head); 1.766 + } 1.767 + 1.768 + /** A visitor class for type validation. 1.769 + */ 1.770 + class Validator extends JCTree.Visitor { 1.771 + 1.772 + public void visitTypeArray(JCArrayTypeTree tree) { 1.773 + validate(tree.elemtype); 1.774 + } 1.775 + 1.776 + public void visitTypeApply(JCTypeApply tree) { 1.777 + if (tree.type.tag == CLASS) { 1.778 + List<Type> formals = tree.type.tsym.type.getTypeArguments(); 1.779 + List<Type> actuals = tree.type.getTypeArguments(); 1.780 + List<JCExpression> args = tree.arguments; 1.781 + List<Type> forms = formals; 1.782 + ListBuffer<TypeVar> tvars_buf = new ListBuffer<TypeVar>(); 1.783 + 1.784 + // For matching pairs of actual argument types `a' and 1.785 + // formal type parameters with declared bound `b' ... 1.786 + while (args.nonEmpty() && forms.nonEmpty()) { 1.787 + validate(args.head); 1.788 + 1.789 + // exact type arguments needs to know their 1.790 + // bounds (for upper and lower bound 1.791 + // calculations). So we create new TypeVars with 1.792 + // bounds substed with actuals. 1.793 + tvars_buf.append(types.substBound(((TypeVar)forms.head), 1.794 + formals, 1.795 + Type.removeBounds(actuals))); 1.796 + 1.797 + args = args.tail; 1.798 + forms = forms.tail; 1.799 + } 1.800 + 1.801 + args = tree.arguments; 1.802 + List<TypeVar> tvars = tvars_buf.toList(); 1.803 + while (args.nonEmpty() && tvars.nonEmpty()) { 1.804 + // Let the actual arguments know their bound 1.805 + args.head.type.withTypeVar(tvars.head); 1.806 + args = args.tail; 1.807 + tvars = tvars.tail; 1.808 + } 1.809 + 1.810 + args = tree.arguments; 1.811 + tvars = tvars_buf.toList(); 1.812 + while (args.nonEmpty() && tvars.nonEmpty()) { 1.813 + checkExtends(args.head.pos(), 1.814 + args.head.type, 1.815 + tvars.head); 1.816 + args = args.tail; 1.817 + tvars = tvars.tail; 1.818 + } 1.819 + 1.820 + // Check that this type is either fully parameterized, or 1.821 + // not parameterized at all. 1.822 + if (tree.type.getEnclosingType().isRaw()) 1.823 + log.error(tree.pos(), "improperly.formed.type.inner.raw.param"); 1.824 + if (tree.clazz.getTag() == JCTree.SELECT) 1.825 + visitSelectInternal((JCFieldAccess)tree.clazz); 1.826 + } 1.827 + } 1.828 + 1.829 + public void visitTypeParameter(JCTypeParameter tree) { 1.830 + validate(tree.bounds); 1.831 + checkClassBounds(tree.pos(), tree.type); 1.832 + } 1.833 + 1.834 + @Override 1.835 + public void visitWildcard(JCWildcard tree) { 1.836 + if (tree.inner != null) 1.837 + validate(tree.inner); 1.838 + } 1.839 + 1.840 + public void visitSelect(JCFieldAccess tree) { 1.841 + if (tree.type.tag == CLASS) { 1.842 + visitSelectInternal(tree); 1.843 + 1.844 + // Check that this type is either fully parameterized, or 1.845 + // not parameterized at all. 1.846 + if (tree.selected.type.isParameterized() && tree.type.tsym.type.getTypeArguments().nonEmpty()) 1.847 + log.error(tree.pos(), "improperly.formed.type.param.missing"); 1.848 + } 1.849 + } 1.850 + public void visitSelectInternal(JCFieldAccess tree) { 1.851 + if (tree.type.getEnclosingType().tag != CLASS && 1.852 + tree.selected.type.isParameterized()) { 1.853 + // The enclosing type is not a class, so we are 1.854 + // looking at a static member type. However, the 1.855 + // qualifying expression is parameterized. 1.856 + log.error(tree.pos(), "cant.select.static.class.from.param.type"); 1.857 + } else { 1.858 + // otherwise validate the rest of the expression 1.859 + validate(tree.selected); 1.860 + } 1.861 + } 1.862 + 1.863 + /** Default visitor method: do nothing. 1.864 + */ 1.865 + public void visitTree(JCTree tree) { 1.866 + } 1.867 + } 1.868 + 1.869 +/* ************************************************************************* 1.870 + * Exception checking 1.871 + **************************************************************************/ 1.872 + 1.873 + /* The following methods treat classes as sets that contain 1.874 + * the class itself and all their subclasses 1.875 + */ 1.876 + 1.877 + /** Is given type a subtype of some of the types in given list? 1.878 + */ 1.879 + boolean subset(Type t, List<Type> ts) { 1.880 + for (List<Type> l = ts; l.nonEmpty(); l = l.tail) 1.881 + if (types.isSubtype(t, l.head)) return true; 1.882 + return false; 1.883 + } 1.884 + 1.885 + /** Is given type a subtype or supertype of 1.886 + * some of the types in given list? 1.887 + */ 1.888 + boolean intersects(Type t, List<Type> ts) { 1.889 + for (List<Type> l = ts; l.nonEmpty(); l = l.tail) 1.890 + if (types.isSubtype(t, l.head) || types.isSubtype(l.head, t)) return true; 1.891 + return false; 1.892 + } 1.893 + 1.894 + /** Add type set to given type list, unless it is a subclass of some class 1.895 + * in the list. 1.896 + */ 1.897 + List<Type> incl(Type t, List<Type> ts) { 1.898 + return subset(t, ts) ? ts : excl(t, ts).prepend(t); 1.899 + } 1.900 + 1.901 + /** Remove type set from type set list. 1.902 + */ 1.903 + List<Type> excl(Type t, List<Type> ts) { 1.904 + if (ts.isEmpty()) { 1.905 + return ts; 1.906 + } else { 1.907 + List<Type> ts1 = excl(t, ts.tail); 1.908 + if (types.isSubtype(ts.head, t)) return ts1; 1.909 + else if (ts1 == ts.tail) return ts; 1.910 + else return ts1.prepend(ts.head); 1.911 + } 1.912 + } 1.913 + 1.914 + /** Form the union of two type set lists. 1.915 + */ 1.916 + List<Type> union(List<Type> ts1, List<Type> ts2) { 1.917 + List<Type> ts = ts1; 1.918 + for (List<Type> l = ts2; l.nonEmpty(); l = l.tail) 1.919 + ts = incl(l.head, ts); 1.920 + return ts; 1.921 + } 1.922 + 1.923 + /** Form the difference of two type lists. 1.924 + */ 1.925 + List<Type> diff(List<Type> ts1, List<Type> ts2) { 1.926 + List<Type> ts = ts1; 1.927 + for (List<Type> l = ts2; l.nonEmpty(); l = l.tail) 1.928 + ts = excl(l.head, ts); 1.929 + return ts; 1.930 + } 1.931 + 1.932 + /** Form the intersection of two type lists. 1.933 + */ 1.934 + public List<Type> intersect(List<Type> ts1, List<Type> ts2) { 1.935 + List<Type> ts = List.nil(); 1.936 + for (List<Type> l = ts1; l.nonEmpty(); l = l.tail) 1.937 + if (subset(l.head, ts2)) ts = incl(l.head, ts); 1.938 + for (List<Type> l = ts2; l.nonEmpty(); l = l.tail) 1.939 + if (subset(l.head, ts1)) ts = incl(l.head, ts); 1.940 + return ts; 1.941 + } 1.942 + 1.943 + /** Is exc an exception symbol that need not be declared? 1.944 + */ 1.945 + boolean isUnchecked(ClassSymbol exc) { 1.946 + return 1.947 + exc.kind == ERR || 1.948 + exc.isSubClass(syms.errorType.tsym, types) || 1.949 + exc.isSubClass(syms.runtimeExceptionType.tsym, types); 1.950 + } 1.951 + 1.952 + /** Is exc an exception type that need not be declared? 1.953 + */ 1.954 + boolean isUnchecked(Type exc) { 1.955 + return 1.956 + (exc.tag == TYPEVAR) ? isUnchecked(types.supertype(exc)) : 1.957 + (exc.tag == CLASS) ? isUnchecked((ClassSymbol)exc.tsym) : 1.958 + exc.tag == BOT; 1.959 + } 1.960 + 1.961 + /** Same, but handling completion failures. 1.962 + */ 1.963 + boolean isUnchecked(DiagnosticPosition pos, Type exc) { 1.964 + try { 1.965 + return isUnchecked(exc); 1.966 + } catch (CompletionFailure ex) { 1.967 + completionError(pos, ex); 1.968 + return true; 1.969 + } 1.970 + } 1.971 + 1.972 + /** Is exc handled by given exception list? 1.973 + */ 1.974 + boolean isHandled(Type exc, List<Type> handled) { 1.975 + return isUnchecked(exc) || subset(exc, handled); 1.976 + } 1.977 + 1.978 + /** Return all exceptions in thrown list that are not in handled list. 1.979 + * @param thrown The list of thrown exceptions. 1.980 + * @param handled The list of handled exceptions. 1.981 + */ 1.982 + List<Type> unHandled(List<Type> thrown, List<Type> handled) { 1.983 + List<Type> unhandled = List.nil(); 1.984 + for (List<Type> l = thrown; l.nonEmpty(); l = l.tail) 1.985 + if (!isHandled(l.head, handled)) unhandled = unhandled.prepend(l.head); 1.986 + return unhandled; 1.987 + } 1.988 + 1.989 +/* ************************************************************************* 1.990 + * Overriding/Implementation checking 1.991 + **************************************************************************/ 1.992 + 1.993 + /** The level of access protection given by a flag set, 1.994 + * where PRIVATE is highest and PUBLIC is lowest. 1.995 + */ 1.996 + static int protection(long flags) { 1.997 + switch ((short)(flags & AccessFlags)) { 1.998 + case PRIVATE: return 3; 1.999 + case PROTECTED: return 1; 1.1000 + default: 1.1001 + case PUBLIC: return 0; 1.1002 + case 0: return 2; 1.1003 + } 1.1004 + } 1.1005 + 1.1006 + /** A string describing the access permission given by a flag set. 1.1007 + * This always returns a space-separated list of Java Keywords. 1.1008 + */ 1.1009 + private static String protectionString(long flags) { 1.1010 + long flags1 = flags & AccessFlags; 1.1011 + return (flags1 == 0) ? "package" : TreeInfo.flagNames(flags1); 1.1012 + } 1.1013 + 1.1014 + /** A customized "cannot override" error message. 1.1015 + * @param m The overriding method. 1.1016 + * @param other The overridden method. 1.1017 + * @return An internationalized string. 1.1018 + */ 1.1019 + static Object cannotOverride(MethodSymbol m, MethodSymbol other) { 1.1020 + String key; 1.1021 + if ((other.owner.flags() & INTERFACE) == 0) 1.1022 + key = "cant.override"; 1.1023 + else if ((m.owner.flags() & INTERFACE) == 0) 1.1024 + key = "cant.implement"; 1.1025 + else 1.1026 + key = "clashes.with"; 1.1027 + return JCDiagnostic.fragment(key, m, m.location(), other, other.location()); 1.1028 + } 1.1029 + 1.1030 + /** A customized "override" warning message. 1.1031 + * @param m The overriding method. 1.1032 + * @param other The overridden method. 1.1033 + * @return An internationalized string. 1.1034 + */ 1.1035 + static Object uncheckedOverrides(MethodSymbol m, MethodSymbol other) { 1.1036 + String key; 1.1037 + if ((other.owner.flags() & INTERFACE) == 0) 1.1038 + key = "unchecked.override"; 1.1039 + else if ((m.owner.flags() & INTERFACE) == 0) 1.1040 + key = "unchecked.implement"; 1.1041 + else 1.1042 + key = "unchecked.clash.with"; 1.1043 + return JCDiagnostic.fragment(key, m, m.location(), other, other.location()); 1.1044 + } 1.1045 + 1.1046 + /** A customized "override" warning message. 1.1047 + * @param m The overriding method. 1.1048 + * @param other The overridden method. 1.1049 + * @return An internationalized string. 1.1050 + */ 1.1051 + static Object varargsOverrides(MethodSymbol m, MethodSymbol other) { 1.1052 + String key; 1.1053 + if ((other.owner.flags() & INTERFACE) == 0) 1.1054 + key = "varargs.override"; 1.1055 + else if ((m.owner.flags() & INTERFACE) == 0) 1.1056 + key = "varargs.implement"; 1.1057 + else 1.1058 + key = "varargs.clash.with"; 1.1059 + return JCDiagnostic.fragment(key, m, m.location(), other, other.location()); 1.1060 + } 1.1061 + 1.1062 + /** Check that this method conforms with overridden method 'other'. 1.1063 + * where `origin' is the class where checking started. 1.1064 + * Complications: 1.1065 + * (1) Do not check overriding of synthetic methods 1.1066 + * (reason: they might be final). 1.1067 + * todo: check whether this is still necessary. 1.1068 + * (2) Admit the case where an interface proxy throws fewer exceptions 1.1069 + * than the method it implements. Augment the proxy methods with the 1.1070 + * undeclared exceptions in this case. 1.1071 + * (3) When generics are enabled, admit the case where an interface proxy 1.1072 + * has a result type 1.1073 + * extended by the result type of the method it implements. 1.1074 + * Change the proxies result type to the smaller type in this case. 1.1075 + * 1.1076 + * @param tree The tree from which positions 1.1077 + * are extracted for errors. 1.1078 + * @param m The overriding method. 1.1079 + * @param other The overridden method. 1.1080 + * @param origin The class of which the overriding method 1.1081 + * is a member. 1.1082 + */ 1.1083 + void checkOverride(JCTree tree, 1.1084 + MethodSymbol m, 1.1085 + MethodSymbol other, 1.1086 + ClassSymbol origin) { 1.1087 + // Don't check overriding of synthetic methods or by bridge methods. 1.1088 + if ((m.flags() & (SYNTHETIC|BRIDGE)) != 0 || (other.flags() & SYNTHETIC) != 0) { 1.1089 + return; 1.1090 + } 1.1091 + 1.1092 + // Error if static method overrides instance method (JLS 8.4.6.2). 1.1093 + if ((m.flags() & STATIC) != 0 && 1.1094 + (other.flags() & STATIC) == 0) { 1.1095 + log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.static", 1.1096 + cannotOverride(m, other)); 1.1097 + return; 1.1098 + } 1.1099 + 1.1100 + // Error if instance method overrides static or final 1.1101 + // method (JLS 8.4.6.1). 1.1102 + if ((other.flags() & FINAL) != 0 || 1.1103 + (m.flags() & STATIC) == 0 && 1.1104 + (other.flags() & STATIC) != 0) { 1.1105 + log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.meth", 1.1106 + cannotOverride(m, other), 1.1107 + TreeInfo.flagNames(other.flags() & (FINAL | STATIC))); 1.1108 + return; 1.1109 + } 1.1110 + 1.1111 + if ((m.owner.flags() & ANNOTATION) != 0) { 1.1112 + // handled in validateAnnotationMethod 1.1113 + return; 1.1114 + } 1.1115 + 1.1116 + // Error if overriding method has weaker access (JLS 8.4.6.3). 1.1117 + if ((origin.flags() & INTERFACE) == 0 && 1.1118 + protection(m.flags()) > protection(other.flags())) { 1.1119 + log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.weaker.access", 1.1120 + cannotOverride(m, other), 1.1121 + protectionString(other.flags())); 1.1122 + return; 1.1123 + 1.1124 + } 1.1125 + 1.1126 + Type mt = types.memberType(origin.type, m); 1.1127 + Type ot = types.memberType(origin.type, other); 1.1128 + // Error if overriding result type is different 1.1129 + // (or, in the case of generics mode, not a subtype) of 1.1130 + // overridden result type. We have to rename any type parameters 1.1131 + // before comparing types. 1.1132 + List<Type> mtvars = mt.getTypeArguments(); 1.1133 + List<Type> otvars = ot.getTypeArguments(); 1.1134 + Type mtres = mt.getReturnType(); 1.1135 + Type otres = types.subst(ot.getReturnType(), otvars, mtvars); 1.1136 + 1.1137 + overrideWarner.warned = false; 1.1138 + boolean resultTypesOK = 1.1139 + types.returnTypeSubstitutable(mt, ot, otres, overrideWarner); 1.1140 + if (!resultTypesOK) { 1.1141 + if (!source.allowCovariantReturns() && 1.1142 + m.owner != origin && 1.1143 + m.owner.isSubClass(other.owner, types)) { 1.1144 + // allow limited interoperability with covariant returns 1.1145 + } else { 1.1146 + typeError(TreeInfo.diagnosticPositionFor(m, tree), 1.1147 + JCDiagnostic.fragment("override.incompatible.ret", 1.1148 + cannotOverride(m, other)), 1.1149 + mtres, otres); 1.1150 + return; 1.1151 + } 1.1152 + } else if (overrideWarner.warned) { 1.1153 + warnUnchecked(TreeInfo.diagnosticPositionFor(m, tree), 1.1154 + "prob.found.req", 1.1155 + JCDiagnostic.fragment("override.unchecked.ret", 1.1156 + uncheckedOverrides(m, other)), 1.1157 + mtres, otres); 1.1158 + } 1.1159 + 1.1160 + // Error if overriding method throws an exception not reported 1.1161 + // by overridden method. 1.1162 + List<Type> otthrown = types.subst(ot.getThrownTypes(), otvars, mtvars); 1.1163 + List<Type> unhandled = unHandled(mt.getThrownTypes(), otthrown); 1.1164 + if (unhandled.nonEmpty()) { 1.1165 + log.error(TreeInfo.diagnosticPositionFor(m, tree), 1.1166 + "override.meth.doesnt.throw", 1.1167 + cannotOverride(m, other), 1.1168 + unhandled.head); 1.1169 + return; 1.1170 + } 1.1171 + 1.1172 + // Optional warning if varargs don't agree 1.1173 + if ((((m.flags() ^ other.flags()) & Flags.VARARGS) != 0) 1.1174 + && lint.isEnabled(Lint.LintCategory.OVERRIDES)) { 1.1175 + log.warning(TreeInfo.diagnosticPositionFor(m, tree), 1.1176 + ((m.flags() & Flags.VARARGS) != 0) 1.1177 + ? "override.varargs.missing" 1.1178 + : "override.varargs.extra", 1.1179 + varargsOverrides(m, other)); 1.1180 + } 1.1181 + 1.1182 + // Warn if instance method overrides bridge method (compiler spec ??) 1.1183 + if ((other.flags() & BRIDGE) != 0) { 1.1184 + log.warning(TreeInfo.diagnosticPositionFor(m, tree), "override.bridge", 1.1185 + uncheckedOverrides(m, other)); 1.1186 + } 1.1187 + 1.1188 + // Warn if a deprecated method overridden by a non-deprecated one. 1.1189 + if ((other.flags() & DEPRECATED) != 0 1.1190 + && (m.flags() & DEPRECATED) == 0 1.1191 + && m.outermostClass() != other.outermostClass() 1.1192 + && !isDeprecatedOverrideIgnorable(other, origin)) { 1.1193 + warnDeprecated(TreeInfo.diagnosticPositionFor(m, tree), other); 1.1194 + } 1.1195 + } 1.1196 + // where 1.1197 + private boolean isDeprecatedOverrideIgnorable(MethodSymbol m, ClassSymbol origin) { 1.1198 + // If the method, m, is defined in an interface, then ignore the issue if the method 1.1199 + // is only inherited via a supertype and also implemented in the supertype, 1.1200 + // because in that case, we will rediscover the issue when examining the method 1.1201 + // in the supertype. 1.1202 + // If the method, m, is not defined in an interface, then the only time we need to 1.1203 + // address the issue is when the method is the supertype implemementation: any other 1.1204 + // case, we will have dealt with when examining the supertype classes 1.1205 + ClassSymbol mc = m.enclClass(); 1.1206 + Type st = types.supertype(origin.type); 1.1207 + if (st.tag != CLASS) 1.1208 + return true; 1.1209 + MethodSymbol stimpl = m.implementation((ClassSymbol)st.tsym, types, false); 1.1210 + 1.1211 + if (mc != null && ((mc.flags() & INTERFACE) != 0)) { 1.1212 + List<Type> intfs = types.interfaces(origin.type); 1.1213 + return (intfs.contains(mc.type) ? false : (stimpl != null)); 1.1214 + } 1.1215 + else 1.1216 + return (stimpl != m); 1.1217 + } 1.1218 + 1.1219 + 1.1220 + // used to check if there were any unchecked conversions 1.1221 + Warner overrideWarner = new Warner(); 1.1222 + 1.1223 + /** Check that a class does not inherit two concrete methods 1.1224 + * with the same signature. 1.1225 + * @param pos Position to be used for error reporting. 1.1226 + * @param site The class type to be checked. 1.1227 + */ 1.1228 + public void checkCompatibleConcretes(DiagnosticPosition pos, Type site) { 1.1229 + Type sup = types.supertype(site); 1.1230 + if (sup.tag != CLASS) return; 1.1231 + 1.1232 + for (Type t1 = sup; 1.1233 + t1.tsym.type.isParameterized(); 1.1234 + t1 = types.supertype(t1)) { 1.1235 + for (Scope.Entry e1 = t1.tsym.members().elems; 1.1236 + e1 != null; 1.1237 + e1 = e1.sibling) { 1.1238 + Symbol s1 = e1.sym; 1.1239 + if (s1.kind != MTH || 1.1240 + (s1.flags() & (STATIC|SYNTHETIC|BRIDGE)) != 0 || 1.1241 + !s1.isInheritedIn(site.tsym, types) || 1.1242 + ((MethodSymbol)s1).implementation(site.tsym, 1.1243 + types, 1.1244 + true) != s1) 1.1245 + continue; 1.1246 + Type st1 = types.memberType(t1, s1); 1.1247 + int s1ArgsLength = st1.getParameterTypes().length(); 1.1248 + if (st1 == s1.type) continue; 1.1249 + 1.1250 + for (Type t2 = sup; 1.1251 + t2.tag == CLASS; 1.1252 + t2 = types.supertype(t2)) { 1.1253 + for (Scope.Entry e2 = t1.tsym.members().lookup(s1.name); 1.1254 + e2.scope != null; 1.1255 + e2 = e2.next()) { 1.1256 + Symbol s2 = e2.sym; 1.1257 + if (s2 == s1 || 1.1258 + s2.kind != MTH || 1.1259 + (s2.flags() & (STATIC|SYNTHETIC|BRIDGE)) != 0 || 1.1260 + s2.type.getParameterTypes().length() != s1ArgsLength || 1.1261 + !s2.isInheritedIn(site.tsym, types) || 1.1262 + ((MethodSymbol)s2).implementation(site.tsym, 1.1263 + types, 1.1264 + true) != s2) 1.1265 + continue; 1.1266 + Type st2 = types.memberType(t2, s2); 1.1267 + if (types.overrideEquivalent(st1, st2)) 1.1268 + log.error(pos, "concrete.inheritance.conflict", 1.1269 + s1, t1, s2, t2, sup); 1.1270 + } 1.1271 + } 1.1272 + } 1.1273 + } 1.1274 + } 1.1275 + 1.1276 + /** Check that classes (or interfaces) do not each define an abstract 1.1277 + * method with same name and arguments but incompatible return types. 1.1278 + * @param pos Position to be used for error reporting. 1.1279 + * @param t1 The first argument type. 1.1280 + * @param t2 The second argument type. 1.1281 + */ 1.1282 + public boolean checkCompatibleAbstracts(DiagnosticPosition pos, 1.1283 + Type t1, 1.1284 + Type t2) { 1.1285 + return checkCompatibleAbstracts(pos, t1, t2, 1.1286 + types.makeCompoundType(t1, t2)); 1.1287 + } 1.1288 + 1.1289 + public boolean checkCompatibleAbstracts(DiagnosticPosition pos, 1.1290 + Type t1, 1.1291 + Type t2, 1.1292 + Type site) { 1.1293 + Symbol sym = firstIncompatibility(t1, t2, site); 1.1294 + if (sym != null) { 1.1295 + log.error(pos, "types.incompatible.diff.ret", 1.1296 + t1, t2, sym.name + 1.1297 + "(" + types.memberType(t2, sym).getParameterTypes() + ")"); 1.1298 + return false; 1.1299 + } 1.1300 + return true; 1.1301 + } 1.1302 + 1.1303 + /** Return the first method which is defined with same args 1.1304 + * but different return types in two given interfaces, or null if none 1.1305 + * exists. 1.1306 + * @param t1 The first type. 1.1307 + * @param t2 The second type. 1.1308 + * @param site The most derived type. 1.1309 + * @returns symbol from t2 that conflicts with one in t1. 1.1310 + */ 1.1311 + private Symbol firstIncompatibility(Type t1, Type t2, Type site) { 1.1312 + Map<TypeSymbol,Type> interfaces1 = new HashMap<TypeSymbol,Type>(); 1.1313 + closure(t1, interfaces1); 1.1314 + Map<TypeSymbol,Type> interfaces2; 1.1315 + if (t1 == t2) 1.1316 + interfaces2 = interfaces1; 1.1317 + else 1.1318 + closure(t2, interfaces1, interfaces2 = new HashMap<TypeSymbol,Type>()); 1.1319 + 1.1320 + for (Type t3 : interfaces1.values()) { 1.1321 + for (Type t4 : interfaces2.values()) { 1.1322 + Symbol s = firstDirectIncompatibility(t3, t4, site); 1.1323 + if (s != null) return s; 1.1324 + } 1.1325 + } 1.1326 + return null; 1.1327 + } 1.1328 + 1.1329 + /** Compute all the supertypes of t, indexed by type symbol. */ 1.1330 + private void closure(Type t, Map<TypeSymbol,Type> typeMap) { 1.1331 + if (t.tag != CLASS) return; 1.1332 + if (typeMap.put(t.tsym, t) == null) { 1.1333 + closure(types.supertype(t), typeMap); 1.1334 + for (Type i : types.interfaces(t)) 1.1335 + closure(i, typeMap); 1.1336 + } 1.1337 + } 1.1338 + 1.1339 + /** Compute all the supertypes of t, indexed by type symbol (except thise in typesSkip). */ 1.1340 + private void closure(Type t, Map<TypeSymbol,Type> typesSkip, Map<TypeSymbol,Type> typeMap) { 1.1341 + if (t.tag != CLASS) return; 1.1342 + if (typesSkip.get(t.tsym) != null) return; 1.1343 + if (typeMap.put(t.tsym, t) == null) { 1.1344 + closure(types.supertype(t), typesSkip, typeMap); 1.1345 + for (Type i : types.interfaces(t)) 1.1346 + closure(i, typesSkip, typeMap); 1.1347 + } 1.1348 + } 1.1349 + 1.1350 + /** Return the first method in t2 that conflicts with a method from t1. */ 1.1351 + private Symbol firstDirectIncompatibility(Type t1, Type t2, Type site) { 1.1352 + for (Scope.Entry e1 = t1.tsym.members().elems; e1 != null; e1 = e1.sibling) { 1.1353 + Symbol s1 = e1.sym; 1.1354 + Type st1 = null; 1.1355 + if (s1.kind != MTH || !s1.isInheritedIn(site.tsym, types)) continue; 1.1356 + Symbol impl = ((MethodSymbol)s1).implementation(site.tsym, types, false); 1.1357 + if (impl != null && (impl.flags() & ABSTRACT) == 0) continue; 1.1358 + for (Scope.Entry e2 = t2.tsym.members().lookup(s1.name); e2.scope != null; e2 = e2.next()) { 1.1359 + Symbol s2 = e2.sym; 1.1360 + if (s1 == s2) continue; 1.1361 + if (s2.kind != MTH || !s2.isInheritedIn(site.tsym, types)) continue; 1.1362 + if (st1 == null) st1 = types.memberType(t1, s1); 1.1363 + Type st2 = types.memberType(t2, s2); 1.1364 + if (types.overrideEquivalent(st1, st2)) { 1.1365 + List<Type> tvars1 = st1.getTypeArguments(); 1.1366 + List<Type> tvars2 = st2.getTypeArguments(); 1.1367 + Type rt1 = st1.getReturnType(); 1.1368 + Type rt2 = types.subst(st2.getReturnType(), tvars2, tvars1); 1.1369 + boolean compat = 1.1370 + types.isSameType(rt1, rt2) || 1.1371 + rt1.tag >= CLASS && rt2.tag >= CLASS && 1.1372 + (types.covariantReturnType(rt1, rt2, Warner.noWarnings) || 1.1373 + types.covariantReturnType(rt2, rt1, Warner.noWarnings)); 1.1374 + if (!compat) return s2; 1.1375 + } 1.1376 + } 1.1377 + } 1.1378 + return null; 1.1379 + } 1.1380 + 1.1381 + /** Check that a given method conforms with any method it overrides. 1.1382 + * @param tree The tree from which positions are extracted 1.1383 + * for errors. 1.1384 + * @param m The overriding method. 1.1385 + */ 1.1386 + void checkOverride(JCTree tree, MethodSymbol m) { 1.1387 + ClassSymbol origin = (ClassSymbol)m.owner; 1.1388 + if ((origin.flags() & ENUM) != 0 && names.finalize.equals(m.name)) 1.1389 + if (m.overrides(syms.enumFinalFinalize, origin, types, false)) { 1.1390 + log.error(tree.pos(), "enum.no.finalize"); 1.1391 + return; 1.1392 + } 1.1393 + for (Type t = types.supertype(origin.type); t.tag == CLASS; 1.1394 + t = types.supertype(t)) { 1.1395 + TypeSymbol c = t.tsym; 1.1396 + Scope.Entry e = c.members().lookup(m.name); 1.1397 + while (e.scope != null) { 1.1398 + if (m.overrides(e.sym, origin, types, false)) 1.1399 + checkOverride(tree, m, (MethodSymbol)e.sym, origin); 1.1400 + e = e.next(); 1.1401 + } 1.1402 + } 1.1403 + } 1.1404 + 1.1405 + /** Check that all abstract members of given class have definitions. 1.1406 + * @param pos Position to be used for error reporting. 1.1407 + * @param c The class. 1.1408 + */ 1.1409 + void checkAllDefined(DiagnosticPosition pos, ClassSymbol c) { 1.1410 + try { 1.1411 + MethodSymbol undef = firstUndef(c, c); 1.1412 + if (undef != null) { 1.1413 + if ((c.flags() & ENUM) != 0 && 1.1414 + types.supertype(c.type).tsym == syms.enumSym && 1.1415 + (c.flags() & FINAL) == 0) { 1.1416 + // add the ABSTRACT flag to an enum 1.1417 + c.flags_field |= ABSTRACT; 1.1418 + } else { 1.1419 + MethodSymbol undef1 = 1.1420 + new MethodSymbol(undef.flags(), undef.name, 1.1421 + types.memberType(c.type, undef), undef.owner); 1.1422 + log.error(pos, "does.not.override.abstract", 1.1423 + c, undef1, undef1.location()); 1.1424 + } 1.1425 + } 1.1426 + } catch (CompletionFailure ex) { 1.1427 + completionError(pos, ex); 1.1428 + } 1.1429 + } 1.1430 +//where 1.1431 + /** Return first abstract member of class `c' that is not defined 1.1432 + * in `impl', null if there is none. 1.1433 + */ 1.1434 + private MethodSymbol firstUndef(ClassSymbol impl, ClassSymbol c) { 1.1435 + MethodSymbol undef = null; 1.1436 + // Do not bother to search in classes that are not abstract, 1.1437 + // since they cannot have abstract members. 1.1438 + if (c == impl || (c.flags() & (ABSTRACT | INTERFACE)) != 0) { 1.1439 + Scope s = c.members(); 1.1440 + for (Scope.Entry e = s.elems; 1.1441 + undef == null && e != null; 1.1442 + e = e.sibling) { 1.1443 + if (e.sym.kind == MTH && 1.1444 + (e.sym.flags() & (ABSTRACT|IPROXY)) == ABSTRACT) { 1.1445 + MethodSymbol absmeth = (MethodSymbol)e.sym; 1.1446 + MethodSymbol implmeth = absmeth.implementation(impl, types, true); 1.1447 + if (implmeth == null || implmeth == absmeth) 1.1448 + undef = absmeth; 1.1449 + } 1.1450 + } 1.1451 + if (undef == null) { 1.1452 + Type st = types.supertype(c.type); 1.1453 + if (st.tag == CLASS) 1.1454 + undef = firstUndef(impl, (ClassSymbol)st.tsym); 1.1455 + } 1.1456 + for (List<Type> l = types.interfaces(c.type); 1.1457 + undef == null && l.nonEmpty(); 1.1458 + l = l.tail) { 1.1459 + undef = firstUndef(impl, (ClassSymbol)l.head.tsym); 1.1460 + } 1.1461 + } 1.1462 + return undef; 1.1463 + } 1.1464 + 1.1465 + /** Check for cyclic references. Issue an error if the 1.1466 + * symbol of the type referred to has a LOCKED flag set. 1.1467 + * 1.1468 + * @param pos Position to be used for error reporting. 1.1469 + * @param t The type referred to. 1.1470 + */ 1.1471 + void checkNonCyclic(DiagnosticPosition pos, Type t) { 1.1472 + checkNonCyclicInternal(pos, t); 1.1473 + } 1.1474 + 1.1475 + 1.1476 + void checkNonCyclic(DiagnosticPosition pos, TypeVar t) { 1.1477 + checkNonCyclic1(pos, t, new HashSet<TypeVar>()); 1.1478 + } 1.1479 + 1.1480 + private void checkNonCyclic1(DiagnosticPosition pos, Type t, Set<TypeVar> seen) { 1.1481 + final TypeVar tv; 1.1482 + if (seen.contains(t)) { 1.1483 + tv = (TypeVar)t; 1.1484 + tv.bound = new ErrorType(); 1.1485 + log.error(pos, "cyclic.inheritance", t); 1.1486 + } else if (t.tag == TYPEVAR) { 1.1487 + tv = (TypeVar)t; 1.1488 + seen.add(tv); 1.1489 + for (Type b : types.getBounds(tv)) 1.1490 + checkNonCyclic1(pos, b, seen); 1.1491 + } 1.1492 + } 1.1493 + 1.1494 + /** Check for cyclic references. Issue an error if the 1.1495 + * symbol of the type referred to has a LOCKED flag set. 1.1496 + * 1.1497 + * @param pos Position to be used for error reporting. 1.1498 + * @param t The type referred to. 1.1499 + * @returns True if the check completed on all attributed classes 1.1500 + */ 1.1501 + private boolean checkNonCyclicInternal(DiagnosticPosition pos, Type t) { 1.1502 + boolean complete = true; // was the check complete? 1.1503 + //- System.err.println("checkNonCyclicInternal("+t+");");//DEBUG 1.1504 + Symbol c = t.tsym; 1.1505 + if ((c.flags_field & ACYCLIC) != 0) return true; 1.1506 + 1.1507 + if ((c.flags_field & LOCKED) != 0) { 1.1508 + noteCyclic(pos, (ClassSymbol)c); 1.1509 + } else if (!c.type.isErroneous()) { 1.1510 + try { 1.1511 + c.flags_field |= LOCKED; 1.1512 + if (c.type.tag == CLASS) { 1.1513 + ClassType clazz = (ClassType)c.type; 1.1514 + if (clazz.interfaces_field != null) 1.1515 + for (List<Type> l=clazz.interfaces_field; l.nonEmpty(); l=l.tail) 1.1516 + complete &= checkNonCyclicInternal(pos, l.head); 1.1517 + if (clazz.supertype_field != null) { 1.1518 + Type st = clazz.supertype_field; 1.1519 + if (st != null && st.tag == CLASS) 1.1520 + complete &= checkNonCyclicInternal(pos, st); 1.1521 + } 1.1522 + if (c.owner.kind == TYP) 1.1523 + complete &= checkNonCyclicInternal(pos, c.owner.type); 1.1524 + } 1.1525 + } finally { 1.1526 + c.flags_field &= ~LOCKED; 1.1527 + } 1.1528 + } 1.1529 + if (complete) 1.1530 + complete = ((c.flags_field & UNATTRIBUTED) == 0) && c.completer == null; 1.1531 + if (complete) c.flags_field |= ACYCLIC; 1.1532 + return complete; 1.1533 + } 1.1534 + 1.1535 + /** Note that we found an inheritance cycle. */ 1.1536 + private void noteCyclic(DiagnosticPosition pos, ClassSymbol c) { 1.1537 + log.error(pos, "cyclic.inheritance", c); 1.1538 + for (List<Type> l=types.interfaces(c.type); l.nonEmpty(); l=l.tail) 1.1539 + l.head = new ErrorType((ClassSymbol)l.head.tsym); 1.1540 + Type st = types.supertype(c.type); 1.1541 + if (st.tag == CLASS) 1.1542 + ((ClassType)c.type).supertype_field = new ErrorType((ClassSymbol)st.tsym); 1.1543 + c.type = new ErrorType(c); 1.1544 + c.flags_field |= ACYCLIC; 1.1545 + } 1.1546 + 1.1547 + /** Check that all methods which implement some 1.1548 + * method conform to the method they implement. 1.1549 + * @param tree The class definition whose members are checked. 1.1550 + */ 1.1551 + void checkImplementations(JCClassDecl tree) { 1.1552 + checkImplementations(tree, tree.sym); 1.1553 + } 1.1554 +//where 1.1555 + /** Check that all methods which implement some 1.1556 + * method in `ic' conform to the method they implement. 1.1557 + */ 1.1558 + void checkImplementations(JCClassDecl tree, ClassSymbol ic) { 1.1559 + ClassSymbol origin = tree.sym; 1.1560 + for (List<Type> l = types.closure(ic.type); l.nonEmpty(); l = l.tail) { 1.1561 + ClassSymbol lc = (ClassSymbol)l.head.tsym; 1.1562 + if ((allowGenerics || origin != lc) && (lc.flags() & ABSTRACT) != 0) { 1.1563 + for (Scope.Entry e=lc.members().elems; e != null; e=e.sibling) { 1.1564 + if (e.sym.kind == MTH && 1.1565 + (e.sym.flags() & (STATIC|ABSTRACT)) == ABSTRACT) { 1.1566 + MethodSymbol absmeth = (MethodSymbol)e.sym; 1.1567 + MethodSymbol implmeth = absmeth.implementation(origin, types, false); 1.1568 + if (implmeth != null && implmeth != absmeth && 1.1569 + (implmeth.owner.flags() & INTERFACE) == 1.1570 + (origin.flags() & INTERFACE)) { 1.1571 + // don't check if implmeth is in a class, yet 1.1572 + // origin is an interface. This case arises only 1.1573 + // if implmeth is declared in Object. The reason is 1.1574 + // that interfaces really don't inherit from 1.1575 + // Object it's just that the compiler represents 1.1576 + // things that way. 1.1577 + checkOverride(tree, implmeth, absmeth, origin); 1.1578 + } 1.1579 + } 1.1580 + } 1.1581 + } 1.1582 + } 1.1583 + } 1.1584 + 1.1585 + /** Check that all abstract methods implemented by a class are 1.1586 + * mutually compatible. 1.1587 + * @param pos Position to be used for error reporting. 1.1588 + * @param c The class whose interfaces are checked. 1.1589 + */ 1.1590 + void checkCompatibleSupertypes(DiagnosticPosition pos, Type c) { 1.1591 + List<Type> supertypes = types.interfaces(c); 1.1592 + Type supertype = types.supertype(c); 1.1593 + if (supertype.tag == CLASS && 1.1594 + (supertype.tsym.flags() & ABSTRACT) != 0) 1.1595 + supertypes = supertypes.prepend(supertype); 1.1596 + for (List<Type> l = supertypes; l.nonEmpty(); l = l.tail) { 1.1597 + if (allowGenerics && !l.head.getTypeArguments().isEmpty() && 1.1598 + !checkCompatibleAbstracts(pos, l.head, l.head, c)) 1.1599 + return; 1.1600 + for (List<Type> m = supertypes; m != l; m = m.tail) 1.1601 + if (!checkCompatibleAbstracts(pos, l.head, m.head, c)) 1.1602 + return; 1.1603 + } 1.1604 + checkCompatibleConcretes(pos, c); 1.1605 + } 1.1606 + 1.1607 + /** Check that class c does not implement directly or indirectly 1.1608 + * the same parameterized interface with two different argument lists. 1.1609 + * @param pos Position to be used for error reporting. 1.1610 + * @param type The type whose interfaces are checked. 1.1611 + */ 1.1612 + void checkClassBounds(DiagnosticPosition pos, Type type) { 1.1613 + checkClassBounds(pos, new HashMap<TypeSymbol,Type>(), type); 1.1614 + } 1.1615 +//where 1.1616 + /** Enter all interfaces of type `type' into the hash table `seensofar' 1.1617 + * with their class symbol as key and their type as value. Make 1.1618 + * sure no class is entered with two different types. 1.1619 + */ 1.1620 + void checkClassBounds(DiagnosticPosition pos, 1.1621 + Map<TypeSymbol,Type> seensofar, 1.1622 + Type type) { 1.1623 + if (type.isErroneous()) return; 1.1624 + for (List<Type> l = types.interfaces(type); l.nonEmpty(); l = l.tail) { 1.1625 + Type it = l.head; 1.1626 + Type oldit = seensofar.put(it.tsym, it); 1.1627 + if (oldit != null) { 1.1628 + List<Type> oldparams = oldit.allparams(); 1.1629 + List<Type> newparams = it.allparams(); 1.1630 + if (!types.containsTypeEquivalent(oldparams, newparams)) 1.1631 + log.error(pos, "cant.inherit.diff.arg", 1.1632 + it.tsym, Type.toString(oldparams), 1.1633 + Type.toString(newparams)); 1.1634 + } 1.1635 + checkClassBounds(pos, seensofar, it); 1.1636 + } 1.1637 + Type st = types.supertype(type); 1.1638 + if (st != null) checkClassBounds(pos, seensofar, st); 1.1639 + } 1.1640 + 1.1641 + /** Enter interface into into set. 1.1642 + * If it existed already, issue a "repeated interface" error. 1.1643 + */ 1.1644 + void checkNotRepeated(DiagnosticPosition pos, Type it, Set<Type> its) { 1.1645 + if (its.contains(it)) 1.1646 + log.error(pos, "repeated.interface"); 1.1647 + else { 1.1648 + its.add(it); 1.1649 + } 1.1650 + } 1.1651 + 1.1652 +/* ************************************************************************* 1.1653 + * Check annotations 1.1654 + **************************************************************************/ 1.1655 + 1.1656 + /** Annotation types are restricted to primitives, String, an 1.1657 + * enum, an annotation, Class, Class<?>, Class<? extends 1.1658 + * Anything>, arrays of the preceding. 1.1659 + */ 1.1660 + void validateAnnotationType(JCTree restype) { 1.1661 + // restype may be null if an error occurred, so don't bother validating it 1.1662 + if (restype != null) { 1.1663 + validateAnnotationType(restype.pos(), restype.type); 1.1664 + } 1.1665 + } 1.1666 + 1.1667 + void validateAnnotationType(DiagnosticPosition pos, Type type) { 1.1668 + if (type.isPrimitive()) return; 1.1669 + if (types.isSameType(type, syms.stringType)) return; 1.1670 + if ((type.tsym.flags() & Flags.ENUM) != 0) return; 1.1671 + if ((type.tsym.flags() & Flags.ANNOTATION) != 0) return; 1.1672 + if (types.lowerBound(type).tsym == syms.classType.tsym) return; 1.1673 + if (types.isArray(type) && !types.isArray(types.elemtype(type))) { 1.1674 + validateAnnotationType(pos, types.elemtype(type)); 1.1675 + return; 1.1676 + } 1.1677 + log.error(pos, "invalid.annotation.member.type"); 1.1678 + } 1.1679 + 1.1680 + /** 1.1681 + * "It is also a compile-time error if any method declared in an 1.1682 + * annotation type has a signature that is override-equivalent to 1.1683 + * that of any public or protected method declared in class Object 1.1684 + * or in the interface annotation.Annotation." 1.1685 + * 1.1686 + * @jls3 9.6 Annotation Types 1.1687 + */ 1.1688 + void validateAnnotationMethod(DiagnosticPosition pos, MethodSymbol m) { 1.1689 + for (Type sup = syms.annotationType; sup.tag == CLASS; sup = types.supertype(sup)) { 1.1690 + Scope s = sup.tsym.members(); 1.1691 + for (Scope.Entry e = s.lookup(m.name); e.scope != null; e = e.next()) { 1.1692 + if (e.sym.kind == MTH && 1.1693 + (e.sym.flags() & (PUBLIC | PROTECTED)) != 0 && 1.1694 + types.overrideEquivalent(m.type, e.sym.type)) 1.1695 + log.error(pos, "intf.annotation.member.clash", e.sym, sup); 1.1696 + } 1.1697 + } 1.1698 + } 1.1699 + 1.1700 + /** Check the annotations of a symbol. 1.1701 + */ 1.1702 + public void validateAnnotations(List<JCAnnotation> annotations, Symbol s) { 1.1703 + if (skipAnnotations) return; 1.1704 + for (JCAnnotation a : annotations) 1.1705 + validateAnnotation(a, s); 1.1706 + } 1.1707 + 1.1708 + /** Check an annotation of a symbol. 1.1709 + */ 1.1710 + public void validateAnnotation(JCAnnotation a, Symbol s) { 1.1711 + validateAnnotation(a); 1.1712 + 1.1713 + if (!annotationApplicable(a, s)) 1.1714 + log.error(a.pos(), "annotation.type.not.applicable"); 1.1715 + 1.1716 + if (a.annotationType.type.tsym == syms.overrideType.tsym) { 1.1717 + if (!isOverrider(s)) 1.1718 + log.error(a.pos(), "method.does.not.override.superclass"); 1.1719 + } 1.1720 + } 1.1721 + 1.1722 + /** Is s a method symbol that overrides a method in a superclass? */ 1.1723 + boolean isOverrider(Symbol s) { 1.1724 + if (s.kind != MTH || s.isStatic()) 1.1725 + return false; 1.1726 + MethodSymbol m = (MethodSymbol)s; 1.1727 + TypeSymbol owner = (TypeSymbol)m.owner; 1.1728 + for (Type sup : types.closure(owner.type)) { 1.1729 + if (sup == owner.type) 1.1730 + continue; // skip "this" 1.1731 + Scope scope = sup.tsym.members(); 1.1732 + for (Scope.Entry e = scope.lookup(m.name); e.scope != null; e = e.next()) { 1.1733 + if (!e.sym.isStatic() && m.overrides(e.sym, owner, types, true)) 1.1734 + return true; 1.1735 + } 1.1736 + } 1.1737 + return false; 1.1738 + } 1.1739 + 1.1740 + /** Is the annotation applicable to the symbol? */ 1.1741 + boolean annotationApplicable(JCAnnotation a, Symbol s) { 1.1742 + Attribute.Compound atTarget = 1.1743 + a.annotationType.type.tsym.attribute(syms.annotationTargetType.tsym); 1.1744 + if (atTarget == null) return true; 1.1745 + Attribute atValue = atTarget.member(names.value); 1.1746 + if (!(atValue instanceof Attribute.Array)) return true; // error recovery 1.1747 + Attribute.Array arr = (Attribute.Array) atValue; 1.1748 + for (Attribute app : arr.values) { 1.1749 + if (!(app instanceof Attribute.Enum)) return true; // recovery 1.1750 + Attribute.Enum e = (Attribute.Enum) app; 1.1751 + if (e.value.name == names.TYPE) 1.1752 + { if (s.kind == TYP) return true; } 1.1753 + else if (e.value.name == names.FIELD) 1.1754 + { if (s.kind == VAR && s.owner.kind != MTH) return true; } 1.1755 + else if (e.value.name == names.METHOD) 1.1756 + { if (s.kind == MTH && !s.isConstructor()) return true; } 1.1757 + else if (e.value.name == names.PARAMETER) 1.1758 + { if (s.kind == VAR && 1.1759 + s.owner.kind == MTH && 1.1760 + (s.flags() & PARAMETER) != 0) 1.1761 + return true; 1.1762 + } 1.1763 + else if (e.value.name == names.CONSTRUCTOR) 1.1764 + { if (s.kind == MTH && s.isConstructor()) return true; } 1.1765 + else if (e.value.name == names.LOCAL_VARIABLE) 1.1766 + { if (s.kind == VAR && s.owner.kind == MTH && 1.1767 + (s.flags() & PARAMETER) == 0) 1.1768 + return true; 1.1769 + } 1.1770 + else if (e.value.name == names.ANNOTATION_TYPE) 1.1771 + { if (s.kind == TYP && (s.flags() & ANNOTATION) != 0) 1.1772 + return true; 1.1773 + } 1.1774 + else if (e.value.name == names.PACKAGE) 1.1775 + { if (s.kind == PCK) return true; } 1.1776 + else 1.1777 + return true; // recovery 1.1778 + } 1.1779 + return false; 1.1780 + } 1.1781 + 1.1782 + /** Check an annotation value. 1.1783 + */ 1.1784 + public void validateAnnotation(JCAnnotation a) { 1.1785 + if (a.type.isErroneous()) return; 1.1786 + 1.1787 + // collect an inventory of the members 1.1788 + Set<MethodSymbol> members = new HashSet<MethodSymbol>(); 1.1789 + for (Scope.Entry e = a.annotationType.type.tsym.members().elems; 1.1790 + e != null; 1.1791 + e = e.sibling) 1.1792 + if (e.sym.kind == MTH) 1.1793 + members.add((MethodSymbol) e.sym); 1.1794 + 1.1795 + // count them off as they're annotated 1.1796 + for (JCTree arg : a.args) { 1.1797 + if (arg.getTag() != JCTree.ASSIGN) continue; // recovery 1.1798 + JCAssign assign = (JCAssign) arg; 1.1799 + Symbol m = TreeInfo.symbol(assign.lhs); 1.1800 + if (m == null || m.type.isErroneous()) continue; 1.1801 + if (!members.remove(m)) 1.1802 + log.error(arg.pos(), "duplicate.annotation.member.value", 1.1803 + m.name, a.type); 1.1804 + if (assign.rhs.getTag() == ANNOTATION) 1.1805 + validateAnnotation((JCAnnotation)assign.rhs); 1.1806 + } 1.1807 + 1.1808 + // all the remaining ones better have default values 1.1809 + for (MethodSymbol m : members) 1.1810 + if (m.defaultValue == null && !m.type.isErroneous()) 1.1811 + log.error(a.pos(), "annotation.missing.default.value", 1.1812 + a.type, m.name); 1.1813 + 1.1814 + // special case: java.lang.annotation.Target must not have 1.1815 + // repeated values in its value member 1.1816 + if (a.annotationType.type.tsym != syms.annotationTargetType.tsym || 1.1817 + a.args.tail == null) 1.1818 + return; 1.1819 + 1.1820 + if (a.args.head.getTag() != JCTree.ASSIGN) return; // error recovery 1.1821 + JCAssign assign = (JCAssign) a.args.head; 1.1822 + Symbol m = TreeInfo.symbol(assign.lhs); 1.1823 + if (m.name != names.value) return; 1.1824 + JCTree rhs = assign.rhs; 1.1825 + if (rhs.getTag() != JCTree.NEWARRAY) return; 1.1826 + JCNewArray na = (JCNewArray) rhs; 1.1827 + Set<Symbol> targets = new HashSet<Symbol>(); 1.1828 + for (JCTree elem : na.elems) { 1.1829 + if (!targets.add(TreeInfo.symbol(elem))) { 1.1830 + log.error(elem.pos(), "repeated.annotation.target"); 1.1831 + } 1.1832 + } 1.1833 + } 1.1834 + 1.1835 + void checkDeprecatedAnnotation(DiagnosticPosition pos, Symbol s) { 1.1836 + if (allowAnnotations && 1.1837 + lint.isEnabled(Lint.LintCategory.DEP_ANN) && 1.1838 + (s.flags() & DEPRECATED) != 0 && 1.1839 + !syms.deprecatedType.isErroneous() && 1.1840 + s.attribute(syms.deprecatedType.tsym) == null) { 1.1841 + log.warning(pos, "missing.deprecated.annotation"); 1.1842 + } 1.1843 + } 1.1844 + 1.1845 +/* ************************************************************************* 1.1846 + * Check for recursive annotation elements. 1.1847 + **************************************************************************/ 1.1848 + 1.1849 + /** Check for cycles in the graph of annotation elements. 1.1850 + */ 1.1851 + void checkNonCyclicElements(JCClassDecl tree) { 1.1852 + if ((tree.sym.flags_field & ANNOTATION) == 0) return; 1.1853 + assert (tree.sym.flags_field & LOCKED) == 0; 1.1854 + try { 1.1855 + tree.sym.flags_field |= LOCKED; 1.1856 + for (JCTree def : tree.defs) { 1.1857 + if (def.getTag() != JCTree.METHODDEF) continue; 1.1858 + JCMethodDecl meth = (JCMethodDecl)def; 1.1859 + checkAnnotationResType(meth.pos(), meth.restype.type); 1.1860 + } 1.1861 + } finally { 1.1862 + tree.sym.flags_field &= ~LOCKED; 1.1863 + tree.sym.flags_field |= ACYCLIC_ANN; 1.1864 + } 1.1865 + } 1.1866 + 1.1867 + void checkNonCyclicElementsInternal(DiagnosticPosition pos, TypeSymbol tsym) { 1.1868 + if ((tsym.flags_field & ACYCLIC_ANN) != 0) 1.1869 + return; 1.1870 + if ((tsym.flags_field & LOCKED) != 0) { 1.1871 + log.error(pos, "cyclic.annotation.element"); 1.1872 + return; 1.1873 + } 1.1874 + try { 1.1875 + tsym.flags_field |= LOCKED; 1.1876 + for (Scope.Entry e = tsym.members().elems; e != null; e = e.sibling) { 1.1877 + Symbol s = e.sym; 1.1878 + if (s.kind != Kinds.MTH) 1.1879 + continue; 1.1880 + checkAnnotationResType(pos, ((MethodSymbol)s).type.getReturnType()); 1.1881 + } 1.1882 + } finally { 1.1883 + tsym.flags_field &= ~LOCKED; 1.1884 + tsym.flags_field |= ACYCLIC_ANN; 1.1885 + } 1.1886 + } 1.1887 + 1.1888 + void checkAnnotationResType(DiagnosticPosition pos, Type type) { 1.1889 + switch (type.tag) { 1.1890 + case TypeTags.CLASS: 1.1891 + if ((type.tsym.flags() & ANNOTATION) != 0) 1.1892 + checkNonCyclicElementsInternal(pos, type.tsym); 1.1893 + break; 1.1894 + case TypeTags.ARRAY: 1.1895 + checkAnnotationResType(pos, types.elemtype(type)); 1.1896 + break; 1.1897 + default: 1.1898 + break; // int etc 1.1899 + } 1.1900 + } 1.1901 + 1.1902 +/* ************************************************************************* 1.1903 + * Check for cycles in the constructor call graph. 1.1904 + **************************************************************************/ 1.1905 + 1.1906 + /** Check for cycles in the graph of constructors calling other 1.1907 + * constructors. 1.1908 + */ 1.1909 + void checkCyclicConstructors(JCClassDecl tree) { 1.1910 + Map<Symbol,Symbol> callMap = new HashMap<Symbol, Symbol>(); 1.1911 + 1.1912 + // enter each constructor this-call into the map 1.1913 + for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { 1.1914 + JCMethodInvocation app = TreeInfo.firstConstructorCall(l.head); 1.1915 + if (app == null) continue; 1.1916 + JCMethodDecl meth = (JCMethodDecl) l.head; 1.1917 + if (TreeInfo.name(app.meth) == names._this) { 1.1918 + callMap.put(meth.sym, TreeInfo.symbol(app.meth)); 1.1919 + } else { 1.1920 + meth.sym.flags_field |= ACYCLIC; 1.1921 + } 1.1922 + } 1.1923 + 1.1924 + // Check for cycles in the map 1.1925 + Symbol[] ctors = new Symbol[0]; 1.1926 + ctors = callMap.keySet().toArray(ctors); 1.1927 + for (Symbol caller : ctors) { 1.1928 + checkCyclicConstructor(tree, caller, callMap); 1.1929 + } 1.1930 + } 1.1931 + 1.1932 + /** Look in the map to see if the given constructor is part of a 1.1933 + * call cycle. 1.1934 + */ 1.1935 + private void checkCyclicConstructor(JCClassDecl tree, Symbol ctor, 1.1936 + Map<Symbol,Symbol> callMap) { 1.1937 + if (ctor != null && (ctor.flags_field & ACYCLIC) == 0) { 1.1938 + if ((ctor.flags_field & LOCKED) != 0) { 1.1939 + log.error(TreeInfo.diagnosticPositionFor(ctor, tree), 1.1940 + "recursive.ctor.invocation"); 1.1941 + } else { 1.1942 + ctor.flags_field |= LOCKED; 1.1943 + checkCyclicConstructor(tree, callMap.remove(ctor), callMap); 1.1944 + ctor.flags_field &= ~LOCKED; 1.1945 + } 1.1946 + ctor.flags_field |= ACYCLIC; 1.1947 + } 1.1948 + } 1.1949 + 1.1950 +/* ************************************************************************* 1.1951 + * Miscellaneous 1.1952 + **************************************************************************/ 1.1953 + 1.1954 + /** 1.1955 + * Return the opcode of the operator but emit an error if it is an 1.1956 + * error. 1.1957 + * @param pos position for error reporting. 1.1958 + * @param operator an operator 1.1959 + * @param tag a tree tag 1.1960 + * @param left type of left hand side 1.1961 + * @param right type of right hand side 1.1962 + */ 1.1963 + int checkOperator(DiagnosticPosition pos, 1.1964 + OperatorSymbol operator, 1.1965 + int tag, 1.1966 + Type left, 1.1967 + Type right) { 1.1968 + if (operator.opcode == ByteCodes.error) { 1.1969 + log.error(pos, 1.1970 + "operator.cant.be.applied", 1.1971 + treeinfo.operatorName(tag), 1.1972 + left + "," + right); 1.1973 + } 1.1974 + return operator.opcode; 1.1975 + } 1.1976 + 1.1977 + 1.1978 + /** 1.1979 + * Check for division by integer constant zero 1.1980 + * @param pos Position for error reporting. 1.1981 + * @param operator The operator for the expression 1.1982 + * @param operand The right hand operand for the expression 1.1983 + */ 1.1984 + void checkDivZero(DiagnosticPosition pos, Symbol operator, Type operand) { 1.1985 + if (operand.constValue() != null 1.1986 + && lint.isEnabled(Lint.LintCategory.DIVZERO) 1.1987 + && operand.tag <= LONG 1.1988 + && ((Number) (operand.constValue())).longValue() == 0) { 1.1989 + int opc = ((OperatorSymbol)operator).opcode; 1.1990 + if (opc == ByteCodes.idiv || opc == ByteCodes.imod 1.1991 + || opc == ByteCodes.ldiv || opc == ByteCodes.lmod) { 1.1992 + log.warning(pos, "div.zero"); 1.1993 + } 1.1994 + } 1.1995 + } 1.1996 + 1.1997 + /** 1.1998 + * Check for empty statements after if 1.1999 + */ 1.2000 + void checkEmptyIf(JCIf tree) { 1.2001 + if (tree.thenpart.getTag() == JCTree.SKIP && tree.elsepart == null && lint.isEnabled(Lint.LintCategory.EMPTY)) 1.2002 + log.warning(tree.thenpart.pos(), "empty.if"); 1.2003 + } 1.2004 + 1.2005 + /** Check that symbol is unique in given scope. 1.2006 + * @param pos Position for error reporting. 1.2007 + * @param sym The symbol. 1.2008 + * @param s The scope. 1.2009 + */ 1.2010 + boolean checkUnique(DiagnosticPosition pos, Symbol sym, Scope s) { 1.2011 + if (sym.type.isErroneous()) 1.2012 + return true; 1.2013 + if (sym.owner.name == names.any) return false; 1.2014 + for (Scope.Entry e = s.lookup(sym.name); e.scope == s; e = e.next()) { 1.2015 + if (sym != e.sym && 1.2016 + sym.kind == e.sym.kind && 1.2017 + sym.name != names.error && 1.2018 + (sym.kind != MTH || types.overrideEquivalent(sym.type, e.sym.type))) { 1.2019 + if ((sym.flags() & VARARGS) != (e.sym.flags() & VARARGS)) 1.2020 + varargsDuplicateError(pos, sym, e.sym); 1.2021 + else 1.2022 + duplicateError(pos, e.sym); 1.2023 + return false; 1.2024 + } 1.2025 + } 1.2026 + return true; 1.2027 + } 1.2028 + 1.2029 + /** Check that single-type import is not already imported or top-level defined, 1.2030 + * but make an exception for two single-type imports which denote the same type. 1.2031 + * @param pos Position for error reporting. 1.2032 + * @param sym The symbol. 1.2033 + * @param s The scope 1.2034 + */ 1.2035 + boolean checkUniqueImport(DiagnosticPosition pos, Symbol sym, Scope s) { 1.2036 + return checkUniqueImport(pos, sym, s, false); 1.2037 + } 1.2038 + 1.2039 + /** Check that static single-type import is not already imported or top-level defined, 1.2040 + * but make an exception for two single-type imports which denote the same type. 1.2041 + * @param pos Position for error reporting. 1.2042 + * @param sym The symbol. 1.2043 + * @param s The scope 1.2044 + * @param staticImport Whether or not this was a static import 1.2045 + */ 1.2046 + boolean checkUniqueStaticImport(DiagnosticPosition pos, Symbol sym, Scope s) { 1.2047 + return checkUniqueImport(pos, sym, s, true); 1.2048 + } 1.2049 + 1.2050 + /** Check that single-type import is not already imported or top-level defined, 1.2051 + * but make an exception for two single-type imports which denote the same type. 1.2052 + * @param pos Position for error reporting. 1.2053 + * @param sym The symbol. 1.2054 + * @param s The scope. 1.2055 + * @param staticImport Whether or not this was a static import 1.2056 + */ 1.2057 + private boolean checkUniqueImport(DiagnosticPosition pos, Symbol sym, Scope s, boolean staticImport) { 1.2058 + for (Scope.Entry e = s.lookup(sym.name); e.scope != null; e = e.next()) { 1.2059 + // is encountered class entered via a class declaration? 1.2060 + boolean isClassDecl = e.scope == s; 1.2061 + if ((isClassDecl || sym != e.sym) && 1.2062 + sym.kind == e.sym.kind && 1.2063 + sym.name != names.error) { 1.2064 + if (!e.sym.type.isErroneous()) { 1.2065 + String what = e.sym.toString(); 1.2066 + if (!isClassDecl) { 1.2067 + if (staticImport) 1.2068 + log.error(pos, "already.defined.static.single.import", what); 1.2069 + else 1.2070 + log.error(pos, "already.defined.single.import", what); 1.2071 + } 1.2072 + else if (sym != e.sym) 1.2073 + log.error(pos, "already.defined.this.unit", what); 1.2074 + } 1.2075 + return false; 1.2076 + } 1.2077 + } 1.2078 + return true; 1.2079 + } 1.2080 + 1.2081 + /** Check that a qualified name is in canonical form (for import decls). 1.2082 + */ 1.2083 + public void checkCanonical(JCTree tree) { 1.2084 + if (!isCanonical(tree)) 1.2085 + log.error(tree.pos(), "import.requires.canonical", 1.2086 + TreeInfo.symbol(tree)); 1.2087 + } 1.2088 + // where 1.2089 + private boolean isCanonical(JCTree tree) { 1.2090 + while (tree.getTag() == JCTree.SELECT) { 1.2091 + JCFieldAccess s = (JCFieldAccess) tree; 1.2092 + if (s.sym.owner != TreeInfo.symbol(s.selected)) 1.2093 + return false; 1.2094 + tree = s.selected; 1.2095 + } 1.2096 + return true; 1.2097 + } 1.2098 + 1.2099 + private class ConversionWarner extends Warner { 1.2100 + final String key; 1.2101 + final Type found; 1.2102 + final Type expected; 1.2103 + public ConversionWarner(DiagnosticPosition pos, String key, Type found, Type expected) { 1.2104 + super(pos); 1.2105 + this.key = key; 1.2106 + this.found = found; 1.2107 + this.expected = expected; 1.2108 + } 1.2109 + 1.2110 + public void warnUnchecked() { 1.2111 + boolean warned = this.warned; 1.2112 + super.warnUnchecked(); 1.2113 + if (warned) return; // suppress redundant diagnostics 1.2114 + Object problem = JCDiagnostic.fragment(key); 1.2115 + Check.this.warnUnchecked(pos(), "prob.found.req", problem, found, expected); 1.2116 + } 1.2117 + } 1.2118 + 1.2119 + public Warner castWarner(DiagnosticPosition pos, Type found, Type expected) { 1.2120 + return new ConversionWarner(pos, "unchecked.cast.to.type", found, expected); 1.2121 + } 1.2122 + 1.2123 + public Warner convertWarner(DiagnosticPosition pos, Type found, Type expected) { 1.2124 + return new ConversionWarner(pos, "unchecked.assign", found, expected); 1.2125 + } 1.2126 +}