|
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 } |