| 1 | /* | 
| 2 |  * Copyright 1999-2006 Sun Microsystems, Inc.  All Rights Reserved. | 
| 3 |  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 
| 4 |  * | 
| 5 |  * This code is free software; you can redistribute it and/or modify it | 
| 6 |  * under the terms of the GNU General Public License version 2 only, as | 
| 7 |  * published by the Free Software Foundation.  Sun designates this | 
| 8 |  * particular file as subject to the "Classpath" exception as provided | 
| 9 |  * by Sun in the LICENSE file that accompanied this code. | 
| 10 |  * | 
| 11 |  * This code is distributed in the hope that it will be useful, but WITHOUT | 
| 12 |  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 
| 13 |  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License | 
| 14 |  * version 2 for more details (a copy is included in the LICENSE file that | 
| 15 |  * accompanied this code). | 
| 16 |  * | 
| 17 |  * You should have received a copy of the GNU General Public License version | 
| 18 |  * 2 along with this work; if not, write to the Free Software Foundation, | 
| 19 |  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | 
| 20 |  * | 
| 21 |  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | 
| 22 |  * CA 95054 USA or visit www.sun.com if you need additional information or | 
| 23 |  * have any questions. | 
| 24 |  */ | 
| 25 |   | 
| 26 | package com.sun.tools.javac.comp; | 
| 27 |   | 
| 28 | import java.util.*; | 
| 29 | import java.util.Set; | 
| 30 |   | 
| 31 | import com.sun.tools.javac.code.*; | 
| 32 | import com.sun.tools.javac.jvm.*; | 
| 33 | import com.sun.tools.javac.tree.*; | 
| 34 | import com.sun.tools.javac.util.*; | 
| 35 | import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; | 
| 36 | import com.sun.tools.javac.util.List; | 
| 37 |   | 
| 38 | import com.sun.tools.javac.tree.JCTree.*; | 
| 39 | import com.sun.tools.javac.code.Lint; | 
| 40 | import com.sun.tools.javac.code.Lint.LintCategory; | 
| 41 | import com.sun.tools.javac.code.Type.*; | 
| 42 | import com.sun.tools.javac.code.Symbol.*; | 
| 43 |   | 
| 44 | import static com.sun.tools.javac.code.Flags.*; | 
| 45 | import static com.sun.tools.javac.code.Kinds.*; | 
| 46 | import static com.sun.tools.javac.code.TypeTags.*; | 
| 47 |   | 
| 48 | /** Type checking helper class for the attribution phase. | 
| 49 |  * | 
| 50 |  *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If | 
| 51 |  *  you write code that depends on this, you do so at your own risk. | 
| 52 |  *  This code and its internal interfaces are subject to change or | 
| 53 |  *  deletion without notice.</b> | 
| 54 |  */ | 
| 55 | public class Check { | 
| 56 |     protected static final Context.Key<Check> checkKey = | 
| 57 |         new Context.Key<Check>(); | 
| 58 |   | 
| 59 |     private final Name.Table names; | 
| 60 |     private final Log log; | 
| 61 |     private final Symtab syms; | 
| 62 |     private final Infer infer; | 
| 63 |     private final Target target; | 
| 64 |     private final Source source; | 
| 65 |     private final Types types; | 
| 66 |     private final boolean skipAnnotations; | 
| 67 |     private final TreeInfo treeinfo; | 
| 68 |   | 
| 69 |     // The set of lint options currently in effect. It is initialized | 
| 70 |     // from the context, and then is set/reset as needed by Attr as it | 
| 71 |     // visits all the various parts of the trees during attribution. | 
| 72 |     private Lint lint; | 
| 73 |   | 
| 74 |     public static Check instance(Context context) { | 
| 75 |         Check instance = context.get(checkKey); | 
| 76 |         if (instance == null) | 
| 77 |             instance = new Check(context); | 
| 78 |         return instance; | 
| 79 |     } | 
| 80 |   | 
| 81 |     protected Check(Context context) { | 
| 82 |         context.put(checkKey, this); | 
| 83 |   | 
| 84 |         names = Name.Table.instance(context); | 
| 85 |         log = Log.instance(context); | 
| 86 |         syms = Symtab.instance(context); | 
| 87 |         infer = Infer.instance(context); | 
| 88 |         this.types = Types.instance(context); | 
| 89 |         Options options = Options.instance(context); | 
| 90 |         target = Target.instance(context); | 
| 91 |         source = Source.instance(context); | 
| 92 |         lint = Lint.instance(context); | 
| 93 |         treeinfo = TreeInfo.instance(context); | 
| 94 |   | 
| 95 |         Source source = Source.instance(context); | 
| 96 |         allowGenerics = source.allowGenerics(); | 
| 97 |         allowAnnotations = source.allowAnnotations(); | 
| 98 |         complexInference = options.get("-complexinference") != null; | 
| 99 |         skipAnnotations = options.get("skipAnnotations") != null; | 
| 100 |   | 
| 101 |         boolean verboseDeprecated = lint.isEnabled(LintCategory.DEPRECATION); | 
| 102 |         boolean verboseUnchecked = lint.isEnabled(LintCategory.UNCHECKED); | 
| 103 |   | 
| 104 |         deprecationHandler = new MandatoryWarningHandler(log,verboseDeprecated, "deprecated"); | 
| 105 |         uncheckedHandler = new MandatoryWarningHandler(log, verboseUnchecked, "unchecked"); | 
| 106 |     } | 
| 107 |   | 
| 108 |     /** Switch: generics enabled? | 
| 109 |      */ | 
| 110 |     boolean allowGenerics; | 
| 111 |   | 
| 112 |     /** Switch: annotations enabled? | 
| 113 |      */ | 
| 114 |     boolean allowAnnotations; | 
| 115 |   | 
| 116 |     /** Switch: -complexinference option set? | 
| 117 |      */ | 
| 118 |     boolean complexInference; | 
| 119 |   | 
| 120 |     /** A table mapping flat names of all compiled classes in this run to their | 
| 121 |      *  symbols; maintained from outside. | 
| 122 |      */ | 
| 123 |     public Map<Name,ClassSymbol> compiled = new HashMap<Name, ClassSymbol>(); | 
| 124 |   | 
| 125 |     /** A handler for messages about deprecated usage. | 
| 126 |      */ | 
| 127 |     private MandatoryWarningHandler deprecationHandler; | 
| 128 |   | 
| 129 |     /** A handler for messages about unchecked or unsafe usage. | 
| 130 |      */ | 
| 131 |     private MandatoryWarningHandler uncheckedHandler; | 
| 132 |   | 
| 133 |   | 
| 134 | /* ************************************************************************* | 
| 135 |  * Errors and Warnings | 
| 136 |  **************************************************************************/ | 
| 137 |   | 
| 138 |     Lint setLint(Lint newLint) { | 
| 139 |         Lint prev = lint; | 
| 140 |         lint = newLint; | 
| 141 |         return prev; | 
| 142 |     } | 
| 143 |   | 
| 144 |     /** Warn about deprecated symbol. | 
| 145 |      *  @param pos        Position to be used for error reporting. | 
| 146 |      *  @param sym        The deprecated symbol. | 
| 147 |      */ | 
| 148 |     void warnDeprecated(DiagnosticPosition pos, Symbol sym) { | 
| 149 |         if (!lint.isSuppressed(LintCategory.DEPRECATION)) | 
| 150 |             deprecationHandler.report(pos, "has.been.deprecated", sym, sym.location()); | 
| 151 |     } | 
| 152 |   | 
| 153 |     /** Warn about unchecked operation. | 
| 154 |      *  @param pos        Position to be used for error reporting. | 
| 155 |      *  @param msg        A string describing the problem. | 
| 156 |      */ | 
| 157 |     public void warnUnchecked(DiagnosticPosition pos, String msg, Object... args) { | 
| 158 |         if (!lint.isSuppressed(LintCategory.UNCHECKED)) | 
| 159 |             uncheckedHandler.report(pos, msg, args); | 
| 160 |     } | 
| 161 |   | 
| 162 |     /** | 
| 163 |      * Report any deferred diagnostics. | 
| 164 |      */ | 
| 165 |     public void reportDeferredDiagnostics() { | 
| 166 |         deprecationHandler.reportDeferredDiagnostic(); | 
| 167 |         uncheckedHandler.reportDeferredDiagnostic(); | 
| 168 |     } | 
| 169 |   | 
| 170 |   | 
| 171 |     /** Report a failure to complete a class. | 
| 172 |      *  @param pos        Position to be used for error reporting. | 
| 173 |      *  @param ex         The failure to report. | 
| 174 |      */ | 
| 175 |     public Type completionError(DiagnosticPosition pos, CompletionFailure ex) { | 
| 176 |         log.error(pos, "cant.access", ex.sym, ex.errmsg); | 
| 177 |         if (ex instanceof ClassReader.BadClassFile) throw new Abort(); | 
| 178 |         else return syms.errType; | 
| 179 |     } | 
| 180 |   | 
| 181 |     /** Report a type error. | 
| 182 |      *  @param pos        Position to be used for error reporting. | 
| 183 |      *  @param problem    A string describing the error. | 
| 184 |      *  @param found      The type that was found. | 
| 185 |      *  @param req        The type that was required. | 
| 186 |      */ | 
| 187 |     Type typeError(DiagnosticPosition pos, Object problem, Type found, Type req) { | 
| 188 |         log.error(pos, "prob.found.req", | 
| 189 |                   problem, found, req); | 
| 190 |         return syms.errType; | 
| 191 |     } | 
| 192 |   | 
| 193 |     Type typeError(DiagnosticPosition pos, String problem, Type found, Type req, Object explanation) { | 
| 194 |         log.error(pos, "prob.found.req.1", problem, found, req, explanation); | 
| 195 |         return syms.errType; | 
| 196 |     } | 
| 197 |   | 
| 198 |     /** Report an error that wrong type tag was found. | 
| 199 |      *  @param pos        Position to be used for error reporting. | 
| 200 |      *  @param required   An internationalized string describing the type tag | 
| 201 |      *                    required. | 
| 202 |      *  @param found      The type that was found. | 
| 203 |      */ | 
| 204 |     Type typeTagError(DiagnosticPosition pos, Object required, Object found) { | 
| 205 |         log.error(pos, "type.found.req", found, required); | 
| 206 |         return syms.errType; | 
| 207 |     } | 
| 208 |   | 
| 209 |     /** Report an error that symbol cannot be referenced before super | 
| 210 |      *  has been called. | 
| 211 |      *  @param pos        Position to be used for error reporting. | 
| 212 |      *  @param sym        The referenced symbol. | 
| 213 |      */ | 
| 214 |     void earlyRefError(DiagnosticPosition pos, Symbol sym) { | 
| 215 |         log.error(pos, "cant.ref.before.ctor.called", sym); | 
| 216 |     } | 
| 217 |   | 
| 218 |     /** Report duplicate declaration error. | 
| 219 |      */ | 
| 220 |     void duplicateError(DiagnosticPosition pos, Symbol sym) { | 
| 221 |         if (!sym.type.isErroneous()) { | 
| 222 |             log.error(pos, "already.defined", sym, sym.location()); | 
| 223 |         } | 
| 224 |     } | 
| 225 |   | 
| 226 |     /** Report array/varargs duplicate declaration | 
| 227 |      */ | 
| 228 |     void varargsDuplicateError(DiagnosticPosition pos, Symbol sym1, Symbol sym2) { | 
| 229 |         if (!sym1.type.isErroneous() && !sym2.type.isErroneous()) { | 
| 230 |             log.error(pos, "array.and.varargs", sym1, sym2, sym2.location()); | 
| 231 |         } | 
| 232 |     } | 
| 233 |   | 
| 234 | /* ************************************************************************ | 
| 235 |  * duplicate declaration checking | 
| 236 |  *************************************************************************/ | 
| 237 |   | 
| 238 |     /** Check that variable does not hide variable with same name in | 
| 239 |      *  immediately enclosing local scope. | 
| 240 |      *  @param pos           Position for error reporting. | 
| 241 |      *  @param v             The symbol. | 
| 242 |      *  @param s             The scope. | 
| 243 |      */ | 
| 244 |     void checkTransparentVar(DiagnosticPosition pos, VarSymbol v, Scope s) { | 
| 245 |         if (s.next != null) { | 
| 246 |             for (Scope.Entry e = s.next.lookup(v.name); | 
| 247 |                  e.scope != null && e.sym.owner == v.owner; | 
| 248 |                  e = e.next()) { | 
| 249 |                 if (e.sym.kind == VAR && | 
| 250 |                     (e.sym.owner.kind & (VAR | MTH)) != 0 && | 
| 251 |                     v.name != names.error) { | 
| 252 |                     duplicateError(pos, e.sym); | 
| 253 |                     return; | 
| 254 |                 } | 
| 255 |             } | 
| 256 |         } | 
| 257 |     } | 
| 258 |   | 
| 259 |     /** Check that a class or interface does not hide a class or | 
| 260 |      *  interface with same name in immediately enclosing local scope. | 
| 261 |      *  @param pos           Position for error reporting. | 
| 262 |      *  @param c             The symbol. | 
| 263 |      *  @param s             The scope. | 
| 264 |      */ | 
| 265 |     void checkTransparentClass(DiagnosticPosition pos, ClassSymbol c, Scope s) { | 
| 266 |         if (s.next != null) { | 
| 267 |             for (Scope.Entry e = s.next.lookup(c.name); | 
| 268 |                  e.scope != null && e.sym.owner == c.owner; | 
| 269 |                  e = e.next()) { | 
| 270 |                 if (e.sym.kind == TYP && | 
| 271 |                     (e.sym.owner.kind & (VAR | MTH)) != 0 && | 
| 272 |                     c.name != names.error) { | 
| 273 |                     duplicateError(pos, e.sym); | 
| 274 |                     return; | 
| 275 |                 } | 
| 276 |             } | 
| 277 |         } | 
| 278 |     } | 
| 279 |   | 
| 280 |     /** Check that class does not have the same name as one of | 
| 281 |      *  its enclosing classes, or as a class defined in its enclosing scope. | 
| 282 |      *  return true if class is unique in its enclosing scope. | 
| 283 |      *  @param pos           Position for error reporting. | 
| 284 |      *  @param name          The class name. | 
| 285 |      *  @param s             The enclosing scope. | 
| 286 |      */ | 
| 287 |     boolean checkUniqueClassName(DiagnosticPosition pos, Name name, Scope s) { | 
| 288 |         for (Scope.Entry e = s.lookup(name); e.scope == s; e = e.next()) { | 
| 289 |             if (e.sym.kind == TYP && e.sym.name != names.error) { | 
| 290 |                 duplicateError(pos, e.sym); | 
| 291 |                 return false; | 
| 292 |             } | 
| 293 |         } | 
| 294 |         for (Symbol sym = s.owner; sym != null; sym = sym.owner) { | 
| 295 |             if (sym.kind == TYP && sym.name == name && sym.name != names.error) { | 
| 296 |                 duplicateError(pos, sym); | 
| 297 |                 return true; | 
| 298 |             } | 
| 299 |         } | 
| 300 |         return true; | 
| 301 |     } | 
| 302 |   | 
| 303 | /* ************************************************************************* | 
| 304 |  * Class name generation | 
| 305 |  **************************************************************************/ | 
| 306 |   | 
| 307 |     /** Return name of local class. | 
| 308 |      *  This is of the form    <enclClass> $ n <classname> | 
| 309 |      *  where | 
| 310 |      *    enclClass is the flat name of the enclosing class, | 
| 311 |      *    classname is the simple name of the local class | 
| 312 |      */ | 
| 313 |     Name localClassName(ClassSymbol c) { | 
| 314 |         for (int i=1; ; i++) { | 
| 315 |             Name flatname = names. | 
| 316 |                 fromString("" + c.owner.enclClass().flatname + | 
| 317 |                            target.syntheticNameChar() + i + | 
| 318 |                            c.name); | 
| 319 |             if (compiled.get(flatname) == null) return flatname; | 
| 320 |         } | 
| 321 |     } | 
| 322 |   | 
| 323 | /* ************************************************************************* | 
| 324 |  * Type Checking | 
| 325 |  **************************************************************************/ | 
| 326 |   | 
| 327 |     /** Check that a given type is assignable to a given proto-type. | 
| 328 |      *  If it is, return the type, otherwise return errType. | 
| 329 |      *  @param pos        Position to be used for error reporting. | 
| 330 |      *  @param found      The type that was found. | 
| 331 |      *  @param req        The type that was required. | 
| 332 |      */ | 
| 333 |     Type checkType(DiagnosticPosition pos, Type found, Type req) { | 
| 334 |         if (req.tag == ERROR) | 
| 335 |             return req; | 
| 336 |         if (found.tag == FORALL) | 
| 337 |             return instantiatePoly(pos, (ForAll)found, req, convertWarner(pos, found, req)); | 
| 338 |         if (req.tag == NONE) | 
| 339 |             return found; | 
| 340 |         if (types.isAssignable(found, req, convertWarner(pos, found, req))) | 
| 341 |             return found; | 
| 342 |         if (found.tag <= DOUBLE && req.tag <= DOUBLE) | 
| 343 |             return typeError(pos, JCDiagnostic.fragment("possible.loss.of.precision"), found, req); | 
| 344 |         if (found.isSuperBound()) { | 
| 345 |             log.error(pos, "assignment.from.super-bound", found); | 
| 346 |             return syms.errType; | 
| 347 |         } | 
| 348 |         if (req.isExtendsBound()) { | 
| 349 |             log.error(pos, "assignment.to.extends-bound", req); | 
| 350 |             return syms.errType; | 
| 351 |         } | 
| 352 |         return typeError(pos, JCDiagnostic.fragment("incompatible.types"), found, req); | 
| 353 |     } | 
| 354 |   | 
| 355 |     /** Instantiate polymorphic type to some prototype, unless | 
| 356 |      *  prototype is `anyPoly' in which case polymorphic type | 
| 357 |      *  is returned unchanged. | 
| 358 |      */ | 
| 359 |     Type instantiatePoly(DiagnosticPosition pos, ForAll t, Type pt, Warner warn) { | 
| 360 |         if (pt == Infer.anyPoly && complexInference) { | 
| 361 |             return t; | 
| 362 |         } else if (pt == Infer.anyPoly || pt.tag == NONE) { | 
| 363 |             Type newpt = t.qtype.tag <= VOID ? t.qtype : syms.objectType; | 
| 364 |             return instantiatePoly(pos, t, newpt, warn); | 
| 365 |         } else if (pt.tag == ERROR) { | 
| 366 |             return pt; | 
| 367 |         } else { | 
| 368 |             try { | 
| 369 |                 return infer.instantiateExpr(t, pt, warn); | 
| 370 |             } catch (Infer.NoInstanceException ex) { | 
| 371 |                 if (ex.isAmbiguous) { | 
| 372 |                     JCDiagnostic d = ex.getDiagnostic(); | 
| 373 |                     log.error(pos, | 
| 374 |                               "undetermined.type" + (d!=null ? ".1" : ""), | 
| 375 |                               t, d); | 
| 376 |                     return syms.errType; | 
| 377 |                 } else { | 
| 378 |                     JCDiagnostic d = ex.getDiagnostic(); | 
| 379 |                     return typeError(pos, | 
| 380 |                                      JCDiagnostic.fragment("incompatible.types" + (d!=null ? ".1" : ""), d), | 
| 381 |                                      t, pt); | 
| 382 |                 } | 
| 383 |             } | 
| 384 |         } | 
| 385 |     } | 
| 386 |   | 
| 387 |     /** Check that a given type can be cast to a given target type. | 
| 388 |      *  Return the result of the cast. | 
| 389 |      *  @param pos        Position to be used for error reporting. | 
| 390 |      *  @param found      The type that is being cast. | 
| 391 |      *  @param req        The target type of the cast. | 
| 392 |      */ | 
| 393 |     Type checkCastable(DiagnosticPosition pos, Type found, Type req) { | 
| 394 |         if (found.tag == FORALL) { | 
| 395 |             instantiatePoly(pos, (ForAll) found, req, castWarner(pos, found, req)); | 
| 396 |             return req; | 
| 397 |         } else if (types.isCastable(found, req, castWarner(pos, found, req))) { | 
| 398 |             return req; | 
| 399 |         } else { | 
| 400 |             return typeError(pos, | 
| 401 |                              JCDiagnostic.fragment("inconvertible.types"), | 
| 402 |                              found, req); | 
| 403 |         } | 
| 404 |     } | 
| 405 | //where | 
| 406 |         /** Is type a type variable, or a (possibly multi-dimensional) array of | 
| 407 |          *  type variables? | 
| 408 |          */ | 
| 409 |         boolean isTypeVar(Type t) { | 
| 410 |             return t.tag == TYPEVAR || t.tag == ARRAY && isTypeVar(types.elemtype(t)); | 
| 411 |         } | 
| 412 |   | 
| 413 |     /** Check that a type is within some bounds. | 
| 414 |      * | 
| 415 |      *  Used in TypeApply to verify that, e.g., X in V<X> is a valid | 
| 416 |      *  type argument. | 
| 417 |      *  @param pos           Position to be used for error reporting. | 
| 418 |      *  @param a             The type that should be bounded by bs. | 
| 419 |      *  @param bs            The bound. | 
| 420 |      */ | 
| 421 |     private void checkExtends(DiagnosticPosition pos, Type a, TypeVar bs) { | 
| 422 |         if (a.isUnbound()) { | 
| 423 |             return; | 
| 424 |         } else if (a.tag != WILDCARD) { | 
| 425 |             a = types.upperBound(a); | 
| 426 |             for (List<Type> l = types.getBounds(bs); l.nonEmpty(); l = l.tail) { | 
| 427 |                 if (!types.isSubtype(a, l.head)) { | 
| 428 |                     log.error(pos, "not.within.bounds", a); | 
| 429 |                     return; | 
| 430 |                 } | 
| 431 |             } | 
| 432 |         } else if (a.isExtendsBound()) { | 
| 433 |             if (!types.isCastable(bs.getUpperBound(), types.upperBound(a), Warner.noWarnings)) | 
| 434 |                 log.error(pos, "not.within.bounds", a); | 
| 435 |         } else if (a.isSuperBound()) { | 
| 436 |             if (types.notSoftSubtype(types.lowerBound(a), bs.getUpperBound())) | 
| 437 |                 log.error(pos, "not.within.bounds", a); | 
| 438 |         } | 
| 439 |     } | 
| 440 |   | 
| 441 |     /** Check that type is different from 'void'. | 
| 442 |      *  @param pos           Position to be used for error reporting. | 
| 443 |      *  @param t             The type to be checked. | 
| 444 |      */ | 
| 445 |     Type checkNonVoid(DiagnosticPosition pos, Type t) { | 
| 446 |         if (t.tag == VOID) { | 
| 447 |             log.error(pos, "void.not.allowed.here"); | 
| 448 |             return syms.errType; | 
| 449 |         } else { | 
| 450 |             return t; | 
| 451 |         } | 
| 452 |     } | 
| 453 |   | 
| 454 |     /** Check that type is a class or interface type. | 
| 455 |      *  @param pos           Position to be used for error reporting. | 
| 456 |      *  @param t             The type to be checked. | 
| 457 |      */ | 
| 458 |     Type checkClassType(DiagnosticPosition pos, Type t) { | 
| 459 |         if (t.tag != CLASS && t.tag != ERROR) | 
| 460 |             return typeTagError(pos, | 
| 461 |                                 JCDiagnostic.fragment("type.req.class"), | 
| 462 |                                 (t.tag == TYPEVAR) | 
| 463 |                                 ? JCDiagnostic.fragment("type.parameter", t) | 
| 464 |                                 : t); | 
| 465 |         else | 
| 466 |             return t; | 
| 467 |     } | 
| 468 |   | 
| 469 |     /** Check that type is a class or interface type. | 
| 470 |      *  @param pos           Position to be used for error reporting. | 
| 471 |      *  @param t             The type to be checked. | 
| 472 |      *  @param noBounds    True if type bounds are illegal here. | 
| 473 |      */ | 
| 474 |     Type checkClassType(DiagnosticPosition pos, Type t, boolean noBounds) { | 
| 475 |         t = checkClassType(pos, t); | 
| 476 |         if (noBounds && t.isParameterized()) { | 
| 477 |             List<Type> args = t.getTypeArguments(); | 
| 478 |             while (args.nonEmpty()) { | 
| 479 |                 if (args.head.tag == WILDCARD) | 
| 480 |                     return typeTagError(pos, | 
| 481 |                                         log.getLocalizedString("type.req.exact"), | 
| 482 |                                         args.head); | 
| 483 |                 args = args.tail; | 
| 484 |             } | 
| 485 |         } | 
| 486 |         return t; | 
| 487 |     } | 
| 488 |   | 
| 489 |     /** Check that type is a reifiable class, interface or array type. | 
| 490 |      *  @param pos           Position to be used for error reporting. | 
| 491 |      *  @param t             The type to be checked. | 
| 492 |      */ | 
| 493 |     Type checkReifiableReferenceType(DiagnosticPosition pos, Type t) { | 
| 494 |         if (t.tag != CLASS && t.tag != ARRAY && t.tag != ERROR) { | 
| 495 |             return typeTagError(pos, | 
| 496 |                                 JCDiagnostic.fragment("type.req.class.array"), | 
| 497 |                                 t); | 
| 498 |         } else if (!types.isReifiable(t)) { | 
| 499 |             log.error(pos, "illegal.generic.type.for.instof"); | 
| 500 |             return syms.errType; | 
| 501 |         } else { | 
| 502 |             return t; | 
| 503 |         } | 
| 504 |     } | 
| 505 |   | 
| 506 |     /** Check that type is a reference type, i.e. a class, interface or array type | 
| 507 |      *  or a type variable. | 
| 508 |      *  @param pos           Position to be used for error reporting. | 
| 509 |      *  @param t             The type to be checked. | 
| 510 |      */ | 
| 511 |     Type checkRefType(DiagnosticPosition pos, Type t) { | 
| 512 |         switch (t.tag) { | 
| 513 |         case CLASS: | 
| 514 |         case ARRAY: | 
| 515 |         case TYPEVAR: | 
| 516 |         case WILDCARD: | 
| 517 |         case ERROR: | 
| 518 |             return t; | 
| 519 |         default: | 
| 520 |             return typeTagError(pos, | 
| 521 |                                 JCDiagnostic.fragment("type.req.ref"), | 
| 522 |                                 t); | 
| 523 |         } | 
| 524 |     } | 
| 525 |   | 
| 526 |     /** Check that type is a null or reference type. | 
| 527 |      *  @param pos           Position to be used for error reporting. | 
| 528 |      *  @param t             The type to be checked. | 
| 529 |      */ | 
| 530 |     Type checkNullOrRefType(DiagnosticPosition pos, Type t) { | 
| 531 |         switch (t.tag) { | 
| 532 |         case CLASS: | 
| 533 |         case ARRAY: | 
| 534 |         case TYPEVAR: | 
| 535 |         case WILDCARD: | 
| 536 |         case BOT: | 
| 537 |         case ERROR: | 
| 538 |             return t; | 
| 539 |         default: | 
| 540 |             return typeTagError(pos, | 
| 541 |                                 JCDiagnostic.fragment("type.req.ref"), | 
| 542 |                                 t); | 
| 543 |         } | 
| 544 |     } | 
| 545 |   | 
| 546 |     /** Check that flag set does not contain elements of two conflicting sets. s | 
| 547 |      *  Return true if it doesn't. | 
| 548 |      *  @param pos           Position to be used for error reporting. | 
| 549 |      *  @param flags         The set of flags to be checked. | 
| 550 |      *  @param set1          Conflicting flags set #1. | 
| 551 |      *  @param set2          Conflicting flags set #2. | 
| 552 |      */ | 
| 553 |     boolean checkDisjoint(DiagnosticPosition pos, long flags, long set1, long set2) { | 
| 554 |         if ((flags & set1) != 0 && (flags & set2) != 0) { | 
| 555 |             log.error(pos, | 
| 556 |                       "illegal.combination.of.modifiers", | 
| 557 |                       TreeInfo.flagNames(TreeInfo.firstFlag(flags & set1)), | 
| 558 |                       TreeInfo.flagNames(TreeInfo.firstFlag(flags & set2))); | 
| 559 |             return false; | 
| 560 |         } else | 
| 561 |             return true; | 
| 562 |     } | 
| 563 |   | 
| 564 |     /** Check that given modifiers are legal for given symbol and | 
| 565 |      *  return modifiers together with any implicit modififiers for that symbol. | 
| 566 |      *  Warning: we can't use flags() here since this method | 
| 567 |      *  is called during class enter, when flags() would cause a premature | 
| 568 |      *  completion. | 
| 569 |      *  @param pos           Position to be used for error reporting. | 
| 570 |      *  @param flags         The set of modifiers given in a definition. | 
| 571 |      *  @param sym           The defined symbol. | 
| 572 |      */ | 
| 573 |     long checkFlags(DiagnosticPosition pos, long flags, Symbol sym, JCTree tree) { | 
| 574 |         long mask; | 
| 575 |         long implicit = 0; | 
| 576 |         switch (sym.kind) { | 
| 577 |         case VAR: | 
| 578 |             if (sym.owner.kind != TYP) | 
| 579 |                 mask = LocalVarFlags; | 
| 580 |             else if ((sym.owner.flags_field & INTERFACE) != 0) | 
| 581 |                 mask = implicit = InterfaceVarFlags; | 
| 582 |             else | 
| 583 |                 mask = VarFlags; | 
| 584 |             break; | 
| 585 |         case MTH: | 
| 586 |             if (sym.name == names.init) { | 
| 587 |                 if ((sym.owner.flags_field & ENUM) != 0) { | 
| 588 |                     // enum constructors cannot be declared public or | 
| 589 |                     // protected and must be implicitly or explicitly | 
| 590 |                     // private | 
| 591 |                     implicit = PRIVATE; | 
| 592 |                     mask = PRIVATE; | 
| 593 |                 } else | 
| 594 |                     mask = ConstructorFlags; | 
| 595 |             }  else if ((sym.owner.flags_field & INTERFACE) != 0) | 
| 596 |                 mask = implicit = InterfaceMethodFlags; | 
| 597 |             else { | 
| 598 |                 mask = MethodFlags; | 
| 599 |             } | 
| 600 |             // Imply STRICTFP if owner has STRICTFP set. | 
| 601 |             if (((flags|implicit) & Flags.ABSTRACT) == 0) | 
| 602 |               implicit |= sym.owner.flags_field & STRICTFP; | 
| 603 |             break; | 
| 604 |         case TYP: | 
| 605 |             if (sym.isLocal()) { | 
| 606 |                 mask = LocalClassFlags; | 
| 607 |                 if (sym.name.len == 0) { // Anonymous class | 
| 608 |                     // Anonymous classes in static methods are themselves static; | 
| 609 |                     // that's why we admit STATIC here. | 
| 610 |                     mask |= STATIC; | 
| 611 |                     // JLS: Anonymous classes are final. | 
| 612 |                     implicit |= FINAL; | 
| 613 |                 } | 
| 614 |                 if ((sym.owner.flags_field & STATIC) == 0 && | 
| 615 |                     (flags & ENUM) != 0) | 
| 616 |                     log.error(pos, "enums.must.be.static"); | 
| 617 |             } else if (sym.owner.kind == TYP) { | 
| 618 |                 mask = MemberClassFlags; | 
| 619 |                 if (sym.owner.owner.kind == PCK || | 
| 620 |                     (sym.owner.flags_field & STATIC) != 0) | 
| 621 |                     mask |= STATIC; | 
| 622 |                 else if ((flags & ENUM) != 0) | 
| 623 |                     log.error(pos, "enums.must.be.static"); | 
| 624 |                 // Nested interfaces and enums are always STATIC (Spec ???) | 
| 625 |                 if ((flags & (INTERFACE | ENUM)) != 0 ) implicit = STATIC; | 
| 626 |             } else { | 
| 627 |                 mask = ClassFlags; | 
| 628 |             } | 
| 629 |             // Interfaces are always ABSTRACT | 
| 630 |             if ((flags & INTERFACE) != 0) implicit |= ABSTRACT; | 
| 631 |   | 
| 632 |             if ((flags & ENUM) != 0) { | 
| 633 |                 // enums can't be declared abstract or final | 
| 634 |                 mask &= ~(ABSTRACT | FINAL); | 
| 635 |                 implicit |= implicitEnumFinalFlag(tree); | 
| 636 |             } | 
| 637 |             // Imply STRICTFP if owner has STRICTFP set. | 
| 638 |             implicit |= sym.owner.flags_field & STRICTFP; | 
| 639 |             break; | 
| 640 |         default: | 
| 641 |             throw new AssertionError(); | 
| 642 |         } | 
| 643 |         long illegal = flags & StandardFlags & ~mask; | 
| 644 |         if (illegal != 0) { | 
| 645 |             if ((illegal & INTERFACE) != 0) { | 
| 646 |                 log.error(pos, "intf.not.allowed.here"); | 
| 647 |                 mask |= INTERFACE; | 
| 648 |             } | 
| 649 |             else { | 
| 650 |                 log.error(pos, | 
| 651 |                           "mod.not.allowed.here", TreeInfo.flagNames(illegal)); | 
| 652 |             } | 
| 653 |         } | 
| 654 |         else if ((sym.kind == TYP || | 
| 655 |                   // ISSUE: Disallowing abstract&private is no longer appropriate | 
| 656 |                   // in the presence of inner classes. Should it be deleted here? | 
| 657 |                   checkDisjoint(pos, flags, | 
| 658 |                                 ABSTRACT, | 
| 659 |                                 PRIVATE | STATIC)) | 
| 660 |                  && | 
| 661 |                  checkDisjoint(pos, flags, | 
| 662 |                                ABSTRACT | INTERFACE, | 
| 663 |                                FINAL | NATIVE | SYNCHRONIZED) | 
| 664 |                  && | 
| 665 |                  checkDisjoint(pos, flags, | 
| 666 |                                PUBLIC, | 
| 667 |                                PRIVATE | PROTECTED) | 
| 668 |                  && | 
| 669 |                  checkDisjoint(pos, flags, | 
| 670 |                                PRIVATE, | 
| 671 |                                PUBLIC | PROTECTED) | 
| 672 |                  && | 
| 673 |                  checkDisjoint(pos, flags, | 
| 674 |                                FINAL, | 
| 675 |                                VOLATILE) | 
| 676 |                  && | 
| 677 |                  (sym.kind == TYP || | 
| 678 |                   checkDisjoint(pos, flags, | 
| 679 |                                 ABSTRACT | NATIVE, | 
| 680 |                                 STRICTFP))) { | 
| 681 |             // skip | 
| 682 |         } | 
| 683 |         return flags & (mask | ~StandardFlags) | implicit; | 
| 684 |     } | 
| 685 |   | 
| 686 |   | 
| 687 |     /** Determine if this enum should be implicitly final. | 
| 688 |      * | 
| 689 |      *  If the enum has no specialized enum contants, it is final. | 
| 690 |      * | 
| 691 |      *  If the enum does have specialized enum contants, it is | 
| 692 |      *  <i>not</i> final. | 
| 693 |      */ | 
| 694 |     private long implicitEnumFinalFlag(JCTree tree) { | 
| 695 |         if (tree.getTag() != JCTree.CLASSDEF) return 0; | 
| 696 |         class SpecialTreeVisitor extends JCTree.Visitor { | 
| 697 |             boolean specialized; | 
| 698 |             SpecialTreeVisitor() { | 
| 699 |                 this.specialized = false; | 
| 700 |             }; | 
| 701 |   | 
| 702 |             public void visitTree(JCTree tree) { /* no-op */ } | 
| 703 |   | 
| 704 |             public void visitVarDef(JCVariableDecl tree) { | 
| 705 |                 if ((tree.mods.flags & ENUM) != 0) { | 
| 706 |                     if (tree.init instanceof JCNewClass && | 
| 707 |                         ((JCNewClass) tree.init).def != null) { | 
| 708 |                         specialized = true; | 
| 709 |                     } | 
| 710 |                 } | 
| 711 |             } | 
| 712 |         } | 
| 713 |   | 
| 714 |         SpecialTreeVisitor sts = new SpecialTreeVisitor(); | 
| 715 |         JCClassDecl cdef = (JCClassDecl) tree; | 
| 716 |         for (JCTree defs: cdef.defs) { | 
| 717 |             defs.accept(sts); | 
| 718 |             if (sts.specialized) return 0; | 
| 719 |         } | 
| 720 |         return FINAL; | 
| 721 |     } | 
| 722 |   | 
| 723 | /* ************************************************************************* | 
| 724 |  * Type Validation | 
| 725 |  **************************************************************************/ | 
| 726 |   | 
| 727 |     /** Validate a type expression. That is, | 
| 728 |      *  check that all type arguments of a parametric type are within | 
| 729 |      *  their bounds. This must be done in a second phase after type attributon | 
| 730 |      *  since a class might have a subclass as type parameter bound. E.g: | 
| 731 |      * | 
| 732 |      *  class B<A extends C> { ... } | 
| 733 |      *  class C extends B<C> { ... } | 
| 734 |      * | 
| 735 |      *  and we can't make sure that the bound is already attributed because | 
| 736 |      *  of possible cycles. | 
| 737 |      */ | 
| 738 |     private Validator validator = new Validator(); | 
| 739 |   | 
| 740 |     /** Visitor method: Validate a type expression, if it is not null, catching | 
| 741 |      *  and reporting any completion failures. | 
| 742 |      */ | 
| 743 |     void validate(JCTree tree) { | 
| 744 |         try { | 
| 745 |             if (tree != null) tree.accept(validator); | 
| 746 |         } catch (CompletionFailure ex) { | 
| 747 |             completionError(tree.pos(), ex); | 
| 748 |         } | 
| 749 |     } | 
| 750 |   | 
| 751 |     /** Visitor method: Validate a list of type expressions. | 
| 752 |      */ | 
| 753 |     void validate(List<? extends JCTree> trees) { | 
| 754 |         for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) | 
| 755 |             validate(l.head); | 
| 756 |     } | 
| 757 |   | 
| 758 |     /** Visitor method: Validate a list of type parameters. | 
| 759 |      */ | 
| 760 |     void validateTypeParams(List<JCTypeParameter> trees) { | 
| 761 |         for (List<JCTypeParameter> l = trees; l.nonEmpty(); l = l.tail) | 
| 762 |             validate(l.head); | 
| 763 |     } | 
| 764 |   | 
| 765 |     /** A visitor class for type validation. | 
| 766 |      */ | 
| 767 |     class Validator extends JCTree.Visitor { | 
| 768 |   | 
| 769 |         public void visitTypeArray(JCArrayTypeTree tree) { | 
| 770 |             validate(tree.elemtype); | 
| 771 |         } | 
| 772 |   | 
| 773 |         public void visitTypeApply(JCTypeApply tree) { | 
| 774 |             if (tree.type.tag == CLASS) { | 
| 775 |                 List<Type> formals = tree.type.tsym.type.getTypeArguments(); | 
| 776 |                 List<Type> actuals = tree.type.getTypeArguments(); | 
| 777 |                 List<JCExpression> args = tree.arguments; | 
| 778 |                 List<Type> forms = formals; | 
| 779 |                 ListBuffer<TypeVar> tvars_buf = new ListBuffer<TypeVar>(); | 
| 780 |   | 
| 781 |                 // For matching pairs of actual argument types `a' and | 
| 782 |                 // formal type parameters with declared bound `b' ... | 
| 783 |                 while (args.nonEmpty() && forms.nonEmpty()) { | 
| 784 |                     validate(args.head); | 
| 785 |   | 
| 786 |                     // exact type arguments needs to know their | 
| 787 |                     // bounds (for upper and lower bound | 
| 788 |                     // calculations).  So we create new TypeVars with | 
| 789 |                     // bounds substed with actuals. | 
| 790 |                     tvars_buf.append(types.substBound(((TypeVar)forms.head), | 
| 791 |                                                       formals, | 
| 792 |                                                       Type.removeBounds(actuals))); | 
| 793 |   | 
| 794 |                     args = args.tail; | 
| 795 |                     forms = forms.tail; | 
| 796 |                 } | 
| 797 |   | 
| 798 |                 args = tree.arguments; | 
| 799 |                 List<TypeVar> tvars = tvars_buf.toList(); | 
| 800 |                 while (args.nonEmpty() && tvars.nonEmpty()) { | 
| 801 |                     // Let the actual arguments know their bound | 
| 802 |                     args.head.type.withTypeVar(tvars.head); | 
| 803 |                     args = args.tail; | 
| 804 |                     tvars = tvars.tail; | 
| 805 |                 } | 
| 806 |   | 
| 807 |                 args = tree.arguments; | 
| 808 |                 tvars = tvars_buf.toList(); | 
| 809 |                 while (args.nonEmpty() && tvars.nonEmpty()) { | 
| 810 |                     checkExtends(args.head.pos(), | 
| 811 |                                  args.head.type, | 
| 812 |                                  tvars.head); | 
| 813 |                     args = args.tail; | 
| 814 |                     tvars = tvars.tail; | 
| 815 |                 } | 
| 816 |   | 
| 817 |                 // Check that this type is either fully parameterized, or | 
| 818 |                 // not parameterized at all. | 
| 819 |                 if (tree.type.getEnclosingType().isRaw()) | 
| 820 |                     log.error(tree.pos(), "improperly.formed.type.inner.raw.param"); | 
| 821 |                 if (tree.clazz.getTag() == JCTree.SELECT) | 
| 822 |                     visitSelectInternal((JCFieldAccess)tree.clazz); | 
| 823 |             } | 
| 824 |         } | 
| 825 |   | 
| 826 |         public void visitTypeParameter(JCTypeParameter tree) { | 
| 827 |             validate(tree.bounds); | 
| 828 |             checkClassBounds(tree.pos(), tree.type); | 
| 829 |         } | 
| 830 |   | 
| 831 |         @Override | 
| 832 |         public void visitWildcard(JCWildcard tree) { | 
| 833 |             if (tree.inner != null) | 
| 834 |                 validate(tree.inner); | 
| 835 |         } | 
| 836 |   | 
| 837 |         public void visitSelect(JCFieldAccess tree) { | 
| 838 |             if (tree.type.tag == CLASS) { | 
| 839 |                 visitSelectInternal(tree); | 
| 840 |   | 
| 841 |                 // Check that this type is either fully parameterized, or | 
| 842 |                 // not parameterized at all. | 
| 843 |                 if (tree.selected.type.isParameterized() && tree.type.tsym.type.getTypeArguments().nonEmpty()) | 
| 844 |                     log.error(tree.pos(), "improperly.formed.type.param.missing"); | 
| 845 |             } | 
| 846 |         } | 
| 847 |         public void visitSelectInternal(JCFieldAccess tree) { | 
| 848 |             if (tree.type.getEnclosingType().tag != CLASS && | 
| 849 |                 tree.selected.type.isParameterized()) { | 
| 850 |                 // The enclosing type is not a class, so we are | 
| 851 |                 // looking at a static member type.  However, the | 
| 852 |                 // qualifying expression is parameterized. | 
| 853 |                 log.error(tree.pos(), "cant.select.static.class.from.param.type"); | 
| 854 |             } else { | 
| 855 |                 // otherwise validate the rest of the expression | 
| 856 |                 validate(tree.selected); | 
| 857 |             } | 
| 858 |         } | 
| 859 |   | 
| 860 |         /** Default visitor method: do nothing. | 
| 861 |          */ | 
| 862 |         public void visitTree(JCTree tree) { | 
| 863 |         } | 
| 864 |     } | 
| 865 |   | 
| 866 | /* ************************************************************************* | 
| 867 |  * Exception checking | 
| 868 |  **************************************************************************/ | 
| 869 |   | 
| 870 |     /* The following methods treat classes as sets that contain | 
| 871 |      * the class itself and all their subclasses | 
| 872 |      */ | 
| 873 |   | 
| 874 |     /** Is given type a subtype of some of the types in given list? | 
| 875 |      */ | 
| 876 |     boolean subset(Type t, List<Type> ts) { | 
| 877 |         for (List<Type> l = ts; l.nonEmpty(); l = l.tail) | 
| 878 |             if (types.isSubtype(t, l.head)) return true; | 
| 879 |         return false; | 
| 880 |     } | 
| 881 |   | 
| 882 |     /** Is given type a subtype or supertype of | 
| 883 |      *  some of the types in given list? | 
| 884 |      */ | 
| 885 |     boolean intersects(Type t, List<Type> ts) { | 
| 886 |         for (List<Type> l = ts; l.nonEmpty(); l = l.tail) | 
| 887 |             if (types.isSubtype(t, l.head) || types.isSubtype(l.head, t)) return true; | 
| 888 |         return false; | 
| 889 |     } | 
| 890 |   | 
| 891 |     /** Add type set to given type list, unless it is a subclass of some class | 
| 892 |      *  in the list. | 
| 893 |      */ | 
| 894 |     List<Type> incl(Type t, List<Type> ts) { | 
| 895 |         return subset(t, ts) ? ts : excl(t, ts).prepend(t); | 
| 896 |     } | 
| 897 |   | 
| 898 |     /** Remove type set from type set list. | 
| 899 |      */ | 
| 900 |     List<Type> excl(Type t, List<Type> ts) { | 
| 901 |         if (ts.isEmpty()) { | 
| 902 |             return ts; | 
| 903 |         } else { | 
| 904 |             List<Type> ts1 = excl(t, ts.tail); | 
| 905 |             if (types.isSubtype(ts.head, t)) return ts1; | 
| 906 |             else if (ts1 == ts.tail) return ts; | 
| 907 |             else return ts1.prepend(ts.head); | 
| 908 |         } | 
| 909 |     } | 
| 910 |   | 
| 911 |     /** Form the union of two type set lists. | 
| 912 |      */ | 
| 913 |     List<Type> union(List<Type> ts1, List<Type> ts2) { | 
| 914 |         List<Type> ts = ts1; | 
| 915 |         for (List<Type> l = ts2; l.nonEmpty(); l = l.tail) | 
| 916 |             ts = incl(l.head, ts); | 
| 917 |         return ts; | 
| 918 |     } | 
| 919 |   | 
| 920 |     /** Form the difference of two type lists. | 
| 921 |      */ | 
| 922 |     List<Type> diff(List<Type> ts1, List<Type> ts2) { | 
| 923 |         List<Type> ts = ts1; | 
| 924 |         for (List<Type> l = ts2; l.nonEmpty(); l = l.tail) | 
| 925 |             ts = excl(l.head, ts); | 
| 926 |         return ts; | 
| 927 |     } | 
| 928 |   | 
| 929 |     /** Form the intersection of two type lists. | 
| 930 |      */ | 
| 931 |     public List<Type> intersect(List<Type> ts1, List<Type> ts2) { | 
| 932 |         List<Type> ts = List.nil(); | 
| 933 |         for (List<Type> l = ts1; l.nonEmpty(); l = l.tail) | 
| 934 |             if (subset(l.head, ts2)) ts = incl(l.head, ts); | 
| 935 |         for (List<Type> l = ts2; l.nonEmpty(); l = l.tail) | 
| 936 |             if (subset(l.head, ts1)) ts = incl(l.head, ts); | 
| 937 |         return ts; | 
| 938 |     } | 
| 939 |   | 
| 940 |     /** Is exc an exception symbol that need not be declared? | 
| 941 |      */ | 
| 942 |     boolean isUnchecked(ClassSymbol exc) { | 
| 943 |         return | 
| 944 |             exc.kind == ERR || | 
| 945 |             exc.isSubClass(syms.errorType.tsym, types) || | 
| 946 |             exc.isSubClass(syms.runtimeExceptionType.tsym, types); | 
| 947 |     } | 
| 948 |   | 
| 949 |     /** Is exc an exception type that need not be declared? | 
| 950 |      */ | 
| 951 |     boolean isUnchecked(Type exc) { | 
| 952 |         return | 
| 953 |             (exc.tag == TYPEVAR) ? isUnchecked(types.supertype(exc)) : | 
| 954 |             (exc.tag == CLASS) ? isUnchecked((ClassSymbol)exc.tsym) : | 
| 955 |             exc.tag == BOT; | 
| 956 |     } | 
| 957 |   | 
| 958 |     /** Same, but handling completion failures. | 
| 959 |      */ | 
| 960 |     boolean isUnchecked(DiagnosticPosition pos, Type exc) { | 
| 961 |         try { | 
| 962 |             return isUnchecked(exc); | 
| 963 |         } catch (CompletionFailure ex) { | 
| 964 |             completionError(pos, ex); | 
| 965 |             return true; | 
| 966 |         } | 
| 967 |     } | 
| 968 |   | 
| 969 |     /** Is exc handled by given exception list? | 
| 970 |      */ | 
| 971 |     boolean isHandled(Type exc, List<Type> handled) { | 
| 972 |         return isUnchecked(exc) || subset(exc, handled); | 
| 973 |     } | 
| 974 |   | 
| 975 |     /** Return all exceptions in thrown list that are not in handled list. | 
| 976 |      *  @param thrown     The list of thrown exceptions. | 
| 977 |      *  @param handled    The list of handled exceptions. | 
| 978 |      */ | 
| 979 |     List<Type> unHandled(List<Type> thrown, List<Type> handled) { | 
| 980 |         List<Type> unhandled = List.nil(); | 
| 981 |         for (List<Type> l = thrown; l.nonEmpty(); l = l.tail) | 
| 982 |             if (!isHandled(l.head, handled)) unhandled = unhandled.prepend(l.head); | 
| 983 |         return unhandled; | 
| 984 |     } | 
| 985 |   | 
| 986 | /* ************************************************************************* | 
| 987 |  * Overriding/Implementation checking | 
| 988 |  **************************************************************************/ | 
| 989 |   | 
| 990 |     /** The level of access protection given by a flag set, | 
| 991 |      *  where PRIVATE is highest and PUBLIC is lowest. | 
| 992 |      */ | 
| 993 |     static int protection(long flags) { | 
| 994 |         switch ((short)(flags & AccessFlags)) { | 
| 995 |         case PRIVATE: return 3; | 
| 996 |         case PROTECTED: return 1; | 
| 997 |         default: | 
| 998 |         case PUBLIC: return 0; | 
| 999 |         case 0: return 2; | 
| 1000 |         } | 
| 1001 |     } | 
| 1002 |   | 
| 1003 |     /** A string describing the access permission given by a flag set. | 
| 1004 |      *  This always returns a space-separated list of Java Keywords. | 
| 1005 |      */ | 
| 1006 |     private static String protectionString(long flags) { | 
| 1007 |         long flags1 = flags & AccessFlags; | 
| 1008 |         return (flags1 == 0) ? "package" : TreeInfo.flagNames(flags1); | 
| 1009 |     } | 
| 1010 |   | 
| 1011 |     /** A customized "cannot override" error message. | 
| 1012 |      *  @param m      The overriding method. | 
| 1013 |      *  @param other  The overridden method. | 
| 1014 |      *  @return       An internationalized string. | 
| 1015 |      */ | 
| 1016 |     static Object cannotOverride(MethodSymbol m, MethodSymbol other) { | 
| 1017 |         String key; | 
| 1018 |         if ((other.owner.flags() & INTERFACE) == 0) | 
| 1019 |             key = "cant.override"; | 
| 1020 |         else if ((m.owner.flags() & INTERFACE) == 0) | 
| 1021 |             key = "cant.implement"; | 
| 1022 |         else | 
| 1023 |             key = "clashes.with"; | 
| 1024 |         return JCDiagnostic.fragment(key, m, m.location(), other, other.location()); | 
| 1025 |     } | 
| 1026 |   | 
| 1027 |     /** A customized "override" warning message. | 
| 1028 |      *  @param m      The overriding method. | 
| 1029 |      *  @param other  The overridden method. | 
| 1030 |      *  @return       An internationalized string. | 
| 1031 |      */ | 
| 1032 |     static Object uncheckedOverrides(MethodSymbol m, MethodSymbol other) { | 
| 1033 |         String key; | 
| 1034 |         if ((other.owner.flags() & INTERFACE) == 0) | 
| 1035 |             key = "unchecked.override"; | 
| 1036 |         else if ((m.owner.flags() & INTERFACE) == 0) | 
| 1037 |             key = "unchecked.implement"; | 
| 1038 |         else | 
| 1039 |             key = "unchecked.clash.with"; | 
| 1040 |         return JCDiagnostic.fragment(key, m, m.location(), other, other.location()); | 
| 1041 |     } | 
| 1042 |   | 
| 1043 |     /** A customized "override" warning message. | 
| 1044 |      *  @param m      The overriding method. | 
| 1045 |      *  @param other  The overridden method. | 
| 1046 |      *  @return       An internationalized string. | 
| 1047 |      */ | 
| 1048 |     static Object varargsOverrides(MethodSymbol m, MethodSymbol other) { | 
| 1049 |         String key; | 
| 1050 |         if ((other.owner.flags() & INTERFACE) == 0) | 
| 1051 |             key = "varargs.override"; | 
| 1052 |         else  if ((m.owner.flags() & INTERFACE) == 0) | 
| 1053 |             key = "varargs.implement"; | 
| 1054 |         else | 
| 1055 |             key = "varargs.clash.with"; | 
| 1056 |         return JCDiagnostic.fragment(key, m, m.location(), other, other.location()); | 
| 1057 |     } | 
| 1058 |   | 
| 1059 |     /** Check that this method conforms with overridden method 'other'. | 
| 1060 |      *  where `origin' is the class where checking started. | 
| 1061 |      *  Complications: | 
| 1062 |      *  (1) Do not check overriding of synthetic methods | 
| 1063 |      *      (reason: they might be final). | 
| 1064 |      *      todo: check whether this is still necessary. | 
| 1065 |      *  (2) Admit the case where an interface proxy throws fewer exceptions | 
| 1066 |      *      than the method it implements. Augment the proxy methods with the | 
| 1067 |      *      undeclared exceptions in this case. | 
| 1068 |      *  (3) When generics are enabled, admit the case where an interface proxy | 
| 1069 |      *      has a result type | 
| 1070 |      *      extended by the result type of the method it implements. | 
| 1071 |      *      Change the proxies result type to the smaller type in this case. | 
| 1072 |      * | 
| 1073 |      *  @param tree         The tree from which positions | 
| 1074 |      *                      are extracted for errors. | 
| 1075 |      *  @param m            The overriding method. | 
| 1076 |      *  @param other        The overridden method. | 
| 1077 |      *  @param origin       The class of which the overriding method | 
| 1078 |      *                      is a member. | 
| 1079 |      */ | 
| 1080 |     void checkOverride(JCTree tree, | 
| 1081 |                        MethodSymbol m, | 
| 1082 |                        MethodSymbol other, | 
| 1083 |                        ClassSymbol origin) { | 
| 1084 |         // Don't check overriding of synthetic methods or by bridge methods. | 
| 1085 |         if ((m.flags() & (SYNTHETIC|BRIDGE)) != 0 || (other.flags() & SYNTHETIC) != 0) { | 
| 1086 |             return; | 
| 1087 |         } | 
| 1088 |   | 
| 1089 |         // Error if static method overrides instance method (JLS 8.4.6.2). | 
| 1090 |         if ((m.flags() & STATIC) != 0 && | 
| 1091 |                    (other.flags() & STATIC) == 0) { | 
| 1092 |             log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.static", | 
| 1093 |                       cannotOverride(m, other)); | 
| 1094 |             return; | 
| 1095 |         } | 
| 1096 |   | 
| 1097 |         // Error if instance method overrides static or final | 
| 1098 |         // method (JLS 8.4.6.1). | 
| 1099 |         if ((other.flags() & FINAL) != 0 || | 
| 1100 |                  (m.flags() & STATIC) == 0 && | 
| 1101 |                  (other.flags() & STATIC) != 0) { | 
| 1102 |             log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.meth", | 
| 1103 |                       cannotOverride(m, other), | 
| 1104 |                       TreeInfo.flagNames(other.flags() & (FINAL | STATIC))); | 
| 1105 |             return; | 
| 1106 |         } | 
| 1107 |   | 
| 1108 |         if ((m.owner.flags() & ANNOTATION) != 0) { | 
| 1109 |             // handled in validateAnnotationMethod | 
| 1110 |             return; | 
| 1111 |         } | 
| 1112 |   | 
| 1113 |         // Error if overriding method has weaker access (JLS 8.4.6.3). | 
| 1114 |         if ((origin.flags() & INTERFACE) == 0 && | 
| 1115 |                  protection(m.flags()) > protection(other.flags())) { | 
| 1116 |             log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.weaker.access", | 
| 1117 |                       cannotOverride(m, other), | 
| 1118 |                       protectionString(other.flags())); | 
| 1119 |             return; | 
| 1120 |   | 
| 1121 |         } | 
| 1122 |   | 
| 1123 |         Type mt = types.memberType(origin.type, m); | 
| 1124 |         Type ot = types.memberType(origin.type, other); | 
| 1125 |         // Error if overriding result type is different | 
| 1126 |         // (or, in the case of generics mode, not a subtype) of | 
| 1127 |         // overridden result type. We have to rename any type parameters | 
| 1128 |         // before comparing types. | 
| 1129 |         List<Type> mtvars = mt.getTypeArguments(); | 
| 1130 |         List<Type> otvars = ot.getTypeArguments(); | 
| 1131 |         Type mtres = mt.getReturnType(); | 
| 1132 |         Type otres = types.subst(ot.getReturnType(), otvars, mtvars); | 
| 1133 |   | 
| 1134 |         overrideWarner.warned = false; | 
| 1135 |         boolean resultTypesOK = | 
| 1136 |             types.returnTypeSubstitutable(mt, ot, otres, overrideWarner); | 
| 1137 |         if (!resultTypesOK) { | 
| 1138 |             if (!source.allowCovariantReturns() && | 
| 1139 |                 m.owner != origin && | 
| 1140 |                 m.owner.isSubClass(other.owner, types)) { | 
| 1141 |                 // allow limited interoperability with covariant returns | 
| 1142 |             } else { | 
| 1143 |                 typeError(TreeInfo.diagnosticPositionFor(m, tree), | 
| 1144 |                           JCDiagnostic.fragment("override.incompatible.ret", | 
| 1145 |                                          cannotOverride(m, other)), | 
| 1146 |                           mtres, otres); | 
| 1147 |                 return; | 
| 1148 |             } | 
| 1149 |         } else if (overrideWarner.warned) { | 
| 1150 |             warnUnchecked(TreeInfo.diagnosticPositionFor(m, tree), | 
| 1151 |                           "prob.found.req", | 
| 1152 |                           JCDiagnostic.fragment("override.unchecked.ret", | 
| 1153 |                                               uncheckedOverrides(m, other)), | 
| 1154 |                           mtres, otres); | 
| 1155 |         } | 
| 1156 |   | 
| 1157 |         // Error if overriding method throws an exception not reported | 
| 1158 |         // by overridden method. | 
| 1159 |         List<Type> otthrown = types.subst(ot.getThrownTypes(), otvars, mtvars); | 
| 1160 |         List<Type> unhandled = unHandled(mt.getThrownTypes(), otthrown); | 
| 1161 |         if (unhandled.nonEmpty()) { | 
| 1162 |             log.error(TreeInfo.diagnosticPositionFor(m, tree), | 
| 1163 |                       "override.meth.doesnt.throw", | 
| 1164 |                       cannotOverride(m, other), | 
| 1165 |                       unhandled.head); | 
| 1166 |             return; | 
| 1167 |         } | 
| 1168 |   | 
| 1169 |         // Optional warning if varargs don't agree | 
| 1170 |         if ((((m.flags() ^ other.flags()) & Flags.VARARGS) != 0) | 
| 1171 |             && lint.isEnabled(Lint.LintCategory.OVERRIDES)) { | 
| 1172 |             log.warning(TreeInfo.diagnosticPositionFor(m, tree), | 
| 1173 |                         ((m.flags() & Flags.VARARGS) != 0) | 
| 1174 |                         ? "override.varargs.missing" | 
| 1175 |                         : "override.varargs.extra", | 
| 1176 |                         varargsOverrides(m, other)); | 
| 1177 |         } | 
| 1178 |   | 
| 1179 |         // Warn if instance method overrides bridge method (compiler spec ??) | 
| 1180 |         if ((other.flags() & BRIDGE) != 0) { | 
| 1181 |             log.warning(TreeInfo.diagnosticPositionFor(m, tree), "override.bridge", | 
| 1182 |                         uncheckedOverrides(m, other)); | 
| 1183 |         } | 
| 1184 |   | 
| 1185 |         // Warn if a deprecated method overridden by a non-deprecated one. | 
| 1186 |         if ((other.flags() & DEPRECATED) != 0 | 
| 1187 |             && (m.flags() & DEPRECATED) == 0 | 
| 1188 |             && m.outermostClass() != other.outermostClass() | 
| 1189 |             && !isDeprecatedOverrideIgnorable(other, origin)) { | 
| 1190 |             warnDeprecated(TreeInfo.diagnosticPositionFor(m, tree), other); | 
| 1191 |         } | 
| 1192 |     } | 
| 1193 |     // where | 
| 1194 |         private boolean isDeprecatedOverrideIgnorable(MethodSymbol m, ClassSymbol origin) { | 
| 1195 |             // If the method, m, is defined in an interface, then ignore the issue if the method | 
| 1196 |             // is only inherited via a supertype and also implemented in the supertype, | 
| 1197 |             // because in that case, we will rediscover the issue when examining the method | 
| 1198 |             // in the supertype. | 
| 1199 |             // If the method, m, is not defined in an interface, then the only time we need to | 
| 1200 |             // address the issue is when the method is the supertype implemementation: any other | 
| 1201 |             // case, we will have dealt with when examining the supertype classes | 
| 1202 |             ClassSymbol mc = m.enclClass(); | 
| 1203 |             Type st = types.supertype(origin.type); | 
| 1204 |             if (st.tag != CLASS) | 
| 1205 |                 return true; | 
| 1206 |             MethodSymbol stimpl = m.implementation((ClassSymbol)st.tsym, types, false); | 
| 1207 |   | 
| 1208 |             if (mc != null && ((mc.flags() & INTERFACE) != 0)) { | 
| 1209 |                 List<Type> intfs = types.interfaces(origin.type); | 
| 1210 |                 return (intfs.contains(mc.type) ? false : (stimpl != null)); | 
| 1211 |             } | 
| 1212 |             else | 
| 1213 |                 return (stimpl != m); | 
| 1214 |         } | 
| 1215 |   | 
| 1216 |   | 
| 1217 |     // used to check if there were any unchecked conversions | 
| 1218 |     Warner overrideWarner = new Warner(); | 
| 1219 |   | 
| 1220 |     /** Check that a class does not inherit two concrete methods | 
| 1221 |      *  with the same signature. | 
| 1222 |      *  @param pos          Position to be used for error reporting. | 
| 1223 |      *  @param site         The class type to be checked. | 
| 1224 |      */ | 
| 1225 |     public void checkCompatibleConcretes(DiagnosticPosition pos, Type site) { | 
| 1226 |         Type sup = types.supertype(site); | 
| 1227 |         if (sup.tag != CLASS) return; | 
| 1228 |   | 
| 1229 |         for (Type t1 = sup; | 
| 1230 |              t1.tsym.type.isParameterized(); | 
| 1231 |              t1 = types.supertype(t1)) { | 
| 1232 |             for (Scope.Entry e1 = t1.tsym.members().elems; | 
| 1233 |                  e1 != null; | 
| 1234 |                  e1 = e1.sibling) { | 
| 1235 |                 Symbol s1 = e1.sym; | 
| 1236 |                 if (s1.kind != MTH || | 
| 1237 |                     (s1.flags() & (STATIC|SYNTHETIC|BRIDGE)) != 0 || | 
| 1238 |                     !s1.isInheritedIn(site.tsym, types) || | 
| 1239 |                     ((MethodSymbol)s1).implementation(site.tsym, | 
| 1240 |                                                       types, | 
| 1241 |                                                       true) != s1) | 
| 1242 |                     continue; | 
| 1243 |                 Type st1 = types.memberType(t1, s1); | 
| 1244 |                 int s1ArgsLength = st1.getParameterTypes().length(); | 
| 1245 |                 if (st1 == s1.type) continue; | 
| 1246 |   | 
| 1247 |                 for (Type t2 = sup; | 
| 1248 |                      t2.tag == CLASS; | 
| 1249 |                      t2 = types.supertype(t2)) { | 
| 1250 |                     for (Scope.Entry e2 = t1.tsym.members().lookup(s1.name); | 
| 1251 |                          e2.scope != null; | 
| 1252 |                          e2 = e2.next()) { | 
| 1253 |                         Symbol s2 = e2.sym; | 
| 1254 |                         if (s2 == s1 || | 
| 1255 |                             s2.kind != MTH || | 
| 1256 |                             (s2.flags() & (STATIC|SYNTHETIC|BRIDGE)) != 0 || | 
| 1257 |                             s2.type.getParameterTypes().length() != s1ArgsLength || | 
| 1258 |                             !s2.isInheritedIn(site.tsym, types) || | 
| 1259 |                             ((MethodSymbol)s2).implementation(site.tsym, | 
| 1260 |                                                               types, | 
| 1261 |                                                               true) != s2) | 
| 1262 |                             continue; | 
| 1263 |                         Type st2 = types.memberType(t2, s2); | 
| 1264 |                         if (types.overrideEquivalent(st1, st2)) | 
| 1265 |                             log.error(pos, "concrete.inheritance.conflict", | 
| 1266 |                                       s1, t1, s2, t2, sup); | 
| 1267 |                     } | 
| 1268 |                 } | 
| 1269 |             } | 
| 1270 |         } | 
| 1271 |     } | 
| 1272 |   | 
| 1273 |     /** Check that classes (or interfaces) do not each define an abstract | 
| 1274 |      *  method with same name and arguments but incompatible return types. | 
| 1275 |      *  @param pos          Position to be used for error reporting. | 
| 1276 |      *  @param t1           The first argument type. | 
| 1277 |      *  @param t2           The second argument type. | 
| 1278 |      */ | 
| 1279 |     public boolean checkCompatibleAbstracts(DiagnosticPosition pos, | 
| 1280 |                                             Type t1, | 
| 1281 |                                             Type t2) { | 
| 1282 |         return checkCompatibleAbstracts(pos, t1, t2, | 
| 1283 |                                         types.makeCompoundType(t1, t2)); | 
| 1284 |     } | 
| 1285 |   | 
| 1286 |     public boolean checkCompatibleAbstracts(DiagnosticPosition pos, | 
| 1287 |                                             Type t1, | 
| 1288 |                                             Type t2, | 
| 1289 |                                             Type site) { | 
| 1290 |         Symbol sym = firstIncompatibility(t1, t2, site); | 
| 1291 |         if (sym != null) { | 
| 1292 |             log.error(pos, "types.incompatible.diff.ret", | 
| 1293 |                       t1, t2, sym.name + | 
| 1294 |                       "(" + types.memberType(t2, sym).getParameterTypes() + ")"); | 
| 1295 |             return false; | 
| 1296 |         } | 
| 1297 |         return true; | 
| 1298 |     } | 
| 1299 |   | 
| 1300 |     /** Return the first method which is defined with same args | 
| 1301 |      *  but different return types in two given interfaces, or null if none | 
| 1302 |      *  exists. | 
| 1303 |      *  @param t1     The first type. | 
| 1304 |      *  @param t2     The second type. | 
| 1305 |      *  @param site   The most derived type. | 
| 1306 |      *  @returns symbol from t2 that conflicts with one in t1. | 
| 1307 |      */ | 
| 1308 |     private Symbol firstIncompatibility(Type t1, Type t2, Type site) { | 
| 1309 |         Map<TypeSymbol,Type> interfaces1 = new HashMap<TypeSymbol,Type>(); | 
| 1310 |         closure(t1, interfaces1); | 
| 1311 |         Map<TypeSymbol,Type> interfaces2; | 
| 1312 |         if (t1 == t2) | 
| 1313 |             interfaces2 = interfaces1; | 
| 1314 |         else | 
| 1315 |             closure(t2, interfaces1, interfaces2 = new HashMap<TypeSymbol,Type>()); | 
| 1316 |   | 
| 1317 |         for (Type t3 : interfaces1.values()) { | 
| 1318 |             for (Type t4 : interfaces2.values()) { | 
| 1319 |                 Symbol s = firstDirectIncompatibility(t3, t4, site); | 
| 1320 |                 if (s != null) return s; | 
| 1321 |             } | 
| 1322 |         } | 
| 1323 |         return null; | 
| 1324 |     } | 
| 1325 |   | 
| 1326 |     /** Compute all the supertypes of t, indexed by type symbol. */ | 
| 1327 |     private void closure(Type t, Map<TypeSymbol,Type> typeMap) { | 
| 1328 |         if (t.tag != CLASS) return; | 
| 1329 |         if (typeMap.put(t.tsym, t) == null) { | 
| 1330 |             closure(types.supertype(t), typeMap); | 
| 1331 |             for (Type i : types.interfaces(t)) | 
| 1332 |                 closure(i, typeMap); | 
| 1333 |         } | 
| 1334 |     } | 
| 1335 |   | 
| 1336 |     /** Compute all the supertypes of t, indexed by type symbol (except thise in typesSkip). */ | 
| 1337 |     private void closure(Type t, Map<TypeSymbol,Type> typesSkip, Map<TypeSymbol,Type> typeMap) { | 
| 1338 |         if (t.tag != CLASS) return; | 
| 1339 |         if (typesSkip.get(t.tsym) != null) return; | 
| 1340 |         if (typeMap.put(t.tsym, t) == null) { | 
| 1341 |             closure(types.supertype(t), typesSkip, typeMap); | 
| 1342 |             for (Type i : types.interfaces(t)) | 
| 1343 |                 closure(i, typesSkip, typeMap); | 
| 1344 |         } | 
| 1345 |     } | 
| 1346 |   | 
| 1347 |     /** Return the first method in t2 that conflicts with a method from t1. */ | 
| 1348 |     private Symbol firstDirectIncompatibility(Type t1, Type t2, Type site) { | 
| 1349 |         for (Scope.Entry e1 = t1.tsym.members().elems; e1 != null; e1 = e1.sibling) { | 
| 1350 |             Symbol s1 = e1.sym; | 
| 1351 |             Type st1 = null; | 
| 1352 |             if (s1.kind != MTH || !s1.isInheritedIn(site.tsym, types)) continue; | 
| 1353 |             Symbol impl = ((MethodSymbol)s1).implementation(site.tsym, types, false); | 
| 1354 |             if (impl != null && (impl.flags() & ABSTRACT) == 0) continue; | 
| 1355 |             for (Scope.Entry e2 = t2.tsym.members().lookup(s1.name); e2.scope != null; e2 = e2.next()) { | 
| 1356 |                 Symbol s2 = e2.sym; | 
| 1357 |                 if (s1 == s2) continue; | 
| 1358 |                 if (s2.kind != MTH || !s2.isInheritedIn(site.tsym, types)) continue; | 
| 1359 |                 if (st1 == null) st1 = types.memberType(t1, s1); | 
| 1360 |                 Type st2 = types.memberType(t2, s2); | 
| 1361 |                 if (types.overrideEquivalent(st1, st2)) { | 
| 1362 |                     List<Type> tvars1 = st1.getTypeArguments(); | 
| 1363 |                     List<Type> tvars2 = st2.getTypeArguments(); | 
| 1364 |                     Type rt1 = st1.getReturnType(); | 
| 1365 |                     Type rt2 = types.subst(st2.getReturnType(), tvars2, tvars1); | 
| 1366 |                     boolean compat = | 
| 1367 |                         types.isSameType(rt1, rt2) || | 
| 1368 |                         rt1.tag >= CLASS && rt2.tag >= CLASS && | 
| 1369 |                         (types.covariantReturnType(rt1, rt2, Warner.noWarnings) || | 
| 1370 |                          types.covariantReturnType(rt2, rt1, Warner.noWarnings)); | 
| 1371 |                     if (!compat) return s2; | 
| 1372 |                 } | 
| 1373 |             } | 
| 1374 |         } | 
| 1375 |         return null; | 
| 1376 |     } | 
| 1377 |   | 
| 1378 |     /** Check that a given method conforms with any method it overrides. | 
| 1379 |      *  @param tree         The tree from which positions are extracted | 
| 1380 |      *                      for errors. | 
| 1381 |      *  @param m            The overriding method. | 
| 1382 |      */ | 
| 1383 |     void checkOverride(JCTree tree, MethodSymbol m) { | 
| 1384 |         ClassSymbol origin = (ClassSymbol)m.owner; | 
| 1385 |         if ((origin.flags() & ENUM) != 0 && names.finalize.equals(m.name)) | 
| 1386 |             if (m.overrides(syms.enumFinalFinalize, origin, types, false)) { | 
| 1387 |                 log.error(tree.pos(), "enum.no.finalize"); | 
| 1388 |                 return; | 
| 1389 |             } | 
| 1390 |         for (Type t = types.supertype(origin.type); t.tag == CLASS; | 
| 1391 |              t = types.supertype(t)) { | 
| 1392 |             TypeSymbol c = t.tsym; | 
| 1393 |             Scope.Entry e = c.members().lookup(m.name); | 
| 1394 |             while (e.scope != null) { | 
| 1395 |                 if (m.overrides(e.sym, origin, types, false)) | 
| 1396 |                     checkOverride(tree, m, (MethodSymbol)e.sym, origin); | 
| 1397 |                 e = e.next(); | 
| 1398 |             } | 
| 1399 |         } | 
| 1400 |     } | 
| 1401 |   | 
| 1402 |     /** Check that all abstract members of given class have definitions. | 
| 1403 |      *  @param pos          Position to be used for error reporting. | 
| 1404 |      *  @param c            The class. | 
| 1405 |      */ | 
| 1406 |     void checkAllDefined(DiagnosticPosition pos, ClassSymbol c) { | 
| 1407 |         try { | 
| 1408 |             MethodSymbol undef = firstUndef(c, c); | 
| 1409 |             if (undef != null) { | 
| 1410 |                 if ((c.flags() & ENUM) != 0 && | 
| 1411 |                     types.supertype(c.type).tsym == syms.enumSym && | 
| 1412 |                     (c.flags() & FINAL) == 0) { | 
| 1413 |                     // add the ABSTRACT flag to an enum | 
| 1414 |                     c.flags_field |= ABSTRACT; | 
| 1415 |                 } else { | 
| 1416 |                     MethodSymbol undef1 = | 
| 1417 |                         new MethodSymbol(undef.flags(), undef.name, | 
| 1418 |                                          types.memberType(c.type, undef), undef.owner); | 
| 1419 |                     log.error(pos, "does.not.override.abstract", | 
| 1420 |                               c, undef1, undef1.location()); | 
| 1421 |                 } | 
| 1422 |             } | 
| 1423 |         } catch (CompletionFailure ex) { | 
| 1424 |             completionError(pos, ex); | 
| 1425 |         } | 
| 1426 |     } | 
| 1427 | //where | 
| 1428 |         /** Return first abstract member of class `c' that is not defined | 
| 1429 |          *  in `impl', null if there is none. | 
| 1430 |          */ | 
| 1431 |         private MethodSymbol firstUndef(ClassSymbol impl, ClassSymbol c) { | 
| 1432 |             MethodSymbol undef = null; | 
| 1433 |             // Do not bother to search in classes that are not abstract, | 
| 1434 |             // since they cannot have abstract members. | 
| 1435 |             if (c == impl || (c.flags() & (ABSTRACT | INTERFACE)) != 0) { | 
| 1436 |                 Scope s = c.members(); | 
| 1437 |                 for (Scope.Entry e = s.elems; | 
| 1438 |                      undef == null && e != null; | 
| 1439 |                      e = e.sibling) { | 
| 1440 |                     if (e.sym.kind == MTH && | 
| 1441 |                         (e.sym.flags() & (ABSTRACT|IPROXY)) == ABSTRACT) { | 
| 1442 |                         MethodSymbol absmeth = (MethodSymbol)e.sym; | 
| 1443 |                         MethodSymbol implmeth = absmeth.implementation(impl, types, true); | 
| 1444 |                         if (implmeth == null || implmeth == absmeth) | 
| 1445 |                             undef = absmeth; | 
| 1446 |                     } | 
| 1447 |                 } | 
| 1448 |                 if (undef == null) { | 
| 1449 |                     Type st = types.supertype(c.type); | 
| 1450 |                     if (st.tag == CLASS) | 
| 1451 |                         undef = firstUndef(impl, (ClassSymbol)st.tsym); | 
| 1452 |                 } | 
| 1453 |                 for (List<Type> l = types.interfaces(c.type); | 
| 1454 |                      undef == null && l.nonEmpty(); | 
| 1455 |                      l = l.tail) { | 
| 1456 |                     undef = firstUndef(impl, (ClassSymbol)l.head.tsym); | 
| 1457 |                 } | 
| 1458 |             } | 
| 1459 |             return undef; | 
| 1460 |         } | 
| 1461 |   | 
| 1462 |     /** Check for cyclic references. Issue an error if the | 
| 1463 |      *  symbol of the type referred to has a LOCKED flag set. | 
| 1464 |      * | 
| 1465 |      *  @param pos      Position to be used for error reporting. | 
| 1466 |      *  @param t        The type referred to. | 
| 1467 |      */ | 
| 1468 |     void checkNonCyclic(DiagnosticPosition pos, Type t) { | 
| 1469 |         checkNonCyclicInternal(pos, t); | 
| 1470 |     } | 
| 1471 |   | 
| 1472 |   | 
| 1473 |     void checkNonCyclic(DiagnosticPosition pos, TypeVar t) { | 
| 1474 |         checkNonCyclic1(pos, t, new HashSet<TypeVar>()); | 
| 1475 |     } | 
| 1476 |   | 
| 1477 |     private void checkNonCyclic1(DiagnosticPosition pos, Type t, Set<TypeVar> seen) { | 
| 1478 |         final TypeVar tv; | 
| 1479 |         if (seen.contains(t)) { | 
| 1480 |             tv = (TypeVar)t; | 
| 1481 |             tv.bound = new ErrorType(); | 
| 1482 |             log.error(pos, "cyclic.inheritance", t); | 
| 1483 |         } else if (t.tag == TYPEVAR) { | 
| 1484 |             tv = (TypeVar)t; | 
| 1485 |             seen.add(tv); | 
| 1486 |             for (Type b : types.getBounds(tv)) | 
| 1487 |                 checkNonCyclic1(pos, b, seen); | 
| 1488 |         } | 
| 1489 |     } | 
| 1490 |   | 
| 1491 |     /** Check for cyclic references. Issue an error if the | 
| 1492 |      *  symbol of the type referred to has a LOCKED flag set. | 
| 1493 |      * | 
| 1494 |      *  @param pos      Position to be used for error reporting. | 
| 1495 |      *  @param t        The type referred to. | 
| 1496 |      *  @returns        True if the check completed on all attributed classes | 
| 1497 |      */ | 
| 1498 |     private boolean checkNonCyclicInternal(DiagnosticPosition pos, Type t) { | 
| 1499 |         boolean complete = true; // was the check complete? | 
| 1500 |         //- System.err.println("checkNonCyclicInternal("+t+");");//DEBUG | 
| 1501 |         Symbol c = t.tsym; | 
| 1502 |         if ((c.flags_field & ACYCLIC) != 0) return true; | 
| 1503 |   | 
| 1504 |         if ((c.flags_field & LOCKED) != 0) { | 
| 1505 |             noteCyclic(pos, (ClassSymbol)c); | 
| 1506 |         } else if (!c.type.isErroneous()) { | 
| 1507 |             try { | 
| 1508 |                 c.flags_field |= LOCKED; | 
| 1509 |                 if (c.type.tag == CLASS) { | 
| 1510 |                     ClassType clazz = (ClassType)c.type; | 
| 1511 |                     if (clazz.interfaces_field != null) | 
| 1512 |                         for (List<Type> l=clazz.interfaces_field; l.nonEmpty(); l=l.tail) | 
| 1513 |                             complete &= checkNonCyclicInternal(pos, l.head); | 
| 1514 |                     if (clazz.supertype_field != null) { | 
| 1515 |                         Type st = clazz.supertype_field; | 
| 1516 |                         if (st != null && st.tag == CLASS) | 
| 1517 |                             complete &= checkNonCyclicInternal(pos, st); | 
| 1518 |                     } | 
| 1519 |                     if (c.owner.kind == TYP) | 
| 1520 |                         complete &= checkNonCyclicInternal(pos, c.owner.type); | 
| 1521 |                 } | 
| 1522 |             } finally { | 
| 1523 |                 c.flags_field &= ~LOCKED; | 
| 1524 |             } | 
| 1525 |         } | 
| 1526 |         if (complete) | 
| 1527 |             complete = ((c.flags_field & UNATTRIBUTED) == 0) && c.completer == null; | 
| 1528 |         if (complete) c.flags_field |= ACYCLIC; | 
| 1529 |         return complete; | 
| 1530 |     } | 
| 1531 |   | 
| 1532 |     /** Note that we found an inheritance cycle. */ | 
| 1533 |     private void noteCyclic(DiagnosticPosition pos, ClassSymbol c) { | 
| 1534 |         log.error(pos, "cyclic.inheritance", c); | 
| 1535 |         for (List<Type> l=types.interfaces(c.type); l.nonEmpty(); l=l.tail) | 
| 1536 |             l.head = new ErrorType((ClassSymbol)l.head.tsym); | 
| 1537 |         Type st = types.supertype(c.type); | 
| 1538 |         if (st.tag == CLASS) | 
| 1539 |             ((ClassType)c.type).supertype_field = new ErrorType((ClassSymbol)st.tsym); | 
| 1540 |         c.type = new ErrorType(c); | 
| 1541 |         c.flags_field |= ACYCLIC; | 
| 1542 |     } | 
| 1543 |   | 
| 1544 |     /** Check that all methods which implement some | 
| 1545 |      *  method conform to the method they implement. | 
| 1546 |      *  @param tree         The class definition whose members are checked. | 
| 1547 |      */ | 
| 1548 |     void checkImplementations(JCClassDecl tree) { | 
| 1549 |         checkImplementations(tree, tree.sym); | 
| 1550 |     } | 
| 1551 | //where | 
| 1552 |         /** Check that all methods which implement some | 
| 1553 |          *  method in `ic' conform to the method they implement. | 
| 1554 |          */ | 
| 1555 |         void checkImplementations(JCClassDecl tree, ClassSymbol ic) { | 
| 1556 |             ClassSymbol origin = tree.sym; | 
| 1557 |             for (List<Type> l = types.closure(ic.type); l.nonEmpty(); l = l.tail) { | 
| 1558 |                 ClassSymbol lc = (ClassSymbol)l.head.tsym; | 
| 1559 |                 if ((allowGenerics || origin != lc) && (lc.flags() & ABSTRACT) != 0) { | 
| 1560 |                     for (Scope.Entry e=lc.members().elems; e != null; e=e.sibling) { | 
| 1561 |                         if (e.sym.kind == MTH && | 
| 1562 |                             (e.sym.flags() & (STATIC|ABSTRACT)) == ABSTRACT) { | 
| 1563 |                             MethodSymbol absmeth = (MethodSymbol)e.sym; | 
| 1564 |                             MethodSymbol implmeth = absmeth.implementation(origin, types, false); | 
| 1565 |                             if (implmeth != null && implmeth != absmeth && | 
| 1566 |                                 (implmeth.owner.flags() & INTERFACE) == | 
| 1567 |                                 (origin.flags() & INTERFACE)) { | 
| 1568 |                                 // don't check if implmeth is in a class, yet | 
| 1569 |                                 // origin is an interface. This case arises only | 
| 1570 |                                 // if implmeth is declared in Object. The reason is | 
| 1571 |                                 // that interfaces really don't inherit from | 
| 1572 |                                 // Object it's just that the compiler represents | 
| 1573 |                                 // things that way. | 
| 1574 |                                 checkOverride(tree, implmeth, absmeth, origin); | 
| 1575 |                             } | 
| 1576 |                         } | 
| 1577 |                     } | 
| 1578 |                 } | 
| 1579 |             } | 
| 1580 |         } | 
| 1581 |   | 
| 1582 |     /** Check that all abstract methods implemented by a class are | 
| 1583 |      *  mutually compatible. | 
| 1584 |      *  @param pos          Position to be used for error reporting. | 
| 1585 |      *  @param c            The class whose interfaces are checked. | 
| 1586 |      */ | 
| 1587 |     void checkCompatibleSupertypes(DiagnosticPosition pos, Type c) { | 
| 1588 |         List<Type> supertypes = types.interfaces(c); | 
| 1589 |         Type supertype = types.supertype(c); | 
| 1590 |         if (supertype.tag == CLASS && | 
| 1591 |             (supertype.tsym.flags() & ABSTRACT) != 0) | 
| 1592 |             supertypes = supertypes.prepend(supertype); | 
| 1593 |         for (List<Type> l = supertypes; l.nonEmpty(); l = l.tail) { | 
| 1594 |             if (allowGenerics && !l.head.getTypeArguments().isEmpty() && | 
| 1595 |                 !checkCompatibleAbstracts(pos, l.head, l.head, c)) | 
| 1596 |                 return; | 
| 1597 |             for (List<Type> m = supertypes; m != l; m = m.tail) | 
| 1598 |                 if (!checkCompatibleAbstracts(pos, l.head, m.head, c)) | 
| 1599 |                     return; | 
| 1600 |         } | 
| 1601 |         checkCompatibleConcretes(pos, c); | 
| 1602 |     } | 
| 1603 |   | 
| 1604 |     /** Check that class c does not implement directly or indirectly | 
| 1605 |      *  the same parameterized interface with two different argument lists. | 
| 1606 |      *  @param pos          Position to be used for error reporting. | 
| 1607 |      *  @param type         The type whose interfaces are checked. | 
| 1608 |      */ | 
| 1609 |     void checkClassBounds(DiagnosticPosition pos, Type type) { | 
| 1610 |         checkClassBounds(pos, new HashMap<TypeSymbol,Type>(), type); | 
| 1611 |     } | 
| 1612 | //where | 
| 1613 |         /** Enter all interfaces of type `type' into the hash table `seensofar' | 
| 1614 |          *  with their class symbol as key and their type as value. Make | 
| 1615 |          *  sure no class is entered with two different types. | 
| 1616 |          */ | 
| 1617 |         void checkClassBounds(DiagnosticPosition pos, | 
| 1618 |                               Map<TypeSymbol,Type> seensofar, | 
| 1619 |                               Type type) { | 
| 1620 |             if (type.isErroneous()) return; | 
| 1621 |             for (List<Type> l = types.interfaces(type); l.nonEmpty(); l = l.tail) { | 
| 1622 |                 Type it = l.head; | 
| 1623 |                 Type oldit = seensofar.put(it.tsym, it); | 
| 1624 |                 if (oldit != null) { | 
| 1625 |                     List<Type> oldparams = oldit.allparams(); | 
| 1626 |                     List<Type> newparams = it.allparams(); | 
| 1627 |                     if (!types.containsTypeEquivalent(oldparams, newparams)) | 
| 1628 |                         log.error(pos, "cant.inherit.diff.arg", | 
| 1629 |                                   it.tsym, Type.toString(oldparams), | 
| 1630 |                                   Type.toString(newparams)); | 
| 1631 |                 } | 
| 1632 |                 checkClassBounds(pos, seensofar, it); | 
| 1633 |             } | 
| 1634 |             Type st = types.supertype(type); | 
| 1635 |             if (st != null) checkClassBounds(pos, seensofar, st); | 
| 1636 |         } | 
| 1637 |   | 
| 1638 |     /** Enter interface into into set. | 
| 1639 |      *  If it existed already, issue a "repeated interface" error. | 
| 1640 |      */ | 
| 1641 |     void checkNotRepeated(DiagnosticPosition pos, Type it, Set<Type> its) { | 
| 1642 |         if (its.contains(it)) | 
| 1643 |             log.error(pos, "repeated.interface"); | 
| 1644 |         else { | 
| 1645 |             its.add(it); | 
| 1646 |         } | 
| 1647 |     } | 
| 1648 |   | 
| 1649 | /* ************************************************************************* | 
| 1650 |  * Check annotations | 
| 1651 |  **************************************************************************/ | 
| 1652 |   | 
| 1653 |     /** Annotation types are restricted to primitives, String, an | 
| 1654 |      *  enum, an annotation, Class, Class<?>, Class<? extends | 
| 1655 |      *  Anything>, arrays of the preceding. | 
| 1656 |      */ | 
| 1657 |     void validateAnnotationType(JCTree restype) { | 
| 1658 |         // restype may be null if an error occurred, so don't bother validating it | 
| 1659 |         if (restype != null) { | 
| 1660 |             validateAnnotationType(restype.pos(), restype.type); | 
| 1661 |         } | 
| 1662 |     } | 
| 1663 |   | 
| 1664 |     void validateAnnotationType(DiagnosticPosition pos, Type type) { | 
| 1665 |         if (type.isPrimitive()) return; | 
| 1666 |         if (types.isSameType(type, syms.stringType)) return; | 
| 1667 |         if ((type.tsym.flags() & Flags.ENUM) != 0) return; | 
| 1668 |         if ((type.tsym.flags() & Flags.ANNOTATION) != 0) return; | 
| 1669 |         if (types.lowerBound(type).tsym == syms.classType.tsym) return; | 
| 1670 |         if (types.isArray(type) && !types.isArray(types.elemtype(type))) { | 
| 1671 |             validateAnnotationType(pos, types.elemtype(type)); | 
| 1672 |             return; | 
| 1673 |         } | 
| 1674 |         log.error(pos, "invalid.annotation.member.type"); | 
| 1675 |     } | 
| 1676 |   | 
| 1677 |     /** | 
| 1678 |      * "It is also a compile-time error if any method declared in an | 
| 1679 |      * annotation type has a signature that is override-equivalent to | 
| 1680 |      * that of any public or protected method declared in class Object | 
| 1681 |      * or in the interface annotation.Annotation." | 
| 1682 |      * | 
| 1683 |      * @jls3 9.6 Annotation Types | 
| 1684 |      */ | 
| 1685 |     void validateAnnotationMethod(DiagnosticPosition pos, MethodSymbol m) { | 
| 1686 |         for (Type sup = syms.annotationType; sup.tag == CLASS; sup = types.supertype(sup)) { | 
| 1687 |             Scope s = sup.tsym.members(); | 
| 1688 |             for (Scope.Entry e = s.lookup(m.name); e.scope != null; e = e.next()) { | 
| 1689 |                 if (e.sym.kind == MTH && | 
| 1690 |                     (e.sym.flags() & (PUBLIC | PROTECTED)) != 0 && | 
| 1691 |                     types.overrideEquivalent(m.type, e.sym.type)) | 
| 1692 |                     log.error(pos, "intf.annotation.member.clash", e.sym, sup); | 
| 1693 |             } | 
| 1694 |         } | 
| 1695 |     } | 
| 1696 |   | 
| 1697 |     /** Check the annotations of a symbol. | 
| 1698 |      */ | 
| 1699 |     public void validateAnnotations(List<JCAnnotation> annotations, Symbol s) { | 
| 1700 |         if (skipAnnotations) return; | 
| 1701 |         for (JCAnnotation a : annotations) | 
| 1702 |             validateAnnotation(a, s); | 
| 1703 |     } | 
| 1704 |   | 
| 1705 |     /** Check an annotation of a symbol. | 
| 1706 |      */ | 
| 1707 |     public void validateAnnotation(JCAnnotation a, Symbol s) { | 
| 1708 |         validateAnnotation(a); | 
| 1709 |   | 
| 1710 |         if (!annotationApplicable(a, s)) | 
| 1711 |             log.error(a.pos(), "annotation.type.not.applicable"); | 
| 1712 |   | 
| 1713 |         if (a.annotationType.type.tsym == syms.overrideType.tsym) { | 
| 1714 |             if (!isOverrider(s)) | 
| 1715 |                 log.error(a.pos(), "method.does.not.override.superclass"); | 
| 1716 |         } | 
| 1717 |     } | 
| 1718 |   | 
| 1719 |     /** Is s a method symbol that overrides a method in a superclass? */ | 
| 1720 |     boolean isOverrider(Symbol s) { | 
| 1721 |         if (s.kind != MTH || s.isStatic()) | 
| 1722 |             return false; | 
| 1723 |         MethodSymbol m = (MethodSymbol)s; | 
| 1724 |         TypeSymbol owner = (TypeSymbol)m.owner; | 
| 1725 |         for (Type sup : types.closure(owner.type)) { | 
| 1726 |             if (sup == owner.type) | 
| 1727 |                 continue; // skip "this" | 
| 1728 |             Scope scope = sup.tsym.members(); | 
| 1729 |             for (Scope.Entry e = scope.lookup(m.name); e.scope != null; e = e.next()) { | 
| 1730 |                 if (!e.sym.isStatic() && m.overrides(e.sym, owner, types, true)) | 
| 1731 |                     return true; | 
| 1732 |             } | 
| 1733 |         } | 
| 1734 |         return false; | 
| 1735 |     } | 
| 1736 |   | 
| 1737 |     /** Is the annotation applicable to the symbol? */ | 
| 1738 |     boolean annotationApplicable(JCAnnotation a, Symbol s) { | 
| 1739 |         Attribute.Compound atTarget = | 
| 1740 |             a.annotationType.type.tsym.attribute(syms.annotationTargetType.tsym); | 
| 1741 |         if (atTarget == null) return true; | 
| 1742 |         Attribute atValue = atTarget.member(names.value); | 
| 1743 |         if (!(atValue instanceof Attribute.Array)) return true; // error recovery | 
| 1744 |         Attribute.Array arr = (Attribute.Array) atValue; | 
| 1745 |         for (Attribute app : arr.values) { | 
| 1746 |             if (!(app instanceof Attribute.Enum)) return true; // recovery | 
| 1747 |             Attribute.Enum e = (Attribute.Enum) app; | 
| 1748 |             if (e.value.name == names.TYPE) | 
| 1749 |                 { if (s.kind == TYP) return true; } | 
| 1750 |             else if (e.value.name == names.FIELD) | 
| 1751 |                 { if (s.kind == VAR && s.owner.kind != MTH) return true; } | 
| 1752 |             else if (e.value.name == names.METHOD) | 
| 1753 |                 { if (s.kind == MTH && !s.isConstructor()) return true; } | 
| 1754 |             else if (e.value.name == names.PARAMETER) | 
| 1755 |                 { if (s.kind == VAR && | 
| 1756 |                       s.owner.kind == MTH && | 
| 1757 |                       (s.flags() & PARAMETER) != 0) | 
| 1758 |                     return true; | 
| 1759 |                 } | 
| 1760 |             else if (e.value.name == names.CONSTRUCTOR) | 
| 1761 |                 { if (s.kind == MTH && s.isConstructor()) return true; } | 
| 1762 |             else if (e.value.name == names.LOCAL_VARIABLE) | 
| 1763 |                 { if (s.kind == VAR && s.owner.kind == MTH && | 
| 1764 |                       (s.flags() & PARAMETER) == 0) | 
| 1765 |                     return true; | 
| 1766 |                 } | 
| 1767 |             else if (e.value.name == names.ANNOTATION_TYPE) | 
| 1768 |                 { if (s.kind == TYP && (s.flags() & ANNOTATION) != 0) | 
| 1769 |                     return true; | 
| 1770 |                 } | 
| 1771 |             else if (e.value.name == names.PACKAGE) | 
| 1772 |                 { if (s.kind == PCK) return true; } | 
| 1773 |             else | 
| 1774 |                 return true; // recovery | 
| 1775 |         } | 
| 1776 |         return false; | 
| 1777 |     } | 
| 1778 |   | 
| 1779 |     /** Check an annotation value. | 
| 1780 |      */ | 
| 1781 |     public void validateAnnotation(JCAnnotation a) { | 
| 1782 |         if (a.type.isErroneous()) return; | 
| 1783 |   | 
| 1784 |         // collect an inventory of the members | 
| 1785 |         Set<MethodSymbol> members = new HashSet<MethodSymbol>(); | 
| 1786 |         for (Scope.Entry e = a.annotationType.type.tsym.members().elems; | 
| 1787 |              e != null; | 
| 1788 |              e = e.sibling) | 
| 1789 |             if (e.sym.kind == MTH) | 
| 1790 |                 members.add((MethodSymbol) e.sym); | 
| 1791 |   | 
| 1792 |         // count them off as they're annotated | 
| 1793 |         for (JCTree arg : a.args) { | 
| 1794 |             if (arg.getTag() != JCTree.ASSIGN) continue; // recovery | 
| 1795 |             JCAssign assign = (JCAssign) arg; | 
| 1796 |             Symbol m = TreeInfo.symbol(assign.lhs); | 
| 1797 |             if (m == null || m.type.isErroneous()) continue; | 
| 1798 |             if (!members.remove(m)) | 
| 1799 |                 log.error(arg.pos(), "duplicate.annotation.member.value", | 
| 1800 |                           m.name, a.type); | 
| 1801 |             if (assign.rhs.getTag() == ANNOTATION) | 
| 1802 |                 validateAnnotation((JCAnnotation)assign.rhs); | 
| 1803 |         } | 
| 1804 |   | 
| 1805 |         // all the remaining ones better have default values | 
| 1806 |         for (MethodSymbol m : members) | 
| 1807 |             if (m.defaultValue == null && !m.type.isErroneous()) | 
| 1808 |                 log.error(a.pos(), "annotation.missing.default.value", | 
| 1809 |                           a.type, m.name); | 
| 1810 |   | 
| 1811 |         // special case: java.lang.annotation.Target must not have | 
| 1812 |         // repeated values in its value member | 
| 1813 |         if (a.annotationType.type.tsym != syms.annotationTargetType.tsym || | 
| 1814 |             a.args.tail == null) | 
| 1815 |             return; | 
| 1816 |   | 
| 1817 |         if (a.args.head.getTag() != JCTree.ASSIGN) return; // error recovery | 
| 1818 |         JCAssign assign = (JCAssign) a.args.head; | 
| 1819 |         Symbol m = TreeInfo.symbol(assign.lhs); | 
| 1820 |         if (m.name != names.value) return; | 
| 1821 |         JCTree rhs = assign.rhs; | 
| 1822 |         if (rhs.getTag() != JCTree.NEWARRAY) return; | 
| 1823 |         JCNewArray na = (JCNewArray) rhs; | 
| 1824 |         Set<Symbol> targets = new HashSet<Symbol>(); | 
| 1825 |         for (JCTree elem : na.elems) { | 
| 1826 |             if (!targets.add(TreeInfo.symbol(elem))) { | 
| 1827 |                 log.error(elem.pos(), "repeated.annotation.target"); | 
| 1828 |             } | 
| 1829 |         } | 
| 1830 |     } | 
| 1831 |   | 
| 1832 |     void checkDeprecatedAnnotation(DiagnosticPosition pos, Symbol s) { | 
| 1833 |         if (allowAnnotations && | 
| 1834 |             lint.isEnabled(Lint.LintCategory.DEP_ANN) && | 
| 1835 |             (s.flags() & DEPRECATED) != 0 && | 
| 1836 |             !syms.deprecatedType.isErroneous() && | 
| 1837 |             s.attribute(syms.deprecatedType.tsym) == null) { | 
| 1838 |             log.warning(pos, "missing.deprecated.annotation"); | 
| 1839 |         } | 
| 1840 |     } | 
| 1841 |   | 
| 1842 | /* ************************************************************************* | 
| 1843 |  * Check for recursive annotation elements. | 
| 1844 |  **************************************************************************/ | 
| 1845 |   | 
| 1846 |     /** Check for cycles in the graph of annotation elements. | 
| 1847 |      */ | 
| 1848 |     void checkNonCyclicElements(JCClassDecl tree) { | 
| 1849 |         if ((tree.sym.flags_field & ANNOTATION) == 0) return; | 
| 1850 |         assert (tree.sym.flags_field & LOCKED) == 0; | 
| 1851 |         try { | 
| 1852 |             tree.sym.flags_field |= LOCKED; | 
| 1853 |             for (JCTree def : tree.defs) { | 
| 1854 |                 if (def.getTag() != JCTree.METHODDEF) continue; | 
| 1855 |                 JCMethodDecl meth = (JCMethodDecl)def; | 
| 1856 |                 checkAnnotationResType(meth.pos(), meth.restype.type); | 
| 1857 |             } | 
| 1858 |         } finally { | 
| 1859 |             tree.sym.flags_field &= ~LOCKED; | 
| 1860 |             tree.sym.flags_field |= ACYCLIC_ANN; | 
| 1861 |         } | 
| 1862 |     } | 
| 1863 |   | 
| 1864 |     void checkNonCyclicElementsInternal(DiagnosticPosition pos, TypeSymbol tsym) { | 
| 1865 |         if ((tsym.flags_field & ACYCLIC_ANN) != 0) | 
| 1866 |             return; | 
| 1867 |         if ((tsym.flags_field & LOCKED) != 0) { | 
| 1868 |             log.error(pos, "cyclic.annotation.element"); | 
| 1869 |             return; | 
| 1870 |         } | 
| 1871 |         try { | 
| 1872 |             tsym.flags_field |= LOCKED; | 
| 1873 |             for (Scope.Entry e = tsym.members().elems; e != null; e = e.sibling) { | 
| 1874 |                 Symbol s = e.sym; | 
| 1875 |                 if (s.kind != Kinds.MTH) | 
| 1876 |                     continue; | 
| 1877 |                 checkAnnotationResType(pos, ((MethodSymbol)s).type.getReturnType()); | 
| 1878 |             } | 
| 1879 |         } finally { | 
| 1880 |             tsym.flags_field &= ~LOCKED; | 
| 1881 |             tsym.flags_field |= ACYCLIC_ANN; | 
| 1882 |         } | 
| 1883 |     } | 
| 1884 |   | 
| 1885 |     void checkAnnotationResType(DiagnosticPosition pos, Type type) { | 
| 1886 |         switch (type.tag) { | 
| 1887 |         case TypeTags.CLASS: | 
| 1888 |             if ((type.tsym.flags() & ANNOTATION) != 0) | 
| 1889 |                 checkNonCyclicElementsInternal(pos, type.tsym); | 
| 1890 |             break; | 
| 1891 |         case TypeTags.ARRAY: | 
| 1892 |             checkAnnotationResType(pos, types.elemtype(type)); | 
| 1893 |             break; | 
| 1894 |         default: | 
| 1895 |             break; // int etc | 
| 1896 |         } | 
| 1897 |     } | 
| 1898 |   | 
| 1899 | /* ************************************************************************* | 
| 1900 |  * Check for cycles in the constructor call graph. | 
| 1901 |  **************************************************************************/ | 
| 1902 |   | 
| 1903 |     /** Check for cycles in the graph of constructors calling other | 
| 1904 |      *  constructors. | 
| 1905 |      */ | 
| 1906 |     void checkCyclicConstructors(JCClassDecl tree) { | 
| 1907 |         Map<Symbol,Symbol> callMap = new HashMap<Symbol, Symbol>(); | 
| 1908 |   | 
| 1909 |         // enter each constructor this-call into the map | 
| 1910 |         for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { | 
| 1911 |             JCMethodInvocation app = TreeInfo.firstConstructorCall(l.head); | 
| 1912 |             if (app == null) continue; | 
| 1913 |             JCMethodDecl meth = (JCMethodDecl) l.head; | 
| 1914 |             if (TreeInfo.name(app.meth) == names._this) { | 
| 1915 |                 callMap.put(meth.sym, TreeInfo.symbol(app.meth)); | 
| 1916 |             } else { | 
| 1917 |                 meth.sym.flags_field |= ACYCLIC; | 
| 1918 |             } | 
| 1919 |         } | 
| 1920 |   | 
| 1921 |         // Check for cycles in the map | 
| 1922 |         Symbol[] ctors = new Symbol[0]; | 
| 1923 |         ctors = callMap.keySet().toArray(ctors); | 
| 1924 |         for (Symbol caller : ctors) { | 
| 1925 |             checkCyclicConstructor(tree, caller, callMap); | 
| 1926 |         } | 
| 1927 |     } | 
| 1928 |   | 
| 1929 |     /** Look in the map to see if the given constructor is part of a | 
| 1930 |      *  call cycle. | 
| 1931 |      */ | 
| 1932 |     private void checkCyclicConstructor(JCClassDecl tree, Symbol ctor, | 
| 1933 |                                         Map<Symbol,Symbol> callMap) { | 
| 1934 |         if (ctor != null && (ctor.flags_field & ACYCLIC) == 0) { | 
| 1935 |             if ((ctor.flags_field & LOCKED) != 0) { | 
| 1936 |                 log.error(TreeInfo.diagnosticPositionFor(ctor, tree), | 
| 1937 |                           "recursive.ctor.invocation"); | 
| 1938 |             } else { | 
| 1939 |                 ctor.flags_field |= LOCKED; | 
| 1940 |                 checkCyclicConstructor(tree, callMap.remove(ctor), callMap); | 
| 1941 |                 ctor.flags_field &= ~LOCKED; | 
| 1942 |             } | 
| 1943 |             ctor.flags_field |= ACYCLIC; | 
| 1944 |         } | 
| 1945 |     } | 
| 1946 |   | 
| 1947 | /* ************************************************************************* | 
| 1948 |  * Miscellaneous | 
| 1949 |  **************************************************************************/ | 
| 1950 |   | 
| 1951 |     /** | 
| 1952 |      * Return the opcode of the operator but emit an error if it is an | 
| 1953 |      * error. | 
| 1954 |      * @param pos        position for error reporting. | 
| 1955 |      * @param operator   an operator | 
| 1956 |      * @param tag        a tree tag | 
| 1957 |      * @param left       type of left hand side | 
| 1958 |      * @param right      type of right hand side | 
| 1959 |      */ | 
| 1960 |     int checkOperator(DiagnosticPosition pos, | 
| 1961 |                        OperatorSymbol operator, | 
| 1962 |                        int tag, | 
| 1963 |                        Type left, | 
| 1964 |                        Type right) { | 
| 1965 |         if (operator.opcode == ByteCodes.error) { | 
| 1966 |             log.error(pos, | 
| 1967 |                       "operator.cant.be.applied", | 
| 1968 |                       treeinfo.operatorName(tag), | 
| 1969 |                       left + "," + right); | 
| 1970 |         } | 
| 1971 |         return operator.opcode; | 
| 1972 |     } | 
| 1973 |   | 
| 1974 |   | 
| 1975 |     /** | 
| 1976 |      *  Check for division by integer constant zero | 
| 1977 |      *  @param pos           Position for error reporting. | 
| 1978 |      *  @param operator      The operator for the expression | 
| 1979 |      *  @param operand       The right hand operand for the expression | 
| 1980 |      */ | 
| 1981 |     void checkDivZero(DiagnosticPosition pos, Symbol operator, Type operand) { | 
| 1982 |         if (operand.constValue() != null | 
| 1983 |             && lint.isEnabled(Lint.LintCategory.DIVZERO) | 
| 1984 |             && operand.tag <= LONG | 
| 1985 |             && ((Number) (operand.constValue())).longValue() == 0) { | 
| 1986 |             int opc = ((OperatorSymbol)operator).opcode; | 
| 1987 |             if (opc == ByteCodes.idiv || opc == ByteCodes.imod | 
| 1988 |                 || opc == ByteCodes.ldiv || opc == ByteCodes.lmod) { | 
| 1989 |                 log.warning(pos, "div.zero"); | 
| 1990 |             } | 
| 1991 |         } | 
| 1992 |     } | 
| 1993 |   | 
| 1994 |     /** | 
| 1995 |      * Check for empty statements after if | 
| 1996 |      */ | 
| 1997 |     void checkEmptyIf(JCIf tree) { | 
| 1998 |         if (tree.thenpart.getTag() == JCTree.SKIP && tree.elsepart == null && lint.isEnabled(Lint.LintCategory.EMPTY)) | 
| 1999 |             log.warning(tree.thenpart.pos(), "empty.if"); | 
| 2000 |     } | 
| 2001 |   | 
| 2002 |     /** Check that symbol is unique in given scope. | 
| 2003 |      *  @param pos           Position for error reporting. | 
| 2004 |      *  @param sym           The symbol. | 
| 2005 |      *  @param s             The scope. | 
| 2006 |      */ | 
| 2007 |     boolean checkUnique(DiagnosticPosition pos, Symbol sym, Scope s) { | 
| 2008 |         if (sym.type.isErroneous()) | 
| 2009 |             return true; | 
| 2010 |         if (sym.owner.name == names.any) return false; | 
| 2011 |         for (Scope.Entry e = s.lookup(sym.name); e.scope == s; e = e.next()) { | 
| 2012 |             if (sym != e.sym && | 
| 2013 |                 sym.kind == e.sym.kind && | 
| 2014 |                 sym.name != names.error && | 
| 2015 |                 (sym.kind != MTH || types.overrideEquivalent(sym.type, e.sym.type))) { | 
| 2016 |                 if ((sym.flags() & VARARGS) != (e.sym.flags() & VARARGS)) | 
| 2017 |                     varargsDuplicateError(pos, sym, e.sym); | 
| 2018 |                 else | 
| 2019 |                     duplicateError(pos, e.sym); | 
| 2020 |                 return false; | 
| 2021 |             } | 
| 2022 |         } | 
| 2023 |         return true; | 
| 2024 |     } | 
| 2025 |   | 
| 2026 |     /** Check that single-type import is not already imported or top-level defined, | 
| 2027 |      *  but make an exception for two single-type imports which denote the same type. | 
| 2028 |      *  @param pos           Position for error reporting. | 
| 2029 |      *  @param sym           The symbol. | 
| 2030 |      *  @param s             The scope | 
| 2031 |      */ | 
| 2032 |     boolean checkUniqueImport(DiagnosticPosition pos, Symbol sym, Scope s) { | 
| 2033 |         return checkUniqueImport(pos, sym, s, false); | 
| 2034 |     } | 
| 2035 |   | 
| 2036 |     /** Check that static single-type import is not already imported or top-level defined, | 
| 2037 |      *  but make an exception for two single-type imports which denote the same type. | 
| 2038 |      *  @param pos           Position for error reporting. | 
| 2039 |      *  @param sym           The symbol. | 
| 2040 |      *  @param s             The scope | 
| 2041 |      *  @param staticImport  Whether or not this was a static import | 
| 2042 |      */ | 
| 2043 |     boolean checkUniqueStaticImport(DiagnosticPosition pos, Symbol sym, Scope s) { | 
| 2044 |         return checkUniqueImport(pos, sym, s, true); | 
| 2045 |     } | 
| 2046 |   | 
| 2047 |     /** Check that single-type import is not already imported or top-level defined, | 
| 2048 |      *  but make an exception for two single-type imports which denote the same type. | 
| 2049 |      *  @param pos           Position for error reporting. | 
| 2050 |      *  @param sym           The symbol. | 
| 2051 |      *  @param s             The scope. | 
| 2052 |      *  @param staticImport  Whether or not this was a static import | 
| 2053 |      */ | 
| 2054 |     private boolean checkUniqueImport(DiagnosticPosition pos, Symbol sym, Scope s, boolean staticImport) { | 
| 2055 |         for (Scope.Entry e = s.lookup(sym.name); e.scope != null; e = e.next()) { | 
| 2056 |             // is encountered class entered via a class declaration? | 
| 2057 |             boolean isClassDecl = e.scope == s; | 
| 2058 |             if ((isClassDecl || sym != e.sym) && | 
| 2059 |                 sym.kind == e.sym.kind && | 
| 2060 |                 sym.name != names.error) { | 
| 2061 |                 if (!e.sym.type.isErroneous()) { | 
| 2062 |                     String what = e.sym.toString(); | 
| 2063 |                     if (!isClassDecl) { | 
| 2064 |                         if (staticImport) | 
| 2065 |                             log.error(pos, "already.defined.static.single.import", what); | 
| 2066 |                         else | 
| 2067 |                             log.error(pos, "already.defined.single.import", what); | 
| 2068 |                     } | 
| 2069 |                     else if (sym != e.sym) | 
| 2070 |                         log.error(pos, "already.defined.this.unit", what); | 
| 2071 |                 } | 
| 2072 |                 return false; | 
| 2073 |             } | 
| 2074 |         } | 
| 2075 |         return true; | 
| 2076 |     } | 
| 2077 |   | 
| 2078 |     /** Check that a qualified name is in canonical form (for import decls). | 
| 2079 |      */ | 
| 2080 |     public void checkCanonical(JCTree tree) { | 
| 2081 |         if (!isCanonical(tree)) | 
| 2082 |             log.error(tree.pos(), "import.requires.canonical", | 
| 2083 |                       TreeInfo.symbol(tree)); | 
| 2084 |     } | 
| 2085 |         // where | 
| 2086 |         private boolean isCanonical(JCTree tree) { | 
| 2087 |             while (tree.getTag() == JCTree.SELECT) { | 
| 2088 |                 JCFieldAccess s = (JCFieldAccess) tree; | 
| 2089 |                 if (s.sym.owner != TreeInfo.symbol(s.selected)) | 
| 2090 |                     return false; | 
| 2091 |                 tree = s.selected; | 
| 2092 |             } | 
| 2093 |             return true; | 
| 2094 |         } | 
| 2095 |   | 
| 2096 |     private class ConversionWarner extends Warner { | 
| 2097 |         final String key; | 
| 2098 |         final Type found; | 
| 2099 |         final Type expected; | 
| 2100 |         public ConversionWarner(DiagnosticPosition pos, String key, Type found, Type expected) { | 
| 2101 |             super(pos); | 
| 2102 |             this.key = key; | 
| 2103 |             this.found = found; | 
| 2104 |             this.expected = expected; | 
| 2105 |         } | 
| 2106 |   | 
| 2107 |         public void warnUnchecked() { | 
| 2108 |             boolean warned = this.warned; | 
| 2109 |             super.warnUnchecked(); | 
| 2110 |             if (warned) return; // suppress redundant diagnostics | 
| 2111 |             Object problem = JCDiagnostic.fragment(key); | 
| 2112 |             Check.this.warnUnchecked(pos(), "prob.found.req", problem, found, expected); | 
| 2113 |         } | 
| 2114 |     } | 
| 2115 |   | 
| 2116 |     public Warner castWarner(DiagnosticPosition pos, Type found, Type expected) { | 
| 2117 |         return new ConversionWarner(pos, "unchecked.cast.to.type", found, expected); | 
| 2118 |     } | 
| 2119 |   | 
| 2120 |     public Warner convertWarner(DiagnosticPosition pos, Type found, Type expected) { | 
| 2121 |         return new ConversionWarner(pos, "unchecked.assign", found, expected); | 
| 2122 |     } | 
| 2123 | } |