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 Wed Apr 27 01:34:52 2016 +0800 1.3 @@ -0,0 +1,3588 @@ 1.4 +/* 1.5 + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. 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. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 + 1.29 +package com.sun.tools.javac.comp; 1.30 + 1.31 +import java.util.*; 1.32 + 1.33 +import javax.tools.JavaFileManager; 1.34 + 1.35 +import com.sun.tools.javac.code.*; 1.36 +import com.sun.tools.javac.code.Attribute.Compound; 1.37 +import com.sun.tools.javac.jvm.*; 1.38 +import com.sun.tools.javac.tree.*; 1.39 +import com.sun.tools.javac.util.*; 1.40 +import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 1.41 +import com.sun.tools.javac.util.List; 1.42 + 1.43 +import com.sun.tools.javac.code.Lint; 1.44 +import com.sun.tools.javac.code.Lint.LintCategory; 1.45 +import com.sun.tools.javac.code.Type.*; 1.46 +import com.sun.tools.javac.code.Symbol.*; 1.47 +import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext; 1.48 +import com.sun.tools.javac.comp.Infer.InferenceContext; 1.49 +import com.sun.tools.javac.comp.Infer.FreeTypeListener; 1.50 +import com.sun.tools.javac.tree.JCTree.*; 1.51 +import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*; 1.52 + 1.53 +import static com.sun.tools.javac.code.Flags.*; 1.54 +import static com.sun.tools.javac.code.Flags.ANNOTATION; 1.55 +import static com.sun.tools.javac.code.Flags.SYNCHRONIZED; 1.56 +import static com.sun.tools.javac.code.Kinds.*; 1.57 +import static com.sun.tools.javac.code.TypeTag.*; 1.58 +import static com.sun.tools.javac.code.TypeTag.WILDCARD; 1.59 + 1.60 +import static com.sun.tools.javac.tree.JCTree.Tag.*; 1.61 + 1.62 +/** Type checking helper class for the attribution phase. 1.63 + * 1.64 + * <p><b>This is NOT part of any supported API. 1.65 + * If you write code that depends on this, you do so at your own risk. 1.66 + * This code and its internal interfaces are subject to change or 1.67 + * deletion without notice.</b> 1.68 + */ 1.69 +public class Check { 1.70 + protected static final Context.Key<Check> checkKey = 1.71 + new Context.Key<Check>(); 1.72 + 1.73 + private final Names names; 1.74 + private final Log log; 1.75 + private final Resolve rs; 1.76 + private final Symtab syms; 1.77 + private final Enter enter; 1.78 + private final DeferredAttr deferredAttr; 1.79 + private final Infer infer; 1.80 + private final Types types; 1.81 + private final JCDiagnostic.Factory diags; 1.82 + private boolean warnOnSyntheticConflicts; 1.83 + private boolean suppressAbortOnBadClassFile; 1.84 + private boolean enableSunApiLintControl; 1.85 + private final TreeInfo treeinfo; 1.86 + private final JavaFileManager fileManager; 1.87 + private final Profile profile; 1.88 + private final boolean warnOnAccessToSensitiveMembers; 1.89 + 1.90 + // The set of lint options currently in effect. It is initialized 1.91 + // from the context, and then is set/reset as needed by Attr as it 1.92 + // visits all the various parts of the trees during attribution. 1.93 + private Lint lint; 1.94 + 1.95 + // The method being analyzed in Attr - it is set/reset as needed by 1.96 + // Attr as it visits new method declarations. 1.97 + private MethodSymbol method; 1.98 + 1.99 + public static Check instance(Context context) { 1.100 + Check instance = context.get(checkKey); 1.101 + if (instance == null) 1.102 + instance = new Check(context); 1.103 + return instance; 1.104 + } 1.105 + 1.106 + protected Check(Context context) { 1.107 + context.put(checkKey, this); 1.108 + 1.109 + names = Names.instance(context); 1.110 + dfltTargetMeta = new Name[] { names.PACKAGE, names.TYPE, 1.111 + names.FIELD, names.METHOD, names.CONSTRUCTOR, 1.112 + names.ANNOTATION_TYPE, names.LOCAL_VARIABLE, names.PARAMETER}; 1.113 + log = Log.instance(context); 1.114 + rs = Resolve.instance(context); 1.115 + syms = Symtab.instance(context); 1.116 + enter = Enter.instance(context); 1.117 + deferredAttr = DeferredAttr.instance(context); 1.118 + infer = Infer.instance(context); 1.119 + types = Types.instance(context); 1.120 + diags = JCDiagnostic.Factory.instance(context); 1.121 + Options options = Options.instance(context); 1.122 + lint = Lint.instance(context); 1.123 + treeinfo = TreeInfo.instance(context); 1.124 + fileManager = context.get(JavaFileManager.class); 1.125 + 1.126 + Source source = Source.instance(context); 1.127 + allowGenerics = source.allowGenerics(); 1.128 + allowVarargs = source.allowVarargs(); 1.129 + allowAnnotations = source.allowAnnotations(); 1.130 + allowCovariantReturns = source.allowCovariantReturns(); 1.131 + allowSimplifiedVarargs = source.allowSimplifiedVarargs(); 1.132 + allowDefaultMethods = source.allowDefaultMethods(); 1.133 + allowStrictMethodClashCheck = source.allowStrictMethodClashCheck(); 1.134 + complexInference = options.isSet("complexinference"); 1.135 + warnOnSyntheticConflicts = options.isSet("warnOnSyntheticConflicts"); 1.136 + suppressAbortOnBadClassFile = options.isSet("suppressAbortOnBadClassFile"); 1.137 + enableSunApiLintControl = options.isSet("enableSunApiLintControl"); 1.138 + warnOnAccessToSensitiveMembers = options.isSet("warnOnAccessToSensitiveMembers"); 1.139 + 1.140 + Target target = Target.instance(context); 1.141 + syntheticNameChar = target.syntheticNameChar(); 1.142 + 1.143 + profile = Profile.instance(context); 1.144 + 1.145 + boolean verboseDeprecated = lint.isEnabled(LintCategory.DEPRECATION); 1.146 + boolean verboseUnchecked = lint.isEnabled(LintCategory.UNCHECKED); 1.147 + boolean verboseSunApi = lint.isEnabled(LintCategory.SUNAPI); 1.148 + boolean enforceMandatoryWarnings = source.enforceMandatoryWarnings(); 1.149 + 1.150 + deprecationHandler = new MandatoryWarningHandler(log, verboseDeprecated, 1.151 + enforceMandatoryWarnings, "deprecated", LintCategory.DEPRECATION); 1.152 + uncheckedHandler = new MandatoryWarningHandler(log, verboseUnchecked, 1.153 + enforceMandatoryWarnings, "unchecked", LintCategory.UNCHECKED); 1.154 + sunApiHandler = new MandatoryWarningHandler(log, verboseSunApi, 1.155 + enforceMandatoryWarnings, "sunapi", null); 1.156 + 1.157 + deferredLintHandler = DeferredLintHandler.instance(context); 1.158 + } 1.159 + 1.160 + /** Switch: generics enabled? 1.161 + */ 1.162 + boolean allowGenerics; 1.163 + 1.164 + /** Switch: varargs enabled? 1.165 + */ 1.166 + boolean allowVarargs; 1.167 + 1.168 + /** Switch: annotations enabled? 1.169 + */ 1.170 + boolean allowAnnotations; 1.171 + 1.172 + /** Switch: covariant returns enabled? 1.173 + */ 1.174 + boolean allowCovariantReturns; 1.175 + 1.176 + /** Switch: simplified varargs enabled? 1.177 + */ 1.178 + boolean allowSimplifiedVarargs; 1.179 + 1.180 + /** Switch: default methods enabled? 1.181 + */ 1.182 + boolean allowDefaultMethods; 1.183 + 1.184 + /** Switch: should unrelated return types trigger a method clash? 1.185 + */ 1.186 + boolean allowStrictMethodClashCheck; 1.187 + 1.188 + /** Switch: -complexinference option set? 1.189 + */ 1.190 + boolean complexInference; 1.191 + 1.192 + /** Character for synthetic names 1.193 + */ 1.194 + char syntheticNameChar; 1.195 + 1.196 + /** A table mapping flat names of all compiled classes in this run to their 1.197 + * symbols; maintained from outside. 1.198 + */ 1.199 + public Map<Name,ClassSymbol> compiled = new HashMap<Name, ClassSymbol>(); 1.200 + 1.201 + /** A handler for messages about deprecated usage. 1.202 + */ 1.203 + private MandatoryWarningHandler deprecationHandler; 1.204 + 1.205 + /** A handler for messages about unchecked or unsafe usage. 1.206 + */ 1.207 + private MandatoryWarningHandler uncheckedHandler; 1.208 + 1.209 + /** A handler for messages about using proprietary API. 1.210 + */ 1.211 + private MandatoryWarningHandler sunApiHandler; 1.212 + 1.213 + /** A handler for deferred lint warnings. 1.214 + */ 1.215 + private DeferredLintHandler deferredLintHandler; 1.216 + 1.217 +/* ************************************************************************* 1.218 + * Errors and Warnings 1.219 + **************************************************************************/ 1.220 + 1.221 + Lint setLint(Lint newLint) { 1.222 + Lint prev = lint; 1.223 + lint = newLint; 1.224 + return prev; 1.225 + } 1.226 + 1.227 + MethodSymbol setMethod(MethodSymbol newMethod) { 1.228 + MethodSymbol prev = method; 1.229 + method = newMethod; 1.230 + return prev; 1.231 + } 1.232 + 1.233 + /** Warn about deprecated symbol. 1.234 + * @param pos Position to be used for error reporting. 1.235 + * @param sym The deprecated symbol. 1.236 + */ 1.237 + void warnDeprecated(DiagnosticPosition pos, Symbol sym) { 1.238 + if (!lint.isSuppressed(LintCategory.DEPRECATION)) 1.239 + deprecationHandler.report(pos, "has.been.deprecated", sym, sym.location()); 1.240 + } 1.241 + 1.242 + /** Warn about unchecked operation. 1.243 + * @param pos Position to be used for error reporting. 1.244 + * @param msg A string describing the problem. 1.245 + */ 1.246 + public void warnUnchecked(DiagnosticPosition pos, String msg, Object... args) { 1.247 + if (!lint.isSuppressed(LintCategory.UNCHECKED)) 1.248 + uncheckedHandler.report(pos, msg, args); 1.249 + } 1.250 + 1.251 + /** Warn about unsafe vararg method decl. 1.252 + * @param pos Position to be used for error reporting. 1.253 + */ 1.254 + void warnUnsafeVararg(DiagnosticPosition pos, String key, Object... args) { 1.255 + if (lint.isEnabled(LintCategory.VARARGS) && allowSimplifiedVarargs) 1.256 + log.warning(LintCategory.VARARGS, pos, key, args); 1.257 + } 1.258 + 1.259 + /** Warn about using proprietary API. 1.260 + * @param pos Position to be used for error reporting. 1.261 + * @param msg A string describing the problem. 1.262 + */ 1.263 + public void warnSunApi(DiagnosticPosition pos, String msg, Object... args) { 1.264 + if (!lint.isSuppressed(LintCategory.SUNAPI)) 1.265 + sunApiHandler.report(pos, msg, args); 1.266 + } 1.267 + 1.268 + public void warnStatic(DiagnosticPosition pos, String msg, Object... args) { 1.269 + if (lint.isEnabled(LintCategory.STATIC)) 1.270 + log.warning(LintCategory.STATIC, pos, msg, args); 1.271 + } 1.272 + 1.273 + /** 1.274 + * Report any deferred diagnostics. 1.275 + */ 1.276 + public void reportDeferredDiagnostics() { 1.277 + deprecationHandler.reportDeferredDiagnostic(); 1.278 + uncheckedHandler.reportDeferredDiagnostic(); 1.279 + sunApiHandler.reportDeferredDiagnostic(); 1.280 + } 1.281 + 1.282 + 1.283 + /** Report a failure to complete a class. 1.284 + * @param pos Position to be used for error reporting. 1.285 + * @param ex The failure to report. 1.286 + */ 1.287 + public Type completionError(DiagnosticPosition pos, CompletionFailure ex) { 1.288 + log.error(JCDiagnostic.DiagnosticFlag.NON_DEFERRABLE, pos, "cant.access", ex.sym, ex.getDetailValue()); 1.289 + if (ex instanceof ClassReader.BadClassFile 1.290 + && !suppressAbortOnBadClassFile) throw new Abort(); 1.291 + else return syms.errType; 1.292 + } 1.293 + 1.294 + /** Report an error that wrong type tag was found. 1.295 + * @param pos Position to be used for error reporting. 1.296 + * @param required An internationalized string describing the type tag 1.297 + * required. 1.298 + * @param found The type that was found. 1.299 + */ 1.300 + Type typeTagError(DiagnosticPosition pos, Object required, Object found) { 1.301 + // this error used to be raised by the parser, 1.302 + // but has been delayed to this point: 1.303 + if (found instanceof Type && ((Type)found).hasTag(VOID)) { 1.304 + log.error(pos, "illegal.start.of.type"); 1.305 + return syms.errType; 1.306 + } 1.307 + log.error(pos, "type.found.req", found, required); 1.308 + return types.createErrorType(found instanceof Type ? (Type)found : syms.errType); 1.309 + } 1.310 + 1.311 + /** Report an error that symbol cannot be referenced before super 1.312 + * has been called. 1.313 + * @param pos Position to be used for error reporting. 1.314 + * @param sym The referenced symbol. 1.315 + */ 1.316 + void earlyRefError(DiagnosticPosition pos, Symbol sym) { 1.317 + log.error(pos, "cant.ref.before.ctor.called", sym); 1.318 + } 1.319 + 1.320 + /** Report duplicate declaration error. 1.321 + */ 1.322 + void duplicateError(DiagnosticPosition pos, Symbol sym) { 1.323 + if (!sym.type.isErroneous()) { 1.324 + Symbol location = sym.location(); 1.325 + if (location.kind == MTH && 1.326 + ((MethodSymbol)location).isStaticOrInstanceInit()) { 1.327 + log.error(pos, "already.defined.in.clinit", kindName(sym), sym, 1.328 + kindName(sym.location()), kindName(sym.location().enclClass()), 1.329 + sym.location().enclClass()); 1.330 + } else { 1.331 + log.error(pos, "already.defined", kindName(sym), sym, 1.332 + kindName(sym.location()), sym.location()); 1.333 + } 1.334 + } 1.335 + } 1.336 + 1.337 + /** Report array/varargs duplicate declaration 1.338 + */ 1.339 + void varargsDuplicateError(DiagnosticPosition pos, Symbol sym1, Symbol sym2) { 1.340 + if (!sym1.type.isErroneous() && !sym2.type.isErroneous()) { 1.341 + log.error(pos, "array.and.varargs", sym1, sym2, sym2.location()); 1.342 + } 1.343 + } 1.344 + 1.345 +/* ************************************************************************ 1.346 + * duplicate declaration checking 1.347 + *************************************************************************/ 1.348 + 1.349 + /** Check that variable does not hide variable with same name in 1.350 + * immediately enclosing local scope. 1.351 + * @param pos Position for error reporting. 1.352 + * @param v The symbol. 1.353 + * @param s The scope. 1.354 + */ 1.355 + void checkTransparentVar(DiagnosticPosition pos, VarSymbol v, Scope s) { 1.356 + if (s.next != null) { 1.357 + for (Scope.Entry e = s.next.lookup(v.name); 1.358 + e.scope != null && e.sym.owner == v.owner; 1.359 + e = e.next()) { 1.360 + if (e.sym.kind == VAR && 1.361 + (e.sym.owner.kind & (VAR | MTH)) != 0 && 1.362 + v.name != names.error) { 1.363 + duplicateError(pos, e.sym); 1.364 + return; 1.365 + } 1.366 + } 1.367 + } 1.368 + } 1.369 + 1.370 + /** Check that a class or interface does not hide a class or 1.371 + * interface with same name in immediately enclosing local scope. 1.372 + * @param pos Position for error reporting. 1.373 + * @param c The symbol. 1.374 + * @param s The scope. 1.375 + */ 1.376 + void checkTransparentClass(DiagnosticPosition pos, ClassSymbol c, Scope s) { 1.377 + if (s.next != null) { 1.378 + for (Scope.Entry e = s.next.lookup(c.name); 1.379 + e.scope != null && e.sym.owner == c.owner; 1.380 + e = e.next()) { 1.381 + if (e.sym.kind == TYP && !e.sym.type.hasTag(TYPEVAR) && 1.382 + (e.sym.owner.kind & (VAR | MTH)) != 0 && 1.383 + c.name != names.error) { 1.384 + duplicateError(pos, e.sym); 1.385 + return; 1.386 + } 1.387 + } 1.388 + } 1.389 + } 1.390 + 1.391 + /** Check that class does not have the same name as one of 1.392 + * its enclosing classes, or as a class defined in its enclosing scope. 1.393 + * return true if class is unique in its enclosing scope. 1.394 + * @param pos Position for error reporting. 1.395 + * @param name The class name. 1.396 + * @param s The enclosing scope. 1.397 + */ 1.398 + boolean checkUniqueClassName(DiagnosticPosition pos, Name name, Scope s) { 1.399 + for (Scope.Entry e = s.lookup(name); e.scope == s; e = e.next()) { 1.400 + if (e.sym.kind == TYP && e.sym.name != names.error) { 1.401 + duplicateError(pos, e.sym); 1.402 + return false; 1.403 + } 1.404 + } 1.405 + for (Symbol sym = s.owner; sym != null; sym = sym.owner) { 1.406 + if (sym.kind == TYP && sym.name == name && sym.name != names.error) { 1.407 + duplicateError(pos, sym); 1.408 + return true; 1.409 + } 1.410 + } 1.411 + return true; 1.412 + } 1.413 + 1.414 +/* ************************************************************************* 1.415 + * Class name generation 1.416 + **************************************************************************/ 1.417 + 1.418 + /** Return name of local class. 1.419 + * This is of the form {@code <enclClass> $ n <classname> } 1.420 + * where 1.421 + * enclClass is the flat name of the enclosing class, 1.422 + * classname is the simple name of the local class 1.423 + */ 1.424 + Name localClassName(ClassSymbol c) { 1.425 + for (int i=1; ; i++) { 1.426 + Name flatname = names. 1.427 + fromString("" + c.owner.enclClass().flatname + 1.428 + syntheticNameChar + i + 1.429 + c.name); 1.430 + if (compiled.get(flatname) == null) return flatname; 1.431 + } 1.432 + } 1.433 + 1.434 +/* ************************************************************************* 1.435 + * Type Checking 1.436 + **************************************************************************/ 1.437 + 1.438 + /** 1.439 + * A check context is an object that can be used to perform compatibility 1.440 + * checks - depending on the check context, meaning of 'compatibility' might 1.441 + * vary significantly. 1.442 + */ 1.443 + public interface CheckContext { 1.444 + /** 1.445 + * Is type 'found' compatible with type 'req' in given context 1.446 + */ 1.447 + boolean compatible(Type found, Type req, Warner warn); 1.448 + /** 1.449 + * Report a check error 1.450 + */ 1.451 + void report(DiagnosticPosition pos, JCDiagnostic details); 1.452 + /** 1.453 + * Obtain a warner for this check context 1.454 + */ 1.455 + public Warner checkWarner(DiagnosticPosition pos, Type found, Type req); 1.456 + 1.457 + public Infer.InferenceContext inferenceContext(); 1.458 + 1.459 + public DeferredAttr.DeferredAttrContext deferredAttrContext(); 1.460 + } 1.461 + 1.462 + /** 1.463 + * This class represent a check context that is nested within another check 1.464 + * context - useful to check sub-expressions. The default behavior simply 1.465 + * redirects all method calls to the enclosing check context leveraging 1.466 + * the forwarding pattern. 1.467 + */ 1.468 + static class NestedCheckContext implements CheckContext { 1.469 + CheckContext enclosingContext; 1.470 + 1.471 + NestedCheckContext(CheckContext enclosingContext) { 1.472 + this.enclosingContext = enclosingContext; 1.473 + } 1.474 + 1.475 + public boolean compatible(Type found, Type req, Warner warn) { 1.476 + return enclosingContext.compatible(found, req, warn); 1.477 + } 1.478 + 1.479 + public void report(DiagnosticPosition pos, JCDiagnostic details) { 1.480 + enclosingContext.report(pos, details); 1.481 + } 1.482 + 1.483 + public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) { 1.484 + return enclosingContext.checkWarner(pos, found, req); 1.485 + } 1.486 + 1.487 + public Infer.InferenceContext inferenceContext() { 1.488 + return enclosingContext.inferenceContext(); 1.489 + } 1.490 + 1.491 + public DeferredAttrContext deferredAttrContext() { 1.492 + return enclosingContext.deferredAttrContext(); 1.493 + } 1.494 + } 1.495 + 1.496 + /** 1.497 + * Check context to be used when evaluating assignment/return statements 1.498 + */ 1.499 + CheckContext basicHandler = new CheckContext() { 1.500 + public void report(DiagnosticPosition pos, JCDiagnostic details) { 1.501 + log.error(pos, "prob.found.req", details); 1.502 + } 1.503 + public boolean compatible(Type found, Type req, Warner warn) { 1.504 + return types.isAssignable(found, req, warn); 1.505 + } 1.506 + 1.507 + public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) { 1.508 + return convertWarner(pos, found, req); 1.509 + } 1.510 + 1.511 + public InferenceContext inferenceContext() { 1.512 + return infer.emptyContext; 1.513 + } 1.514 + 1.515 + public DeferredAttrContext deferredAttrContext() { 1.516 + return deferredAttr.emptyDeferredAttrContext; 1.517 + } 1.518 + 1.519 + @Override 1.520 + public String toString() { 1.521 + return "CheckContext: basicHandler"; 1.522 + } 1.523 + }; 1.524 + 1.525 + /** Check that a given type is assignable to a given proto-type. 1.526 + * If it is, return the type, otherwise return errType. 1.527 + * @param pos Position to be used for error reporting. 1.528 + * @param found The type that was found. 1.529 + * @param req The type that was required. 1.530 + */ 1.531 + Type checkType(DiagnosticPosition pos, Type found, Type req) { 1.532 + return checkType(pos, found, req, basicHandler); 1.533 + } 1.534 + 1.535 + Type checkType(final DiagnosticPosition pos, final Type found, final Type req, final CheckContext checkContext) { 1.536 + final Infer.InferenceContext inferenceContext = checkContext.inferenceContext(); 1.537 + if (inferenceContext.free(req)) { 1.538 + inferenceContext.addFreeTypeListener(List.of(req), new FreeTypeListener() { 1.539 + @Override 1.540 + public void typesInferred(InferenceContext inferenceContext) { 1.541 + checkType(pos, inferenceContext.asInstType(found), inferenceContext.asInstType(req), checkContext); 1.542 + } 1.543 + }); 1.544 + } 1.545 + if (req.hasTag(ERROR)) 1.546 + return req; 1.547 + if (req.hasTag(NONE)) 1.548 + return found; 1.549 + if (checkContext.compatible(found, req, checkContext.checkWarner(pos, found, req))) { 1.550 + return found; 1.551 + } else { 1.552 + if (found.isNumeric() && req.isNumeric()) { 1.553 + checkContext.report(pos, diags.fragment("possible.loss.of.precision", found, req)); 1.554 + return types.createErrorType(found); 1.555 + } 1.556 + checkContext.report(pos, diags.fragment("inconvertible.types", found, req)); 1.557 + return types.createErrorType(found); 1.558 + } 1.559 + } 1.560 + 1.561 + /** Check that a given type can be cast to a given target type. 1.562 + * Return the result of the cast. 1.563 + * @param pos Position to be used for error reporting. 1.564 + * @param found The type that is being cast. 1.565 + * @param req The target type of the cast. 1.566 + */ 1.567 + Type checkCastable(DiagnosticPosition pos, Type found, Type req) { 1.568 + return checkCastable(pos, found, req, basicHandler); 1.569 + } 1.570 + Type checkCastable(DiagnosticPosition pos, Type found, Type req, CheckContext checkContext) { 1.571 + if (types.isCastable(found, req, castWarner(pos, found, req))) { 1.572 + return req; 1.573 + } else { 1.574 + checkContext.report(pos, diags.fragment("inconvertible.types", found, req)); 1.575 + return types.createErrorType(found); 1.576 + } 1.577 + } 1.578 + 1.579 + /** Check for redundant casts (i.e. where source type is a subtype of target type) 1.580 + * The problem should only be reported for non-292 cast 1.581 + */ 1.582 + public void checkRedundantCast(Env<AttrContext> env, final JCTypeCast tree) { 1.583 + if (!tree.type.isErroneous() 1.584 + && types.isSameType(tree.expr.type, tree.clazz.type) 1.585 + && !(ignoreAnnotatedCasts && TreeInfo.containsTypeAnnotation(tree.clazz)) 1.586 + && !is292targetTypeCast(tree)) { 1.587 + deferredLintHandler.report(new DeferredLintHandler.LintLogger() { 1.588 + @Override 1.589 + public void report() { 1.590 + if (lint.isEnabled(Lint.LintCategory.CAST)) 1.591 + log.warning(Lint.LintCategory.CAST, 1.592 + tree.pos(), "redundant.cast", tree.expr.type); 1.593 + } 1.594 + }); 1.595 + } 1.596 + } 1.597 + //where 1.598 + private boolean is292targetTypeCast(JCTypeCast tree) { 1.599 + boolean is292targetTypeCast = false; 1.600 + JCExpression expr = TreeInfo.skipParens(tree.expr); 1.601 + if (expr.hasTag(APPLY)) { 1.602 + JCMethodInvocation apply = (JCMethodInvocation)expr; 1.603 + Symbol sym = TreeInfo.symbol(apply.meth); 1.604 + is292targetTypeCast = sym != null && 1.605 + sym.kind == MTH && 1.606 + (sym.flags() & HYPOTHETICAL) != 0; 1.607 + } 1.608 + return is292targetTypeCast; 1.609 + } 1.610 + 1.611 + private static final boolean ignoreAnnotatedCasts = true; 1.612 + 1.613 + /** Check that a type is within some bounds. 1.614 + * 1.615 + * Used in TypeApply to verify that, e.g., X in {@code V<X>} is a valid 1.616 + * type argument. 1.617 + * @param a The type that should be bounded by bs. 1.618 + * @param bound The bound. 1.619 + */ 1.620 + private boolean checkExtends(Type a, Type bound) { 1.621 + if (a.isUnbound()) { 1.622 + return true; 1.623 + } else if (!a.hasTag(WILDCARD)) { 1.624 + a = types.cvarUpperBound(a); 1.625 + return types.isSubtype(a, bound); 1.626 + } else if (a.isExtendsBound()) { 1.627 + return types.isCastable(bound, types.wildUpperBound(a), types.noWarnings); 1.628 + } else if (a.isSuperBound()) { 1.629 + return !types.notSoftSubtype(types.wildLowerBound(a), bound); 1.630 + } 1.631 + return true; 1.632 + } 1.633 + 1.634 + /** Check that type is different from 'void'. 1.635 + * @param pos Position to be used for error reporting. 1.636 + * @param t The type to be checked. 1.637 + */ 1.638 + Type checkNonVoid(DiagnosticPosition pos, Type t) { 1.639 + if (t.hasTag(VOID)) { 1.640 + log.error(pos, "void.not.allowed.here"); 1.641 + return types.createErrorType(t); 1.642 + } else { 1.643 + return t; 1.644 + } 1.645 + } 1.646 + 1.647 + Type checkClassOrArrayType(DiagnosticPosition pos, Type t) { 1.648 + if (!t.hasTag(CLASS) && !t.hasTag(ARRAY) && !t.hasTag(ERROR)) { 1.649 + return typeTagError(pos, 1.650 + diags.fragment("type.req.class.array"), 1.651 + asTypeParam(t)); 1.652 + } else { 1.653 + return t; 1.654 + } 1.655 + } 1.656 + 1.657 + /** Check that type is a class or interface type. 1.658 + * @param pos Position to be used for error reporting. 1.659 + * @param t The type to be checked. 1.660 + */ 1.661 + Type checkClassType(DiagnosticPosition pos, Type t) { 1.662 + if (!t.hasTag(CLASS) && !t.hasTag(ERROR)) { 1.663 + return typeTagError(pos, 1.664 + diags.fragment("type.req.class"), 1.665 + asTypeParam(t)); 1.666 + } else { 1.667 + return t; 1.668 + } 1.669 + } 1.670 + //where 1.671 + private Object asTypeParam(Type t) { 1.672 + return (t.hasTag(TYPEVAR)) 1.673 + ? diags.fragment("type.parameter", t) 1.674 + : t; 1.675 + } 1.676 + 1.677 + /** Check that type is a valid qualifier for a constructor reference expression 1.678 + */ 1.679 + Type checkConstructorRefType(DiagnosticPosition pos, Type t) { 1.680 + t = checkClassOrArrayType(pos, t); 1.681 + if (t.hasTag(CLASS)) { 1.682 + if ((t.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) { 1.683 + log.error(pos, "abstract.cant.be.instantiated", t.tsym); 1.684 + t = types.createErrorType(t); 1.685 + } else if ((t.tsym.flags() & ENUM) != 0) { 1.686 + log.error(pos, "enum.cant.be.instantiated"); 1.687 + t = types.createErrorType(t); 1.688 + } else { 1.689 + t = checkClassType(pos, t, true); 1.690 + } 1.691 + } else if (t.hasTag(ARRAY)) { 1.692 + if (!types.isReifiable(((ArrayType)t).elemtype)) { 1.693 + log.error(pos, "generic.array.creation"); 1.694 + t = types.createErrorType(t); 1.695 + } 1.696 + } 1.697 + return t; 1.698 + } 1.699 + 1.700 + /** Check that type is a class or interface type. 1.701 + * @param pos Position to be used for error reporting. 1.702 + * @param t The type to be checked. 1.703 + * @param noBounds True if type bounds are illegal here. 1.704 + */ 1.705 + Type checkClassType(DiagnosticPosition pos, Type t, boolean noBounds) { 1.706 + t = checkClassType(pos, t); 1.707 + if (noBounds && t.isParameterized()) { 1.708 + List<Type> args = t.getTypeArguments(); 1.709 + while (args.nonEmpty()) { 1.710 + if (args.head.hasTag(WILDCARD)) 1.711 + return typeTagError(pos, 1.712 + diags.fragment("type.req.exact"), 1.713 + args.head); 1.714 + args = args.tail; 1.715 + } 1.716 + } 1.717 + return t; 1.718 + } 1.719 + 1.720 + /** Check that type is a reference type, i.e. a class, interface or array type 1.721 + * or a type variable. 1.722 + * @param pos Position to be used for error reporting. 1.723 + * @param t The type to be checked. 1.724 + */ 1.725 + Type checkRefType(DiagnosticPosition pos, Type t) { 1.726 + if (t.isReference()) 1.727 + return t; 1.728 + else 1.729 + return typeTagError(pos, 1.730 + diags.fragment("type.req.ref"), 1.731 + t); 1.732 + } 1.733 + 1.734 + /** Check that each type is a reference type, i.e. a class, interface or array type 1.735 + * or a type variable. 1.736 + * @param trees Original trees, used for error reporting. 1.737 + * @param types The types to be checked. 1.738 + */ 1.739 + List<Type> checkRefTypes(List<JCExpression> trees, List<Type> types) { 1.740 + List<JCExpression> tl = trees; 1.741 + for (List<Type> l = types; l.nonEmpty(); l = l.tail) { 1.742 + l.head = checkRefType(tl.head.pos(), l.head); 1.743 + tl = tl.tail; 1.744 + } 1.745 + return types; 1.746 + } 1.747 + 1.748 + /** Check that type is a null or reference type. 1.749 + * @param pos Position to be used for error reporting. 1.750 + * @param t The type to be checked. 1.751 + */ 1.752 + Type checkNullOrRefType(DiagnosticPosition pos, Type t) { 1.753 + if (t.isReference() || t.hasTag(BOT)) 1.754 + return t; 1.755 + else 1.756 + return typeTagError(pos, 1.757 + diags.fragment("type.req.ref"), 1.758 + t); 1.759 + } 1.760 + 1.761 + /** Check that flag set does not contain elements of two conflicting sets. s 1.762 + * Return true if it doesn't. 1.763 + * @param pos Position to be used for error reporting. 1.764 + * @param flags The set of flags to be checked. 1.765 + * @param set1 Conflicting flags set #1. 1.766 + * @param set2 Conflicting flags set #2. 1.767 + */ 1.768 + boolean checkDisjoint(DiagnosticPosition pos, long flags, long set1, long set2) { 1.769 + if ((flags & set1) != 0 && (flags & set2) != 0) { 1.770 + log.error(pos, 1.771 + "illegal.combination.of.modifiers", 1.772 + asFlagSet(TreeInfo.firstFlag(flags & set1)), 1.773 + asFlagSet(TreeInfo.firstFlag(flags & set2))); 1.774 + return false; 1.775 + } else 1.776 + return true; 1.777 + } 1.778 + 1.779 + /** Check that usage of diamond operator is correct (i.e. diamond should not 1.780 + * be used with non-generic classes or in anonymous class creation expressions) 1.781 + */ 1.782 + Type checkDiamond(JCNewClass tree, Type t) { 1.783 + if (!TreeInfo.isDiamond(tree) || 1.784 + t.isErroneous()) { 1.785 + return checkClassType(tree.clazz.pos(), t, true); 1.786 + } else if (tree.def != null) { 1.787 + log.error(tree.clazz.pos(), 1.788 + "cant.apply.diamond.1", 1.789 + t, diags.fragment("diamond.and.anon.class", t)); 1.790 + return types.createErrorType(t); 1.791 + } else if (t.tsym.type.getTypeArguments().isEmpty()) { 1.792 + log.error(tree.clazz.pos(), 1.793 + "cant.apply.diamond.1", 1.794 + t, diags.fragment("diamond.non.generic", t)); 1.795 + return types.createErrorType(t); 1.796 + } else if (tree.typeargs != null && 1.797 + tree.typeargs.nonEmpty()) { 1.798 + log.error(tree.clazz.pos(), 1.799 + "cant.apply.diamond.1", 1.800 + t, diags.fragment("diamond.and.explicit.params", t)); 1.801 + return types.createErrorType(t); 1.802 + } else { 1.803 + return t; 1.804 + } 1.805 + } 1.806 + 1.807 + void checkVarargsMethodDecl(Env<AttrContext> env, JCMethodDecl tree) { 1.808 + MethodSymbol m = tree.sym; 1.809 + if (!allowSimplifiedVarargs) return; 1.810 + boolean hasTrustMeAnno = m.attribute(syms.trustMeType.tsym) != null; 1.811 + Type varargElemType = null; 1.812 + if (m.isVarArgs()) { 1.813 + varargElemType = types.elemtype(tree.params.last().type); 1.814 + } 1.815 + if (hasTrustMeAnno && !isTrustMeAllowedOnMethod(m)) { 1.816 + if (varargElemType != null) { 1.817 + log.error(tree, 1.818 + "varargs.invalid.trustme.anno", 1.819 + syms.trustMeType.tsym, 1.820 + diags.fragment("varargs.trustme.on.virtual.varargs", m)); 1.821 + } else { 1.822 + log.error(tree, 1.823 + "varargs.invalid.trustme.anno", 1.824 + syms.trustMeType.tsym, 1.825 + diags.fragment("varargs.trustme.on.non.varargs.meth", m)); 1.826 + } 1.827 + } else if (hasTrustMeAnno && varargElemType != null && 1.828 + types.isReifiable(varargElemType)) { 1.829 + warnUnsafeVararg(tree, 1.830 + "varargs.redundant.trustme.anno", 1.831 + syms.trustMeType.tsym, 1.832 + diags.fragment("varargs.trustme.on.reifiable.varargs", varargElemType)); 1.833 + } 1.834 + else if (!hasTrustMeAnno && varargElemType != null && 1.835 + !types.isReifiable(varargElemType)) { 1.836 + warnUnchecked(tree.params.head.pos(), "unchecked.varargs.non.reifiable.type", varargElemType); 1.837 + } 1.838 + } 1.839 + //where 1.840 + private boolean isTrustMeAllowedOnMethod(Symbol s) { 1.841 + return (s.flags() & VARARGS) != 0 && 1.842 + (s.isConstructor() || 1.843 + (s.flags() & (STATIC | FINAL)) != 0); 1.844 + } 1.845 + 1.846 + Type checkMethod(final Type mtype, 1.847 + final Symbol sym, 1.848 + final Env<AttrContext> env, 1.849 + final List<JCExpression> argtrees, 1.850 + final List<Type> argtypes, 1.851 + final boolean useVarargs, 1.852 + InferenceContext inferenceContext) { 1.853 + // System.out.println("call : " + env.tree); 1.854 + // System.out.println("method : " + owntype); 1.855 + // System.out.println("actuals: " + argtypes); 1.856 + if (inferenceContext.free(mtype)) { 1.857 + inferenceContext.addFreeTypeListener(List.of(mtype), new FreeTypeListener() { 1.858 + public void typesInferred(InferenceContext inferenceContext) { 1.859 + checkMethod(inferenceContext.asInstType(mtype), sym, env, argtrees, argtypes, useVarargs, inferenceContext); 1.860 + } 1.861 + }); 1.862 + return mtype; 1.863 + } 1.864 + Type owntype = mtype; 1.865 + List<Type> formals = owntype.getParameterTypes(); 1.866 + List<Type> nonInferred = sym.type.getParameterTypes(); 1.867 + if (nonInferred.length() != formals.length()) nonInferred = formals; 1.868 + Type last = useVarargs ? formals.last() : null; 1.869 + if (sym.name == names.init && sym.owner == syms.enumSym) { 1.870 + formals = formals.tail.tail; 1.871 + nonInferred = nonInferred.tail.tail; 1.872 + } 1.873 + List<JCExpression> args = argtrees; 1.874 + if (args != null) { 1.875 + //this is null when type-checking a method reference 1.876 + while (formals.head != last) { 1.877 + JCTree arg = args.head; 1.878 + Warner warn = convertWarner(arg.pos(), arg.type, nonInferred.head); 1.879 + assertConvertible(arg, arg.type, formals.head, warn); 1.880 + args = args.tail; 1.881 + formals = formals.tail; 1.882 + nonInferred = nonInferred.tail; 1.883 + } 1.884 + if (useVarargs) { 1.885 + Type varArg = types.elemtype(last); 1.886 + while (args.tail != null) { 1.887 + JCTree arg = args.head; 1.888 + Warner warn = convertWarner(arg.pos(), arg.type, varArg); 1.889 + assertConvertible(arg, arg.type, varArg, warn); 1.890 + args = args.tail; 1.891 + } 1.892 + } else if ((sym.flags() & (VARARGS | SIGNATURE_POLYMORPHIC)) == VARARGS && 1.893 + allowVarargs) { 1.894 + // non-varargs call to varargs method 1.895 + Type varParam = owntype.getParameterTypes().last(); 1.896 + Type lastArg = argtypes.last(); 1.897 + if (types.isSubtypeUnchecked(lastArg, types.elemtype(varParam)) && 1.898 + !types.isSameType(types.erasure(varParam), types.erasure(lastArg))) 1.899 + log.warning(argtrees.last().pos(), "inexact.non-varargs.call", 1.900 + types.elemtype(varParam), varParam); 1.901 + } 1.902 + } 1.903 + if (useVarargs) { 1.904 + Type argtype = owntype.getParameterTypes().last(); 1.905 + if (!types.isReifiable(argtype) && 1.906 + (!allowSimplifiedVarargs || 1.907 + sym.attribute(syms.trustMeType.tsym) == null || 1.908 + !isTrustMeAllowedOnMethod(sym))) { 1.909 + warnUnchecked(env.tree.pos(), 1.910 + "unchecked.generic.array.creation", 1.911 + argtype); 1.912 + } 1.913 + if ((sym.baseSymbol().flags() & SIGNATURE_POLYMORPHIC) == 0) { 1.914 + TreeInfo.setVarargsElement(env.tree, types.elemtype(argtype)); 1.915 + } 1.916 + } 1.917 + PolyKind pkind = (sym.type.hasTag(FORALL) && 1.918 + sym.type.getReturnType().containsAny(((ForAll)sym.type).tvars)) ? 1.919 + PolyKind.POLY : PolyKind.STANDALONE; 1.920 + TreeInfo.setPolyKind(env.tree, pkind); 1.921 + return owntype; 1.922 + } 1.923 + //where 1.924 + private void assertConvertible(JCTree tree, Type actual, Type formal, Warner warn) { 1.925 + if (types.isConvertible(actual, formal, warn)) 1.926 + return; 1.927 + 1.928 + if (formal.isCompound() 1.929 + && types.isSubtype(actual, types.supertype(formal)) 1.930 + && types.isSubtypeUnchecked(actual, types.interfaces(formal), warn)) 1.931 + return; 1.932 + } 1.933 + 1.934 + /** 1.935 + * Check that type 't' is a valid instantiation of a generic class 1.936 + * (see JLS 4.5) 1.937 + * 1.938 + * @param t class type to be checked 1.939 + * @return true if 't' is well-formed 1.940 + */ 1.941 + public boolean checkValidGenericType(Type t) { 1.942 + return firstIncompatibleTypeArg(t) == null; 1.943 + } 1.944 + //WHERE 1.945 + private Type firstIncompatibleTypeArg(Type type) { 1.946 + List<Type> formals = type.tsym.type.allparams(); 1.947 + List<Type> actuals = type.allparams(); 1.948 + List<Type> args = type.getTypeArguments(); 1.949 + List<Type> forms = type.tsym.type.getTypeArguments(); 1.950 + ListBuffer<Type> bounds_buf = new ListBuffer<Type>(); 1.951 + 1.952 + // For matching pairs of actual argument types `a' and 1.953 + // formal type parameters with declared bound `b' ... 1.954 + while (args.nonEmpty() && forms.nonEmpty()) { 1.955 + // exact type arguments needs to know their 1.956 + // bounds (for upper and lower bound 1.957 + // calculations). So we create new bounds where 1.958 + // type-parameters are replaced with actuals argument types. 1.959 + bounds_buf.append(types.subst(forms.head.getUpperBound(), formals, actuals)); 1.960 + args = args.tail; 1.961 + forms = forms.tail; 1.962 + } 1.963 + 1.964 + args = type.getTypeArguments(); 1.965 + List<Type> tvars_cap = types.substBounds(formals, 1.966 + formals, 1.967 + types.capture(type).allparams()); 1.968 + while (args.nonEmpty() && tvars_cap.nonEmpty()) { 1.969 + // Let the actual arguments know their bound 1.970 + args.head.withTypeVar((TypeVar)tvars_cap.head); 1.971 + args = args.tail; 1.972 + tvars_cap = tvars_cap.tail; 1.973 + } 1.974 + 1.975 + args = type.getTypeArguments(); 1.976 + List<Type> bounds = bounds_buf.toList(); 1.977 + 1.978 + while (args.nonEmpty() && bounds.nonEmpty()) { 1.979 + Type actual = args.head; 1.980 + if (!isTypeArgErroneous(actual) && 1.981 + !bounds.head.isErroneous() && 1.982 + !checkExtends(actual, bounds.head)) { 1.983 + return args.head; 1.984 + } 1.985 + args = args.tail; 1.986 + bounds = bounds.tail; 1.987 + } 1.988 + 1.989 + args = type.getTypeArguments(); 1.990 + bounds = bounds_buf.toList(); 1.991 + 1.992 + for (Type arg : types.capture(type).getTypeArguments()) { 1.993 + if (arg.hasTag(TYPEVAR) && 1.994 + arg.getUpperBound().isErroneous() && 1.995 + !bounds.head.isErroneous() && 1.996 + !isTypeArgErroneous(args.head)) { 1.997 + return args.head; 1.998 + } 1.999 + bounds = bounds.tail; 1.1000 + args = args.tail; 1.1001 + } 1.1002 + 1.1003 + return null; 1.1004 + } 1.1005 + //where 1.1006 + boolean isTypeArgErroneous(Type t) { 1.1007 + return isTypeArgErroneous.visit(t); 1.1008 + } 1.1009 + 1.1010 + Types.UnaryVisitor<Boolean> isTypeArgErroneous = new Types.UnaryVisitor<Boolean>() { 1.1011 + public Boolean visitType(Type t, Void s) { 1.1012 + return t.isErroneous(); 1.1013 + } 1.1014 + @Override 1.1015 + public Boolean visitTypeVar(TypeVar t, Void s) { 1.1016 + return visit(t.getUpperBound()); 1.1017 + } 1.1018 + @Override 1.1019 + public Boolean visitCapturedType(CapturedType t, Void s) { 1.1020 + return visit(t.getUpperBound()) || 1.1021 + visit(t.getLowerBound()); 1.1022 + } 1.1023 + @Override 1.1024 + public Boolean visitWildcardType(WildcardType t, Void s) { 1.1025 + return visit(t.type); 1.1026 + } 1.1027 + }; 1.1028 + 1.1029 + /** Check that given modifiers are legal for given symbol and 1.1030 + * return modifiers together with any implicit modifiers for that symbol. 1.1031 + * Warning: we can't use flags() here since this method 1.1032 + * is called during class enter, when flags() would cause a premature 1.1033 + * completion. 1.1034 + * @param pos Position to be used for error reporting. 1.1035 + * @param flags The set of modifiers given in a definition. 1.1036 + * @param sym The defined symbol. 1.1037 + */ 1.1038 + long checkFlags(DiagnosticPosition pos, long flags, Symbol sym, JCTree tree) { 1.1039 + long mask; 1.1040 + long implicit = 0; 1.1041 + 1.1042 + switch (sym.kind) { 1.1043 + case VAR: 1.1044 + if (TreeInfo.isReceiverParam(tree)) 1.1045 + mask = ReceiverParamFlags; 1.1046 + else if (sym.owner.kind != TYP) 1.1047 + mask = LocalVarFlags; 1.1048 + else if ((sym.owner.flags_field & INTERFACE) != 0) 1.1049 + mask = implicit = InterfaceVarFlags; 1.1050 + else 1.1051 + mask = VarFlags; 1.1052 + break; 1.1053 + case MTH: 1.1054 + if (sym.name == names.init) { 1.1055 + if ((sym.owner.flags_field & ENUM) != 0) { 1.1056 + // enum constructors cannot be declared public or 1.1057 + // protected and must be implicitly or explicitly 1.1058 + // private 1.1059 + implicit = PRIVATE; 1.1060 + mask = PRIVATE; 1.1061 + } else 1.1062 + mask = ConstructorFlags; 1.1063 + } else if ((sym.owner.flags_field & INTERFACE) != 0) { 1.1064 + if ((sym.owner.flags_field & ANNOTATION) != 0) { 1.1065 + mask = AnnotationTypeElementMask; 1.1066 + implicit = PUBLIC | ABSTRACT; 1.1067 + } else if ((flags & (DEFAULT | STATIC)) != 0) { 1.1068 + mask = InterfaceMethodMask; 1.1069 + implicit = PUBLIC; 1.1070 + if ((flags & DEFAULT) != 0) { 1.1071 + implicit |= ABSTRACT; 1.1072 + } 1.1073 + } else { 1.1074 + mask = implicit = InterfaceMethodFlags; 1.1075 + } 1.1076 + } else { 1.1077 + mask = MethodFlags; 1.1078 + } 1.1079 + // Imply STRICTFP if owner has STRICTFP set. 1.1080 + if (((flags|implicit) & Flags.ABSTRACT) == 0 || 1.1081 + ((flags) & Flags.DEFAULT) != 0) 1.1082 + implicit |= sym.owner.flags_field & STRICTFP; 1.1083 + break; 1.1084 + case TYP: 1.1085 + if (sym.isLocal()) { 1.1086 + mask = LocalClassFlags; 1.1087 + if (sym.name.isEmpty()) { // Anonymous class 1.1088 + // Anonymous classes in static methods are themselves static; 1.1089 + // that's why we admit STATIC here. 1.1090 + mask |= STATIC; 1.1091 + // JLS: Anonymous classes are final. 1.1092 + implicit |= FINAL; 1.1093 + } 1.1094 + if ((sym.owner.flags_field & STATIC) == 0 && 1.1095 + (flags & ENUM) != 0) 1.1096 + log.error(pos, "enums.must.be.static"); 1.1097 + } else if (sym.owner.kind == TYP) { 1.1098 + mask = MemberClassFlags; 1.1099 + if (sym.owner.owner.kind == PCK || 1.1100 + (sym.owner.flags_field & STATIC) != 0) 1.1101 + mask |= STATIC; 1.1102 + else if ((flags & ENUM) != 0) 1.1103 + log.error(pos, "enums.must.be.static"); 1.1104 + // Nested interfaces and enums are always STATIC (Spec ???) 1.1105 + if ((flags & (INTERFACE | ENUM)) != 0 ) implicit = STATIC; 1.1106 + } else { 1.1107 + mask = ClassFlags; 1.1108 + } 1.1109 + // Interfaces are always ABSTRACT 1.1110 + if ((flags & INTERFACE) != 0) implicit |= ABSTRACT; 1.1111 + 1.1112 + if ((flags & ENUM) != 0) { 1.1113 + // enums can't be declared abstract or final 1.1114 + mask &= ~(ABSTRACT | FINAL); 1.1115 + implicit |= implicitEnumFinalFlag(tree); 1.1116 + } 1.1117 + // Imply STRICTFP if owner has STRICTFP set. 1.1118 + implicit |= sym.owner.flags_field & STRICTFP; 1.1119 + break; 1.1120 + default: 1.1121 + throw new AssertionError(); 1.1122 + } 1.1123 + long illegal = flags & ExtendedStandardFlags & ~mask; 1.1124 + if (illegal != 0) { 1.1125 + if ((illegal & INTERFACE) != 0) { 1.1126 + log.error(pos, "intf.not.allowed.here"); 1.1127 + mask |= INTERFACE; 1.1128 + } 1.1129 + else { 1.1130 + log.error(pos, 1.1131 + "mod.not.allowed.here", asFlagSet(illegal)); 1.1132 + } 1.1133 + } 1.1134 + else if ((sym.kind == TYP || 1.1135 + // ISSUE: Disallowing abstract&private is no longer appropriate 1.1136 + // in the presence of inner classes. Should it be deleted here? 1.1137 + checkDisjoint(pos, flags, 1.1138 + ABSTRACT, 1.1139 + PRIVATE | STATIC | DEFAULT)) 1.1140 + && 1.1141 + checkDisjoint(pos, flags, 1.1142 + STATIC, 1.1143 + DEFAULT) 1.1144 + && 1.1145 + checkDisjoint(pos, flags, 1.1146 + ABSTRACT | INTERFACE, 1.1147 + FINAL | NATIVE | SYNCHRONIZED) 1.1148 + && 1.1149 + checkDisjoint(pos, flags, 1.1150 + PUBLIC, 1.1151 + PRIVATE | PROTECTED) 1.1152 + && 1.1153 + checkDisjoint(pos, flags, 1.1154 + PRIVATE, 1.1155 + PUBLIC | PROTECTED) 1.1156 + && 1.1157 + checkDisjoint(pos, flags, 1.1158 + FINAL, 1.1159 + VOLATILE) 1.1160 + && 1.1161 + (sym.kind == TYP || 1.1162 + checkDisjoint(pos, flags, 1.1163 + ABSTRACT | NATIVE, 1.1164 + STRICTFP))) { 1.1165 + // skip 1.1166 + } 1.1167 + return flags & (mask | ~ExtendedStandardFlags) | implicit; 1.1168 + } 1.1169 + 1.1170 + 1.1171 + /** Determine if this enum should be implicitly final. 1.1172 + * 1.1173 + * If the enum has no specialized enum contants, it is final. 1.1174 + * 1.1175 + * If the enum does have specialized enum contants, it is 1.1176 + * <i>not</i> final. 1.1177 + */ 1.1178 + private long implicitEnumFinalFlag(JCTree tree) { 1.1179 + if (!tree.hasTag(CLASSDEF)) return 0; 1.1180 + class SpecialTreeVisitor extends JCTree.Visitor { 1.1181 + boolean specialized; 1.1182 + SpecialTreeVisitor() { 1.1183 + this.specialized = false; 1.1184 + }; 1.1185 + 1.1186 + @Override 1.1187 + public void visitTree(JCTree tree) { /* no-op */ } 1.1188 + 1.1189 + @Override 1.1190 + public void visitVarDef(JCVariableDecl tree) { 1.1191 + if ((tree.mods.flags & ENUM) != 0) { 1.1192 + if (tree.init instanceof JCNewClass && 1.1193 + ((JCNewClass) tree.init).def != null) { 1.1194 + specialized = true; 1.1195 + } 1.1196 + } 1.1197 + } 1.1198 + } 1.1199 + 1.1200 + SpecialTreeVisitor sts = new SpecialTreeVisitor(); 1.1201 + JCClassDecl cdef = (JCClassDecl) tree; 1.1202 + for (JCTree defs: cdef.defs) { 1.1203 + defs.accept(sts); 1.1204 + if (sts.specialized) return 0; 1.1205 + } 1.1206 + return FINAL; 1.1207 + } 1.1208 + 1.1209 +/* ************************************************************************* 1.1210 + * Type Validation 1.1211 + **************************************************************************/ 1.1212 + 1.1213 + /** Validate a type expression. That is, 1.1214 + * check that all type arguments of a parametric type are within 1.1215 + * their bounds. This must be done in a second phase after type attribution 1.1216 + * since a class might have a subclass as type parameter bound. E.g: 1.1217 + * 1.1218 + * <pre>{@code 1.1219 + * class B<A extends C> { ... } 1.1220 + * class C extends B<C> { ... } 1.1221 + * }</pre> 1.1222 + * 1.1223 + * and we can't make sure that the bound is already attributed because 1.1224 + * of possible cycles. 1.1225 + * 1.1226 + * Visitor method: Validate a type expression, if it is not null, catching 1.1227 + * and reporting any completion failures. 1.1228 + */ 1.1229 + void validate(JCTree tree, Env<AttrContext> env) { 1.1230 + validate(tree, env, true); 1.1231 + } 1.1232 + void validate(JCTree tree, Env<AttrContext> env, boolean checkRaw) { 1.1233 + new Validator(env).validateTree(tree, checkRaw, true); 1.1234 + } 1.1235 + 1.1236 + /** Visitor method: Validate a list of type expressions. 1.1237 + */ 1.1238 + void validate(List<? extends JCTree> trees, Env<AttrContext> env) { 1.1239 + for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) 1.1240 + validate(l.head, env); 1.1241 + } 1.1242 + 1.1243 + /** A visitor class for type validation. 1.1244 + */ 1.1245 + class Validator extends JCTree.Visitor { 1.1246 + 1.1247 + boolean checkRaw; 1.1248 + boolean isOuter; 1.1249 + Env<AttrContext> env; 1.1250 + 1.1251 + Validator(Env<AttrContext> env) { 1.1252 + this.env = env; 1.1253 + } 1.1254 + 1.1255 + @Override 1.1256 + public void visitTypeArray(JCArrayTypeTree tree) { 1.1257 + validateTree(tree.elemtype, checkRaw, isOuter); 1.1258 + } 1.1259 + 1.1260 + @Override 1.1261 + public void visitTypeApply(JCTypeApply tree) { 1.1262 + if (tree.type.hasTag(CLASS)) { 1.1263 + List<JCExpression> args = tree.arguments; 1.1264 + List<Type> forms = tree.type.tsym.type.getTypeArguments(); 1.1265 + 1.1266 + Type incompatibleArg = firstIncompatibleTypeArg(tree.type); 1.1267 + if (incompatibleArg != null) { 1.1268 + for (JCTree arg : tree.arguments) { 1.1269 + if (arg.type == incompatibleArg) { 1.1270 + log.error(arg, "not.within.bounds", incompatibleArg, forms.head); 1.1271 + } 1.1272 + forms = forms.tail; 1.1273 + } 1.1274 + } 1.1275 + 1.1276 + forms = tree.type.tsym.type.getTypeArguments(); 1.1277 + 1.1278 + boolean is_java_lang_Class = tree.type.tsym.flatName() == names.java_lang_Class; 1.1279 + 1.1280 + // For matching pairs of actual argument types `a' and 1.1281 + // formal type parameters with declared bound `b' ... 1.1282 + while (args.nonEmpty() && forms.nonEmpty()) { 1.1283 + validateTree(args.head, 1.1284 + !(isOuter && is_java_lang_Class), 1.1285 + false); 1.1286 + args = args.tail; 1.1287 + forms = forms.tail; 1.1288 + } 1.1289 + 1.1290 + // Check that this type is either fully parameterized, or 1.1291 + // not parameterized at all. 1.1292 + if (tree.type.getEnclosingType().isRaw()) 1.1293 + log.error(tree.pos(), "improperly.formed.type.inner.raw.param"); 1.1294 + if (tree.clazz.hasTag(SELECT)) 1.1295 + visitSelectInternal((JCFieldAccess)tree.clazz); 1.1296 + } 1.1297 + } 1.1298 + 1.1299 + @Override 1.1300 + public void visitTypeParameter(JCTypeParameter tree) { 1.1301 + validateTrees(tree.bounds, true, isOuter); 1.1302 + checkClassBounds(tree.pos(), tree.type); 1.1303 + } 1.1304 + 1.1305 + @Override 1.1306 + public void visitWildcard(JCWildcard tree) { 1.1307 + if (tree.inner != null) 1.1308 + validateTree(tree.inner, true, isOuter); 1.1309 + } 1.1310 + 1.1311 + @Override 1.1312 + public void visitSelect(JCFieldAccess tree) { 1.1313 + if (tree.type.hasTag(CLASS)) { 1.1314 + visitSelectInternal(tree); 1.1315 + 1.1316 + // Check that this type is either fully parameterized, or 1.1317 + // not parameterized at all. 1.1318 + if (tree.selected.type.isParameterized() && tree.type.tsym.type.getTypeArguments().nonEmpty()) 1.1319 + log.error(tree.pos(), "improperly.formed.type.param.missing"); 1.1320 + } 1.1321 + } 1.1322 + 1.1323 + public void visitSelectInternal(JCFieldAccess tree) { 1.1324 + if (tree.type.tsym.isStatic() && 1.1325 + tree.selected.type.isParameterized()) { 1.1326 + // The enclosing type is not a class, so we are 1.1327 + // looking at a static member type. However, the 1.1328 + // qualifying expression is parameterized. 1.1329 + log.error(tree.pos(), "cant.select.static.class.from.param.type"); 1.1330 + } else { 1.1331 + // otherwise validate the rest of the expression 1.1332 + tree.selected.accept(this); 1.1333 + } 1.1334 + } 1.1335 + 1.1336 + @Override 1.1337 + public void visitAnnotatedType(JCAnnotatedType tree) { 1.1338 + tree.underlyingType.accept(this); 1.1339 + } 1.1340 + 1.1341 + @Override 1.1342 + public void visitTypeIdent(JCPrimitiveTypeTree that) { 1.1343 + if (that.type.hasTag(TypeTag.VOID)) { 1.1344 + log.error(that.pos(), "void.not.allowed.here"); 1.1345 + } 1.1346 + super.visitTypeIdent(that); 1.1347 + } 1.1348 + 1.1349 + /** Default visitor method: do nothing. 1.1350 + */ 1.1351 + @Override 1.1352 + public void visitTree(JCTree tree) { 1.1353 + } 1.1354 + 1.1355 + public void validateTree(JCTree tree, boolean checkRaw, boolean isOuter) { 1.1356 + if (tree != null) { 1.1357 + boolean prevCheckRaw = this.checkRaw; 1.1358 + this.checkRaw = checkRaw; 1.1359 + this.isOuter = isOuter; 1.1360 + 1.1361 + try { 1.1362 + tree.accept(this); 1.1363 + if (checkRaw) 1.1364 + checkRaw(tree, env); 1.1365 + } catch (CompletionFailure ex) { 1.1366 + completionError(tree.pos(), ex); 1.1367 + } finally { 1.1368 + this.checkRaw = prevCheckRaw; 1.1369 + } 1.1370 + } 1.1371 + } 1.1372 + 1.1373 + public void validateTrees(List<? extends JCTree> trees, boolean checkRaw, boolean isOuter) { 1.1374 + for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) 1.1375 + validateTree(l.head, checkRaw, isOuter); 1.1376 + } 1.1377 + } 1.1378 + 1.1379 + void checkRaw(JCTree tree, Env<AttrContext> env) { 1.1380 + if (lint.isEnabled(LintCategory.RAW) && 1.1381 + tree.type.hasTag(CLASS) && 1.1382 + !TreeInfo.isDiamond(tree) && 1.1383 + !withinAnonConstr(env) && 1.1384 + tree.type.isRaw()) { 1.1385 + log.warning(LintCategory.RAW, 1.1386 + tree.pos(), "raw.class.use", tree.type, tree.type.tsym.type); 1.1387 + } 1.1388 + } 1.1389 + //where 1.1390 + private boolean withinAnonConstr(Env<AttrContext> env) { 1.1391 + return env.enclClass.name.isEmpty() && 1.1392 + env.enclMethod != null && env.enclMethod.name == names.init; 1.1393 + } 1.1394 + 1.1395 +/* ************************************************************************* 1.1396 + * Exception checking 1.1397 + **************************************************************************/ 1.1398 + 1.1399 + /* The following methods treat classes as sets that contain 1.1400 + * the class itself and all their subclasses 1.1401 + */ 1.1402 + 1.1403 + /** Is given type a subtype of some of the types in given list? 1.1404 + */ 1.1405 + boolean subset(Type t, List<Type> ts) { 1.1406 + for (List<Type> l = ts; l.nonEmpty(); l = l.tail) 1.1407 + if (types.isSubtype(t, l.head)) return true; 1.1408 + return false; 1.1409 + } 1.1410 + 1.1411 + /** Is given type a subtype or supertype of 1.1412 + * some of the types in given list? 1.1413 + */ 1.1414 + boolean intersects(Type t, List<Type> ts) { 1.1415 + for (List<Type> l = ts; l.nonEmpty(); l = l.tail) 1.1416 + if (types.isSubtype(t, l.head) || types.isSubtype(l.head, t)) return true; 1.1417 + return false; 1.1418 + } 1.1419 + 1.1420 + /** Add type set to given type list, unless it is a subclass of some class 1.1421 + * in the list. 1.1422 + */ 1.1423 + List<Type> incl(Type t, List<Type> ts) { 1.1424 + return subset(t, ts) ? ts : excl(t, ts).prepend(t); 1.1425 + } 1.1426 + 1.1427 + /** Remove type set from type set list. 1.1428 + */ 1.1429 + List<Type> excl(Type t, List<Type> ts) { 1.1430 + if (ts.isEmpty()) { 1.1431 + return ts; 1.1432 + } else { 1.1433 + List<Type> ts1 = excl(t, ts.tail); 1.1434 + if (types.isSubtype(ts.head, t)) return ts1; 1.1435 + else if (ts1 == ts.tail) return ts; 1.1436 + else return ts1.prepend(ts.head); 1.1437 + } 1.1438 + } 1.1439 + 1.1440 + /** Form the union of two type set lists. 1.1441 + */ 1.1442 + List<Type> union(List<Type> ts1, List<Type> ts2) { 1.1443 + List<Type> ts = ts1; 1.1444 + for (List<Type> l = ts2; l.nonEmpty(); l = l.tail) 1.1445 + ts = incl(l.head, ts); 1.1446 + return ts; 1.1447 + } 1.1448 + 1.1449 + /** Form the difference of two type lists. 1.1450 + */ 1.1451 + List<Type> diff(List<Type> ts1, List<Type> ts2) { 1.1452 + List<Type> ts = ts1; 1.1453 + for (List<Type> l = ts2; l.nonEmpty(); l = l.tail) 1.1454 + ts = excl(l.head, ts); 1.1455 + return ts; 1.1456 + } 1.1457 + 1.1458 + /** Form the intersection of two type lists. 1.1459 + */ 1.1460 + public List<Type> intersect(List<Type> ts1, List<Type> ts2) { 1.1461 + List<Type> ts = List.nil(); 1.1462 + for (List<Type> l = ts1; l.nonEmpty(); l = l.tail) 1.1463 + if (subset(l.head, ts2)) ts = incl(l.head, ts); 1.1464 + for (List<Type> l = ts2; l.nonEmpty(); l = l.tail) 1.1465 + if (subset(l.head, ts1)) ts = incl(l.head, ts); 1.1466 + return ts; 1.1467 + } 1.1468 + 1.1469 + /** Is exc an exception symbol that need not be declared? 1.1470 + */ 1.1471 + boolean isUnchecked(ClassSymbol exc) { 1.1472 + return 1.1473 + exc.kind == ERR || 1.1474 + exc.isSubClass(syms.errorType.tsym, types) || 1.1475 + exc.isSubClass(syms.runtimeExceptionType.tsym, types); 1.1476 + } 1.1477 + 1.1478 + /** Is exc an exception type that need not be declared? 1.1479 + */ 1.1480 + boolean isUnchecked(Type exc) { 1.1481 + return 1.1482 + (exc.hasTag(TYPEVAR)) ? isUnchecked(types.supertype(exc)) : 1.1483 + (exc.hasTag(CLASS)) ? isUnchecked((ClassSymbol)exc.tsym) : 1.1484 + exc.hasTag(BOT); 1.1485 + } 1.1486 + 1.1487 + /** Same, but handling completion failures. 1.1488 + */ 1.1489 + boolean isUnchecked(DiagnosticPosition pos, Type exc) { 1.1490 + try { 1.1491 + return isUnchecked(exc); 1.1492 + } catch (CompletionFailure ex) { 1.1493 + completionError(pos, ex); 1.1494 + return true; 1.1495 + } 1.1496 + } 1.1497 + 1.1498 + /** Is exc handled by given exception list? 1.1499 + */ 1.1500 + boolean isHandled(Type exc, List<Type> handled) { 1.1501 + return isUnchecked(exc) || subset(exc, handled); 1.1502 + } 1.1503 + 1.1504 + /** Return all exceptions in thrown list that are not in handled list. 1.1505 + * @param thrown The list of thrown exceptions. 1.1506 + * @param handled The list of handled exceptions. 1.1507 + */ 1.1508 + List<Type> unhandled(List<Type> thrown, List<Type> handled) { 1.1509 + List<Type> unhandled = List.nil(); 1.1510 + for (List<Type> l = thrown; l.nonEmpty(); l = l.tail) 1.1511 + if (!isHandled(l.head, handled)) unhandled = unhandled.prepend(l.head); 1.1512 + return unhandled; 1.1513 + } 1.1514 + 1.1515 +/* ************************************************************************* 1.1516 + * Overriding/Implementation checking 1.1517 + **************************************************************************/ 1.1518 + 1.1519 + /** The level of access protection given by a flag set, 1.1520 + * where PRIVATE is highest and PUBLIC is lowest. 1.1521 + */ 1.1522 + static int protection(long flags) { 1.1523 + switch ((short)(flags & AccessFlags)) { 1.1524 + case PRIVATE: return 3; 1.1525 + case PROTECTED: return 1; 1.1526 + default: 1.1527 + case PUBLIC: return 0; 1.1528 + case 0: return 2; 1.1529 + } 1.1530 + } 1.1531 + 1.1532 + /** A customized "cannot override" error message. 1.1533 + * @param m The overriding method. 1.1534 + * @param other The overridden method. 1.1535 + * @return An internationalized string. 1.1536 + */ 1.1537 + Object cannotOverride(MethodSymbol m, MethodSymbol other) { 1.1538 + String key; 1.1539 + if ((other.owner.flags() & INTERFACE) == 0) 1.1540 + key = "cant.override"; 1.1541 + else if ((m.owner.flags() & INTERFACE) == 0) 1.1542 + key = "cant.implement"; 1.1543 + else 1.1544 + key = "clashes.with"; 1.1545 + return diags.fragment(key, m, m.location(), other, other.location()); 1.1546 + } 1.1547 + 1.1548 + /** A customized "override" warning message. 1.1549 + * @param m The overriding method. 1.1550 + * @param other The overridden method. 1.1551 + * @return An internationalized string. 1.1552 + */ 1.1553 + Object uncheckedOverrides(MethodSymbol m, MethodSymbol other) { 1.1554 + String key; 1.1555 + if ((other.owner.flags() & INTERFACE) == 0) 1.1556 + key = "unchecked.override"; 1.1557 + else if ((m.owner.flags() & INTERFACE) == 0) 1.1558 + key = "unchecked.implement"; 1.1559 + else 1.1560 + key = "unchecked.clash.with"; 1.1561 + return diags.fragment(key, m, m.location(), other, other.location()); 1.1562 + } 1.1563 + 1.1564 + /** A customized "override" warning message. 1.1565 + * @param m The overriding method. 1.1566 + * @param other The overridden method. 1.1567 + * @return An internationalized string. 1.1568 + */ 1.1569 + Object varargsOverrides(MethodSymbol m, MethodSymbol other) { 1.1570 + String key; 1.1571 + if ((other.owner.flags() & INTERFACE) == 0) 1.1572 + key = "varargs.override"; 1.1573 + else if ((m.owner.flags() & INTERFACE) == 0) 1.1574 + key = "varargs.implement"; 1.1575 + else 1.1576 + key = "varargs.clash.with"; 1.1577 + return diags.fragment(key, m, m.location(), other, other.location()); 1.1578 + } 1.1579 + 1.1580 + /** Check that this method conforms with overridden method 'other'. 1.1581 + * where `origin' is the class where checking started. 1.1582 + * Complications: 1.1583 + * (1) Do not check overriding of synthetic methods 1.1584 + * (reason: they might be final). 1.1585 + * todo: check whether this is still necessary. 1.1586 + * (2) Admit the case where an interface proxy throws fewer exceptions 1.1587 + * than the method it implements. Augment the proxy methods with the 1.1588 + * undeclared exceptions in this case. 1.1589 + * (3) When generics are enabled, admit the case where an interface proxy 1.1590 + * has a result type 1.1591 + * extended by the result type of the method it implements. 1.1592 + * Change the proxies result type to the smaller type in this case. 1.1593 + * 1.1594 + * @param tree The tree from which positions 1.1595 + * are extracted for errors. 1.1596 + * @param m The overriding method. 1.1597 + * @param other The overridden method. 1.1598 + * @param origin The class of which the overriding method 1.1599 + * is a member. 1.1600 + */ 1.1601 + void checkOverride(JCTree tree, 1.1602 + MethodSymbol m, 1.1603 + MethodSymbol other, 1.1604 + ClassSymbol origin) { 1.1605 + // Don't check overriding of synthetic methods or by bridge methods. 1.1606 + if ((m.flags() & (SYNTHETIC|BRIDGE)) != 0 || (other.flags() & SYNTHETIC) != 0) { 1.1607 + return; 1.1608 + } 1.1609 + 1.1610 + // Error if static method overrides instance method (JLS 8.4.6.2). 1.1611 + if ((m.flags() & STATIC) != 0 && 1.1612 + (other.flags() & STATIC) == 0) { 1.1613 + log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.static", 1.1614 + cannotOverride(m, other)); 1.1615 + m.flags_field |= BAD_OVERRIDE; 1.1616 + return; 1.1617 + } 1.1618 + 1.1619 + // Error if instance method overrides static or final 1.1620 + // method (JLS 8.4.6.1). 1.1621 + if ((other.flags() & FINAL) != 0 || 1.1622 + (m.flags() & STATIC) == 0 && 1.1623 + (other.flags() & STATIC) != 0) { 1.1624 + log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.meth", 1.1625 + cannotOverride(m, other), 1.1626 + asFlagSet(other.flags() & (FINAL | STATIC))); 1.1627 + m.flags_field |= BAD_OVERRIDE; 1.1628 + return; 1.1629 + } 1.1630 + 1.1631 + if ((m.owner.flags() & ANNOTATION) != 0) { 1.1632 + // handled in validateAnnotationMethod 1.1633 + return; 1.1634 + } 1.1635 + 1.1636 + // Error if overriding method has weaker access (JLS 8.4.6.3). 1.1637 + if ((origin.flags() & INTERFACE) == 0 && 1.1638 + protection(m.flags()) > protection(other.flags())) { 1.1639 + log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.weaker.access", 1.1640 + cannotOverride(m, other), 1.1641 + other.flags() == 0 ? 1.1642 + "package" : 1.1643 + asFlagSet(other.flags() & AccessFlags)); 1.1644 + m.flags_field |= BAD_OVERRIDE; 1.1645 + return; 1.1646 + } 1.1647 + 1.1648 + Type mt = types.memberType(origin.type, m); 1.1649 + Type ot = types.memberType(origin.type, other); 1.1650 + // Error if overriding result type is different 1.1651 + // (or, in the case of generics mode, not a subtype) of 1.1652 + // overridden result type. We have to rename any type parameters 1.1653 + // before comparing types. 1.1654 + List<Type> mtvars = mt.getTypeArguments(); 1.1655 + List<Type> otvars = ot.getTypeArguments(); 1.1656 + Type mtres = mt.getReturnType(); 1.1657 + Type otres = types.subst(ot.getReturnType(), otvars, mtvars); 1.1658 + 1.1659 + overrideWarner.clear(); 1.1660 + boolean resultTypesOK = 1.1661 + types.returnTypeSubstitutable(mt, ot, otres, overrideWarner); 1.1662 + if (!resultTypesOK) { 1.1663 + if (!allowCovariantReturns && 1.1664 + m.owner != origin && 1.1665 + m.owner.isSubClass(other.owner, types)) { 1.1666 + // allow limited interoperability with covariant returns 1.1667 + } else { 1.1668 + log.error(TreeInfo.diagnosticPositionFor(m, tree), 1.1669 + "override.incompatible.ret", 1.1670 + cannotOverride(m, other), 1.1671 + mtres, otres); 1.1672 + m.flags_field |= BAD_OVERRIDE; 1.1673 + return; 1.1674 + } 1.1675 + } else if (overrideWarner.hasNonSilentLint(LintCategory.UNCHECKED)) { 1.1676 + warnUnchecked(TreeInfo.diagnosticPositionFor(m, tree), 1.1677 + "override.unchecked.ret", 1.1678 + uncheckedOverrides(m, other), 1.1679 + mtres, otres); 1.1680 + } 1.1681 + 1.1682 + // Error if overriding method throws an exception not reported 1.1683 + // by overridden method. 1.1684 + List<Type> otthrown = types.subst(ot.getThrownTypes(), otvars, mtvars); 1.1685 + List<Type> unhandledErased = unhandled(mt.getThrownTypes(), types.erasure(otthrown)); 1.1686 + List<Type> unhandledUnerased = unhandled(mt.getThrownTypes(), otthrown); 1.1687 + if (unhandledErased.nonEmpty()) { 1.1688 + log.error(TreeInfo.diagnosticPositionFor(m, tree), 1.1689 + "override.meth.doesnt.throw", 1.1690 + cannotOverride(m, other), 1.1691 + unhandledUnerased.head); 1.1692 + m.flags_field |= BAD_OVERRIDE; 1.1693 + return; 1.1694 + } 1.1695 + else if (unhandledUnerased.nonEmpty()) { 1.1696 + warnUnchecked(TreeInfo.diagnosticPositionFor(m, tree), 1.1697 + "override.unchecked.thrown", 1.1698 + cannotOverride(m, other), 1.1699 + unhandledUnerased.head); 1.1700 + return; 1.1701 + } 1.1702 + 1.1703 + // Optional warning if varargs don't agree 1.1704 + if ((((m.flags() ^ other.flags()) & Flags.VARARGS) != 0) 1.1705 + && lint.isEnabled(LintCategory.OVERRIDES)) { 1.1706 + log.warning(TreeInfo.diagnosticPositionFor(m, tree), 1.1707 + ((m.flags() & Flags.VARARGS) != 0) 1.1708 + ? "override.varargs.missing" 1.1709 + : "override.varargs.extra", 1.1710 + varargsOverrides(m, other)); 1.1711 + } 1.1712 + 1.1713 + // Warn if instance method overrides bridge method (compiler spec ??) 1.1714 + if ((other.flags() & BRIDGE) != 0) { 1.1715 + log.warning(TreeInfo.diagnosticPositionFor(m, tree), "override.bridge", 1.1716 + uncheckedOverrides(m, other)); 1.1717 + } 1.1718 + 1.1719 + // Warn if a deprecated method overridden by a non-deprecated one. 1.1720 + if (!isDeprecatedOverrideIgnorable(other, origin)) { 1.1721 + checkDeprecated(TreeInfo.diagnosticPositionFor(m, tree), m, other); 1.1722 + } 1.1723 + } 1.1724 + // where 1.1725 + private boolean isDeprecatedOverrideIgnorable(MethodSymbol m, ClassSymbol origin) { 1.1726 + // If the method, m, is defined in an interface, then ignore the issue if the method 1.1727 + // is only inherited via a supertype and also implemented in the supertype, 1.1728 + // because in that case, we will rediscover the issue when examining the method 1.1729 + // in the supertype. 1.1730 + // If the method, m, is not defined in an interface, then the only time we need to 1.1731 + // address the issue is when the method is the supertype implemementation: any other 1.1732 + // case, we will have dealt with when examining the supertype classes 1.1733 + ClassSymbol mc = m.enclClass(); 1.1734 + Type st = types.supertype(origin.type); 1.1735 + if (!st.hasTag(CLASS)) 1.1736 + return true; 1.1737 + MethodSymbol stimpl = m.implementation((ClassSymbol)st.tsym, types, false); 1.1738 + 1.1739 + if (mc != null && ((mc.flags() & INTERFACE) != 0)) { 1.1740 + List<Type> intfs = types.interfaces(origin.type); 1.1741 + return (intfs.contains(mc.type) ? false : (stimpl != null)); 1.1742 + } 1.1743 + else 1.1744 + return (stimpl != m); 1.1745 + } 1.1746 + 1.1747 + 1.1748 + // used to check if there were any unchecked conversions 1.1749 + Warner overrideWarner = new Warner(); 1.1750 + 1.1751 + /** Check that a class does not inherit two concrete methods 1.1752 + * with the same signature. 1.1753 + * @param pos Position to be used for error reporting. 1.1754 + * @param site The class type to be checked. 1.1755 + */ 1.1756 + public void checkCompatibleConcretes(DiagnosticPosition pos, Type site) { 1.1757 + Type sup = types.supertype(site); 1.1758 + if (!sup.hasTag(CLASS)) return; 1.1759 + 1.1760 + for (Type t1 = sup; 1.1761 + t1.hasTag(CLASS) && t1.tsym.type.isParameterized(); 1.1762 + t1 = types.supertype(t1)) { 1.1763 + for (Scope.Entry e1 = t1.tsym.members().elems; 1.1764 + e1 != null; 1.1765 + e1 = e1.sibling) { 1.1766 + Symbol s1 = e1.sym; 1.1767 + if (s1.kind != MTH || 1.1768 + (s1.flags() & (STATIC|SYNTHETIC|BRIDGE)) != 0 || 1.1769 + !s1.isInheritedIn(site.tsym, types) || 1.1770 + ((MethodSymbol)s1).implementation(site.tsym, 1.1771 + types, 1.1772 + true) != s1) 1.1773 + continue; 1.1774 + Type st1 = types.memberType(t1, s1); 1.1775 + int s1ArgsLength = st1.getParameterTypes().length(); 1.1776 + if (st1 == s1.type) continue; 1.1777 + 1.1778 + for (Type t2 = sup; 1.1779 + t2.hasTag(CLASS); 1.1780 + t2 = types.supertype(t2)) { 1.1781 + for (Scope.Entry e2 = t2.tsym.members().lookup(s1.name); 1.1782 + e2.scope != null; 1.1783 + e2 = e2.next()) { 1.1784 + Symbol s2 = e2.sym; 1.1785 + if (s2 == s1 || 1.1786 + s2.kind != MTH || 1.1787 + (s2.flags() & (STATIC|SYNTHETIC|BRIDGE)) != 0 || 1.1788 + s2.type.getParameterTypes().length() != s1ArgsLength || 1.1789 + !s2.isInheritedIn(site.tsym, types) || 1.1790 + ((MethodSymbol)s2).implementation(site.tsym, 1.1791 + types, 1.1792 + true) != s2) 1.1793 + continue; 1.1794 + Type st2 = types.memberType(t2, s2); 1.1795 + if (types.overrideEquivalent(st1, st2)) 1.1796 + log.error(pos, "concrete.inheritance.conflict", 1.1797 + s1, t1, s2, t2, sup); 1.1798 + } 1.1799 + } 1.1800 + } 1.1801 + } 1.1802 + } 1.1803 + 1.1804 + /** Check that classes (or interfaces) do not each define an abstract 1.1805 + * method with same name and arguments but incompatible return types. 1.1806 + * @param pos Position to be used for error reporting. 1.1807 + * @param t1 The first argument type. 1.1808 + * @param t2 The second argument type. 1.1809 + */ 1.1810 + public boolean checkCompatibleAbstracts(DiagnosticPosition pos, 1.1811 + Type t1, 1.1812 + Type t2) { 1.1813 + return checkCompatibleAbstracts(pos, t1, t2, 1.1814 + types.makeCompoundType(t1, t2)); 1.1815 + } 1.1816 + 1.1817 + public boolean checkCompatibleAbstracts(DiagnosticPosition pos, 1.1818 + Type t1, 1.1819 + Type t2, 1.1820 + Type site) { 1.1821 + if ((site.tsym.flags() & COMPOUND) != 0) { 1.1822 + // special case for intersections: need to eliminate wildcards in supertypes 1.1823 + t1 = types.capture(t1); 1.1824 + t2 = types.capture(t2); 1.1825 + } 1.1826 + return firstIncompatibility(pos, t1, t2, site) == null; 1.1827 + } 1.1828 + 1.1829 + /** Return the first method which is defined with same args 1.1830 + * but different return types in two given interfaces, or null if none 1.1831 + * exists. 1.1832 + * @param t1 The first type. 1.1833 + * @param t2 The second type. 1.1834 + * @param site The most derived type. 1.1835 + * @returns symbol from t2 that conflicts with one in t1. 1.1836 + */ 1.1837 + private Symbol firstIncompatibility(DiagnosticPosition pos, Type t1, Type t2, Type site) { 1.1838 + Map<TypeSymbol,Type> interfaces1 = new HashMap<TypeSymbol,Type>(); 1.1839 + closure(t1, interfaces1); 1.1840 + Map<TypeSymbol,Type> interfaces2; 1.1841 + if (t1 == t2) 1.1842 + interfaces2 = interfaces1; 1.1843 + else 1.1844 + closure(t2, interfaces1, interfaces2 = new HashMap<TypeSymbol,Type>()); 1.1845 + 1.1846 + for (Type t3 : interfaces1.values()) { 1.1847 + for (Type t4 : interfaces2.values()) { 1.1848 + Symbol s = firstDirectIncompatibility(pos, t3, t4, site); 1.1849 + if (s != null) return s; 1.1850 + } 1.1851 + } 1.1852 + return null; 1.1853 + } 1.1854 + 1.1855 + /** Compute all the supertypes of t, indexed by type symbol. */ 1.1856 + private void closure(Type t, Map<TypeSymbol,Type> typeMap) { 1.1857 + if (!t.hasTag(CLASS)) return; 1.1858 + if (typeMap.put(t.tsym, t) == null) { 1.1859 + closure(types.supertype(t), typeMap); 1.1860 + for (Type i : types.interfaces(t)) 1.1861 + closure(i, typeMap); 1.1862 + } 1.1863 + } 1.1864 + 1.1865 + /** Compute all the supertypes of t, indexed by type symbol (except thise in typesSkip). */ 1.1866 + private void closure(Type t, Map<TypeSymbol,Type> typesSkip, Map<TypeSymbol,Type> typeMap) { 1.1867 + if (!t.hasTag(CLASS)) return; 1.1868 + if (typesSkip.get(t.tsym) != null) return; 1.1869 + if (typeMap.put(t.tsym, t) == null) { 1.1870 + closure(types.supertype(t), typesSkip, typeMap); 1.1871 + for (Type i : types.interfaces(t)) 1.1872 + closure(i, typesSkip, typeMap); 1.1873 + } 1.1874 + } 1.1875 + 1.1876 + /** Return the first method in t2 that conflicts with a method from t1. */ 1.1877 + private Symbol firstDirectIncompatibility(DiagnosticPosition pos, Type t1, Type t2, Type site) { 1.1878 + for (Scope.Entry e1 = t1.tsym.members().elems; e1 != null; e1 = e1.sibling) { 1.1879 + Symbol s1 = e1.sym; 1.1880 + Type st1 = null; 1.1881 + if (s1.kind != MTH || !s1.isInheritedIn(site.tsym, types) || 1.1882 + (s1.flags() & SYNTHETIC) != 0) continue; 1.1883 + Symbol impl = ((MethodSymbol)s1).implementation(site.tsym, types, false); 1.1884 + if (impl != null && (impl.flags() & ABSTRACT) == 0) continue; 1.1885 + for (Scope.Entry e2 = t2.tsym.members().lookup(s1.name); e2.scope != null; e2 = e2.next()) { 1.1886 + Symbol s2 = e2.sym; 1.1887 + if (s1 == s2) continue; 1.1888 + if (s2.kind != MTH || !s2.isInheritedIn(site.tsym, types) || 1.1889 + (s2.flags() & SYNTHETIC) != 0) continue; 1.1890 + if (st1 == null) st1 = types.memberType(t1, s1); 1.1891 + Type st2 = types.memberType(t2, s2); 1.1892 + if (types.overrideEquivalent(st1, st2)) { 1.1893 + List<Type> tvars1 = st1.getTypeArguments(); 1.1894 + List<Type> tvars2 = st2.getTypeArguments(); 1.1895 + Type rt1 = st1.getReturnType(); 1.1896 + Type rt2 = types.subst(st2.getReturnType(), tvars2, tvars1); 1.1897 + boolean compat = 1.1898 + types.isSameType(rt1, rt2) || 1.1899 + !rt1.isPrimitiveOrVoid() && 1.1900 + !rt2.isPrimitiveOrVoid() && 1.1901 + (types.covariantReturnType(rt1, rt2, types.noWarnings) || 1.1902 + types.covariantReturnType(rt2, rt1, types.noWarnings)) || 1.1903 + checkCommonOverriderIn(s1,s2,site); 1.1904 + if (!compat) { 1.1905 + log.error(pos, "types.incompatible.diff.ret", 1.1906 + t1, t2, s2.name + 1.1907 + "(" + types.memberType(t2, s2).getParameterTypes() + ")"); 1.1908 + return s2; 1.1909 + } 1.1910 + } else if (checkNameClash((ClassSymbol)site.tsym, s1, s2) && 1.1911 + !checkCommonOverriderIn(s1, s2, site)) { 1.1912 + log.error(pos, 1.1913 + "name.clash.same.erasure.no.override", 1.1914 + s1, s1.location(), 1.1915 + s2, s2.location()); 1.1916 + return s2; 1.1917 + } 1.1918 + } 1.1919 + } 1.1920 + return null; 1.1921 + } 1.1922 + //WHERE 1.1923 + boolean checkCommonOverriderIn(Symbol s1, Symbol s2, Type site) { 1.1924 + Map<TypeSymbol,Type> supertypes = new HashMap<TypeSymbol,Type>(); 1.1925 + Type st1 = types.memberType(site, s1); 1.1926 + Type st2 = types.memberType(site, s2); 1.1927 + closure(site, supertypes); 1.1928 + for (Type t : supertypes.values()) { 1.1929 + for (Scope.Entry e = t.tsym.members().lookup(s1.name); e.scope != null; e = e.next()) { 1.1930 + Symbol s3 = e.sym; 1.1931 + if (s3 == s1 || s3 == s2 || s3.kind != MTH || (s3.flags() & (BRIDGE|SYNTHETIC)) != 0) continue; 1.1932 + Type st3 = types.memberType(site,s3); 1.1933 + if (types.overrideEquivalent(st3, st1) && 1.1934 + types.overrideEquivalent(st3, st2) && 1.1935 + types.returnTypeSubstitutable(st3, st1) && 1.1936 + types.returnTypeSubstitutable(st3, st2)) { 1.1937 + return true; 1.1938 + } 1.1939 + } 1.1940 + } 1.1941 + return false; 1.1942 + } 1.1943 + 1.1944 + /** Check that a given method conforms with any method it overrides. 1.1945 + * @param tree The tree from which positions are extracted 1.1946 + * for errors. 1.1947 + * @param m The overriding method. 1.1948 + */ 1.1949 + void checkOverride(JCMethodDecl tree, MethodSymbol m) { 1.1950 + ClassSymbol origin = (ClassSymbol)m.owner; 1.1951 + if ((origin.flags() & ENUM) != 0 && names.finalize.equals(m.name)) 1.1952 + if (m.overrides(syms.enumFinalFinalize, origin, types, false)) { 1.1953 + log.error(tree.pos(), "enum.no.finalize"); 1.1954 + return; 1.1955 + } 1.1956 + for (Type t = origin.type; t.hasTag(CLASS); 1.1957 + t = types.supertype(t)) { 1.1958 + if (t != origin.type) { 1.1959 + checkOverride(tree, t, origin, m); 1.1960 + } 1.1961 + for (Type t2 : types.interfaces(t)) { 1.1962 + checkOverride(tree, t2, origin, m); 1.1963 + } 1.1964 + } 1.1965 + 1.1966 + if (m.attribute(syms.overrideType.tsym) != null && !isOverrider(m)) { 1.1967 + DiagnosticPosition pos = tree.pos(); 1.1968 + for (JCAnnotation a : tree.getModifiers().annotations) { 1.1969 + if (a.annotationType.type.tsym == syms.overrideType.tsym) { 1.1970 + pos = a.pos(); 1.1971 + break; 1.1972 + } 1.1973 + } 1.1974 + log.error(pos, "method.does.not.override.superclass"); 1.1975 + } 1.1976 + } 1.1977 + 1.1978 + void checkOverride(JCTree tree, Type site, ClassSymbol origin, MethodSymbol m) { 1.1979 + TypeSymbol c = site.tsym; 1.1980 + Scope.Entry e = c.members().lookup(m.name); 1.1981 + while (e.scope != null) { 1.1982 + if (m.overrides(e.sym, origin, types, false)) { 1.1983 + if ((e.sym.flags() & ABSTRACT) == 0) { 1.1984 + checkOverride(tree, m, (MethodSymbol)e.sym, origin); 1.1985 + } 1.1986 + } 1.1987 + e = e.next(); 1.1988 + } 1.1989 + } 1.1990 + 1.1991 + private Filter<Symbol> equalsHasCodeFilter = new Filter<Symbol>() { 1.1992 + public boolean accepts(Symbol s) { 1.1993 + return MethodSymbol.implementation_filter.accepts(s) && 1.1994 + (s.flags() & BAD_OVERRIDE) == 0; 1.1995 + 1.1996 + } 1.1997 + }; 1.1998 + 1.1999 + public void checkClassOverrideEqualsAndHashIfNeeded(DiagnosticPosition pos, 1.2000 + ClassSymbol someClass) { 1.2001 + /* At present, annotations cannot possibly have a method that is override 1.2002 + * equivalent with Object.equals(Object) but in any case the condition is 1.2003 + * fine for completeness. 1.2004 + */ 1.2005 + if (someClass == (ClassSymbol)syms.objectType.tsym || 1.2006 + someClass.isInterface() || someClass.isEnum() || 1.2007 + (someClass.flags() & ANNOTATION) != 0 || 1.2008 + (someClass.flags() & ABSTRACT) != 0) return; 1.2009 + //anonymous inner classes implementing interfaces need especial treatment 1.2010 + if (someClass.isAnonymous()) { 1.2011 + List<Type> interfaces = types.interfaces(someClass.type); 1.2012 + if (interfaces != null && !interfaces.isEmpty() && 1.2013 + interfaces.head.tsym == syms.comparatorType.tsym) return; 1.2014 + } 1.2015 + checkClassOverrideEqualsAndHash(pos, someClass); 1.2016 + } 1.2017 + 1.2018 + private void checkClassOverrideEqualsAndHash(DiagnosticPosition pos, 1.2019 + ClassSymbol someClass) { 1.2020 + if (lint.isEnabled(LintCategory.OVERRIDES)) { 1.2021 + MethodSymbol equalsAtObject = (MethodSymbol)syms.objectType 1.2022 + .tsym.members().lookup(names.equals).sym; 1.2023 + MethodSymbol hashCodeAtObject = (MethodSymbol)syms.objectType 1.2024 + .tsym.members().lookup(names.hashCode).sym; 1.2025 + boolean overridesEquals = types.implementation(equalsAtObject, 1.2026 + someClass, false, equalsHasCodeFilter).owner == someClass; 1.2027 + boolean overridesHashCode = types.implementation(hashCodeAtObject, 1.2028 + someClass, false, equalsHasCodeFilter) != hashCodeAtObject; 1.2029 + 1.2030 + if (overridesEquals && !overridesHashCode) { 1.2031 + log.warning(LintCategory.OVERRIDES, pos, 1.2032 + "override.equals.but.not.hashcode", someClass); 1.2033 + } 1.2034 + } 1.2035 + } 1.2036 + 1.2037 + private boolean checkNameClash(ClassSymbol origin, Symbol s1, Symbol s2) { 1.2038 + ClashFilter cf = new ClashFilter(origin.type); 1.2039 + return (cf.accepts(s1) && 1.2040 + cf.accepts(s2) && 1.2041 + types.hasSameArgs(s1.erasure(types), s2.erasure(types))); 1.2042 + } 1.2043 + 1.2044 + 1.2045 + /** Check that all abstract members of given class have definitions. 1.2046 + * @param pos Position to be used for error reporting. 1.2047 + * @param c The class. 1.2048 + */ 1.2049 + void checkAllDefined(DiagnosticPosition pos, ClassSymbol c) { 1.2050 + try { 1.2051 + MethodSymbol undef = firstUndef(c, c); 1.2052 + if (undef != null) { 1.2053 + if ((c.flags() & ENUM) != 0 && 1.2054 + types.supertype(c.type).tsym == syms.enumSym && 1.2055 + (c.flags() & FINAL) == 0) { 1.2056 + // add the ABSTRACT flag to an enum 1.2057 + c.flags_field |= ABSTRACT; 1.2058 + } else { 1.2059 + MethodSymbol undef1 = 1.2060 + new MethodSymbol(undef.flags(), undef.name, 1.2061 + types.memberType(c.type, undef), undef.owner); 1.2062 + log.error(pos, "does.not.override.abstract", 1.2063 + c, undef1, undef1.location()); 1.2064 + } 1.2065 + } 1.2066 + } catch (CompletionFailure ex) { 1.2067 + completionError(pos, ex); 1.2068 + } 1.2069 + } 1.2070 +//where 1.2071 + /** Return first abstract member of class `c' that is not defined 1.2072 + * in `impl', null if there is none. 1.2073 + */ 1.2074 + private MethodSymbol firstUndef(ClassSymbol impl, ClassSymbol c) { 1.2075 + MethodSymbol undef = null; 1.2076 + // Do not bother to search in classes that are not abstract, 1.2077 + // since they cannot have abstract members. 1.2078 + if (c == impl || (c.flags() & (ABSTRACT | INTERFACE)) != 0) { 1.2079 + Scope s = c.members(); 1.2080 + for (Scope.Entry e = s.elems; 1.2081 + undef == null && e != null; 1.2082 + e = e.sibling) { 1.2083 + if (e.sym.kind == MTH && 1.2084 + (e.sym.flags() & (ABSTRACT|IPROXY|DEFAULT)) == ABSTRACT) { 1.2085 + MethodSymbol absmeth = (MethodSymbol)e.sym; 1.2086 + MethodSymbol implmeth = absmeth.implementation(impl, types, true); 1.2087 + if (implmeth == null || implmeth == absmeth) { 1.2088 + //look for default implementations 1.2089 + if (allowDefaultMethods) { 1.2090 + MethodSymbol prov = types.interfaceCandidates(impl.type, absmeth).head; 1.2091 + if (prov != null && prov.overrides(absmeth, impl, types, true)) { 1.2092 + implmeth = prov; 1.2093 + } 1.2094 + } 1.2095 + } 1.2096 + if (implmeth == null || implmeth == absmeth) { 1.2097 + undef = absmeth; 1.2098 + } 1.2099 + } 1.2100 + } 1.2101 + if (undef == null) { 1.2102 + Type st = types.supertype(c.type); 1.2103 + if (st.hasTag(CLASS)) 1.2104 + undef = firstUndef(impl, (ClassSymbol)st.tsym); 1.2105 + } 1.2106 + for (List<Type> l = types.interfaces(c.type); 1.2107 + undef == null && l.nonEmpty(); 1.2108 + l = l.tail) { 1.2109 + undef = firstUndef(impl, (ClassSymbol)l.head.tsym); 1.2110 + } 1.2111 + } 1.2112 + return undef; 1.2113 + } 1.2114 + 1.2115 + void checkNonCyclicDecl(JCClassDecl tree) { 1.2116 + CycleChecker cc = new CycleChecker(); 1.2117 + cc.scan(tree); 1.2118 + if (!cc.errorFound && !cc.partialCheck) { 1.2119 + tree.sym.flags_field |= ACYCLIC; 1.2120 + } 1.2121 + } 1.2122 + 1.2123 + class CycleChecker extends TreeScanner { 1.2124 + 1.2125 + List<Symbol> seenClasses = List.nil(); 1.2126 + boolean errorFound = false; 1.2127 + boolean partialCheck = false; 1.2128 + 1.2129 + private void checkSymbol(DiagnosticPosition pos, Symbol sym) { 1.2130 + if (sym != null && sym.kind == TYP) { 1.2131 + Env<AttrContext> classEnv = enter.getEnv((TypeSymbol)sym); 1.2132 + if (classEnv != null) { 1.2133 + DiagnosticSource prevSource = log.currentSource(); 1.2134 + try { 1.2135 + log.useSource(classEnv.toplevel.sourcefile); 1.2136 + scan(classEnv.tree); 1.2137 + } 1.2138 + finally { 1.2139 + log.useSource(prevSource.getFile()); 1.2140 + } 1.2141 + } else if (sym.kind == TYP) { 1.2142 + checkClass(pos, sym, List.<JCTree>nil()); 1.2143 + } 1.2144 + } else { 1.2145 + //not completed yet 1.2146 + partialCheck = true; 1.2147 + } 1.2148 + } 1.2149 + 1.2150 + @Override 1.2151 + public void visitSelect(JCFieldAccess tree) { 1.2152 + super.visitSelect(tree); 1.2153 + checkSymbol(tree.pos(), tree.sym); 1.2154 + } 1.2155 + 1.2156 + @Override 1.2157 + public void visitIdent(JCIdent tree) { 1.2158 + checkSymbol(tree.pos(), tree.sym); 1.2159 + } 1.2160 + 1.2161 + @Override 1.2162 + public void visitTypeApply(JCTypeApply tree) { 1.2163 + scan(tree.clazz); 1.2164 + } 1.2165 + 1.2166 + @Override 1.2167 + public void visitTypeArray(JCArrayTypeTree tree) { 1.2168 + scan(tree.elemtype); 1.2169 + } 1.2170 + 1.2171 + @Override 1.2172 + public void visitClassDef(JCClassDecl tree) { 1.2173 + List<JCTree> supertypes = List.nil(); 1.2174 + if (tree.getExtendsClause() != null) { 1.2175 + supertypes = supertypes.prepend(tree.getExtendsClause()); 1.2176 + } 1.2177 + if (tree.getImplementsClause() != null) { 1.2178 + for (JCTree intf : tree.getImplementsClause()) { 1.2179 + supertypes = supertypes.prepend(intf); 1.2180 + } 1.2181 + } 1.2182 + checkClass(tree.pos(), tree.sym, supertypes); 1.2183 + } 1.2184 + 1.2185 + void checkClass(DiagnosticPosition pos, Symbol c, List<JCTree> supertypes) { 1.2186 + if ((c.flags_field & ACYCLIC) != 0) 1.2187 + return; 1.2188 + if (seenClasses.contains(c)) { 1.2189 + errorFound = true; 1.2190 + noteCyclic(pos, (ClassSymbol)c); 1.2191 + } else if (!c.type.isErroneous()) { 1.2192 + try { 1.2193 + seenClasses = seenClasses.prepend(c); 1.2194 + if (c.type.hasTag(CLASS)) { 1.2195 + if (supertypes.nonEmpty()) { 1.2196 + scan(supertypes); 1.2197 + } 1.2198 + else { 1.2199 + ClassType ct = (ClassType)c.type; 1.2200 + if (ct.supertype_field == null || 1.2201 + ct.interfaces_field == null) { 1.2202 + //not completed yet 1.2203 + partialCheck = true; 1.2204 + return; 1.2205 + } 1.2206 + checkSymbol(pos, ct.supertype_field.tsym); 1.2207 + for (Type intf : ct.interfaces_field) { 1.2208 + checkSymbol(pos, intf.tsym); 1.2209 + } 1.2210 + } 1.2211 + if (c.owner.kind == TYP) { 1.2212 + checkSymbol(pos, c.owner); 1.2213 + } 1.2214 + } 1.2215 + } finally { 1.2216 + seenClasses = seenClasses.tail; 1.2217 + } 1.2218 + } 1.2219 + } 1.2220 + } 1.2221 + 1.2222 + /** Check for cyclic references. Issue an error if the 1.2223 + * symbol of the type referred to has a LOCKED flag set. 1.2224 + * 1.2225 + * @param pos Position to be used for error reporting. 1.2226 + * @param t The type referred to. 1.2227 + */ 1.2228 + void checkNonCyclic(DiagnosticPosition pos, Type t) { 1.2229 + checkNonCyclicInternal(pos, t); 1.2230 + } 1.2231 + 1.2232 + 1.2233 + void checkNonCyclic(DiagnosticPosition pos, TypeVar t) { 1.2234 + checkNonCyclic1(pos, t, List.<TypeVar>nil()); 1.2235 + } 1.2236 + 1.2237 + private void checkNonCyclic1(DiagnosticPosition pos, Type t, List<TypeVar> seen) { 1.2238 + final TypeVar tv; 1.2239 + if (t.hasTag(TYPEVAR) && (t.tsym.flags() & UNATTRIBUTED) != 0) 1.2240 + return; 1.2241 + if (seen.contains(t)) { 1.2242 + tv = (TypeVar)t.unannotatedType(); 1.2243 + tv.bound = types.createErrorType(t); 1.2244 + log.error(pos, "cyclic.inheritance", t); 1.2245 + } else if (t.hasTag(TYPEVAR)) { 1.2246 + tv = (TypeVar)t.unannotatedType(); 1.2247 + seen = seen.prepend(tv); 1.2248 + for (Type b : types.getBounds(tv)) 1.2249 + checkNonCyclic1(pos, b, seen); 1.2250 + } 1.2251 + } 1.2252 + 1.2253 + /** Check for cyclic references. Issue an error if the 1.2254 + * symbol of the type referred to has a LOCKED flag set. 1.2255 + * 1.2256 + * @param pos Position to be used for error reporting. 1.2257 + * @param t The type referred to. 1.2258 + * @returns True if the check completed on all attributed classes 1.2259 + */ 1.2260 + private boolean checkNonCyclicInternal(DiagnosticPosition pos, Type t) { 1.2261 + boolean complete = true; // was the check complete? 1.2262 + //- System.err.println("checkNonCyclicInternal("+t+");");//DEBUG 1.2263 + Symbol c = t.tsym; 1.2264 + if ((c.flags_field & ACYCLIC) != 0) return true; 1.2265 + 1.2266 + if ((c.flags_field & LOCKED) != 0) { 1.2267 + noteCyclic(pos, (ClassSymbol)c); 1.2268 + } else if (!c.type.isErroneous()) { 1.2269 + try { 1.2270 + c.flags_field |= LOCKED; 1.2271 + if (c.type.hasTag(CLASS)) { 1.2272 + ClassType clazz = (ClassType)c.type; 1.2273 + if (clazz.interfaces_field != null) 1.2274 + for (List<Type> l=clazz.interfaces_field; l.nonEmpty(); l=l.tail) 1.2275 + complete &= checkNonCyclicInternal(pos, l.head); 1.2276 + if (clazz.supertype_field != null) { 1.2277 + Type st = clazz.supertype_field; 1.2278 + if (st != null && st.hasTag(CLASS)) 1.2279 + complete &= checkNonCyclicInternal(pos, st); 1.2280 + } 1.2281 + if (c.owner.kind == TYP) 1.2282 + complete &= checkNonCyclicInternal(pos, c.owner.type); 1.2283 + } 1.2284 + } finally { 1.2285 + c.flags_field &= ~LOCKED; 1.2286 + } 1.2287 + } 1.2288 + if (complete) 1.2289 + complete = ((c.flags_field & UNATTRIBUTED) == 0) && c.completer == null; 1.2290 + if (complete) c.flags_field |= ACYCLIC; 1.2291 + return complete; 1.2292 + } 1.2293 + 1.2294 + /** Note that we found an inheritance cycle. */ 1.2295 + private void noteCyclic(DiagnosticPosition pos, ClassSymbol c) { 1.2296 + log.error(pos, "cyclic.inheritance", c); 1.2297 + for (List<Type> l=types.interfaces(c.type); l.nonEmpty(); l=l.tail) 1.2298 + l.head = types.createErrorType((ClassSymbol)l.head.tsym, Type.noType); 1.2299 + Type st = types.supertype(c.type); 1.2300 + if (st.hasTag(CLASS)) 1.2301 + ((ClassType)c.type).supertype_field = types.createErrorType((ClassSymbol)st.tsym, Type.noType); 1.2302 + c.type = types.createErrorType(c, c.type); 1.2303 + c.flags_field |= ACYCLIC; 1.2304 + } 1.2305 + 1.2306 + /** Check that all methods which implement some 1.2307 + * method conform to the method they implement. 1.2308 + * @param tree The class definition whose members are checked. 1.2309 + */ 1.2310 + void checkImplementations(JCClassDecl tree) { 1.2311 + checkImplementations(tree, tree.sym, tree.sym); 1.2312 + } 1.2313 + //where 1.2314 + /** Check that all methods which implement some 1.2315 + * method in `ic' conform to the method they implement. 1.2316 + */ 1.2317 + void checkImplementations(JCTree tree, ClassSymbol origin, ClassSymbol ic) { 1.2318 + for (List<Type> l = types.closure(ic.type); l.nonEmpty(); l = l.tail) { 1.2319 + ClassSymbol lc = (ClassSymbol)l.head.tsym; 1.2320 + if ((allowGenerics || origin != lc) && (lc.flags() & ABSTRACT) != 0) { 1.2321 + for (Scope.Entry e=lc.members().elems; e != null; e=e.sibling) { 1.2322 + if (e.sym.kind == MTH && 1.2323 + (e.sym.flags() & (STATIC|ABSTRACT)) == ABSTRACT) { 1.2324 + MethodSymbol absmeth = (MethodSymbol)e.sym; 1.2325 + MethodSymbol implmeth = absmeth.implementation(origin, types, false); 1.2326 + if (implmeth != null && implmeth != absmeth && 1.2327 + (implmeth.owner.flags() & INTERFACE) == 1.2328 + (origin.flags() & INTERFACE)) { 1.2329 + // don't check if implmeth is in a class, yet 1.2330 + // origin is an interface. This case arises only 1.2331 + // if implmeth is declared in Object. The reason is 1.2332 + // that interfaces really don't inherit from 1.2333 + // Object it's just that the compiler represents 1.2334 + // things that way. 1.2335 + checkOverride(tree, implmeth, absmeth, origin); 1.2336 + } 1.2337 + } 1.2338 + } 1.2339 + } 1.2340 + } 1.2341 + } 1.2342 + 1.2343 + /** Check that all abstract methods implemented by a class are 1.2344 + * mutually compatible. 1.2345 + * @param pos Position to be used for error reporting. 1.2346 + * @param c The class whose interfaces are checked. 1.2347 + */ 1.2348 + void checkCompatibleSupertypes(DiagnosticPosition pos, Type c) { 1.2349 + List<Type> supertypes = types.interfaces(c); 1.2350 + Type supertype = types.supertype(c); 1.2351 + if (supertype.hasTag(CLASS) && 1.2352 + (supertype.tsym.flags() & ABSTRACT) != 0) 1.2353 + supertypes = supertypes.prepend(supertype); 1.2354 + for (List<Type> l = supertypes; l.nonEmpty(); l = l.tail) { 1.2355 + if (allowGenerics && !l.head.getTypeArguments().isEmpty() && 1.2356 + !checkCompatibleAbstracts(pos, l.head, l.head, c)) 1.2357 + return; 1.2358 + for (List<Type> m = supertypes; m != l; m = m.tail) 1.2359 + if (!checkCompatibleAbstracts(pos, l.head, m.head, c)) 1.2360 + return; 1.2361 + } 1.2362 + checkCompatibleConcretes(pos, c); 1.2363 + } 1.2364 + 1.2365 + void checkConflicts(DiagnosticPosition pos, Symbol sym, TypeSymbol c) { 1.2366 + for (Type ct = c.type; ct != Type.noType ; ct = types.supertype(ct)) { 1.2367 + for (Scope.Entry e = ct.tsym.members().lookup(sym.name); e.scope == ct.tsym.members(); e = e.next()) { 1.2368 + // VM allows methods and variables with differing types 1.2369 + if (sym.kind == e.sym.kind && 1.2370 + types.isSameType(types.erasure(sym.type), types.erasure(e.sym.type)) && 1.2371 + sym != e.sym && 1.2372 + (sym.flags() & Flags.SYNTHETIC) != (e.sym.flags() & Flags.SYNTHETIC) && 1.2373 + (sym.flags() & IPROXY) == 0 && (e.sym.flags() & IPROXY) == 0 && 1.2374 + (sym.flags() & BRIDGE) == 0 && (e.sym.flags() & BRIDGE) == 0) { 1.2375 + syntheticError(pos, (e.sym.flags() & SYNTHETIC) == 0 ? e.sym : sym); 1.2376 + return; 1.2377 + } 1.2378 + } 1.2379 + } 1.2380 + } 1.2381 + 1.2382 + /** Check that all non-override equivalent methods accessible from 'site' 1.2383 + * are mutually compatible (JLS 8.4.8/9.4.1). 1.2384 + * 1.2385 + * @param pos Position to be used for error reporting. 1.2386 + * @param site The class whose methods are checked. 1.2387 + * @param sym The method symbol to be checked. 1.2388 + */ 1.2389 + void checkOverrideClashes(DiagnosticPosition pos, Type site, MethodSymbol sym) { 1.2390 + ClashFilter cf = new ClashFilter(site); 1.2391 + //for each method m1 that is overridden (directly or indirectly) 1.2392 + //by method 'sym' in 'site'... 1.2393 + 1.2394 + List<MethodSymbol> potentiallyAmbiguousList = List.nil(); 1.2395 + boolean overridesAny = false; 1.2396 + for (Symbol m1 : types.membersClosure(site, false).getElementsByName(sym.name, cf)) { 1.2397 + if (!sym.overrides(m1, site.tsym, types, false)) { 1.2398 + if (m1 == sym) { 1.2399 + continue; 1.2400 + } 1.2401 + 1.2402 + if (!overridesAny) { 1.2403 + potentiallyAmbiguousList = potentiallyAmbiguousList.prepend((MethodSymbol)m1); 1.2404 + } 1.2405 + continue; 1.2406 + } 1.2407 + 1.2408 + if (m1 != sym) { 1.2409 + overridesAny = true; 1.2410 + potentiallyAmbiguousList = List.nil(); 1.2411 + } 1.2412 + 1.2413 + //...check each method m2 that is a member of 'site' 1.2414 + for (Symbol m2 : types.membersClosure(site, false).getElementsByName(sym.name, cf)) { 1.2415 + if (m2 == m1) continue; 1.2416 + //if (i) the signature of 'sym' is not a subsignature of m1 (seen as 1.2417 + //a member of 'site') and (ii) m1 has the same erasure as m2, issue an error 1.2418 + if (!types.isSubSignature(sym.type, types.memberType(site, m2), allowStrictMethodClashCheck) && 1.2419 + types.hasSameArgs(m2.erasure(types), m1.erasure(types))) { 1.2420 + sym.flags_field |= CLASH; 1.2421 + String key = m1 == sym ? 1.2422 + "name.clash.same.erasure.no.override" : 1.2423 + "name.clash.same.erasure.no.override.1"; 1.2424 + log.error(pos, 1.2425 + key, 1.2426 + sym, sym.location(), 1.2427 + m2, m2.location(), 1.2428 + m1, m1.location()); 1.2429 + return; 1.2430 + } 1.2431 + } 1.2432 + } 1.2433 + 1.2434 + if (!overridesAny) { 1.2435 + for (MethodSymbol m: potentiallyAmbiguousList) { 1.2436 + checkPotentiallyAmbiguousOverloads(pos, site, sym, m); 1.2437 + } 1.2438 + } 1.2439 + } 1.2440 + 1.2441 + /** Check that all static methods accessible from 'site' are 1.2442 + * mutually compatible (JLS 8.4.8). 1.2443 + * 1.2444 + * @param pos Position to be used for error reporting. 1.2445 + * @param site The class whose methods are checked. 1.2446 + * @param sym The method symbol to be checked. 1.2447 + */ 1.2448 + void checkHideClashes(DiagnosticPosition pos, Type site, MethodSymbol sym) { 1.2449 + ClashFilter cf = new ClashFilter(site); 1.2450 + //for each method m1 that is a member of 'site'... 1.2451 + for (Symbol s : types.membersClosure(site, true).getElementsByName(sym.name, cf)) { 1.2452 + //if (i) the signature of 'sym' is not a subsignature of m1 (seen as 1.2453 + //a member of 'site') and (ii) 'sym' has the same erasure as m1, issue an error 1.2454 + if (!types.isSubSignature(sym.type, types.memberType(site, s), allowStrictMethodClashCheck)) { 1.2455 + if (types.hasSameArgs(s.erasure(types), sym.erasure(types))) { 1.2456 + log.error(pos, 1.2457 + "name.clash.same.erasure.no.hide", 1.2458 + sym, sym.location(), 1.2459 + s, s.location()); 1.2460 + return; 1.2461 + } else { 1.2462 + checkPotentiallyAmbiguousOverloads(pos, site, sym, (MethodSymbol)s); 1.2463 + } 1.2464 + } 1.2465 + } 1.2466 + } 1.2467 + 1.2468 + //where 1.2469 + private class ClashFilter implements Filter<Symbol> { 1.2470 + 1.2471 + Type site; 1.2472 + 1.2473 + ClashFilter(Type site) { 1.2474 + this.site = site; 1.2475 + } 1.2476 + 1.2477 + boolean shouldSkip(Symbol s) { 1.2478 + return (s.flags() & CLASH) != 0 && 1.2479 + s.owner == site.tsym; 1.2480 + } 1.2481 + 1.2482 + public boolean accepts(Symbol s) { 1.2483 + return s.kind == MTH && 1.2484 + (s.flags() & SYNTHETIC) == 0 && 1.2485 + !shouldSkip(s) && 1.2486 + s.isInheritedIn(site.tsym, types) && 1.2487 + !s.isConstructor(); 1.2488 + } 1.2489 + } 1.2490 + 1.2491 + void checkDefaultMethodClashes(DiagnosticPosition pos, Type site) { 1.2492 + DefaultMethodClashFilter dcf = new DefaultMethodClashFilter(site); 1.2493 + for (Symbol m : types.membersClosure(site, false).getElements(dcf)) { 1.2494 + Assert.check(m.kind == MTH); 1.2495 + List<MethodSymbol> prov = types.interfaceCandidates(site, (MethodSymbol)m); 1.2496 + if (prov.size() > 1) { 1.2497 + ListBuffer<Symbol> abstracts = new ListBuffer<>(); 1.2498 + ListBuffer<Symbol> defaults = new ListBuffer<>(); 1.2499 + for (MethodSymbol provSym : prov) { 1.2500 + if ((provSym.flags() & DEFAULT) != 0) { 1.2501 + defaults = defaults.append(provSym); 1.2502 + } else if ((provSym.flags() & ABSTRACT) != 0) { 1.2503 + abstracts = abstracts.append(provSym); 1.2504 + } 1.2505 + if (defaults.nonEmpty() && defaults.size() + abstracts.size() >= 2) { 1.2506 + //strong semantics - issue an error if two sibling interfaces 1.2507 + //have two override-equivalent defaults - or if one is abstract 1.2508 + //and the other is default 1.2509 + String errKey; 1.2510 + Symbol s1 = defaults.first(); 1.2511 + Symbol s2; 1.2512 + if (defaults.size() > 1) { 1.2513 + errKey = "types.incompatible.unrelated.defaults"; 1.2514 + s2 = defaults.toList().tail.head; 1.2515 + } else { 1.2516 + errKey = "types.incompatible.abstract.default"; 1.2517 + s2 = abstracts.first(); 1.2518 + } 1.2519 + log.error(pos, errKey, 1.2520 + Kinds.kindName(site.tsym), site, 1.2521 + m.name, types.memberType(site, m).getParameterTypes(), 1.2522 + s1.location(), s2.location()); 1.2523 + break; 1.2524 + } 1.2525 + } 1.2526 + } 1.2527 + } 1.2528 + } 1.2529 + 1.2530 + //where 1.2531 + private class DefaultMethodClashFilter implements Filter<Symbol> { 1.2532 + 1.2533 + Type site; 1.2534 + 1.2535 + DefaultMethodClashFilter(Type site) { 1.2536 + this.site = site; 1.2537 + } 1.2538 + 1.2539 + public boolean accepts(Symbol s) { 1.2540 + return s.kind == MTH && 1.2541 + (s.flags() & DEFAULT) != 0 && 1.2542 + s.isInheritedIn(site.tsym, types) && 1.2543 + !s.isConstructor(); 1.2544 + } 1.2545 + } 1.2546 + 1.2547 + /** 1.2548 + * Report warnings for potentially ambiguous method declarations. Two declarations 1.2549 + * are potentially ambiguous if they feature two unrelated functional interface 1.2550 + * in same argument position (in which case, a call site passing an implicit 1.2551 + * lambda would be ambiguous). 1.2552 + */ 1.2553 + void checkPotentiallyAmbiguousOverloads(DiagnosticPosition pos, Type site, 1.2554 + MethodSymbol msym1, MethodSymbol msym2) { 1.2555 + if (msym1 != msym2 && 1.2556 + allowDefaultMethods && 1.2557 + lint.isEnabled(LintCategory.OVERLOADS) && 1.2558 + (msym1.flags() & POTENTIALLY_AMBIGUOUS) == 0 && 1.2559 + (msym2.flags() & POTENTIALLY_AMBIGUOUS) == 0) { 1.2560 + Type mt1 = types.memberType(site, msym1); 1.2561 + Type mt2 = types.memberType(site, msym2); 1.2562 + //if both generic methods, adjust type variables 1.2563 + if (mt1.hasTag(FORALL) && mt2.hasTag(FORALL) && 1.2564 + types.hasSameBounds((ForAll)mt1, (ForAll)mt2)) { 1.2565 + mt2 = types.subst(mt2, ((ForAll)mt2).tvars, ((ForAll)mt1).tvars); 1.2566 + } 1.2567 + //expand varargs methods if needed 1.2568 + int maxLength = Math.max(mt1.getParameterTypes().length(), mt2.getParameterTypes().length()); 1.2569 + List<Type> args1 = rs.adjustArgs(mt1.getParameterTypes(), msym1, maxLength, true); 1.2570 + List<Type> args2 = rs.adjustArgs(mt2.getParameterTypes(), msym2, maxLength, true); 1.2571 + //if arities don't match, exit 1.2572 + if (args1.length() != args2.length()) return; 1.2573 + boolean potentiallyAmbiguous = false; 1.2574 + while (args1.nonEmpty() && args2.nonEmpty()) { 1.2575 + Type s = args1.head; 1.2576 + Type t = args2.head; 1.2577 + if (!types.isSubtype(t, s) && !types.isSubtype(s, t)) { 1.2578 + if (types.isFunctionalInterface(s) && types.isFunctionalInterface(t) && 1.2579 + types.findDescriptorType(s).getParameterTypes().length() > 0 && 1.2580 + types.findDescriptorType(s).getParameterTypes().length() == 1.2581 + types.findDescriptorType(t).getParameterTypes().length()) { 1.2582 + potentiallyAmbiguous = true; 1.2583 + } else { 1.2584 + break; 1.2585 + } 1.2586 + } 1.2587 + args1 = args1.tail; 1.2588 + args2 = args2.tail; 1.2589 + } 1.2590 + if (potentiallyAmbiguous) { 1.2591 + //we found two incompatible functional interfaces with same arity 1.2592 + //this means a call site passing an implicit lambda would be ambigiuous 1.2593 + msym1.flags_field |= POTENTIALLY_AMBIGUOUS; 1.2594 + msym2.flags_field |= POTENTIALLY_AMBIGUOUS; 1.2595 + log.warning(LintCategory.OVERLOADS, pos, "potentially.ambiguous.overload", 1.2596 + msym1, msym1.location(), 1.2597 + msym2, msym2.location()); 1.2598 + return; 1.2599 + } 1.2600 + } 1.2601 + } 1.2602 + 1.2603 + void checkElemAccessFromSerializableLambda(final JCTree tree) { 1.2604 + if (warnOnAccessToSensitiveMembers) { 1.2605 + Symbol sym = TreeInfo.symbol(tree); 1.2606 + if ((sym.kind & (VAR | MTH)) == 0) { 1.2607 + return; 1.2608 + } 1.2609 + 1.2610 + if (sym.kind == VAR) { 1.2611 + if ((sym.flags() & PARAMETER) != 0 || 1.2612 + sym.isLocal() || 1.2613 + sym.name == names._this || 1.2614 + sym.name == names._super) { 1.2615 + return; 1.2616 + } 1.2617 + } 1.2618 + 1.2619 + if (!types.isSubtype(sym.owner.type, syms.serializableType) && 1.2620 + isEffectivelyNonPublic(sym)) { 1.2621 + log.warning(tree.pos(), 1.2622 + "access.to.sensitive.member.from.serializable.element", sym); 1.2623 + } 1.2624 + } 1.2625 + } 1.2626 + 1.2627 + private boolean isEffectivelyNonPublic(Symbol sym) { 1.2628 + if (sym.packge() == syms.rootPackage) { 1.2629 + return false; 1.2630 + } 1.2631 + 1.2632 + while (sym.kind != Kinds.PCK) { 1.2633 + if ((sym.flags() & PUBLIC) == 0) { 1.2634 + return true; 1.2635 + } 1.2636 + sym = sym.owner; 1.2637 + } 1.2638 + return false; 1.2639 + } 1.2640 + 1.2641 + /** Report a conflict between a user symbol and a synthetic symbol. 1.2642 + */ 1.2643 + private void syntheticError(DiagnosticPosition pos, Symbol sym) { 1.2644 + if (!sym.type.isErroneous()) { 1.2645 + if (warnOnSyntheticConflicts) { 1.2646 + log.warning(pos, "synthetic.name.conflict", sym, sym.location()); 1.2647 + } 1.2648 + else { 1.2649 + log.error(pos, "synthetic.name.conflict", sym, sym.location()); 1.2650 + } 1.2651 + } 1.2652 + } 1.2653 + 1.2654 + /** Check that class c does not implement directly or indirectly 1.2655 + * the same parameterized interface with two different argument lists. 1.2656 + * @param pos Position to be used for error reporting. 1.2657 + * @param type The type whose interfaces are checked. 1.2658 + */ 1.2659 + void checkClassBounds(DiagnosticPosition pos, Type type) { 1.2660 + checkClassBounds(pos, new HashMap<TypeSymbol,Type>(), type); 1.2661 + } 1.2662 +//where 1.2663 + /** Enter all interfaces of type `type' into the hash table `seensofar' 1.2664 + * with their class symbol as key and their type as value. Make 1.2665 + * sure no class is entered with two different types. 1.2666 + */ 1.2667 + void checkClassBounds(DiagnosticPosition pos, 1.2668 + Map<TypeSymbol,Type> seensofar, 1.2669 + Type type) { 1.2670 + if (type.isErroneous()) return; 1.2671 + for (List<Type> l = types.interfaces(type); l.nonEmpty(); l = l.tail) { 1.2672 + Type it = l.head; 1.2673 + Type oldit = seensofar.put(it.tsym, it); 1.2674 + if (oldit != null) { 1.2675 + List<Type> oldparams = oldit.allparams(); 1.2676 + List<Type> newparams = it.allparams(); 1.2677 + if (!types.containsTypeEquivalent(oldparams, newparams)) 1.2678 + log.error(pos, "cant.inherit.diff.arg", 1.2679 + it.tsym, Type.toString(oldparams), 1.2680 + Type.toString(newparams)); 1.2681 + } 1.2682 + checkClassBounds(pos, seensofar, it); 1.2683 + } 1.2684 + Type st = types.supertype(type); 1.2685 + if (st != Type.noType) checkClassBounds(pos, seensofar, st); 1.2686 + } 1.2687 + 1.2688 + /** Enter interface into into set. 1.2689 + * If it existed already, issue a "repeated interface" error. 1.2690 + */ 1.2691 + void checkNotRepeated(DiagnosticPosition pos, Type it, Set<Type> its) { 1.2692 + if (its.contains(it)) 1.2693 + log.error(pos, "repeated.interface"); 1.2694 + else { 1.2695 + its.add(it); 1.2696 + } 1.2697 + } 1.2698 + 1.2699 +/* ************************************************************************* 1.2700 + * Check annotations 1.2701 + **************************************************************************/ 1.2702 + 1.2703 + /** 1.2704 + * Recursively validate annotations values 1.2705 + */ 1.2706 + void validateAnnotationTree(JCTree tree) { 1.2707 + class AnnotationValidator extends TreeScanner { 1.2708 + @Override 1.2709 + public void visitAnnotation(JCAnnotation tree) { 1.2710 + if (!tree.type.isErroneous()) { 1.2711 + super.visitAnnotation(tree); 1.2712 + validateAnnotation(tree); 1.2713 + } 1.2714 + } 1.2715 + } 1.2716 + tree.accept(new AnnotationValidator()); 1.2717 + } 1.2718 + 1.2719 + /** 1.2720 + * {@literal 1.2721 + * Annotation types are restricted to primitives, String, an 1.2722 + * enum, an annotation, Class, Class<?>, Class<? extends 1.2723 + * Anything>, arrays of the preceding. 1.2724 + * } 1.2725 + */ 1.2726 + void validateAnnotationType(JCTree restype) { 1.2727 + // restype may be null if an error occurred, so don't bother validating it 1.2728 + if (restype != null) { 1.2729 + validateAnnotationType(restype.pos(), restype.type); 1.2730 + } 1.2731 + } 1.2732 + 1.2733 + void validateAnnotationType(DiagnosticPosition pos, Type type) { 1.2734 + if (type.isPrimitive()) return; 1.2735 + if (types.isSameType(type, syms.stringType)) return; 1.2736 + if ((type.tsym.flags() & Flags.ENUM) != 0) return; 1.2737 + if ((type.tsym.flags() & Flags.ANNOTATION) != 0) return; 1.2738 + if (types.cvarLowerBound(type).tsym == syms.classType.tsym) return; 1.2739 + if (types.isArray(type) && !types.isArray(types.elemtype(type))) { 1.2740 + validateAnnotationType(pos, types.elemtype(type)); 1.2741 + return; 1.2742 + } 1.2743 + log.error(pos, "invalid.annotation.member.type"); 1.2744 + } 1.2745 + 1.2746 + /** 1.2747 + * "It is also a compile-time error if any method declared in an 1.2748 + * annotation type has a signature that is override-equivalent to 1.2749 + * that of any public or protected method declared in class Object 1.2750 + * or in the interface annotation.Annotation." 1.2751 + * 1.2752 + * @jls 9.6 Annotation Types 1.2753 + */ 1.2754 + void validateAnnotationMethod(DiagnosticPosition pos, MethodSymbol m) { 1.2755 + for (Type sup = syms.annotationType; sup.hasTag(CLASS); sup = types.supertype(sup)) { 1.2756 + Scope s = sup.tsym.members(); 1.2757 + for (Scope.Entry e = s.lookup(m.name); e.scope != null; e = e.next()) { 1.2758 + if (e.sym.kind == MTH && 1.2759 + (e.sym.flags() & (PUBLIC | PROTECTED)) != 0 && 1.2760 + types.overrideEquivalent(m.type, e.sym.type)) 1.2761 + log.error(pos, "intf.annotation.member.clash", e.sym, sup); 1.2762 + } 1.2763 + } 1.2764 + } 1.2765 + 1.2766 + /** Check the annotations of a symbol. 1.2767 + */ 1.2768 + public void validateAnnotations(List<JCAnnotation> annotations, Symbol s) { 1.2769 + for (JCAnnotation a : annotations) 1.2770 + validateAnnotation(a, s); 1.2771 + } 1.2772 + 1.2773 + /** Check the type annotations. 1.2774 + */ 1.2775 + public void validateTypeAnnotations(List<JCAnnotation> annotations, boolean isTypeParameter) { 1.2776 + for (JCAnnotation a : annotations) 1.2777 + validateTypeAnnotation(a, isTypeParameter); 1.2778 + } 1.2779 + 1.2780 + /** Check an annotation of a symbol. 1.2781 + */ 1.2782 + private void validateAnnotation(JCAnnotation a, Symbol s) { 1.2783 + validateAnnotationTree(a); 1.2784 + 1.2785 + if (!annotationApplicable(a, s)) 1.2786 + log.error(a.pos(), "annotation.type.not.applicable"); 1.2787 + 1.2788 + if (a.annotationType.type.tsym == syms.functionalInterfaceType.tsym) { 1.2789 + if (s.kind != TYP) { 1.2790 + log.error(a.pos(), "bad.functional.intf.anno"); 1.2791 + } else if (!s.isInterface() || (s.flags() & ANNOTATION) != 0) { 1.2792 + log.error(a.pos(), "bad.functional.intf.anno.1", diags.fragment("not.a.functional.intf", s)); 1.2793 + } 1.2794 + } 1.2795 + } 1.2796 + 1.2797 + public void validateTypeAnnotation(JCAnnotation a, boolean isTypeParameter) { 1.2798 + Assert.checkNonNull(a.type, "annotation tree hasn't been attributed yet: " + a); 1.2799 + validateAnnotationTree(a); 1.2800 + 1.2801 + if (a.hasTag(TYPE_ANNOTATION) && 1.2802 + !a.annotationType.type.isErroneous() && 1.2803 + !isTypeAnnotation(a, isTypeParameter)) { 1.2804 + log.error(a.pos(), "annotation.type.not.applicable"); 1.2805 + } 1.2806 + } 1.2807 + 1.2808 + /** 1.2809 + * Validate the proposed container 'repeatable' on the 1.2810 + * annotation type symbol 's'. Report errors at position 1.2811 + * 'pos'. 1.2812 + * 1.2813 + * @param s The (annotation)type declaration annotated with a @Repeatable 1.2814 + * @param repeatable the @Repeatable on 's' 1.2815 + * @param pos where to report errors 1.2816 + */ 1.2817 + public void validateRepeatable(TypeSymbol s, Attribute.Compound repeatable, DiagnosticPosition pos) { 1.2818 + Assert.check(types.isSameType(repeatable.type, syms.repeatableType)); 1.2819 + 1.2820 + Type t = null; 1.2821 + List<Pair<MethodSymbol,Attribute>> l = repeatable.values; 1.2822 + if (!l.isEmpty()) { 1.2823 + Assert.check(l.head.fst.name == names.value); 1.2824 + t = ((Attribute.Class)l.head.snd).getValue(); 1.2825 + } 1.2826 + 1.2827 + if (t == null) { 1.2828 + // errors should already have been reported during Annotate 1.2829 + return; 1.2830 + } 1.2831 + 1.2832 + validateValue(t.tsym, s, pos); 1.2833 + validateRetention(t.tsym, s, pos); 1.2834 + validateDocumented(t.tsym, s, pos); 1.2835 + validateInherited(t.tsym, s, pos); 1.2836 + validateTarget(t.tsym, s, pos); 1.2837 + validateDefault(t.tsym, pos); 1.2838 + } 1.2839 + 1.2840 + private void validateValue(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) { 1.2841 + Scope.Entry e = container.members().lookup(names.value); 1.2842 + if (e.scope != null && e.sym.kind == MTH) { 1.2843 + MethodSymbol m = (MethodSymbol) e.sym; 1.2844 + Type ret = m.getReturnType(); 1.2845 + if (!(ret.hasTag(ARRAY) && types.isSameType(((ArrayType)ret).elemtype, contained.type))) { 1.2846 + log.error(pos, "invalid.repeatable.annotation.value.return", 1.2847 + container, ret, types.makeArrayType(contained.type)); 1.2848 + } 1.2849 + } else { 1.2850 + log.error(pos, "invalid.repeatable.annotation.no.value", container); 1.2851 + } 1.2852 + } 1.2853 + 1.2854 + private void validateRetention(Symbol container, Symbol contained, DiagnosticPosition pos) { 1.2855 + Attribute.RetentionPolicy containerRetention = types.getRetention(container); 1.2856 + Attribute.RetentionPolicy containedRetention = types.getRetention(contained); 1.2857 + 1.2858 + boolean error = false; 1.2859 + switch (containedRetention) { 1.2860 + case RUNTIME: 1.2861 + if (containerRetention != Attribute.RetentionPolicy.RUNTIME) { 1.2862 + error = true; 1.2863 + } 1.2864 + break; 1.2865 + case CLASS: 1.2866 + if (containerRetention == Attribute.RetentionPolicy.SOURCE) { 1.2867 + error = true; 1.2868 + } 1.2869 + } 1.2870 + if (error ) { 1.2871 + log.error(pos, "invalid.repeatable.annotation.retention", 1.2872 + container, containerRetention, 1.2873 + contained, containedRetention); 1.2874 + } 1.2875 + } 1.2876 + 1.2877 + private void validateDocumented(Symbol container, Symbol contained, DiagnosticPosition pos) { 1.2878 + if (contained.attribute(syms.documentedType.tsym) != null) { 1.2879 + if (container.attribute(syms.documentedType.tsym) == null) { 1.2880 + log.error(pos, "invalid.repeatable.annotation.not.documented", container, contained); 1.2881 + } 1.2882 + } 1.2883 + } 1.2884 + 1.2885 + private void validateInherited(Symbol container, Symbol contained, DiagnosticPosition pos) { 1.2886 + if (contained.attribute(syms.inheritedType.tsym) != null) { 1.2887 + if (container.attribute(syms.inheritedType.tsym) == null) { 1.2888 + log.error(pos, "invalid.repeatable.annotation.not.inherited", container, contained); 1.2889 + } 1.2890 + } 1.2891 + } 1.2892 + 1.2893 + private void validateTarget(Symbol container, Symbol contained, DiagnosticPosition pos) { 1.2894 + // The set of targets the container is applicable to must be a subset 1.2895 + // (with respect to annotation target semantics) of the set of targets 1.2896 + // the contained is applicable to. The target sets may be implicit or 1.2897 + // explicit. 1.2898 + 1.2899 + Set<Name> containerTargets; 1.2900 + Attribute.Array containerTarget = getAttributeTargetAttribute(container); 1.2901 + if (containerTarget == null) { 1.2902 + containerTargets = getDefaultTargetSet(); 1.2903 + } else { 1.2904 + containerTargets = new HashSet<Name>(); 1.2905 + for (Attribute app : containerTarget.values) { 1.2906 + if (!(app instanceof Attribute.Enum)) { 1.2907 + continue; // recovery 1.2908 + } 1.2909 + Attribute.Enum e = (Attribute.Enum)app; 1.2910 + containerTargets.add(e.value.name); 1.2911 + } 1.2912 + } 1.2913 + 1.2914 + Set<Name> containedTargets; 1.2915 + Attribute.Array containedTarget = getAttributeTargetAttribute(contained); 1.2916 + if (containedTarget == null) { 1.2917 + containedTargets = getDefaultTargetSet(); 1.2918 + } else { 1.2919 + containedTargets = new HashSet<Name>(); 1.2920 + for (Attribute app : containedTarget.values) { 1.2921 + if (!(app instanceof Attribute.Enum)) { 1.2922 + continue; // recovery 1.2923 + } 1.2924 + Attribute.Enum e = (Attribute.Enum)app; 1.2925 + containedTargets.add(e.value.name); 1.2926 + } 1.2927 + } 1.2928 + 1.2929 + if (!isTargetSubsetOf(containerTargets, containedTargets)) { 1.2930 + log.error(pos, "invalid.repeatable.annotation.incompatible.target", container, contained); 1.2931 + } 1.2932 + } 1.2933 + 1.2934 + /* get a set of names for the default target */ 1.2935 + private Set<Name> getDefaultTargetSet() { 1.2936 + if (defaultTargets == null) { 1.2937 + Set<Name> targets = new HashSet<Name>(); 1.2938 + targets.add(names.ANNOTATION_TYPE); 1.2939 + targets.add(names.CONSTRUCTOR); 1.2940 + targets.add(names.FIELD); 1.2941 + targets.add(names.LOCAL_VARIABLE); 1.2942 + targets.add(names.METHOD); 1.2943 + targets.add(names.PACKAGE); 1.2944 + targets.add(names.PARAMETER); 1.2945 + targets.add(names.TYPE); 1.2946 + 1.2947 + defaultTargets = java.util.Collections.unmodifiableSet(targets); 1.2948 + } 1.2949 + 1.2950 + return defaultTargets; 1.2951 + } 1.2952 + private Set<Name> defaultTargets; 1.2953 + 1.2954 + 1.2955 + /** Checks that s is a subset of t, with respect to ElementType 1.2956 + * semantics, specifically {ANNOTATION_TYPE} is a subset of {TYPE}, 1.2957 + * and {TYPE_USE} covers the set {ANNOTATION_TYPE, TYPE, TYPE_USE, 1.2958 + * TYPE_PARAMETER}. 1.2959 + */ 1.2960 + private boolean isTargetSubsetOf(Set<Name> s, Set<Name> t) { 1.2961 + // Check that all elements in s are present in t 1.2962 + for (Name n2 : s) { 1.2963 + boolean currentElementOk = false; 1.2964 + for (Name n1 : t) { 1.2965 + if (n1 == n2) { 1.2966 + currentElementOk = true; 1.2967 + break; 1.2968 + } else if (n1 == names.TYPE && n2 == names.ANNOTATION_TYPE) { 1.2969 + currentElementOk = true; 1.2970 + break; 1.2971 + } else if (n1 == names.TYPE_USE && 1.2972 + (n2 == names.TYPE || 1.2973 + n2 == names.ANNOTATION_TYPE || 1.2974 + n2 == names.TYPE_PARAMETER)) { 1.2975 + currentElementOk = true; 1.2976 + break; 1.2977 + } 1.2978 + } 1.2979 + if (!currentElementOk) 1.2980 + return false; 1.2981 + } 1.2982 + return true; 1.2983 + } 1.2984 + 1.2985 + private void validateDefault(Symbol container, DiagnosticPosition pos) { 1.2986 + // validate that all other elements of containing type has defaults 1.2987 + Scope scope = container.members(); 1.2988 + for(Symbol elm : scope.getElements()) { 1.2989 + if (elm.name != names.value && 1.2990 + elm.kind == Kinds.MTH && 1.2991 + ((MethodSymbol)elm).defaultValue == null) { 1.2992 + log.error(pos, 1.2993 + "invalid.repeatable.annotation.elem.nondefault", 1.2994 + container, 1.2995 + elm); 1.2996 + } 1.2997 + } 1.2998 + } 1.2999 + 1.3000 + /** Is s a method symbol that overrides a method in a superclass? */ 1.3001 + boolean isOverrider(Symbol s) { 1.3002 + if (s.kind != MTH || s.isStatic()) 1.3003 + return false; 1.3004 + MethodSymbol m = (MethodSymbol)s; 1.3005 + TypeSymbol owner = (TypeSymbol)m.owner; 1.3006 + for (Type sup : types.closure(owner.type)) { 1.3007 + if (sup == owner.type) 1.3008 + continue; // skip "this" 1.3009 + Scope scope = sup.tsym.members(); 1.3010 + for (Scope.Entry e = scope.lookup(m.name); e.scope != null; e = e.next()) { 1.3011 + if (!e.sym.isStatic() && m.overrides(e.sym, owner, types, true)) 1.3012 + return true; 1.3013 + } 1.3014 + } 1.3015 + return false; 1.3016 + } 1.3017 + 1.3018 + /** Is the annotation applicable to types? */ 1.3019 + protected boolean isTypeAnnotation(JCAnnotation a, boolean isTypeParameter) { 1.3020 + Attribute.Compound atTarget = 1.3021 + a.annotationType.type.tsym.attribute(syms.annotationTargetType.tsym); 1.3022 + if (atTarget == null) { 1.3023 + // An annotation without @Target is not a type annotation. 1.3024 + return false; 1.3025 + } 1.3026 + 1.3027 + Attribute atValue = atTarget.member(names.value); 1.3028 + if (!(atValue instanceof Attribute.Array)) { 1.3029 + return false; // error recovery 1.3030 + } 1.3031 + 1.3032 + Attribute.Array arr = (Attribute.Array) atValue; 1.3033 + for (Attribute app : arr.values) { 1.3034 + if (!(app instanceof Attribute.Enum)) { 1.3035 + return false; // recovery 1.3036 + } 1.3037 + Attribute.Enum e = (Attribute.Enum) app; 1.3038 + 1.3039 + if (e.value.name == names.TYPE_USE) 1.3040 + return true; 1.3041 + else if (isTypeParameter && e.value.name == names.TYPE_PARAMETER) 1.3042 + return true; 1.3043 + } 1.3044 + return false; 1.3045 + } 1.3046 + 1.3047 + /** Is the annotation applicable to the symbol? */ 1.3048 + boolean annotationApplicable(JCAnnotation a, Symbol s) { 1.3049 + Attribute.Array arr = getAttributeTargetAttribute(a.annotationType.type.tsym); 1.3050 + Name[] targets; 1.3051 + 1.3052 + if (arr == null) { 1.3053 + targets = defaultTargetMetaInfo(a, s); 1.3054 + } else { 1.3055 + // TODO: can we optimize this? 1.3056 + targets = new Name[arr.values.length]; 1.3057 + for (int i=0; i<arr.values.length; ++i) { 1.3058 + Attribute app = arr.values[i]; 1.3059 + if (!(app instanceof Attribute.Enum)) { 1.3060 + return true; // recovery 1.3061 + } 1.3062 + Attribute.Enum e = (Attribute.Enum) app; 1.3063 + targets[i] = e.value.name; 1.3064 + } 1.3065 + } 1.3066 + for (Name target : targets) { 1.3067 + if (target == names.TYPE) 1.3068 + { if (s.kind == TYP) return true; } 1.3069 + else if (target == names.FIELD) 1.3070 + { if (s.kind == VAR && s.owner.kind != MTH) return true; } 1.3071 + else if (target == names.METHOD) 1.3072 + { if (s.kind == MTH && !s.isConstructor()) return true; } 1.3073 + else if (target == names.PARAMETER) 1.3074 + { if (s.kind == VAR && 1.3075 + s.owner.kind == MTH && 1.3076 + (s.flags() & PARAMETER) != 0) 1.3077 + return true; 1.3078 + } 1.3079 + else if (target == names.CONSTRUCTOR) 1.3080 + { if (s.kind == MTH && s.isConstructor()) return true; } 1.3081 + else if (target == names.LOCAL_VARIABLE) 1.3082 + { if (s.kind == VAR && s.owner.kind == MTH && 1.3083 + (s.flags() & PARAMETER) == 0) 1.3084 + return true; 1.3085 + } 1.3086 + else if (target == names.ANNOTATION_TYPE) 1.3087 + { if (s.kind == TYP && (s.flags() & ANNOTATION) != 0) 1.3088 + return true; 1.3089 + } 1.3090 + else if (target == names.PACKAGE) 1.3091 + { if (s.kind == PCK) return true; } 1.3092 + else if (target == names.TYPE_USE) 1.3093 + { if (s.kind == TYP || 1.3094 + s.kind == VAR || 1.3095 + (s.kind == MTH && !s.isConstructor() && 1.3096 + !s.type.getReturnType().hasTag(VOID)) || 1.3097 + (s.kind == MTH && s.isConstructor())) 1.3098 + return true; 1.3099 + } 1.3100 + else if (target == names.TYPE_PARAMETER) 1.3101 + { if (s.kind == TYP && s.type.hasTag(TYPEVAR)) 1.3102 + return true; 1.3103 + } 1.3104 + else 1.3105 + return true; // recovery 1.3106 + } 1.3107 + return false; 1.3108 + } 1.3109 + 1.3110 + 1.3111 + Attribute.Array getAttributeTargetAttribute(Symbol s) { 1.3112 + Attribute.Compound atTarget = 1.3113 + s.attribute(syms.annotationTargetType.tsym); 1.3114 + if (atTarget == null) return null; // ok, is applicable 1.3115 + Attribute atValue = atTarget.member(names.value); 1.3116 + if (!(atValue instanceof Attribute.Array)) return null; // error recovery 1.3117 + return (Attribute.Array) atValue; 1.3118 + } 1.3119 + 1.3120 + private final Name[] dfltTargetMeta; 1.3121 + private Name[] defaultTargetMetaInfo(JCAnnotation a, Symbol s) { 1.3122 + return dfltTargetMeta; 1.3123 + } 1.3124 + 1.3125 + /** Check an annotation value. 1.3126 + * 1.3127 + * @param a The annotation tree to check 1.3128 + * @return true if this annotation tree is valid, otherwise false 1.3129 + */ 1.3130 + public boolean validateAnnotationDeferErrors(JCAnnotation a) { 1.3131 + boolean res = false; 1.3132 + final Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log); 1.3133 + try { 1.3134 + res = validateAnnotation(a); 1.3135 + } finally { 1.3136 + log.popDiagnosticHandler(diagHandler); 1.3137 + } 1.3138 + return res; 1.3139 + } 1.3140 + 1.3141 + private boolean validateAnnotation(JCAnnotation a) { 1.3142 + boolean isValid = true; 1.3143 + // collect an inventory of the annotation elements 1.3144 + Set<MethodSymbol> members = new LinkedHashSet<MethodSymbol>(); 1.3145 + for (Scope.Entry e = a.annotationType.type.tsym.members().elems; 1.3146 + e != null; 1.3147 + e = e.sibling) 1.3148 + if (e.sym.kind == MTH && e.sym.name != names.clinit && 1.3149 + (e.sym.flags() & SYNTHETIC) == 0) 1.3150 + members.add((MethodSymbol) e.sym); 1.3151 + 1.3152 + // remove the ones that are assigned values 1.3153 + for (JCTree arg : a.args) { 1.3154 + if (!arg.hasTag(ASSIGN)) continue; // recovery 1.3155 + JCAssign assign = (JCAssign) arg; 1.3156 + Symbol m = TreeInfo.symbol(assign.lhs); 1.3157 + if (m == null || m.type.isErroneous()) continue; 1.3158 + if (!members.remove(m)) { 1.3159 + isValid = false; 1.3160 + log.error(assign.lhs.pos(), "duplicate.annotation.member.value", 1.3161 + m.name, a.type); 1.3162 + } 1.3163 + } 1.3164 + 1.3165 + // all the remaining ones better have default values 1.3166 + List<Name> missingDefaults = List.nil(); 1.3167 + for (MethodSymbol m : members) { 1.3168 + if (m.defaultValue == null && !m.type.isErroneous()) { 1.3169 + missingDefaults = missingDefaults.append(m.name); 1.3170 + } 1.3171 + } 1.3172 + missingDefaults = missingDefaults.reverse(); 1.3173 + if (missingDefaults.nonEmpty()) { 1.3174 + isValid = false; 1.3175 + String key = (missingDefaults.size() > 1) 1.3176 + ? "annotation.missing.default.value.1" 1.3177 + : "annotation.missing.default.value"; 1.3178 + log.error(a.pos(), key, a.type, missingDefaults); 1.3179 + } 1.3180 + 1.3181 + // special case: java.lang.annotation.Target must not have 1.3182 + // repeated values in its value member 1.3183 + if (a.annotationType.type.tsym != syms.annotationTargetType.tsym || 1.3184 + a.args.tail == null) 1.3185 + return isValid; 1.3186 + 1.3187 + if (!a.args.head.hasTag(ASSIGN)) return false; // error recovery 1.3188 + JCAssign assign = (JCAssign) a.args.head; 1.3189 + Symbol m = TreeInfo.symbol(assign.lhs); 1.3190 + if (m.name != names.value) return false; 1.3191 + JCTree rhs = assign.rhs; 1.3192 + if (!rhs.hasTag(NEWARRAY)) return false; 1.3193 + JCNewArray na = (JCNewArray) rhs; 1.3194 + Set<Symbol> targets = new HashSet<Symbol>(); 1.3195 + for (JCTree elem : na.elems) { 1.3196 + if (!targets.add(TreeInfo.symbol(elem))) { 1.3197 + isValid = false; 1.3198 + log.error(elem.pos(), "repeated.annotation.target"); 1.3199 + } 1.3200 + } 1.3201 + return isValid; 1.3202 + } 1.3203 + 1.3204 + void checkDeprecatedAnnotation(DiagnosticPosition pos, Symbol s) { 1.3205 + if (allowAnnotations && 1.3206 + lint.isEnabled(LintCategory.DEP_ANN) && 1.3207 + (s.flags() & DEPRECATED) != 0 && 1.3208 + !syms.deprecatedType.isErroneous() && 1.3209 + s.attribute(syms.deprecatedType.tsym) == null) { 1.3210 + log.warning(LintCategory.DEP_ANN, 1.3211 + pos, "missing.deprecated.annotation"); 1.3212 + } 1.3213 + } 1.3214 + 1.3215 + void checkDeprecated(final DiagnosticPosition pos, final Symbol other, final Symbol s) { 1.3216 + if ((s.flags() & DEPRECATED) != 0 && 1.3217 + (other.flags() & DEPRECATED) == 0 && 1.3218 + s.outermostClass() != other.outermostClass()) { 1.3219 + deferredLintHandler.report(new DeferredLintHandler.LintLogger() { 1.3220 + @Override 1.3221 + public void report() { 1.3222 + warnDeprecated(pos, s); 1.3223 + } 1.3224 + }); 1.3225 + } 1.3226 + } 1.3227 + 1.3228 + void checkSunAPI(final DiagnosticPosition pos, final Symbol s) { 1.3229 + if ((s.flags() & PROPRIETARY) != 0) { 1.3230 + deferredLintHandler.report(new DeferredLintHandler.LintLogger() { 1.3231 + public void report() { 1.3232 + if (enableSunApiLintControl) 1.3233 + warnSunApi(pos, "sun.proprietary", s); 1.3234 + else 1.3235 + log.mandatoryWarning(pos, "sun.proprietary", s); 1.3236 + } 1.3237 + }); 1.3238 + } 1.3239 + } 1.3240 + 1.3241 + void checkProfile(final DiagnosticPosition pos, final Symbol s) { 1.3242 + if (profile != Profile.DEFAULT && (s.flags() & NOT_IN_PROFILE) != 0) { 1.3243 + log.error(pos, "not.in.profile", s, profile); 1.3244 + } 1.3245 + } 1.3246 + 1.3247 +/* ************************************************************************* 1.3248 + * Check for recursive annotation elements. 1.3249 + **************************************************************************/ 1.3250 + 1.3251 + /** Check for cycles in the graph of annotation elements. 1.3252 + */ 1.3253 + void checkNonCyclicElements(JCClassDecl tree) { 1.3254 + if ((tree.sym.flags_field & ANNOTATION) == 0) return; 1.3255 + Assert.check((tree.sym.flags_field & LOCKED) == 0); 1.3256 + try { 1.3257 + tree.sym.flags_field |= LOCKED; 1.3258 + for (JCTree def : tree.defs) { 1.3259 + if (!def.hasTag(METHODDEF)) continue; 1.3260 + JCMethodDecl meth = (JCMethodDecl)def; 1.3261 + checkAnnotationResType(meth.pos(), meth.restype.type); 1.3262 + } 1.3263 + } finally { 1.3264 + tree.sym.flags_field &= ~LOCKED; 1.3265 + tree.sym.flags_field |= ACYCLIC_ANN; 1.3266 + } 1.3267 + } 1.3268 + 1.3269 + void checkNonCyclicElementsInternal(DiagnosticPosition pos, TypeSymbol tsym) { 1.3270 + if ((tsym.flags_field & ACYCLIC_ANN) != 0) 1.3271 + return; 1.3272 + if ((tsym.flags_field & LOCKED) != 0) { 1.3273 + log.error(pos, "cyclic.annotation.element"); 1.3274 + return; 1.3275 + } 1.3276 + try { 1.3277 + tsym.flags_field |= LOCKED; 1.3278 + for (Scope.Entry e = tsym.members().elems; e != null; e = e.sibling) { 1.3279 + Symbol s = e.sym; 1.3280 + if (s.kind != Kinds.MTH) 1.3281 + continue; 1.3282 + checkAnnotationResType(pos, ((MethodSymbol)s).type.getReturnType()); 1.3283 + } 1.3284 + } finally { 1.3285 + tsym.flags_field &= ~LOCKED; 1.3286 + tsym.flags_field |= ACYCLIC_ANN; 1.3287 + } 1.3288 + } 1.3289 + 1.3290 + void checkAnnotationResType(DiagnosticPosition pos, Type type) { 1.3291 + switch (type.getTag()) { 1.3292 + case CLASS: 1.3293 + if ((type.tsym.flags() & ANNOTATION) != 0) 1.3294 + checkNonCyclicElementsInternal(pos, type.tsym); 1.3295 + break; 1.3296 + case ARRAY: 1.3297 + checkAnnotationResType(pos, types.elemtype(type)); 1.3298 + break; 1.3299 + default: 1.3300 + break; // int etc 1.3301 + } 1.3302 + } 1.3303 + 1.3304 +/* ************************************************************************* 1.3305 + * Check for cycles in the constructor call graph. 1.3306 + **************************************************************************/ 1.3307 + 1.3308 + /** Check for cycles in the graph of constructors calling other 1.3309 + * constructors. 1.3310 + */ 1.3311 + void checkCyclicConstructors(JCClassDecl tree) { 1.3312 + Map<Symbol,Symbol> callMap = new HashMap<Symbol, Symbol>(); 1.3313 + 1.3314 + // enter each constructor this-call into the map 1.3315 + for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { 1.3316 + JCMethodInvocation app = TreeInfo.firstConstructorCall(l.head); 1.3317 + if (app == null) continue; 1.3318 + JCMethodDecl meth = (JCMethodDecl) l.head; 1.3319 + if (TreeInfo.name(app.meth) == names._this) { 1.3320 + callMap.put(meth.sym, TreeInfo.symbol(app.meth)); 1.3321 + } else { 1.3322 + meth.sym.flags_field |= ACYCLIC; 1.3323 + } 1.3324 + } 1.3325 + 1.3326 + // Check for cycles in the map 1.3327 + Symbol[] ctors = new Symbol[0]; 1.3328 + ctors = callMap.keySet().toArray(ctors); 1.3329 + for (Symbol caller : ctors) { 1.3330 + checkCyclicConstructor(tree, caller, callMap); 1.3331 + } 1.3332 + } 1.3333 + 1.3334 + /** Look in the map to see if the given constructor is part of a 1.3335 + * call cycle. 1.3336 + */ 1.3337 + private void checkCyclicConstructor(JCClassDecl tree, Symbol ctor, 1.3338 + Map<Symbol,Symbol> callMap) { 1.3339 + if (ctor != null && (ctor.flags_field & ACYCLIC) == 0) { 1.3340 + if ((ctor.flags_field & LOCKED) != 0) { 1.3341 + log.error(TreeInfo.diagnosticPositionFor(ctor, tree), 1.3342 + "recursive.ctor.invocation"); 1.3343 + } else { 1.3344 + ctor.flags_field |= LOCKED; 1.3345 + checkCyclicConstructor(tree, callMap.remove(ctor), callMap); 1.3346 + ctor.flags_field &= ~LOCKED; 1.3347 + } 1.3348 + ctor.flags_field |= ACYCLIC; 1.3349 + } 1.3350 + } 1.3351 + 1.3352 +/* ************************************************************************* 1.3353 + * Miscellaneous 1.3354 + **************************************************************************/ 1.3355 + 1.3356 + /** 1.3357 + * Return the opcode of the operator but emit an error if it is an 1.3358 + * error. 1.3359 + * @param pos position for error reporting. 1.3360 + * @param operator an operator 1.3361 + * @param tag a tree tag 1.3362 + * @param left type of left hand side 1.3363 + * @param right type of right hand side 1.3364 + */ 1.3365 + int checkOperator(DiagnosticPosition pos, 1.3366 + OperatorSymbol operator, 1.3367 + JCTree.Tag tag, 1.3368 + Type left, 1.3369 + Type right) { 1.3370 + if (operator.opcode == ByteCodes.error) { 1.3371 + log.error(pos, 1.3372 + "operator.cant.be.applied.1", 1.3373 + treeinfo.operatorName(tag), 1.3374 + left, right); 1.3375 + } 1.3376 + return operator.opcode; 1.3377 + } 1.3378 + 1.3379 + 1.3380 + /** 1.3381 + * Check for division by integer constant zero 1.3382 + * @param pos Position for error reporting. 1.3383 + * @param operator The operator for the expression 1.3384 + * @param operand The right hand operand for the expression 1.3385 + */ 1.3386 + void checkDivZero(DiagnosticPosition pos, Symbol operator, Type operand) { 1.3387 + if (operand.constValue() != null 1.3388 + && lint.isEnabled(LintCategory.DIVZERO) 1.3389 + && operand.getTag().isSubRangeOf(LONG) 1.3390 + && ((Number) (operand.constValue())).longValue() == 0) { 1.3391 + int opc = ((OperatorSymbol)operator).opcode; 1.3392 + if (opc == ByteCodes.idiv || opc == ByteCodes.imod 1.3393 + || opc == ByteCodes.ldiv || opc == ByteCodes.lmod) { 1.3394 + log.warning(LintCategory.DIVZERO, pos, "div.zero"); 1.3395 + } 1.3396 + } 1.3397 + } 1.3398 + 1.3399 + /** 1.3400 + * Check for empty statements after if 1.3401 + */ 1.3402 + void checkEmptyIf(JCIf tree) { 1.3403 + if (tree.thenpart.hasTag(SKIP) && tree.elsepart == null && 1.3404 + lint.isEnabled(LintCategory.EMPTY)) 1.3405 + log.warning(LintCategory.EMPTY, tree.thenpart.pos(), "empty.if"); 1.3406 + } 1.3407 + 1.3408 + /** Check that symbol is unique in given scope. 1.3409 + * @param pos Position for error reporting. 1.3410 + * @param sym The symbol. 1.3411 + * @param s The scope. 1.3412 + */ 1.3413 + boolean checkUnique(DiagnosticPosition pos, Symbol sym, Scope s) { 1.3414 + if (sym.type.isErroneous()) 1.3415 + return true; 1.3416 + if (sym.owner.name == names.any) return false; 1.3417 + for (Scope.Entry e = s.lookup(sym.name); e.scope == s; e = e.next()) { 1.3418 + if (sym != e.sym && 1.3419 + (e.sym.flags() & CLASH) == 0 && 1.3420 + sym.kind == e.sym.kind && 1.3421 + sym.name != names.error && 1.3422 + (sym.kind != MTH || 1.3423 + types.hasSameArgs(sym.type, e.sym.type) || 1.3424 + types.hasSameArgs(types.erasure(sym.type), types.erasure(e.sym.type)))) { 1.3425 + if ((sym.flags() & VARARGS) != (e.sym.flags() & VARARGS)) { 1.3426 + varargsDuplicateError(pos, sym, e.sym); 1.3427 + return true; 1.3428 + } else if (sym.kind == MTH && !types.hasSameArgs(sym.type, e.sym.type, false)) { 1.3429 + duplicateErasureError(pos, sym, e.sym); 1.3430 + sym.flags_field |= CLASH; 1.3431 + return true; 1.3432 + } else { 1.3433 + duplicateError(pos, e.sym); 1.3434 + return false; 1.3435 + } 1.3436 + } 1.3437 + } 1.3438 + return true; 1.3439 + } 1.3440 + 1.3441 + /** Report duplicate declaration error. 1.3442 + */ 1.3443 + void duplicateErasureError(DiagnosticPosition pos, Symbol sym1, Symbol sym2) { 1.3444 + if (!sym1.type.isErroneous() && !sym2.type.isErroneous()) { 1.3445 + log.error(pos, "name.clash.same.erasure", sym1, sym2); 1.3446 + } 1.3447 + } 1.3448 + 1.3449 + /** Check that single-type import is not already imported or top-level defined, 1.3450 + * but make an exception for two single-type imports which denote the same type. 1.3451 + * @param pos Position for error reporting. 1.3452 + * @param sym The symbol. 1.3453 + * @param s The scope 1.3454 + */ 1.3455 + boolean checkUniqueImport(DiagnosticPosition pos, Symbol sym, Scope s) { 1.3456 + return checkUniqueImport(pos, sym, s, false); 1.3457 + } 1.3458 + 1.3459 + /** Check that static single-type import is not already imported or top-level defined, 1.3460 + * but make an exception for two single-type imports which denote the same type. 1.3461 + * @param pos Position for error reporting. 1.3462 + * @param sym The symbol. 1.3463 + * @param s The scope 1.3464 + */ 1.3465 + boolean checkUniqueStaticImport(DiagnosticPosition pos, Symbol sym, Scope s) { 1.3466 + return checkUniqueImport(pos, sym, s, true); 1.3467 + } 1.3468 + 1.3469 + /** Check that single-type import is not already imported or top-level defined, 1.3470 + * but make an exception for two single-type imports which denote the same type. 1.3471 + * @param pos Position for error reporting. 1.3472 + * @param sym The symbol. 1.3473 + * @param s The scope. 1.3474 + * @param staticImport Whether or not this was a static import 1.3475 + */ 1.3476 + private boolean checkUniqueImport(DiagnosticPosition pos, Symbol sym, Scope s, boolean staticImport) { 1.3477 + for (Scope.Entry e = s.lookup(sym.name); e.scope != null; e = e.next()) { 1.3478 + // is encountered class entered via a class declaration? 1.3479 + boolean isClassDecl = e.scope == s; 1.3480 + if ((isClassDecl || sym != e.sym) && 1.3481 + sym.kind == e.sym.kind && 1.3482 + sym.name != names.error && 1.3483 + (!staticImport || !e.isStaticallyImported())) { 1.3484 + if (!e.sym.type.isErroneous()) { 1.3485 + if (!isClassDecl) { 1.3486 + if (staticImport) 1.3487 + log.error(pos, "already.defined.static.single.import", e.sym); 1.3488 + else 1.3489 + log.error(pos, "already.defined.single.import", e.sym); 1.3490 + } 1.3491 + else if (sym != e.sym) 1.3492 + log.error(pos, "already.defined.this.unit", e.sym); 1.3493 + } 1.3494 + return false; 1.3495 + } 1.3496 + } 1.3497 + return true; 1.3498 + } 1.3499 + 1.3500 + /** Check that a qualified name is in canonical form (for import decls). 1.3501 + */ 1.3502 + public void checkCanonical(JCTree tree) { 1.3503 + if (!isCanonical(tree)) 1.3504 + log.error(tree.pos(), "import.requires.canonical", 1.3505 + TreeInfo.symbol(tree)); 1.3506 + } 1.3507 + // where 1.3508 + private boolean isCanonical(JCTree tree) { 1.3509 + while (tree.hasTag(SELECT)) { 1.3510 + JCFieldAccess s = (JCFieldAccess) tree; 1.3511 + if (s.sym.owner != TreeInfo.symbol(s.selected)) 1.3512 + return false; 1.3513 + tree = s.selected; 1.3514 + } 1.3515 + return true; 1.3516 + } 1.3517 + 1.3518 + /** Check that an auxiliary class is not accessed from any other file than its own. 1.3519 + */ 1.3520 + void checkForBadAuxiliaryClassAccess(DiagnosticPosition pos, Env<AttrContext> env, ClassSymbol c) { 1.3521 + if (lint.isEnabled(Lint.LintCategory.AUXILIARYCLASS) && 1.3522 + (c.flags() & AUXILIARY) != 0 && 1.3523 + rs.isAccessible(env, c) && 1.3524 + !fileManager.isSameFile(c.sourcefile, env.toplevel.sourcefile)) 1.3525 + { 1.3526 + log.warning(pos, "auxiliary.class.accessed.from.outside.of.its.source.file", 1.3527 + c, c.sourcefile); 1.3528 + } 1.3529 + } 1.3530 + 1.3531 + private class ConversionWarner extends Warner { 1.3532 + final String uncheckedKey; 1.3533 + final Type found; 1.3534 + final Type expected; 1.3535 + public ConversionWarner(DiagnosticPosition pos, String uncheckedKey, Type found, Type expected) { 1.3536 + super(pos); 1.3537 + this.uncheckedKey = uncheckedKey; 1.3538 + this.found = found; 1.3539 + this.expected = expected; 1.3540 + } 1.3541 + 1.3542 + @Override 1.3543 + public void warn(LintCategory lint) { 1.3544 + boolean warned = this.warned; 1.3545 + super.warn(lint); 1.3546 + if (warned) return; // suppress redundant diagnostics 1.3547 + switch (lint) { 1.3548 + case UNCHECKED: 1.3549 + Check.this.warnUnchecked(pos(), "prob.found.req", diags.fragment(uncheckedKey), found, expected); 1.3550 + break; 1.3551 + case VARARGS: 1.3552 + if (method != null && 1.3553 + method.attribute(syms.trustMeType.tsym) != null && 1.3554 + isTrustMeAllowedOnMethod(method) && 1.3555 + !types.isReifiable(method.type.getParameterTypes().last())) { 1.3556 + Check.this.warnUnsafeVararg(pos(), "varargs.unsafe.use.varargs.param", method.params.last()); 1.3557 + } 1.3558 + break; 1.3559 + default: 1.3560 + throw new AssertionError("Unexpected lint: " + lint); 1.3561 + } 1.3562 + } 1.3563 + } 1.3564 + 1.3565 + public Warner castWarner(DiagnosticPosition pos, Type found, Type expected) { 1.3566 + return new ConversionWarner(pos, "unchecked.cast.to.type", found, expected); 1.3567 + } 1.3568 + 1.3569 + public Warner convertWarner(DiagnosticPosition pos, Type found, Type expected) { 1.3570 + return new ConversionWarner(pos, "unchecked.assign", found, expected); 1.3571 + } 1.3572 + 1.3573 + public void checkFunctionalInterface(JCClassDecl tree, ClassSymbol cs) { 1.3574 + Compound functionalType = cs.attribute(syms.functionalInterfaceType.tsym); 1.3575 + 1.3576 + if (functionalType != null) { 1.3577 + try { 1.3578 + types.findDescriptorSymbol((TypeSymbol)cs); 1.3579 + } catch (Types.FunctionDescriptorLookupError ex) { 1.3580 + DiagnosticPosition pos = tree.pos(); 1.3581 + for (JCAnnotation a : tree.getModifiers().annotations) { 1.3582 + if (a.annotationType.type.tsym == syms.functionalInterfaceType.tsym) { 1.3583 + pos = a.pos(); 1.3584 + break; 1.3585 + } 1.3586 + } 1.3587 + log.error(pos, "bad.functional.intf.anno.1", ex.getDiagnostic()); 1.3588 + } 1.3589 + } 1.3590 + } 1.3591 +}