Mon, 21 Jan 2013 01:27:42 -0500
8004182: Add support for profiles in javac
Reviewed-by: mcimadamore
1 /*
2 * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.tools.javac.comp;
28 import java.util.*;
29 import java.util.Set;
30 import javax.tools.JavaFileManager;
32 import com.sun.tools.javac.code.*;
33 import com.sun.tools.javac.jvm.*;
34 import com.sun.tools.javac.tree.*;
35 import com.sun.tools.javac.util.*;
36 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
37 import com.sun.tools.javac.util.List;
39 import com.sun.tools.javac.tree.JCTree.*;
40 import com.sun.tools.javac.code.Lint;
41 import com.sun.tools.javac.code.Lint.LintCategory;
42 import com.sun.tools.javac.code.Type.*;
43 import com.sun.tools.javac.code.Symbol.*;
44 import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext;
45 import com.sun.tools.javac.comp.Infer.InferenceContext;
46 import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener;
48 import static com.sun.tools.javac.code.Flags.*;
49 import static com.sun.tools.javac.code.Flags.ANNOTATION;
50 import static com.sun.tools.javac.code.Flags.SYNCHRONIZED;
51 import static com.sun.tools.javac.code.Kinds.*;
52 import static com.sun.tools.javac.code.TypeTag.*;
53 import static com.sun.tools.javac.code.TypeTag.WILDCARD;
55 import static com.sun.tools.javac.tree.JCTree.Tag.*;
57 /** Type checking helper class for the attribution phase.
58 *
59 * <p><b>This is NOT part of any supported API.
60 * If you write code that depends on this, you do so at your own risk.
61 * This code and its internal interfaces are subject to change or
62 * deletion without notice.</b>
63 */
64 public class Check {
65 protected static final Context.Key<Check> checkKey =
66 new Context.Key<Check>();
68 private final Names names;
69 private final Log log;
70 private final Resolve rs;
71 private final Symtab syms;
72 private final Enter enter;
73 private final DeferredAttr deferredAttr;
74 private final Infer infer;
75 private final Types types;
76 private final JCDiagnostic.Factory diags;
77 private boolean warnOnSyntheticConflicts;
78 private boolean suppressAbortOnBadClassFile;
79 private boolean enableSunApiLintControl;
80 private final TreeInfo treeinfo;
81 private final JavaFileManager fileManager;
82 private final Profile profile;
84 // The set of lint options currently in effect. It is initialized
85 // from the context, and then is set/reset as needed by Attr as it
86 // visits all the various parts of the trees during attribution.
87 private Lint lint;
89 // The method being analyzed in Attr - it is set/reset as needed by
90 // Attr as it visits new method declarations.
91 private MethodSymbol method;
93 public static Check instance(Context context) {
94 Check instance = context.get(checkKey);
95 if (instance == null)
96 instance = new Check(context);
97 return instance;
98 }
100 protected Check(Context context) {
101 context.put(checkKey, this);
103 names = Names.instance(context);
104 log = Log.instance(context);
105 rs = Resolve.instance(context);
106 syms = Symtab.instance(context);
107 enter = Enter.instance(context);
108 deferredAttr = DeferredAttr.instance(context);
109 infer = Infer.instance(context);
110 types = Types.instance(context);
111 diags = JCDiagnostic.Factory.instance(context);
112 Options options = Options.instance(context);
113 lint = Lint.instance(context);
114 treeinfo = TreeInfo.instance(context);
115 fileManager = context.get(JavaFileManager.class);
117 Source source = Source.instance(context);
118 allowGenerics = source.allowGenerics();
119 allowVarargs = source.allowVarargs();
120 allowAnnotations = source.allowAnnotations();
121 allowCovariantReturns = source.allowCovariantReturns();
122 allowSimplifiedVarargs = source.allowSimplifiedVarargs();
123 allowDefaultMethods = source.allowDefaultMethods();
124 allowStrictMethodClashCheck = source.allowStrictMethodClashCheck();
125 complexInference = options.isSet("complexinference");
126 warnOnSyntheticConflicts = options.isSet("warnOnSyntheticConflicts");
127 suppressAbortOnBadClassFile = options.isSet("suppressAbortOnBadClassFile");
128 enableSunApiLintControl = options.isSet("enableSunApiLintControl");
130 Target target = Target.instance(context);
131 syntheticNameChar = target.syntheticNameChar();
133 profile = Profile.instance(context);
135 boolean verboseDeprecated = lint.isEnabled(LintCategory.DEPRECATION);
136 boolean verboseUnchecked = lint.isEnabled(LintCategory.UNCHECKED);
137 boolean verboseSunApi = lint.isEnabled(LintCategory.SUNAPI);
138 boolean enforceMandatoryWarnings = source.enforceMandatoryWarnings();
140 deprecationHandler = new MandatoryWarningHandler(log, verboseDeprecated,
141 enforceMandatoryWarnings, "deprecated", LintCategory.DEPRECATION);
142 uncheckedHandler = new MandatoryWarningHandler(log, verboseUnchecked,
143 enforceMandatoryWarnings, "unchecked", LintCategory.UNCHECKED);
144 sunApiHandler = new MandatoryWarningHandler(log, verboseSunApi,
145 enforceMandatoryWarnings, "sunapi", null);
147 deferredLintHandler = DeferredLintHandler.immediateHandler;
148 }
150 /** Switch: generics enabled?
151 */
152 boolean allowGenerics;
154 /** Switch: varargs enabled?
155 */
156 boolean allowVarargs;
158 /** Switch: annotations enabled?
159 */
160 boolean allowAnnotations;
162 /** Switch: covariant returns enabled?
163 */
164 boolean allowCovariantReturns;
166 /** Switch: simplified varargs enabled?
167 */
168 boolean allowSimplifiedVarargs;
170 /** Switch: default methods enabled?
171 */
172 boolean allowDefaultMethods;
174 /** Switch: should unrelated return types trigger a method clash?
175 */
176 boolean allowStrictMethodClashCheck;
178 /** Switch: -complexinference option set?
179 */
180 boolean complexInference;
182 /** Character for synthetic names
183 */
184 char syntheticNameChar;
186 /** A table mapping flat names of all compiled classes in this run to their
187 * symbols; maintained from outside.
188 */
189 public Map<Name,ClassSymbol> compiled = new HashMap<Name, ClassSymbol>();
191 /** A handler for messages about deprecated usage.
192 */
193 private MandatoryWarningHandler deprecationHandler;
195 /** A handler for messages about unchecked or unsafe usage.
196 */
197 private MandatoryWarningHandler uncheckedHandler;
199 /** A handler for messages about using proprietary API.
200 */
201 private MandatoryWarningHandler sunApiHandler;
203 /** A handler for deferred lint warnings.
204 */
205 private DeferredLintHandler deferredLintHandler;
207 /* *************************************************************************
208 * Errors and Warnings
209 **************************************************************************/
211 Lint setLint(Lint newLint) {
212 Lint prev = lint;
213 lint = newLint;
214 return prev;
215 }
217 DeferredLintHandler setDeferredLintHandler(DeferredLintHandler newDeferredLintHandler) {
218 DeferredLintHandler prev = deferredLintHandler;
219 deferredLintHandler = newDeferredLintHandler;
220 return prev;
221 }
223 MethodSymbol setMethod(MethodSymbol newMethod) {
224 MethodSymbol prev = method;
225 method = newMethod;
226 return prev;
227 }
229 /** Warn about deprecated symbol.
230 * @param pos Position to be used for error reporting.
231 * @param sym The deprecated symbol.
232 */
233 void warnDeprecated(DiagnosticPosition pos, Symbol sym) {
234 if (!lint.isSuppressed(LintCategory.DEPRECATION))
235 deprecationHandler.report(pos, "has.been.deprecated", sym, sym.location());
236 }
238 /** Warn about unchecked operation.
239 * @param pos Position to be used for error reporting.
240 * @param msg A string describing the problem.
241 */
242 public void warnUnchecked(DiagnosticPosition pos, String msg, Object... args) {
243 if (!lint.isSuppressed(LintCategory.UNCHECKED))
244 uncheckedHandler.report(pos, msg, args);
245 }
247 /** Warn about unsafe vararg method decl.
248 * @param pos Position to be used for error reporting.
249 */
250 void warnUnsafeVararg(DiagnosticPosition pos, String key, Object... args) {
251 if (lint.isEnabled(LintCategory.VARARGS) && allowSimplifiedVarargs)
252 log.warning(LintCategory.VARARGS, pos, key, args);
253 }
255 /** Warn about using proprietary API.
256 * @param pos Position to be used for error reporting.
257 * @param msg A string describing the problem.
258 */
259 public void warnSunApi(DiagnosticPosition pos, String msg, Object... args) {
260 if (!lint.isSuppressed(LintCategory.SUNAPI))
261 sunApiHandler.report(pos, msg, args);
262 }
264 public void warnStatic(DiagnosticPosition pos, String msg, Object... args) {
265 if (lint.isEnabled(LintCategory.STATIC))
266 log.warning(LintCategory.STATIC, pos, msg, args);
267 }
269 /**
270 * Report any deferred diagnostics.
271 */
272 public void reportDeferredDiagnostics() {
273 deprecationHandler.reportDeferredDiagnostic();
274 uncheckedHandler.reportDeferredDiagnostic();
275 sunApiHandler.reportDeferredDiagnostic();
276 }
279 /** Report a failure to complete a class.
280 * @param pos Position to be used for error reporting.
281 * @param ex The failure to report.
282 */
283 public Type completionError(DiagnosticPosition pos, CompletionFailure ex) {
284 log.error(pos, "cant.access", ex.sym, ex.getDetailValue());
285 if (ex instanceof ClassReader.BadClassFile
286 && !suppressAbortOnBadClassFile) throw new Abort();
287 else return syms.errType;
288 }
290 /** Report an error that wrong type tag was found.
291 * @param pos Position to be used for error reporting.
292 * @param required An internationalized string describing the type tag
293 * required.
294 * @param found The type that was found.
295 */
296 Type typeTagError(DiagnosticPosition pos, Object required, Object found) {
297 // this error used to be raised by the parser,
298 // but has been delayed to this point:
299 if (found instanceof Type && ((Type)found).hasTag(VOID)) {
300 log.error(pos, "illegal.start.of.type");
301 return syms.errType;
302 }
303 log.error(pos, "type.found.req", found, required);
304 return types.createErrorType(found instanceof Type ? (Type)found : syms.errType);
305 }
307 /** Report an error that symbol cannot be referenced before super
308 * has been called.
309 * @param pos Position to be used for error reporting.
310 * @param sym The referenced symbol.
311 */
312 void earlyRefError(DiagnosticPosition pos, Symbol sym) {
313 log.error(pos, "cant.ref.before.ctor.called", sym);
314 }
316 /** Report duplicate declaration error.
317 */
318 void duplicateError(DiagnosticPosition pos, Symbol sym) {
319 if (!sym.type.isErroneous()) {
320 Symbol location = sym.location();
321 if (location.kind == MTH &&
322 ((MethodSymbol)location).isStaticOrInstanceInit()) {
323 log.error(pos, "already.defined.in.clinit", kindName(sym), sym,
324 kindName(sym.location()), kindName(sym.location().enclClass()),
325 sym.location().enclClass());
326 } else {
327 log.error(pos, "already.defined", kindName(sym), sym,
328 kindName(sym.location()), sym.location());
329 }
330 }
331 }
333 /** Report array/varargs duplicate declaration
334 */
335 void varargsDuplicateError(DiagnosticPosition pos, Symbol sym1, Symbol sym2) {
336 if (!sym1.type.isErroneous() && !sym2.type.isErroneous()) {
337 log.error(pos, "array.and.varargs", sym1, sym2, sym2.location());
338 }
339 }
341 /* ************************************************************************
342 * duplicate declaration checking
343 *************************************************************************/
345 /** Check that variable does not hide variable with same name in
346 * immediately enclosing local scope.
347 * @param pos Position for error reporting.
348 * @param v The symbol.
349 * @param s The scope.
350 */
351 void checkTransparentVar(DiagnosticPosition pos, VarSymbol v, Scope s) {
352 if (s.next != null) {
353 for (Scope.Entry e = s.next.lookup(v.name);
354 e.scope != null && e.sym.owner == v.owner;
355 e = e.next()) {
356 if (e.sym.kind == VAR &&
357 (e.sym.owner.kind & (VAR | MTH)) != 0 &&
358 v.name != names.error) {
359 duplicateError(pos, e.sym);
360 return;
361 }
362 }
363 }
364 }
366 /** Check that a class or interface does not hide a class or
367 * interface with same name in immediately enclosing local scope.
368 * @param pos Position for error reporting.
369 * @param c The symbol.
370 * @param s The scope.
371 */
372 void checkTransparentClass(DiagnosticPosition pos, ClassSymbol c, Scope s) {
373 if (s.next != null) {
374 for (Scope.Entry e = s.next.lookup(c.name);
375 e.scope != null && e.sym.owner == c.owner;
376 e = e.next()) {
377 if (e.sym.kind == TYP && !e.sym.type.hasTag(TYPEVAR) &&
378 (e.sym.owner.kind & (VAR | MTH)) != 0 &&
379 c.name != names.error) {
380 duplicateError(pos, e.sym);
381 return;
382 }
383 }
384 }
385 }
387 /** Check that class does not have the same name as one of
388 * its enclosing classes, or as a class defined in its enclosing scope.
389 * return true if class is unique in its enclosing scope.
390 * @param pos Position for error reporting.
391 * @param name The class name.
392 * @param s The enclosing scope.
393 */
394 boolean checkUniqueClassName(DiagnosticPosition pos, Name name, Scope s) {
395 for (Scope.Entry e = s.lookup(name); e.scope == s; e = e.next()) {
396 if (e.sym.kind == TYP && e.sym.name != names.error) {
397 duplicateError(pos, e.sym);
398 return false;
399 }
400 }
401 for (Symbol sym = s.owner; sym != null; sym = sym.owner) {
402 if (sym.kind == TYP && sym.name == name && sym.name != names.error) {
403 duplicateError(pos, sym);
404 return true;
405 }
406 }
407 return true;
408 }
410 /* *************************************************************************
411 * Class name generation
412 **************************************************************************/
414 /** Return name of local class.
415 * This is of the form {@code <enclClass> $ n <classname> }
416 * where
417 * enclClass is the flat name of the enclosing class,
418 * classname is the simple name of the local class
419 */
420 Name localClassName(ClassSymbol c) {
421 for (int i=1; ; i++) {
422 Name flatname = names.
423 fromString("" + c.owner.enclClass().flatname +
424 syntheticNameChar + i +
425 c.name);
426 if (compiled.get(flatname) == null) return flatname;
427 }
428 }
430 /* *************************************************************************
431 * Type Checking
432 **************************************************************************/
434 /**
435 * A check context is an object that can be used to perform compatibility
436 * checks - depending on the check context, meaning of 'compatibility' might
437 * vary significantly.
438 */
439 public interface CheckContext {
440 /**
441 * Is type 'found' compatible with type 'req' in given context
442 */
443 boolean compatible(Type found, Type req, Warner warn);
444 /**
445 * Report a check error
446 */
447 void report(DiagnosticPosition pos, JCDiagnostic details);
448 /**
449 * Obtain a warner for this check context
450 */
451 public Warner checkWarner(DiagnosticPosition pos, Type found, Type req);
453 public Infer.InferenceContext inferenceContext();
455 public DeferredAttr.DeferredAttrContext deferredAttrContext();
456 }
458 /**
459 * This class represent a check context that is nested within another check
460 * context - useful to check sub-expressions. The default behavior simply
461 * redirects all method calls to the enclosing check context leveraging
462 * the forwarding pattern.
463 */
464 static class NestedCheckContext implements CheckContext {
465 CheckContext enclosingContext;
467 NestedCheckContext(CheckContext enclosingContext) {
468 this.enclosingContext = enclosingContext;
469 }
471 public boolean compatible(Type found, Type req, Warner warn) {
472 return enclosingContext.compatible(found, req, warn);
473 }
475 public void report(DiagnosticPosition pos, JCDiagnostic details) {
476 enclosingContext.report(pos, details);
477 }
479 public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
480 return enclosingContext.checkWarner(pos, found, req);
481 }
483 public Infer.InferenceContext inferenceContext() {
484 return enclosingContext.inferenceContext();
485 }
487 public DeferredAttrContext deferredAttrContext() {
488 return enclosingContext.deferredAttrContext();
489 }
490 }
492 /**
493 * Check context to be used when evaluating assignment/return statements
494 */
495 CheckContext basicHandler = new CheckContext() {
496 public void report(DiagnosticPosition pos, JCDiagnostic details) {
497 log.error(pos, "prob.found.req", details);
498 }
499 public boolean compatible(Type found, Type req, Warner warn) {
500 return types.isAssignable(found, req, warn);
501 }
503 public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
504 return convertWarner(pos, found, req);
505 }
507 public InferenceContext inferenceContext() {
508 return infer.emptyContext;
509 }
511 public DeferredAttrContext deferredAttrContext() {
512 return deferredAttr.emptyDeferredAttrContext;
513 }
514 };
516 /** Check that a given type is assignable to a given proto-type.
517 * If it is, return the type, otherwise return errType.
518 * @param pos Position to be used for error reporting.
519 * @param found The type that was found.
520 * @param req The type that was required.
521 */
522 Type checkType(DiagnosticPosition pos, Type found, Type req) {
523 return checkType(pos, found, req, basicHandler);
524 }
526 Type checkType(final DiagnosticPosition pos, final Type found, final Type req, final CheckContext checkContext) {
527 final Infer.InferenceContext inferenceContext = checkContext.inferenceContext();
528 if (inferenceContext.free(req)) {
529 inferenceContext.addFreeTypeListener(List.of(req), new FreeTypeListener() {
530 @Override
531 public void typesInferred(InferenceContext inferenceContext) {
532 checkType(pos, found, inferenceContext.asInstType(req, types), checkContext);
533 }
534 });
535 }
536 if (req.hasTag(ERROR))
537 return req;
538 if (req.hasTag(NONE))
539 return found;
540 if (checkContext.compatible(found, req, checkContext.checkWarner(pos, found, req))) {
541 return found;
542 } else {
543 if (found.getTag().isSubRangeOf(DOUBLE) && req.getTag().isSubRangeOf(DOUBLE)) {
544 checkContext.report(pos, diags.fragment("possible.loss.of.precision", found, req));
545 return types.createErrorType(found);
546 }
547 checkContext.report(pos, diags.fragment("inconvertible.types", found, req));
548 return types.createErrorType(found);
549 }
550 }
552 /** Check that a given type can be cast to a given target type.
553 * Return the result of the cast.
554 * @param pos Position to be used for error reporting.
555 * @param found The type that is being cast.
556 * @param req The target type of the cast.
557 */
558 Type checkCastable(DiagnosticPosition pos, Type found, Type req) {
559 return checkCastable(pos, found, req, basicHandler);
560 }
561 Type checkCastable(DiagnosticPosition pos, Type found, Type req, CheckContext checkContext) {
562 if (types.isCastable(found, req, castWarner(pos, found, req))) {
563 return req;
564 } else {
565 checkContext.report(pos, diags.fragment("inconvertible.types", found, req));
566 return types.createErrorType(found);
567 }
568 }
570 /** Check for redundant casts (i.e. where source type is a subtype of target type)
571 * The problem should only be reported for non-292 cast
572 */
573 public void checkRedundantCast(Env<AttrContext> env, JCTypeCast tree) {
574 if (!tree.type.isErroneous() &&
575 (env.info.lint == null || env.info.lint.isEnabled(Lint.LintCategory.CAST))
576 && types.isSameType(tree.expr.type, tree.clazz.type)
577 && !is292targetTypeCast(tree)) {
578 log.warning(Lint.LintCategory.CAST,
579 tree.pos(), "redundant.cast", tree.expr.type);
580 }
581 }
582 //where
583 private boolean is292targetTypeCast(JCTypeCast tree) {
584 boolean is292targetTypeCast = false;
585 JCExpression expr = TreeInfo.skipParens(tree.expr);
586 if (expr.hasTag(APPLY)) {
587 JCMethodInvocation apply = (JCMethodInvocation)expr;
588 Symbol sym = TreeInfo.symbol(apply.meth);
589 is292targetTypeCast = sym != null &&
590 sym.kind == MTH &&
591 (sym.flags() & HYPOTHETICAL) != 0;
592 }
593 return is292targetTypeCast;
594 }
598 //where
599 /** Is type a type variable, or a (possibly multi-dimensional) array of
600 * type variables?
601 */
602 boolean isTypeVar(Type t) {
603 return t.hasTag(TYPEVAR) || t.hasTag(ARRAY) && isTypeVar(types.elemtype(t));
604 }
606 /** Check that a type is within some bounds.
607 *
608 * Used in TypeApply to verify that, e.g., X in {@code V<X>} is a valid
609 * type argument.
610 * @param a The type that should be bounded by bs.
611 * @param bound The bound.
612 */
613 private boolean checkExtends(Type a, Type bound) {
614 if (a.isUnbound()) {
615 return true;
616 } else if (!a.hasTag(WILDCARD)) {
617 a = types.upperBound(a);
618 return types.isSubtype(a, bound);
619 } else if (a.isExtendsBound()) {
620 return types.isCastable(bound, types.upperBound(a), types.noWarnings);
621 } else if (a.isSuperBound()) {
622 return !types.notSoftSubtype(types.lowerBound(a), bound);
623 }
624 return true;
625 }
627 /** Check that type is different from 'void'.
628 * @param pos Position to be used for error reporting.
629 * @param t The type to be checked.
630 */
631 Type checkNonVoid(DiagnosticPosition pos, Type t) {
632 if (t.hasTag(VOID)) {
633 log.error(pos, "void.not.allowed.here");
634 return types.createErrorType(t);
635 } else {
636 return t;
637 }
638 }
640 /** Check that type is a class or interface type.
641 * @param pos Position to be used for error reporting.
642 * @param t The type to be checked.
643 */
644 Type checkClassType(DiagnosticPosition pos, Type t) {
645 if (!t.hasTag(CLASS) && !t.hasTag(ERROR))
646 return typeTagError(pos,
647 diags.fragment("type.req.class"),
648 (t.hasTag(TYPEVAR))
649 ? diags.fragment("type.parameter", t)
650 : t);
651 else
652 return t;
653 }
655 /** Check that type is a valid qualifier for a constructor reference expression
656 */
657 Type checkConstructorRefType(DiagnosticPosition pos, Type t) {
658 t = checkClassType(pos, t);
659 if (t.hasTag(CLASS)) {
660 if ((t.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) {
661 log.error(pos, "abstract.cant.be.instantiated");
662 t = types.createErrorType(t);
663 } else if ((t.tsym.flags() & ENUM) != 0) {
664 log.error(pos, "enum.cant.be.instantiated");
665 t = types.createErrorType(t);
666 }
667 }
668 return t;
669 }
671 /** Check that type is a class or interface type.
672 * @param pos Position to be used for error reporting.
673 * @param t The type to be checked.
674 * @param noBounds True if type bounds are illegal here.
675 */
676 Type checkClassType(DiagnosticPosition pos, Type t, boolean noBounds) {
677 t = checkClassType(pos, t);
678 if (noBounds && t.isParameterized()) {
679 List<Type> args = t.getTypeArguments();
680 while (args.nonEmpty()) {
681 if (args.head.hasTag(WILDCARD))
682 return typeTagError(pos,
683 diags.fragment("type.req.exact"),
684 args.head);
685 args = args.tail;
686 }
687 }
688 return t;
689 }
691 /** Check that type is a reifiable class, interface or array type.
692 * @param pos Position to be used for error reporting.
693 * @param t The type to be checked.
694 */
695 Type checkReifiableReferenceType(DiagnosticPosition pos, Type t) {
696 if (!t.hasTag(CLASS) && !t.hasTag(ARRAY) && !t.hasTag(ERROR)) {
697 return typeTagError(pos,
698 diags.fragment("type.req.class.array"),
699 t);
700 } else if (!types.isReifiable(t)) {
701 log.error(pos, "illegal.generic.type.for.instof");
702 return types.createErrorType(t);
703 } else {
704 return t;
705 }
706 }
708 /** Check that type is a reference type, i.e. a class, interface or array type
709 * or a type variable.
710 * @param pos Position to be used for error reporting.
711 * @param t The type to be checked.
712 */
713 Type checkRefType(DiagnosticPosition pos, Type t) {
714 if (t.isReference())
715 return t;
716 else
717 return typeTagError(pos,
718 diags.fragment("type.req.ref"),
719 t);
720 }
722 /** Check that each type is a reference type, i.e. a class, interface or array type
723 * or a type variable.
724 * @param trees Original trees, used for error reporting.
725 * @param types The types to be checked.
726 */
727 List<Type> checkRefTypes(List<JCExpression> trees, List<Type> types) {
728 List<JCExpression> tl = trees;
729 for (List<Type> l = types; l.nonEmpty(); l = l.tail) {
730 l.head = checkRefType(tl.head.pos(), l.head);
731 tl = tl.tail;
732 }
733 return types;
734 }
736 /** Check that type is a null or reference type.
737 * @param pos Position to be used for error reporting.
738 * @param t The type to be checked.
739 */
740 Type checkNullOrRefType(DiagnosticPosition pos, Type t) {
741 if (t.isNullOrReference())
742 return t;
743 else
744 return typeTagError(pos,
745 diags.fragment("type.req.ref"),
746 t);
747 }
749 /** Check that flag set does not contain elements of two conflicting sets. s
750 * Return true if it doesn't.
751 * @param pos Position to be used for error reporting.
752 * @param flags The set of flags to be checked.
753 * @param set1 Conflicting flags set #1.
754 * @param set2 Conflicting flags set #2.
755 */
756 boolean checkDisjoint(DiagnosticPosition pos, long flags, long set1, long set2) {
757 if ((flags & set1) != 0 && (flags & set2) != 0) {
758 log.error(pos,
759 "illegal.combination.of.modifiers",
760 asFlagSet(TreeInfo.firstFlag(flags & set1)),
761 asFlagSet(TreeInfo.firstFlag(flags & set2)));
762 return false;
763 } else
764 return true;
765 }
767 /** Check that usage of diamond operator is correct (i.e. diamond should not
768 * be used with non-generic classes or in anonymous class creation expressions)
769 */
770 Type checkDiamond(JCNewClass tree, Type t) {
771 if (!TreeInfo.isDiamond(tree) ||
772 t.isErroneous()) {
773 return checkClassType(tree.clazz.pos(), t, true);
774 } else if (tree.def != null) {
775 log.error(tree.clazz.pos(),
776 "cant.apply.diamond.1",
777 t, diags.fragment("diamond.and.anon.class", t));
778 return types.createErrorType(t);
779 } else if (t.tsym.type.getTypeArguments().isEmpty()) {
780 log.error(tree.clazz.pos(),
781 "cant.apply.diamond.1",
782 t, diags.fragment("diamond.non.generic", t));
783 return types.createErrorType(t);
784 } else if (tree.typeargs != null &&
785 tree.typeargs.nonEmpty()) {
786 log.error(tree.clazz.pos(),
787 "cant.apply.diamond.1",
788 t, diags.fragment("diamond.and.explicit.params", t));
789 return types.createErrorType(t);
790 } else {
791 return t;
792 }
793 }
795 void checkVarargsMethodDecl(Env<AttrContext> env, JCMethodDecl tree) {
796 MethodSymbol m = tree.sym;
797 if (!allowSimplifiedVarargs) return;
798 boolean hasTrustMeAnno = m.attribute(syms.trustMeType.tsym) != null;
799 Type varargElemType = null;
800 if (m.isVarArgs()) {
801 varargElemType = types.elemtype(tree.params.last().type);
802 }
803 if (hasTrustMeAnno && !isTrustMeAllowedOnMethod(m)) {
804 if (varargElemType != null) {
805 log.error(tree,
806 "varargs.invalid.trustme.anno",
807 syms.trustMeType.tsym,
808 diags.fragment("varargs.trustme.on.virtual.varargs", m));
809 } else {
810 log.error(tree,
811 "varargs.invalid.trustme.anno",
812 syms.trustMeType.tsym,
813 diags.fragment("varargs.trustme.on.non.varargs.meth", m));
814 }
815 } else if (hasTrustMeAnno && varargElemType != null &&
816 types.isReifiable(varargElemType)) {
817 warnUnsafeVararg(tree,
818 "varargs.redundant.trustme.anno",
819 syms.trustMeType.tsym,
820 diags.fragment("varargs.trustme.on.reifiable.varargs", varargElemType));
821 }
822 else if (!hasTrustMeAnno && varargElemType != null &&
823 !types.isReifiable(varargElemType)) {
824 warnUnchecked(tree.params.head.pos(), "unchecked.varargs.non.reifiable.type", varargElemType);
825 }
826 }
827 //where
828 private boolean isTrustMeAllowedOnMethod(Symbol s) {
829 return (s.flags() & VARARGS) != 0 &&
830 (s.isConstructor() ||
831 (s.flags() & (STATIC | FINAL)) != 0);
832 }
834 Type checkMethod(Type owntype,
835 Symbol sym,
836 Env<AttrContext> env,
837 final List<JCExpression> argtrees,
838 List<Type> argtypes,
839 boolean useVarargs,
840 boolean unchecked) {
841 // System.out.println("call : " + env.tree);
842 // System.out.println("method : " + owntype);
843 // System.out.println("actuals: " + argtypes);
844 List<Type> formals = owntype.getParameterTypes();
845 Type last = useVarargs ? formals.last() : null;
846 if (sym.name==names.init &&
847 sym.owner == syms.enumSym)
848 formals = formals.tail.tail;
849 List<JCExpression> args = argtrees;
850 DeferredAttr.DeferredTypeMap checkDeferredMap =
851 deferredAttr.new DeferredTypeMap(DeferredAttr.AttrMode.CHECK, sym, env.info.pendingResolutionPhase);
852 if (args != null) {
853 //this is null when type-checking a method reference
854 while (formals.head != last) {
855 JCTree arg = args.head;
856 Warner warn = convertWarner(arg.pos(), arg.type, formals.head);
857 assertConvertible(arg, arg.type, formals.head, warn);
858 args = args.tail;
859 formals = formals.tail;
860 }
861 if (useVarargs) {
862 Type varArg = types.elemtype(last);
863 while (args.tail != null) {
864 JCTree arg = args.head;
865 Warner warn = convertWarner(arg.pos(), arg.type, varArg);
866 assertConvertible(arg, arg.type, varArg, warn);
867 args = args.tail;
868 }
869 } else if ((sym.flags() & VARARGS) != 0 && allowVarargs) {
870 // non-varargs call to varargs method
871 Type varParam = owntype.getParameterTypes().last();
872 Type lastArg = checkDeferredMap.apply(argtypes.last());
873 if (types.isSubtypeUnchecked(lastArg, types.elemtype(varParam)) &&
874 !types.isSameType(types.erasure(varParam), types.erasure(lastArg)))
875 log.warning(argtrees.last().pos(), "inexact.non-varargs.call",
876 types.elemtype(varParam), varParam);
877 }
878 }
879 if (unchecked) {
880 warnUnchecked(env.tree.pos(),
881 "unchecked.meth.invocation.applied",
882 kindName(sym),
883 sym.name,
884 rs.methodArguments(sym.type.getParameterTypes()),
885 rs.methodArguments(Type.map(argtypes, checkDeferredMap)),
886 kindName(sym.location()),
887 sym.location());
888 owntype = new MethodType(owntype.getParameterTypes(),
889 types.erasure(owntype.getReturnType()),
890 types.erasure(owntype.getThrownTypes()),
891 syms.methodClass);
892 }
893 if (useVarargs) {
894 JCTree tree = env.tree;
895 Type argtype = owntype.getParameterTypes().last();
896 if (!types.isReifiable(argtype) &&
897 (!allowSimplifiedVarargs ||
898 sym.attribute(syms.trustMeType.tsym) == null ||
899 !isTrustMeAllowedOnMethod(sym))) {
900 warnUnchecked(env.tree.pos(),
901 "unchecked.generic.array.creation",
902 argtype);
903 }
904 if (!((MethodSymbol)sym.baseSymbol()).isSignaturePolymorphic(types)) {
905 Type elemtype = types.elemtype(argtype);
906 switch (tree.getTag()) {
907 case APPLY:
908 ((JCMethodInvocation) tree).varargsElement = elemtype;
909 break;
910 case NEWCLASS:
911 ((JCNewClass) tree).varargsElement = elemtype;
912 break;
913 case REFERENCE:
914 ((JCMemberReference) tree).varargsElement = elemtype;
915 break;
916 default:
917 throw new AssertionError(""+tree);
918 }
919 }
920 }
921 return owntype;
922 }
923 //where
924 private void assertConvertible(JCTree tree, Type actual, Type formal, Warner warn) {
925 if (types.isConvertible(actual, formal, warn))
926 return;
928 if (formal.isCompound()
929 && types.isSubtype(actual, types.supertype(formal))
930 && types.isSubtypeUnchecked(actual, types.interfaces(formal), warn))
931 return;
932 }
934 /**
935 * Check that type 't' is a valid instantiation of a generic class
936 * (see JLS 4.5)
937 *
938 * @param t class type to be checked
939 * @return true if 't' is well-formed
940 */
941 public boolean checkValidGenericType(Type t) {
942 return firstIncompatibleTypeArg(t) == null;
943 }
944 //WHERE
945 private Type firstIncompatibleTypeArg(Type type) {
946 List<Type> formals = type.tsym.type.allparams();
947 List<Type> actuals = type.allparams();
948 List<Type> args = type.getTypeArguments();
949 List<Type> forms = type.tsym.type.getTypeArguments();
950 ListBuffer<Type> bounds_buf = new ListBuffer<Type>();
952 // For matching pairs of actual argument types `a' and
953 // formal type parameters with declared bound `b' ...
954 while (args.nonEmpty() && forms.nonEmpty()) {
955 // exact type arguments needs to know their
956 // bounds (for upper and lower bound
957 // calculations). So we create new bounds where
958 // type-parameters are replaced with actuals argument types.
959 bounds_buf.append(types.subst(forms.head.getUpperBound(), formals, actuals));
960 args = args.tail;
961 forms = forms.tail;
962 }
964 args = type.getTypeArguments();
965 List<Type> tvars_cap = types.substBounds(formals,
966 formals,
967 types.capture(type).allparams());
968 while (args.nonEmpty() && tvars_cap.nonEmpty()) {
969 // Let the actual arguments know their bound
970 args.head.withTypeVar((TypeVar)tvars_cap.head);
971 args = args.tail;
972 tvars_cap = tvars_cap.tail;
973 }
975 args = type.getTypeArguments();
976 List<Type> bounds = bounds_buf.toList();
978 while (args.nonEmpty() && bounds.nonEmpty()) {
979 Type actual = args.head;
980 if (!isTypeArgErroneous(actual) &&
981 !bounds.head.isErroneous() &&
982 !checkExtends(actual, bounds.head)) {
983 return args.head;
984 }
985 args = args.tail;
986 bounds = bounds.tail;
987 }
989 args = type.getTypeArguments();
990 bounds = bounds_buf.toList();
992 for (Type arg : types.capture(type).getTypeArguments()) {
993 if (arg.hasTag(TYPEVAR) &&
994 arg.getUpperBound().isErroneous() &&
995 !bounds.head.isErroneous() &&
996 !isTypeArgErroneous(args.head)) {
997 return args.head;
998 }
999 bounds = bounds.tail;
1000 args = args.tail;
1001 }
1003 return null;
1004 }
1005 //where
1006 boolean isTypeArgErroneous(Type t) {
1007 return isTypeArgErroneous.visit(t);
1008 }
1010 Types.UnaryVisitor<Boolean> isTypeArgErroneous = new Types.UnaryVisitor<Boolean>() {
1011 public Boolean visitType(Type t, Void s) {
1012 return t.isErroneous();
1013 }
1014 @Override
1015 public Boolean visitTypeVar(TypeVar t, Void s) {
1016 return visit(t.getUpperBound());
1017 }
1018 @Override
1019 public Boolean visitCapturedType(CapturedType t, Void s) {
1020 return visit(t.getUpperBound()) ||
1021 visit(t.getLowerBound());
1022 }
1023 @Override
1024 public Boolean visitWildcardType(WildcardType t, Void s) {
1025 return visit(t.type);
1026 }
1027 };
1029 /** Check that given modifiers are legal for given symbol and
1030 * return modifiers together with any implicit modififiers for that symbol.
1031 * Warning: we can't use flags() here since this method
1032 * is called during class enter, when flags() would cause a premature
1033 * completion.
1034 * @param pos Position to be used for error reporting.
1035 * @param flags The set of modifiers given in a definition.
1036 * @param sym The defined symbol.
1037 */
1038 long checkFlags(DiagnosticPosition pos, long flags, Symbol sym, JCTree tree) {
1039 long mask;
1040 long implicit = 0;
1041 switch (sym.kind) {
1042 case VAR:
1043 if (sym.owner.kind != TYP)
1044 mask = LocalVarFlags;
1045 else if ((sym.owner.flags_field & INTERFACE) != 0)
1046 mask = implicit = InterfaceVarFlags;
1047 else
1048 mask = VarFlags;
1049 break;
1050 case MTH:
1051 if (sym.name == names.init) {
1052 if ((sym.owner.flags_field & ENUM) != 0) {
1053 // enum constructors cannot be declared public or
1054 // protected and must be implicitly or explicitly
1055 // private
1056 implicit = PRIVATE;
1057 mask = PRIVATE;
1058 } else
1059 mask = ConstructorFlags;
1060 } else if ((sym.owner.flags_field & INTERFACE) != 0) {
1061 if ((flags & DEFAULT) != 0) {
1062 mask = InterfaceDefaultMethodMask;
1063 implicit = PUBLIC | ABSTRACT;
1064 } else {
1065 mask = implicit = InterfaceMethodFlags;
1066 }
1067 }
1068 else {
1069 mask = MethodFlags;
1070 }
1071 // Imply STRICTFP if owner has STRICTFP set.
1072 if (((flags|implicit) & Flags.ABSTRACT) == 0)
1073 implicit |= sym.owner.flags_field & STRICTFP;
1074 break;
1075 case TYP:
1076 if (sym.isLocal()) {
1077 mask = LocalClassFlags;
1078 if (sym.name.isEmpty()) { // Anonymous class
1079 // Anonymous classes in static methods are themselves static;
1080 // that's why we admit STATIC here.
1081 mask |= STATIC;
1082 // JLS: Anonymous classes are final.
1083 implicit |= FINAL;
1084 }
1085 if ((sym.owner.flags_field & STATIC) == 0 &&
1086 (flags & ENUM) != 0)
1087 log.error(pos, "enums.must.be.static");
1088 } else if (sym.owner.kind == TYP) {
1089 mask = MemberClassFlags;
1090 if (sym.owner.owner.kind == PCK ||
1091 (sym.owner.flags_field & STATIC) != 0)
1092 mask |= STATIC;
1093 else if ((flags & ENUM) != 0)
1094 log.error(pos, "enums.must.be.static");
1095 // Nested interfaces and enums are always STATIC (Spec ???)
1096 if ((flags & (INTERFACE | ENUM)) != 0 ) implicit = STATIC;
1097 } else {
1098 mask = ClassFlags;
1099 }
1100 // Interfaces are always ABSTRACT
1101 if ((flags & INTERFACE) != 0) implicit |= ABSTRACT;
1103 if ((flags & ENUM) != 0) {
1104 // enums can't be declared abstract or final
1105 mask &= ~(ABSTRACT | FINAL);
1106 implicit |= implicitEnumFinalFlag(tree);
1107 }
1108 // Imply STRICTFP if owner has STRICTFP set.
1109 implicit |= sym.owner.flags_field & STRICTFP;
1110 break;
1111 default:
1112 throw new AssertionError();
1113 }
1114 long illegal = flags & ExtendedStandardFlags & ~mask;
1115 if (illegal != 0) {
1116 if ((illegal & INTERFACE) != 0) {
1117 log.error(pos, "intf.not.allowed.here");
1118 mask |= INTERFACE;
1119 }
1120 else {
1121 log.error(pos,
1122 "mod.not.allowed.here", asFlagSet(illegal));
1123 }
1124 }
1125 else if ((sym.kind == TYP ||
1126 // ISSUE: Disallowing abstract&private is no longer appropriate
1127 // in the presence of inner classes. Should it be deleted here?
1128 checkDisjoint(pos, flags,
1129 ABSTRACT,
1130 PRIVATE | STATIC | DEFAULT))
1131 &&
1132 checkDisjoint(pos, flags,
1133 ABSTRACT | INTERFACE,
1134 FINAL | NATIVE | SYNCHRONIZED)
1135 &&
1136 checkDisjoint(pos, flags,
1137 PUBLIC,
1138 PRIVATE | PROTECTED)
1139 &&
1140 checkDisjoint(pos, flags,
1141 PRIVATE,
1142 PUBLIC | PROTECTED)
1143 &&
1144 checkDisjoint(pos, flags,
1145 FINAL,
1146 VOLATILE)
1147 &&
1148 (sym.kind == TYP ||
1149 checkDisjoint(pos, flags,
1150 ABSTRACT | NATIVE,
1151 STRICTFP))) {
1152 // skip
1153 }
1154 return flags & (mask | ~ExtendedStandardFlags) | implicit;
1155 }
1158 /** Determine if this enum should be implicitly final.
1159 *
1160 * If the enum has no specialized enum contants, it is final.
1161 *
1162 * If the enum does have specialized enum contants, it is
1163 * <i>not</i> final.
1164 */
1165 private long implicitEnumFinalFlag(JCTree tree) {
1166 if (!tree.hasTag(CLASSDEF)) return 0;
1167 class SpecialTreeVisitor extends JCTree.Visitor {
1168 boolean specialized;
1169 SpecialTreeVisitor() {
1170 this.specialized = false;
1171 };
1173 @Override
1174 public void visitTree(JCTree tree) { /* no-op */ }
1176 @Override
1177 public void visitVarDef(JCVariableDecl tree) {
1178 if ((tree.mods.flags & ENUM) != 0) {
1179 if (tree.init instanceof JCNewClass &&
1180 ((JCNewClass) tree.init).def != null) {
1181 specialized = true;
1182 }
1183 }
1184 }
1185 }
1187 SpecialTreeVisitor sts = new SpecialTreeVisitor();
1188 JCClassDecl cdef = (JCClassDecl) tree;
1189 for (JCTree defs: cdef.defs) {
1190 defs.accept(sts);
1191 if (sts.specialized) return 0;
1192 }
1193 return FINAL;
1194 }
1196 /* *************************************************************************
1197 * Type Validation
1198 **************************************************************************/
1200 /** Validate a type expression. That is,
1201 * check that all type arguments of a parametric type are within
1202 * their bounds. This must be done in a second phase after type attributon
1203 * since a class might have a subclass as type parameter bound. E.g:
1204 *
1205 * <pre>{@code
1206 * class B<A extends C> { ... }
1207 * class C extends B<C> { ... }
1208 * }</pre>
1209 *
1210 * and we can't make sure that the bound is already attributed because
1211 * of possible cycles.
1212 *
1213 * Visitor method: Validate a type expression, if it is not null, catching
1214 * and reporting any completion failures.
1215 */
1216 void validate(JCTree tree, Env<AttrContext> env) {
1217 validate(tree, env, true);
1218 }
1219 void validate(JCTree tree, Env<AttrContext> env, boolean checkRaw) {
1220 new Validator(env).validateTree(tree, checkRaw, true);
1221 }
1223 /** Visitor method: Validate a list of type expressions.
1224 */
1225 void validate(List<? extends JCTree> trees, Env<AttrContext> env) {
1226 for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail)
1227 validate(l.head, env);
1228 }
1230 /** A visitor class for type validation.
1231 */
1232 class Validator extends JCTree.Visitor {
1234 boolean isOuter;
1235 Env<AttrContext> env;
1237 Validator(Env<AttrContext> env) {
1238 this.env = env;
1239 }
1241 @Override
1242 public void visitTypeArray(JCArrayTypeTree tree) {
1243 tree.elemtype.accept(this);
1244 }
1246 @Override
1247 public void visitTypeApply(JCTypeApply tree) {
1248 if (tree.type.hasTag(CLASS)) {
1249 List<JCExpression> args = tree.arguments;
1250 List<Type> forms = tree.type.tsym.type.getTypeArguments();
1252 Type incompatibleArg = firstIncompatibleTypeArg(tree.type);
1253 if (incompatibleArg != null) {
1254 for (JCTree arg : tree.arguments) {
1255 if (arg.type == incompatibleArg) {
1256 log.error(arg, "not.within.bounds", incompatibleArg, forms.head);
1257 }
1258 forms = forms.tail;
1259 }
1260 }
1262 forms = tree.type.tsym.type.getTypeArguments();
1264 boolean is_java_lang_Class = tree.type.tsym.flatName() == names.java_lang_Class;
1266 // For matching pairs of actual argument types `a' and
1267 // formal type parameters with declared bound `b' ...
1268 while (args.nonEmpty() && forms.nonEmpty()) {
1269 validateTree(args.head,
1270 !(isOuter && is_java_lang_Class),
1271 false);
1272 args = args.tail;
1273 forms = forms.tail;
1274 }
1276 // Check that this type is either fully parameterized, or
1277 // not parameterized at all.
1278 if (tree.type.getEnclosingType().isRaw())
1279 log.error(tree.pos(), "improperly.formed.type.inner.raw.param");
1280 if (tree.clazz.hasTag(SELECT))
1281 visitSelectInternal((JCFieldAccess)tree.clazz);
1282 }
1283 }
1285 @Override
1286 public void visitTypeParameter(JCTypeParameter tree) {
1287 validateTrees(tree.bounds, true, isOuter);
1288 checkClassBounds(tree.pos(), tree.type);
1289 }
1291 @Override
1292 public void visitWildcard(JCWildcard tree) {
1293 if (tree.inner != null)
1294 validateTree(tree.inner, true, isOuter);
1295 }
1297 @Override
1298 public void visitSelect(JCFieldAccess tree) {
1299 if (tree.type.hasTag(CLASS)) {
1300 visitSelectInternal(tree);
1302 // Check that this type is either fully parameterized, or
1303 // not parameterized at all.
1304 if (tree.selected.type.isParameterized() && tree.type.tsym.type.getTypeArguments().nonEmpty())
1305 log.error(tree.pos(), "improperly.formed.type.param.missing");
1306 }
1307 }
1309 public void visitSelectInternal(JCFieldAccess tree) {
1310 if (tree.type.tsym.isStatic() &&
1311 tree.selected.type.isParameterized()) {
1312 // The enclosing type is not a class, so we are
1313 // looking at a static member type. However, the
1314 // qualifying expression is parameterized.
1315 log.error(tree.pos(), "cant.select.static.class.from.param.type");
1316 } else {
1317 // otherwise validate the rest of the expression
1318 tree.selected.accept(this);
1319 }
1320 }
1322 /** Default visitor method: do nothing.
1323 */
1324 @Override
1325 public void visitTree(JCTree tree) {
1326 }
1328 public void validateTree(JCTree tree, boolean checkRaw, boolean isOuter) {
1329 try {
1330 if (tree != null) {
1331 this.isOuter = isOuter;
1332 tree.accept(this);
1333 if (checkRaw)
1334 checkRaw(tree, env);
1335 }
1336 } catch (CompletionFailure ex) {
1337 completionError(tree.pos(), ex);
1338 }
1339 }
1341 public void validateTrees(List<? extends JCTree> trees, boolean checkRaw, boolean isOuter) {
1342 for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail)
1343 validateTree(l.head, checkRaw, isOuter);
1344 }
1346 void checkRaw(JCTree tree, Env<AttrContext> env) {
1347 if (lint.isEnabled(LintCategory.RAW) &&
1348 tree.type.hasTag(CLASS) &&
1349 !TreeInfo.isDiamond(tree) &&
1350 !withinAnonConstr(env) &&
1351 tree.type.isRaw()) {
1352 log.warning(LintCategory.RAW,
1353 tree.pos(), "raw.class.use", tree.type, tree.type.tsym.type);
1354 }
1355 }
1357 boolean withinAnonConstr(Env<AttrContext> env) {
1358 return env.enclClass.name.isEmpty() &&
1359 env.enclMethod != null && env.enclMethod.name == names.init;
1360 }
1361 }
1363 /* *************************************************************************
1364 * Exception checking
1365 **************************************************************************/
1367 /* The following methods treat classes as sets that contain
1368 * the class itself and all their subclasses
1369 */
1371 /** Is given type a subtype of some of the types in given list?
1372 */
1373 boolean subset(Type t, List<Type> ts) {
1374 for (List<Type> l = ts; l.nonEmpty(); l = l.tail)
1375 if (types.isSubtype(t, l.head)) return true;
1376 return false;
1377 }
1379 /** Is given type a subtype or supertype of
1380 * some of the types in given list?
1381 */
1382 boolean intersects(Type t, List<Type> ts) {
1383 for (List<Type> l = ts; l.nonEmpty(); l = l.tail)
1384 if (types.isSubtype(t, l.head) || types.isSubtype(l.head, t)) return true;
1385 return false;
1386 }
1388 /** Add type set to given type list, unless it is a subclass of some class
1389 * in the list.
1390 */
1391 List<Type> incl(Type t, List<Type> ts) {
1392 return subset(t, ts) ? ts : excl(t, ts).prepend(t);
1393 }
1395 /** Remove type set from type set list.
1396 */
1397 List<Type> excl(Type t, List<Type> ts) {
1398 if (ts.isEmpty()) {
1399 return ts;
1400 } else {
1401 List<Type> ts1 = excl(t, ts.tail);
1402 if (types.isSubtype(ts.head, t)) return ts1;
1403 else if (ts1 == ts.tail) return ts;
1404 else return ts1.prepend(ts.head);
1405 }
1406 }
1408 /** Form the union of two type set lists.
1409 */
1410 List<Type> union(List<Type> ts1, List<Type> ts2) {
1411 List<Type> ts = ts1;
1412 for (List<Type> l = ts2; l.nonEmpty(); l = l.tail)
1413 ts = incl(l.head, ts);
1414 return ts;
1415 }
1417 /** Form the difference of two type lists.
1418 */
1419 List<Type> diff(List<Type> ts1, List<Type> ts2) {
1420 List<Type> ts = ts1;
1421 for (List<Type> l = ts2; l.nonEmpty(); l = l.tail)
1422 ts = excl(l.head, ts);
1423 return ts;
1424 }
1426 /** Form the intersection of two type lists.
1427 */
1428 public List<Type> intersect(List<Type> ts1, List<Type> ts2) {
1429 List<Type> ts = List.nil();
1430 for (List<Type> l = ts1; l.nonEmpty(); l = l.tail)
1431 if (subset(l.head, ts2)) ts = incl(l.head, ts);
1432 for (List<Type> l = ts2; l.nonEmpty(); l = l.tail)
1433 if (subset(l.head, ts1)) ts = incl(l.head, ts);
1434 return ts;
1435 }
1437 /** Is exc an exception symbol that need not be declared?
1438 */
1439 boolean isUnchecked(ClassSymbol exc) {
1440 return
1441 exc.kind == ERR ||
1442 exc.isSubClass(syms.errorType.tsym, types) ||
1443 exc.isSubClass(syms.runtimeExceptionType.tsym, types);
1444 }
1446 /** Is exc an exception type that need not be declared?
1447 */
1448 boolean isUnchecked(Type exc) {
1449 return
1450 (exc.hasTag(TYPEVAR)) ? isUnchecked(types.supertype(exc)) :
1451 (exc.hasTag(CLASS)) ? isUnchecked((ClassSymbol)exc.tsym) :
1452 exc.hasTag(BOT);
1453 }
1455 /** Same, but handling completion failures.
1456 */
1457 boolean isUnchecked(DiagnosticPosition pos, Type exc) {
1458 try {
1459 return isUnchecked(exc);
1460 } catch (CompletionFailure ex) {
1461 completionError(pos, ex);
1462 return true;
1463 }
1464 }
1466 /** Is exc handled by given exception list?
1467 */
1468 boolean isHandled(Type exc, List<Type> handled) {
1469 return isUnchecked(exc) || subset(exc, handled);
1470 }
1472 /** Return all exceptions in thrown list that are not in handled list.
1473 * @param thrown The list of thrown exceptions.
1474 * @param handled The list of handled exceptions.
1475 */
1476 List<Type> unhandled(List<Type> thrown, List<Type> handled) {
1477 List<Type> unhandled = List.nil();
1478 for (List<Type> l = thrown; l.nonEmpty(); l = l.tail)
1479 if (!isHandled(l.head, handled)) unhandled = unhandled.prepend(l.head);
1480 return unhandled;
1481 }
1483 /* *************************************************************************
1484 * Overriding/Implementation checking
1485 **************************************************************************/
1487 /** The level of access protection given by a flag set,
1488 * where PRIVATE is highest and PUBLIC is lowest.
1489 */
1490 static int protection(long flags) {
1491 switch ((short)(flags & AccessFlags)) {
1492 case PRIVATE: return 3;
1493 case PROTECTED: return 1;
1494 default:
1495 case PUBLIC: return 0;
1496 case 0: return 2;
1497 }
1498 }
1500 /** A customized "cannot override" error message.
1501 * @param m The overriding method.
1502 * @param other The overridden method.
1503 * @return An internationalized string.
1504 */
1505 Object cannotOverride(MethodSymbol m, MethodSymbol other) {
1506 String key;
1507 if ((other.owner.flags() & INTERFACE) == 0)
1508 key = "cant.override";
1509 else if ((m.owner.flags() & INTERFACE) == 0)
1510 key = "cant.implement";
1511 else
1512 key = "clashes.with";
1513 return diags.fragment(key, m, m.location(), other, other.location());
1514 }
1516 /** A customized "override" warning message.
1517 * @param m The overriding method.
1518 * @param other The overridden method.
1519 * @return An internationalized string.
1520 */
1521 Object uncheckedOverrides(MethodSymbol m, MethodSymbol other) {
1522 String key;
1523 if ((other.owner.flags() & INTERFACE) == 0)
1524 key = "unchecked.override";
1525 else if ((m.owner.flags() & INTERFACE) == 0)
1526 key = "unchecked.implement";
1527 else
1528 key = "unchecked.clash.with";
1529 return diags.fragment(key, m, m.location(), other, other.location());
1530 }
1532 /** A customized "override" warning message.
1533 * @param m The overriding method.
1534 * @param other The overridden method.
1535 * @return An internationalized string.
1536 */
1537 Object varargsOverrides(MethodSymbol m, MethodSymbol other) {
1538 String key;
1539 if ((other.owner.flags() & INTERFACE) == 0)
1540 key = "varargs.override";
1541 else if ((m.owner.flags() & INTERFACE) == 0)
1542 key = "varargs.implement";
1543 else
1544 key = "varargs.clash.with";
1545 return diags.fragment(key, m, m.location(), other, other.location());
1546 }
1548 /** Check that this method conforms with overridden method 'other'.
1549 * where `origin' is the class where checking started.
1550 * Complications:
1551 * (1) Do not check overriding of synthetic methods
1552 * (reason: they might be final).
1553 * todo: check whether this is still necessary.
1554 * (2) Admit the case where an interface proxy throws fewer exceptions
1555 * than the method it implements. Augment the proxy methods with the
1556 * undeclared exceptions in this case.
1557 * (3) When generics are enabled, admit the case where an interface proxy
1558 * has a result type
1559 * extended by the result type of the method it implements.
1560 * Change the proxies result type to the smaller type in this case.
1561 *
1562 * @param tree The tree from which positions
1563 * are extracted for errors.
1564 * @param m The overriding method.
1565 * @param other The overridden method.
1566 * @param origin The class of which the overriding method
1567 * is a member.
1568 */
1569 void checkOverride(JCTree tree,
1570 MethodSymbol m,
1571 MethodSymbol other,
1572 ClassSymbol origin) {
1573 // Don't check overriding of synthetic methods or by bridge methods.
1574 if ((m.flags() & (SYNTHETIC|BRIDGE)) != 0 || (other.flags() & SYNTHETIC) != 0) {
1575 return;
1576 }
1578 // Error if static method overrides instance method (JLS 8.4.6.2).
1579 if ((m.flags() & STATIC) != 0 &&
1580 (other.flags() & STATIC) == 0) {
1581 log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.static",
1582 cannotOverride(m, other));
1583 return;
1584 }
1586 // Error if instance method overrides static or final
1587 // method (JLS 8.4.6.1).
1588 if ((other.flags() & FINAL) != 0 ||
1589 (m.flags() & STATIC) == 0 &&
1590 (other.flags() & STATIC) != 0) {
1591 log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.meth",
1592 cannotOverride(m, other),
1593 asFlagSet(other.flags() & (FINAL | STATIC)));
1594 return;
1595 }
1597 if ((m.owner.flags() & ANNOTATION) != 0) {
1598 // handled in validateAnnotationMethod
1599 return;
1600 }
1602 // Error if overriding method has weaker access (JLS 8.4.6.3).
1603 if ((origin.flags() & INTERFACE) == 0 &&
1604 protection(m.flags()) > protection(other.flags())) {
1605 log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.weaker.access",
1606 cannotOverride(m, other),
1607 other.flags() == 0 ?
1608 Flag.PACKAGE :
1609 asFlagSet(other.flags() & AccessFlags));
1610 return;
1611 }
1613 Type mt = types.memberType(origin.type, m);
1614 Type ot = types.memberType(origin.type, other);
1615 // Error if overriding result type is different
1616 // (or, in the case of generics mode, not a subtype) of
1617 // overridden result type. We have to rename any type parameters
1618 // before comparing types.
1619 List<Type> mtvars = mt.getTypeArguments();
1620 List<Type> otvars = ot.getTypeArguments();
1621 Type mtres = mt.getReturnType();
1622 Type otres = types.subst(ot.getReturnType(), otvars, mtvars);
1624 overrideWarner.clear();
1625 boolean resultTypesOK =
1626 types.returnTypeSubstitutable(mt, ot, otres, overrideWarner);
1627 if (!resultTypesOK) {
1628 if (!allowCovariantReturns &&
1629 m.owner != origin &&
1630 m.owner.isSubClass(other.owner, types)) {
1631 // allow limited interoperability with covariant returns
1632 } else {
1633 log.error(TreeInfo.diagnosticPositionFor(m, tree),
1634 "override.incompatible.ret",
1635 cannotOverride(m, other),
1636 mtres, otres);
1637 return;
1638 }
1639 } else if (overrideWarner.hasNonSilentLint(LintCategory.UNCHECKED)) {
1640 warnUnchecked(TreeInfo.diagnosticPositionFor(m, tree),
1641 "override.unchecked.ret",
1642 uncheckedOverrides(m, other),
1643 mtres, otres);
1644 }
1646 // Error if overriding method throws an exception not reported
1647 // by overridden method.
1648 List<Type> otthrown = types.subst(ot.getThrownTypes(), otvars, mtvars);
1649 List<Type> unhandledErased = unhandled(mt.getThrownTypes(), types.erasure(otthrown));
1650 List<Type> unhandledUnerased = unhandled(mt.getThrownTypes(), otthrown);
1651 if (unhandledErased.nonEmpty()) {
1652 log.error(TreeInfo.diagnosticPositionFor(m, tree),
1653 "override.meth.doesnt.throw",
1654 cannotOverride(m, other),
1655 unhandledUnerased.head);
1656 return;
1657 }
1658 else if (unhandledUnerased.nonEmpty()) {
1659 warnUnchecked(TreeInfo.diagnosticPositionFor(m, tree),
1660 "override.unchecked.thrown",
1661 cannotOverride(m, other),
1662 unhandledUnerased.head);
1663 return;
1664 }
1666 // Optional warning if varargs don't agree
1667 if ((((m.flags() ^ other.flags()) & Flags.VARARGS) != 0)
1668 && lint.isEnabled(LintCategory.OVERRIDES)) {
1669 log.warning(TreeInfo.diagnosticPositionFor(m, tree),
1670 ((m.flags() & Flags.VARARGS) != 0)
1671 ? "override.varargs.missing"
1672 : "override.varargs.extra",
1673 varargsOverrides(m, other));
1674 }
1676 // Warn if instance method overrides bridge method (compiler spec ??)
1677 if ((other.flags() & BRIDGE) != 0) {
1678 log.warning(TreeInfo.diagnosticPositionFor(m, tree), "override.bridge",
1679 uncheckedOverrides(m, other));
1680 }
1682 // Warn if a deprecated method overridden by a non-deprecated one.
1683 if (!isDeprecatedOverrideIgnorable(other, origin)) {
1684 checkDeprecated(TreeInfo.diagnosticPositionFor(m, tree), m, other);
1685 }
1686 }
1687 // where
1688 private boolean isDeprecatedOverrideIgnorable(MethodSymbol m, ClassSymbol origin) {
1689 // If the method, m, is defined in an interface, then ignore the issue if the method
1690 // is only inherited via a supertype and also implemented in the supertype,
1691 // because in that case, we will rediscover the issue when examining the method
1692 // in the supertype.
1693 // If the method, m, is not defined in an interface, then the only time we need to
1694 // address the issue is when the method is the supertype implemementation: any other
1695 // case, we will have dealt with when examining the supertype classes
1696 ClassSymbol mc = m.enclClass();
1697 Type st = types.supertype(origin.type);
1698 if (!st.hasTag(CLASS))
1699 return true;
1700 MethodSymbol stimpl = m.implementation((ClassSymbol)st.tsym, types, false);
1702 if (mc != null && ((mc.flags() & INTERFACE) != 0)) {
1703 List<Type> intfs = types.interfaces(origin.type);
1704 return (intfs.contains(mc.type) ? false : (stimpl != null));
1705 }
1706 else
1707 return (stimpl != m);
1708 }
1711 // used to check if there were any unchecked conversions
1712 Warner overrideWarner = new Warner();
1714 /** Check that a class does not inherit two concrete methods
1715 * with the same signature.
1716 * @param pos Position to be used for error reporting.
1717 * @param site The class type to be checked.
1718 */
1719 public void checkCompatibleConcretes(DiagnosticPosition pos, Type site) {
1720 Type sup = types.supertype(site);
1721 if (!sup.hasTag(CLASS)) return;
1723 for (Type t1 = sup;
1724 t1.tsym.type.isParameterized();
1725 t1 = types.supertype(t1)) {
1726 for (Scope.Entry e1 = t1.tsym.members().elems;
1727 e1 != null;
1728 e1 = e1.sibling) {
1729 Symbol s1 = e1.sym;
1730 if (s1.kind != MTH ||
1731 (s1.flags() & (STATIC|SYNTHETIC|BRIDGE)) != 0 ||
1732 !s1.isInheritedIn(site.tsym, types) ||
1733 ((MethodSymbol)s1).implementation(site.tsym,
1734 types,
1735 true) != s1)
1736 continue;
1737 Type st1 = types.memberType(t1, s1);
1738 int s1ArgsLength = st1.getParameterTypes().length();
1739 if (st1 == s1.type) continue;
1741 for (Type t2 = sup;
1742 t2.hasTag(CLASS);
1743 t2 = types.supertype(t2)) {
1744 for (Scope.Entry e2 = t2.tsym.members().lookup(s1.name);
1745 e2.scope != null;
1746 e2 = e2.next()) {
1747 Symbol s2 = e2.sym;
1748 if (s2 == s1 ||
1749 s2.kind != MTH ||
1750 (s2.flags() & (STATIC|SYNTHETIC|BRIDGE)) != 0 ||
1751 s2.type.getParameterTypes().length() != s1ArgsLength ||
1752 !s2.isInheritedIn(site.tsym, types) ||
1753 ((MethodSymbol)s2).implementation(site.tsym,
1754 types,
1755 true) != s2)
1756 continue;
1757 Type st2 = types.memberType(t2, s2);
1758 if (types.overrideEquivalent(st1, st2))
1759 log.error(pos, "concrete.inheritance.conflict",
1760 s1, t1, s2, t2, sup);
1761 }
1762 }
1763 }
1764 }
1765 }
1767 /** Check that classes (or interfaces) do not each define an abstract
1768 * method with same name and arguments but incompatible return types.
1769 * @param pos Position to be used for error reporting.
1770 * @param t1 The first argument type.
1771 * @param t2 The second argument type.
1772 */
1773 public boolean checkCompatibleAbstracts(DiagnosticPosition pos,
1774 Type t1,
1775 Type t2) {
1776 return checkCompatibleAbstracts(pos, t1, t2,
1777 types.makeCompoundType(t1, t2));
1778 }
1780 public boolean checkCompatibleAbstracts(DiagnosticPosition pos,
1781 Type t1,
1782 Type t2,
1783 Type site) {
1784 return firstIncompatibility(pos, t1, t2, site) == null;
1785 }
1787 /** Return the first method which is defined with same args
1788 * but different return types in two given interfaces, or null if none
1789 * exists.
1790 * @param t1 The first type.
1791 * @param t2 The second type.
1792 * @param site The most derived type.
1793 * @returns symbol from t2 that conflicts with one in t1.
1794 */
1795 private Symbol firstIncompatibility(DiagnosticPosition pos, Type t1, Type t2, Type site) {
1796 Map<TypeSymbol,Type> interfaces1 = new HashMap<TypeSymbol,Type>();
1797 closure(t1, interfaces1);
1798 Map<TypeSymbol,Type> interfaces2;
1799 if (t1 == t2)
1800 interfaces2 = interfaces1;
1801 else
1802 closure(t2, interfaces1, interfaces2 = new HashMap<TypeSymbol,Type>());
1804 for (Type t3 : interfaces1.values()) {
1805 for (Type t4 : interfaces2.values()) {
1806 Symbol s = firstDirectIncompatibility(pos, t3, t4, site);
1807 if (s != null) return s;
1808 }
1809 }
1810 return null;
1811 }
1813 /** Compute all the supertypes of t, indexed by type symbol. */
1814 private void closure(Type t, Map<TypeSymbol,Type> typeMap) {
1815 if (!t.hasTag(CLASS)) return;
1816 if (typeMap.put(t.tsym, t) == null) {
1817 closure(types.supertype(t), typeMap);
1818 for (Type i : types.interfaces(t))
1819 closure(i, typeMap);
1820 }
1821 }
1823 /** Compute all the supertypes of t, indexed by type symbol (except thise in typesSkip). */
1824 private void closure(Type t, Map<TypeSymbol,Type> typesSkip, Map<TypeSymbol,Type> typeMap) {
1825 if (!t.hasTag(CLASS)) return;
1826 if (typesSkip.get(t.tsym) != null) return;
1827 if (typeMap.put(t.tsym, t) == null) {
1828 closure(types.supertype(t), typesSkip, typeMap);
1829 for (Type i : types.interfaces(t))
1830 closure(i, typesSkip, typeMap);
1831 }
1832 }
1834 /** Return the first method in t2 that conflicts with a method from t1. */
1835 private Symbol firstDirectIncompatibility(DiagnosticPosition pos, Type t1, Type t2, Type site) {
1836 for (Scope.Entry e1 = t1.tsym.members().elems; e1 != null; e1 = e1.sibling) {
1837 Symbol s1 = e1.sym;
1838 Type st1 = null;
1839 if (s1.kind != MTH || !s1.isInheritedIn(site.tsym, types) ||
1840 (s1.flags() & SYNTHETIC) != 0) continue;
1841 Symbol impl = ((MethodSymbol)s1).implementation(site.tsym, types, false);
1842 if (impl != null && (impl.flags() & ABSTRACT) == 0) continue;
1843 for (Scope.Entry e2 = t2.tsym.members().lookup(s1.name); e2.scope != null; e2 = e2.next()) {
1844 Symbol s2 = e2.sym;
1845 if (s1 == s2) continue;
1846 if (s2.kind != MTH || !s2.isInheritedIn(site.tsym, types) ||
1847 (s2.flags() & SYNTHETIC) != 0) continue;
1848 if (st1 == null) st1 = types.memberType(t1, s1);
1849 Type st2 = types.memberType(t2, s2);
1850 if (types.overrideEquivalent(st1, st2)) {
1851 List<Type> tvars1 = st1.getTypeArguments();
1852 List<Type> tvars2 = st2.getTypeArguments();
1853 Type rt1 = st1.getReturnType();
1854 Type rt2 = types.subst(st2.getReturnType(), tvars2, tvars1);
1855 boolean compat =
1856 types.isSameType(rt1, rt2) ||
1857 !rt1.isPrimitiveOrVoid() &&
1858 !rt2.isPrimitiveOrVoid() &&
1859 (types.covariantReturnType(rt1, rt2, types.noWarnings) ||
1860 types.covariantReturnType(rt2, rt1, types.noWarnings)) ||
1861 checkCommonOverriderIn(s1,s2,site);
1862 if (!compat) {
1863 log.error(pos, "types.incompatible.diff.ret",
1864 t1, t2, s2.name +
1865 "(" + types.memberType(t2, s2).getParameterTypes() + ")");
1866 return s2;
1867 }
1868 } else if (checkNameClash((ClassSymbol)site.tsym, s1, s2) &&
1869 !checkCommonOverriderIn(s1, s2, site)) {
1870 log.error(pos,
1871 "name.clash.same.erasure.no.override",
1872 s1, s1.location(),
1873 s2, s2.location());
1874 return s2;
1875 }
1876 }
1877 }
1878 return null;
1879 }
1880 //WHERE
1881 boolean checkCommonOverriderIn(Symbol s1, Symbol s2, Type site) {
1882 Map<TypeSymbol,Type> supertypes = new HashMap<TypeSymbol,Type>();
1883 Type st1 = types.memberType(site, s1);
1884 Type st2 = types.memberType(site, s2);
1885 closure(site, supertypes);
1886 for (Type t : supertypes.values()) {
1887 for (Scope.Entry e = t.tsym.members().lookup(s1.name); e.scope != null; e = e.next()) {
1888 Symbol s3 = e.sym;
1889 if (s3 == s1 || s3 == s2 || s3.kind != MTH || (s3.flags() & (BRIDGE|SYNTHETIC)) != 0) continue;
1890 Type st3 = types.memberType(site,s3);
1891 if (types.overrideEquivalent(st3, st1) && types.overrideEquivalent(st3, st2)) {
1892 if (s3.owner == site.tsym) {
1893 return true;
1894 }
1895 List<Type> tvars1 = st1.getTypeArguments();
1896 List<Type> tvars2 = st2.getTypeArguments();
1897 List<Type> tvars3 = st3.getTypeArguments();
1898 Type rt1 = st1.getReturnType();
1899 Type rt2 = st2.getReturnType();
1900 Type rt13 = types.subst(st3.getReturnType(), tvars3, tvars1);
1901 Type rt23 = types.subst(st3.getReturnType(), tvars3, tvars2);
1902 boolean compat =
1903 !rt13.isPrimitiveOrVoid() &&
1904 !rt23.isPrimitiveOrVoid() &&
1905 (types.covariantReturnType(rt13, rt1, types.noWarnings) &&
1906 types.covariantReturnType(rt23, rt2, types.noWarnings));
1907 if (compat)
1908 return true;
1909 }
1910 }
1911 }
1912 return false;
1913 }
1915 /** Check that a given method conforms with any method it overrides.
1916 * @param tree The tree from which positions are extracted
1917 * for errors.
1918 * @param m The overriding method.
1919 */
1920 void checkOverride(JCTree tree, MethodSymbol m) {
1921 ClassSymbol origin = (ClassSymbol)m.owner;
1922 if ((origin.flags() & ENUM) != 0 && names.finalize.equals(m.name))
1923 if (m.overrides(syms.enumFinalFinalize, origin, types, false)) {
1924 log.error(tree.pos(), "enum.no.finalize");
1925 return;
1926 }
1927 for (Type t = origin.type; t.hasTag(CLASS);
1928 t = types.supertype(t)) {
1929 if (t != origin.type) {
1930 checkOverride(tree, t, origin, m);
1931 }
1932 for (Type t2 : types.interfaces(t)) {
1933 checkOverride(tree, t2, origin, m);
1934 }
1935 }
1936 }
1938 void checkOverride(JCTree tree, Type site, ClassSymbol origin, MethodSymbol m) {
1939 TypeSymbol c = site.tsym;
1940 Scope.Entry e = c.members().lookup(m.name);
1941 while (e.scope != null) {
1942 if (m.overrides(e.sym, origin, types, false)) {
1943 if ((e.sym.flags() & ABSTRACT) == 0) {
1944 checkOverride(tree, m, (MethodSymbol)e.sym, origin);
1945 }
1946 }
1947 e = e.next();
1948 }
1949 }
1951 private boolean checkNameClash(ClassSymbol origin, Symbol s1, Symbol s2) {
1952 ClashFilter cf = new ClashFilter(origin.type);
1953 return (cf.accepts(s1) &&
1954 cf.accepts(s2) &&
1955 types.hasSameArgs(s1.erasure(types), s2.erasure(types)));
1956 }
1959 /** Check that all abstract members of given class have definitions.
1960 * @param pos Position to be used for error reporting.
1961 * @param c The class.
1962 */
1963 void checkAllDefined(DiagnosticPosition pos, ClassSymbol c) {
1964 try {
1965 MethodSymbol undef = firstUndef(c, c);
1966 if (undef != null) {
1967 if ((c.flags() & ENUM) != 0 &&
1968 types.supertype(c.type).tsym == syms.enumSym &&
1969 (c.flags() & FINAL) == 0) {
1970 // add the ABSTRACT flag to an enum
1971 c.flags_field |= ABSTRACT;
1972 } else {
1973 MethodSymbol undef1 =
1974 new MethodSymbol(undef.flags(), undef.name,
1975 types.memberType(c.type, undef), undef.owner);
1976 log.error(pos, "does.not.override.abstract",
1977 c, undef1, undef1.location());
1978 }
1979 }
1980 } catch (CompletionFailure ex) {
1981 completionError(pos, ex);
1982 }
1983 }
1984 //where
1985 /** Return first abstract member of class `c' that is not defined
1986 * in `impl', null if there is none.
1987 */
1988 private MethodSymbol firstUndef(ClassSymbol impl, ClassSymbol c) {
1989 MethodSymbol undef = null;
1990 // Do not bother to search in classes that are not abstract,
1991 // since they cannot have abstract members.
1992 if (c == impl || (c.flags() & (ABSTRACT | INTERFACE)) != 0) {
1993 Scope s = c.members();
1994 for (Scope.Entry e = s.elems;
1995 undef == null && e != null;
1996 e = e.sibling) {
1997 if (e.sym.kind == MTH &&
1998 (e.sym.flags() & (ABSTRACT|IPROXY|DEFAULT)) == ABSTRACT) {
1999 MethodSymbol absmeth = (MethodSymbol)e.sym;
2000 MethodSymbol implmeth = absmeth.implementation(impl, types, true);
2001 if (implmeth == null || implmeth == absmeth) {
2002 //look for default implementations
2003 if (allowDefaultMethods) {
2004 MethodSymbol prov = types.interfaceCandidates(impl.type, absmeth).head;
2005 if (prov != null && prov.overrides(absmeth, impl, types, true)) {
2006 implmeth = prov;
2007 }
2008 }
2009 }
2010 if (implmeth == null || implmeth == absmeth) {
2011 undef = absmeth;
2012 }
2013 }
2014 }
2015 if (undef == null) {
2016 Type st = types.supertype(c.type);
2017 if (st.hasTag(CLASS))
2018 undef = firstUndef(impl, (ClassSymbol)st.tsym);
2019 }
2020 for (List<Type> l = types.interfaces(c.type);
2021 undef == null && l.nonEmpty();
2022 l = l.tail) {
2023 undef = firstUndef(impl, (ClassSymbol)l.head.tsym);
2024 }
2025 }
2026 return undef;
2027 }
2029 void checkNonCyclicDecl(JCClassDecl tree) {
2030 CycleChecker cc = new CycleChecker();
2031 cc.scan(tree);
2032 if (!cc.errorFound && !cc.partialCheck) {
2033 tree.sym.flags_field |= ACYCLIC;
2034 }
2035 }
2037 class CycleChecker extends TreeScanner {
2039 List<Symbol> seenClasses = List.nil();
2040 boolean errorFound = false;
2041 boolean partialCheck = false;
2043 private void checkSymbol(DiagnosticPosition pos, Symbol sym) {
2044 if (sym != null && sym.kind == TYP) {
2045 Env<AttrContext> classEnv = enter.getEnv((TypeSymbol)sym);
2046 if (classEnv != null) {
2047 DiagnosticSource prevSource = log.currentSource();
2048 try {
2049 log.useSource(classEnv.toplevel.sourcefile);
2050 scan(classEnv.tree);
2051 }
2052 finally {
2053 log.useSource(prevSource.getFile());
2054 }
2055 } else if (sym.kind == TYP) {
2056 checkClass(pos, sym, List.<JCTree>nil());
2057 }
2058 } else {
2059 //not completed yet
2060 partialCheck = true;
2061 }
2062 }
2064 @Override
2065 public void visitSelect(JCFieldAccess tree) {
2066 super.visitSelect(tree);
2067 checkSymbol(tree.pos(), tree.sym);
2068 }
2070 @Override
2071 public void visitIdent(JCIdent tree) {
2072 checkSymbol(tree.pos(), tree.sym);
2073 }
2075 @Override
2076 public void visitTypeApply(JCTypeApply tree) {
2077 scan(tree.clazz);
2078 }
2080 @Override
2081 public void visitTypeArray(JCArrayTypeTree tree) {
2082 scan(tree.elemtype);
2083 }
2085 @Override
2086 public void visitClassDef(JCClassDecl tree) {
2087 List<JCTree> supertypes = List.nil();
2088 if (tree.getExtendsClause() != null) {
2089 supertypes = supertypes.prepend(tree.getExtendsClause());
2090 }
2091 if (tree.getImplementsClause() != null) {
2092 for (JCTree intf : tree.getImplementsClause()) {
2093 supertypes = supertypes.prepend(intf);
2094 }
2095 }
2096 checkClass(tree.pos(), tree.sym, supertypes);
2097 }
2099 void checkClass(DiagnosticPosition pos, Symbol c, List<JCTree> supertypes) {
2100 if ((c.flags_field & ACYCLIC) != 0)
2101 return;
2102 if (seenClasses.contains(c)) {
2103 errorFound = true;
2104 noteCyclic(pos, (ClassSymbol)c);
2105 } else if (!c.type.isErroneous()) {
2106 try {
2107 seenClasses = seenClasses.prepend(c);
2108 if (c.type.hasTag(CLASS)) {
2109 if (supertypes.nonEmpty()) {
2110 scan(supertypes);
2111 }
2112 else {
2113 ClassType ct = (ClassType)c.type;
2114 if (ct.supertype_field == null ||
2115 ct.interfaces_field == null) {
2116 //not completed yet
2117 partialCheck = true;
2118 return;
2119 }
2120 checkSymbol(pos, ct.supertype_field.tsym);
2121 for (Type intf : ct.interfaces_field) {
2122 checkSymbol(pos, intf.tsym);
2123 }
2124 }
2125 if (c.owner.kind == TYP) {
2126 checkSymbol(pos, c.owner);
2127 }
2128 }
2129 } finally {
2130 seenClasses = seenClasses.tail;
2131 }
2132 }
2133 }
2134 }
2136 /** Check for cyclic references. Issue an error if the
2137 * symbol of the type referred to has a LOCKED flag set.
2138 *
2139 * @param pos Position to be used for error reporting.
2140 * @param t The type referred to.
2141 */
2142 void checkNonCyclic(DiagnosticPosition pos, Type t) {
2143 checkNonCyclicInternal(pos, t);
2144 }
2147 void checkNonCyclic(DiagnosticPosition pos, TypeVar t) {
2148 checkNonCyclic1(pos, t, List.<TypeVar>nil());
2149 }
2151 private void checkNonCyclic1(DiagnosticPosition pos, Type t, List<TypeVar> seen) {
2152 final TypeVar tv;
2153 if (t.hasTag(TYPEVAR) && (t.tsym.flags() & UNATTRIBUTED) != 0)
2154 return;
2155 if (seen.contains(t)) {
2156 tv = (TypeVar)t;
2157 tv.bound = types.createErrorType(t);
2158 log.error(pos, "cyclic.inheritance", t);
2159 } else if (t.hasTag(TYPEVAR)) {
2160 tv = (TypeVar)t;
2161 seen = seen.prepend(tv);
2162 for (Type b : types.getBounds(tv))
2163 checkNonCyclic1(pos, b, seen);
2164 }
2165 }
2167 /** Check for cyclic references. Issue an error if the
2168 * symbol of the type referred to has a LOCKED flag set.
2169 *
2170 * @param pos Position to be used for error reporting.
2171 * @param t The type referred to.
2172 * @returns True if the check completed on all attributed classes
2173 */
2174 private boolean checkNonCyclicInternal(DiagnosticPosition pos, Type t) {
2175 boolean complete = true; // was the check complete?
2176 //- System.err.println("checkNonCyclicInternal("+t+");");//DEBUG
2177 Symbol c = t.tsym;
2178 if ((c.flags_field & ACYCLIC) != 0) return true;
2180 if ((c.flags_field & LOCKED) != 0) {
2181 noteCyclic(pos, (ClassSymbol)c);
2182 } else if (!c.type.isErroneous()) {
2183 try {
2184 c.flags_field |= LOCKED;
2185 if (c.type.hasTag(CLASS)) {
2186 ClassType clazz = (ClassType)c.type;
2187 if (clazz.interfaces_field != null)
2188 for (List<Type> l=clazz.interfaces_field; l.nonEmpty(); l=l.tail)
2189 complete &= checkNonCyclicInternal(pos, l.head);
2190 if (clazz.supertype_field != null) {
2191 Type st = clazz.supertype_field;
2192 if (st != null && st.hasTag(CLASS))
2193 complete &= checkNonCyclicInternal(pos, st);
2194 }
2195 if (c.owner.kind == TYP)
2196 complete &= checkNonCyclicInternal(pos, c.owner.type);
2197 }
2198 } finally {
2199 c.flags_field &= ~LOCKED;
2200 }
2201 }
2202 if (complete)
2203 complete = ((c.flags_field & UNATTRIBUTED) == 0) && c.completer == null;
2204 if (complete) c.flags_field |= ACYCLIC;
2205 return complete;
2206 }
2208 /** Note that we found an inheritance cycle. */
2209 private void noteCyclic(DiagnosticPosition pos, ClassSymbol c) {
2210 log.error(pos, "cyclic.inheritance", c);
2211 for (List<Type> l=types.interfaces(c.type); l.nonEmpty(); l=l.tail)
2212 l.head = types.createErrorType((ClassSymbol)l.head.tsym, Type.noType);
2213 Type st = types.supertype(c.type);
2214 if (st.hasTag(CLASS))
2215 ((ClassType)c.type).supertype_field = types.createErrorType((ClassSymbol)st.tsym, Type.noType);
2216 c.type = types.createErrorType(c, c.type);
2217 c.flags_field |= ACYCLIC;
2218 }
2220 /**
2221 * Check that functional interface methods would make sense when seen
2222 * from the perspective of the implementing class
2223 */
2224 void checkFunctionalInterface(JCTree tree, Type funcInterface) {
2225 ClassType c = new ClassType(Type.noType, List.<Type>nil(), null);
2226 ClassSymbol csym = new ClassSymbol(0, names.empty, c, syms.noSymbol);
2227 c.interfaces_field = List.of(funcInterface);
2228 c.supertype_field = syms.objectType;
2229 c.tsym = csym;
2230 csym.members_field = new Scope(csym);
2231 csym.completer = null;
2232 checkImplementations(tree, csym, csym);
2233 }
2235 /** Check that all methods which implement some
2236 * method conform to the method they implement.
2237 * @param tree The class definition whose members are checked.
2238 */
2239 void checkImplementations(JCClassDecl tree) {
2240 checkImplementations(tree, tree.sym, tree.sym);
2241 }
2242 //where
2243 /** Check that all methods which implement some
2244 * method in `ic' conform to the method they implement.
2245 */
2246 void checkImplementations(JCTree tree, ClassSymbol origin, ClassSymbol ic) {
2247 for (List<Type> l = types.closure(ic.type); l.nonEmpty(); l = l.tail) {
2248 ClassSymbol lc = (ClassSymbol)l.head.tsym;
2249 if ((allowGenerics || origin != lc) && (lc.flags() & ABSTRACT) != 0) {
2250 for (Scope.Entry e=lc.members().elems; e != null; e=e.sibling) {
2251 if (e.sym.kind == MTH &&
2252 (e.sym.flags() & (STATIC|ABSTRACT)) == ABSTRACT) {
2253 MethodSymbol absmeth = (MethodSymbol)e.sym;
2254 MethodSymbol implmeth = absmeth.implementation(origin, types, false);
2255 if (implmeth != null && implmeth != absmeth &&
2256 (implmeth.owner.flags() & INTERFACE) ==
2257 (origin.flags() & INTERFACE)) {
2258 // don't check if implmeth is in a class, yet
2259 // origin is an interface. This case arises only
2260 // if implmeth is declared in Object. The reason is
2261 // that interfaces really don't inherit from
2262 // Object it's just that the compiler represents
2263 // things that way.
2264 checkOverride(tree, implmeth, absmeth, origin);
2265 }
2266 }
2267 }
2268 }
2269 }
2270 }
2272 /** Check that all abstract methods implemented by a class are
2273 * mutually compatible.
2274 * @param pos Position to be used for error reporting.
2275 * @param c The class whose interfaces are checked.
2276 */
2277 void checkCompatibleSupertypes(DiagnosticPosition pos, Type c) {
2278 List<Type> supertypes = types.interfaces(c);
2279 Type supertype = types.supertype(c);
2280 if (supertype.hasTag(CLASS) &&
2281 (supertype.tsym.flags() & ABSTRACT) != 0)
2282 supertypes = supertypes.prepend(supertype);
2283 for (List<Type> l = supertypes; l.nonEmpty(); l = l.tail) {
2284 if (allowGenerics && !l.head.getTypeArguments().isEmpty() &&
2285 !checkCompatibleAbstracts(pos, l.head, l.head, c))
2286 return;
2287 for (List<Type> m = supertypes; m != l; m = m.tail)
2288 if (!checkCompatibleAbstracts(pos, l.head, m.head, c))
2289 return;
2290 }
2291 checkCompatibleConcretes(pos, c);
2292 }
2294 void checkConflicts(DiagnosticPosition pos, Symbol sym, TypeSymbol c) {
2295 for (Type ct = c.type; ct != Type.noType ; ct = types.supertype(ct)) {
2296 for (Scope.Entry e = ct.tsym.members().lookup(sym.name); e.scope == ct.tsym.members(); e = e.next()) {
2297 // VM allows methods and variables with differing types
2298 if (sym.kind == e.sym.kind &&
2299 types.isSameType(types.erasure(sym.type), types.erasure(e.sym.type)) &&
2300 sym != e.sym &&
2301 (sym.flags() & Flags.SYNTHETIC) != (e.sym.flags() & Flags.SYNTHETIC) &&
2302 (sym.flags() & IPROXY) == 0 && (e.sym.flags() & IPROXY) == 0 &&
2303 (sym.flags() & BRIDGE) == 0 && (e.sym.flags() & BRIDGE) == 0) {
2304 syntheticError(pos, (e.sym.flags() & SYNTHETIC) == 0 ? e.sym : sym);
2305 return;
2306 }
2307 }
2308 }
2309 }
2311 /** Check that all non-override equivalent methods accessible from 'site'
2312 * are mutually compatible (JLS 8.4.8/9.4.1).
2313 *
2314 * @param pos Position to be used for error reporting.
2315 * @param site The class whose methods are checked.
2316 * @param sym The method symbol to be checked.
2317 */
2318 void checkOverrideClashes(DiagnosticPosition pos, Type site, MethodSymbol sym) {
2319 ClashFilter cf = new ClashFilter(site);
2320 //for each method m1 that is overridden (directly or indirectly)
2321 //by method 'sym' in 'site'...
2322 for (Symbol m1 : types.membersClosure(site, false).getElementsByName(sym.name, cf)) {
2323 if (!sym.overrides(m1, site.tsym, types, false)) continue;
2324 //...check each method m2 that is a member of 'site'
2325 for (Symbol m2 : types.membersClosure(site, false).getElementsByName(sym.name, cf)) {
2326 if (m2 == m1) continue;
2327 //if (i) the signature of 'sym' is not a subsignature of m1 (seen as
2328 //a member of 'site') and (ii) m1 has the same erasure as m2, issue an error
2329 if (!types.isSubSignature(sym.type, types.memberType(site, m2), allowStrictMethodClashCheck) &&
2330 types.hasSameArgs(m2.erasure(types), m1.erasure(types))) {
2331 sym.flags_field |= CLASH;
2332 String key = m1 == sym ?
2333 "name.clash.same.erasure.no.override" :
2334 "name.clash.same.erasure.no.override.1";
2335 log.error(pos,
2336 key,
2337 sym, sym.location(),
2338 m2, m2.location(),
2339 m1, m1.location());
2340 return;
2341 }
2342 }
2343 }
2344 }
2348 /** Check that all static methods accessible from 'site' are
2349 * mutually compatible (JLS 8.4.8).
2350 *
2351 * @param pos Position to be used for error reporting.
2352 * @param site The class whose methods are checked.
2353 * @param sym The method symbol to be checked.
2354 */
2355 void checkHideClashes(DiagnosticPosition pos, Type site, MethodSymbol sym) {
2356 ClashFilter cf = new ClashFilter(site);
2357 //for each method m1 that is a member of 'site'...
2358 for (Symbol s : types.membersClosure(site, true).getElementsByName(sym.name, cf)) {
2359 //if (i) the signature of 'sym' is not a subsignature of m1 (seen as
2360 //a member of 'site') and (ii) 'sym' has the same erasure as m1, issue an error
2361 if (!types.isSubSignature(sym.type, types.memberType(site, s), allowStrictMethodClashCheck) &&
2362 types.hasSameArgs(s.erasure(types), sym.erasure(types))) {
2363 log.error(pos,
2364 "name.clash.same.erasure.no.hide",
2365 sym, sym.location(),
2366 s, s.location());
2367 return;
2368 }
2369 }
2370 }
2372 //where
2373 private class ClashFilter implements Filter<Symbol> {
2375 Type site;
2377 ClashFilter(Type site) {
2378 this.site = site;
2379 }
2381 boolean shouldSkip(Symbol s) {
2382 return (s.flags() & CLASH) != 0 &&
2383 s.owner == site.tsym;
2384 }
2386 public boolean accepts(Symbol s) {
2387 return s.kind == MTH &&
2388 (s.flags() & SYNTHETIC) == 0 &&
2389 !shouldSkip(s) &&
2390 s.isInheritedIn(site.tsym, types) &&
2391 !s.isConstructor();
2392 }
2393 }
2395 void checkDefaultMethodClashes(DiagnosticPosition pos, Type site) {
2396 DefaultMethodClashFilter dcf = new DefaultMethodClashFilter(site);
2397 for (Symbol m : types.membersClosure(site, false).getElements(dcf)) {
2398 Assert.check(m.kind == MTH);
2399 List<MethodSymbol> prov = types.interfaceCandidates(site, (MethodSymbol)m);
2400 if (prov.size() > 1) {
2401 ListBuffer<Symbol> abstracts = ListBuffer.lb();
2402 ListBuffer<Symbol> defaults = ListBuffer.lb();
2403 for (MethodSymbol provSym : prov) {
2404 if ((provSym.flags() & DEFAULT) != 0) {
2405 defaults = defaults.append(provSym);
2406 } else if ((provSym.flags() & ABSTRACT) != 0) {
2407 abstracts = abstracts.append(provSym);
2408 }
2409 if (defaults.nonEmpty() && defaults.size() + abstracts.size() >= 2) {
2410 //strong semantics - issue an error if two sibling interfaces
2411 //have two override-equivalent defaults - or if one is abstract
2412 //and the other is default
2413 String errKey;
2414 Symbol s1 = defaults.first();
2415 Symbol s2;
2416 if (defaults.size() > 1) {
2417 errKey = "types.incompatible.unrelated.defaults";
2418 s2 = defaults.toList().tail.head;
2419 } else {
2420 errKey = "types.incompatible.abstract.default";
2421 s2 = abstracts.first();
2422 }
2423 log.error(pos, errKey,
2424 Kinds.kindName(site.tsym), site,
2425 m.name, types.memberType(site, m).getParameterTypes(),
2426 s1.location(), s2.location());
2427 break;
2428 }
2429 }
2430 }
2431 }
2432 }
2434 //where
2435 private class DefaultMethodClashFilter implements Filter<Symbol> {
2437 Type site;
2439 DefaultMethodClashFilter(Type site) {
2440 this.site = site;
2441 }
2443 public boolean accepts(Symbol s) {
2444 return s.kind == MTH &&
2445 (s.flags() & DEFAULT) != 0 &&
2446 s.isInheritedIn(site.tsym, types) &&
2447 !s.isConstructor();
2448 }
2449 }
2451 /** Report a conflict between a user symbol and a synthetic symbol.
2452 */
2453 private void syntheticError(DiagnosticPosition pos, Symbol sym) {
2454 if (!sym.type.isErroneous()) {
2455 if (warnOnSyntheticConflicts) {
2456 log.warning(pos, "synthetic.name.conflict", sym, sym.location());
2457 }
2458 else {
2459 log.error(pos, "synthetic.name.conflict", sym, sym.location());
2460 }
2461 }
2462 }
2464 /** Check that class c does not implement directly or indirectly
2465 * the same parameterized interface with two different argument lists.
2466 * @param pos Position to be used for error reporting.
2467 * @param type The type whose interfaces are checked.
2468 */
2469 void checkClassBounds(DiagnosticPosition pos, Type type) {
2470 checkClassBounds(pos, new HashMap<TypeSymbol,Type>(), type);
2471 }
2472 //where
2473 /** Enter all interfaces of type `type' into the hash table `seensofar'
2474 * with their class symbol as key and their type as value. Make
2475 * sure no class is entered with two different types.
2476 */
2477 void checkClassBounds(DiagnosticPosition pos,
2478 Map<TypeSymbol,Type> seensofar,
2479 Type type) {
2480 if (type.isErroneous()) return;
2481 for (List<Type> l = types.interfaces(type); l.nonEmpty(); l = l.tail) {
2482 Type it = l.head;
2483 Type oldit = seensofar.put(it.tsym, it);
2484 if (oldit != null) {
2485 List<Type> oldparams = oldit.allparams();
2486 List<Type> newparams = it.allparams();
2487 if (!types.containsTypeEquivalent(oldparams, newparams))
2488 log.error(pos, "cant.inherit.diff.arg",
2489 it.tsym, Type.toString(oldparams),
2490 Type.toString(newparams));
2491 }
2492 checkClassBounds(pos, seensofar, it);
2493 }
2494 Type st = types.supertype(type);
2495 if (st != null) checkClassBounds(pos, seensofar, st);
2496 }
2498 /** Enter interface into into set.
2499 * If it existed already, issue a "repeated interface" error.
2500 */
2501 void checkNotRepeated(DiagnosticPosition pos, Type it, Set<Type> its) {
2502 if (its.contains(it))
2503 log.error(pos, "repeated.interface");
2504 else {
2505 its.add(it);
2506 }
2507 }
2509 /* *************************************************************************
2510 * Check annotations
2511 **************************************************************************/
2513 /**
2514 * Recursively validate annotations values
2515 */
2516 void validateAnnotationTree(JCTree tree) {
2517 class AnnotationValidator extends TreeScanner {
2518 @Override
2519 public void visitAnnotation(JCAnnotation tree) {
2520 if (!tree.type.isErroneous()) {
2521 super.visitAnnotation(tree);
2522 validateAnnotation(tree);
2523 }
2524 }
2525 }
2526 tree.accept(new AnnotationValidator());
2527 }
2529 /**
2530 * {@literal
2531 * Annotation types are restricted to primitives, String, an
2532 * enum, an annotation, Class, Class<?>, Class<? extends
2533 * Anything>, arrays of the preceding.
2534 * }
2535 */
2536 void validateAnnotationType(JCTree restype) {
2537 // restype may be null if an error occurred, so don't bother validating it
2538 if (restype != null) {
2539 validateAnnotationType(restype.pos(), restype.type);
2540 }
2541 }
2543 void validateAnnotationType(DiagnosticPosition pos, Type type) {
2544 if (type.isPrimitive()) return;
2545 if (types.isSameType(type, syms.stringType)) return;
2546 if ((type.tsym.flags() & Flags.ENUM) != 0) return;
2547 if ((type.tsym.flags() & Flags.ANNOTATION) != 0) return;
2548 if (types.lowerBound(type).tsym == syms.classType.tsym) return;
2549 if (types.isArray(type) && !types.isArray(types.elemtype(type))) {
2550 validateAnnotationType(pos, types.elemtype(type));
2551 return;
2552 }
2553 log.error(pos, "invalid.annotation.member.type");
2554 }
2556 /**
2557 * "It is also a compile-time error if any method declared in an
2558 * annotation type has a signature that is override-equivalent to
2559 * that of any public or protected method declared in class Object
2560 * or in the interface annotation.Annotation."
2561 *
2562 * @jls 9.6 Annotation Types
2563 */
2564 void validateAnnotationMethod(DiagnosticPosition pos, MethodSymbol m) {
2565 for (Type sup = syms.annotationType; sup.hasTag(CLASS); sup = types.supertype(sup)) {
2566 Scope s = sup.tsym.members();
2567 for (Scope.Entry e = s.lookup(m.name); e.scope != null; e = e.next()) {
2568 if (e.sym.kind == MTH &&
2569 (e.sym.flags() & (PUBLIC | PROTECTED)) != 0 &&
2570 types.overrideEquivalent(m.type, e.sym.type))
2571 log.error(pos, "intf.annotation.member.clash", e.sym, sup);
2572 }
2573 }
2574 }
2576 /** Check the annotations of a symbol.
2577 */
2578 public void validateAnnotations(List<JCAnnotation> annotations, Symbol s) {
2579 for (JCAnnotation a : annotations)
2580 validateAnnotation(a, s);
2581 }
2583 /** Check an annotation of a symbol.
2584 */
2585 private void validateAnnotation(JCAnnotation a, Symbol s) {
2586 validateAnnotationTree(a);
2588 if (!annotationApplicable(a, s))
2589 log.error(a.pos(), "annotation.type.not.applicable");
2591 if (a.annotationType.type.tsym == syms.overrideType.tsym) {
2592 if (!isOverrider(s))
2593 log.error(a.pos(), "method.does.not.override.superclass");
2594 }
2595 }
2597 /**
2598 * Validate the proposed container 'containedBy' on the
2599 * annotation type symbol 's'. Report errors at position
2600 * 'pos'.
2601 *
2602 * @param s The (annotation)type declaration annotated with a @ContainedBy
2603 * @param containedBy the @ContainedBy on 's'
2604 * @param pos where to report errors
2605 */
2606 public void validateContainedBy(TypeSymbol s, Attribute.Compound containedBy, DiagnosticPosition pos) {
2607 Assert.check(types.isSameType(containedBy.type, syms.containedByType));
2609 Type t = null;
2610 List<Pair<MethodSymbol,Attribute>> l = containedBy.values;
2611 if (!l.isEmpty()) {
2612 Assert.check(l.head.fst.name == names.value);
2613 t = ((Attribute.Class)l.head.snd).getValue();
2614 }
2616 if (t == null) {
2617 log.error(pos, "invalid.container.wrong.containedby", s, containedBy);
2618 return;
2619 }
2621 validateHasContainerFor(t.tsym, s, pos);
2622 validateRetention(t.tsym, s, pos);
2623 validateDocumented(t.tsym, s, pos);
2624 validateInherited(t.tsym, s, pos);
2625 validateTarget(t.tsym, s, pos);
2626 validateDefault(t.tsym, s, pos);
2627 }
2629 /**
2630 * Validate the proposed container 'containerFor' on the
2631 * annotation type symbol 's'. Report errors at position
2632 * 'pos'.
2633 *
2634 * @param s The (annotation)type declaration annotated with a @ContainerFor
2635 * @param containerFor the @ContainedFor on 's'
2636 * @param pos where to report errors
2637 */
2638 public void validateContainerFor(TypeSymbol s, Attribute.Compound containerFor, DiagnosticPosition pos) {
2639 Assert.check(types.isSameType(containerFor.type, syms.containerForType));
2641 Type t = null;
2642 List<Pair<MethodSymbol,Attribute>> l = containerFor.values;
2643 if (!l.isEmpty()) {
2644 Assert.check(l.head.fst.name == names.value);
2645 t = ((Attribute.Class)l.head.snd).getValue();
2646 }
2648 if (t == null) {
2649 log.error(pos, "invalid.container.wrong.containerfor", s, containerFor);
2650 return;
2651 }
2653 validateHasContainedBy(t.tsym, s, pos);
2654 }
2656 private void validateHasContainedBy(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) {
2657 Attribute.Compound containedBy = container.attribute(syms.containedByType.tsym);
2659 if (containedBy == null) {
2660 log.error(pos, "invalid.container.no.containedby", container, syms.containedByType.tsym);
2661 return;
2662 }
2664 Type t = null;
2665 List<Pair<MethodSymbol,Attribute>> l = containedBy.values;
2666 if (!l.isEmpty()) {
2667 Assert.check(l.head.fst.name == names.value);
2668 t = ((Attribute.Class)l.head.snd).getValue();
2669 }
2671 if (t == null) {
2672 log.error(pos, "invalid.container.wrong.containedby", container, contained);
2673 return;
2674 }
2676 if (!types.isSameType(t, contained.type))
2677 log.error(pos, "invalid.container.wrong.containedby", t.tsym, contained);
2678 }
2680 private void validateHasContainerFor(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) {
2681 Attribute.Compound containerFor = container.attribute(syms.containerForType.tsym);
2683 if (containerFor == null) {
2684 log.error(pos, "invalid.container.no.containerfor", container, syms.containerForType.tsym);
2685 return;
2686 }
2688 Type t = null;
2689 List<Pair<MethodSymbol,Attribute>> l = containerFor.values;
2690 if (!l.isEmpty()) {
2691 Assert.check(l.head.fst.name == names.value);
2692 t = ((Attribute.Class)l.head.snd).getValue();
2693 }
2695 if (t == null) {
2696 log.error(pos, "invalid.container.wrong.containerfor", container, contained);
2697 return;
2698 }
2700 if (!types.isSameType(t, contained.type))
2701 log.error(pos, "invalid.container.wrong.containerfor", t.tsym, contained);
2702 }
2704 private void validateRetention(Symbol container, Symbol contained, DiagnosticPosition pos) {
2705 Attribute.RetentionPolicy containerRetention = types.getRetention(container);
2706 Attribute.RetentionPolicy containedRetention = types.getRetention(contained);
2708 boolean error = false;
2709 switch (containedRetention) {
2710 case RUNTIME:
2711 if (containerRetention != Attribute.RetentionPolicy.RUNTIME) {
2712 error = true;
2713 }
2714 break;
2715 case CLASS:
2716 if (containerRetention == Attribute.RetentionPolicy.SOURCE) {
2717 error = true;
2718 }
2719 }
2720 if (error ) {
2721 log.error(pos, "invalid.containedby.annotation.retention",
2722 container, containerRetention,
2723 contained, containedRetention);
2724 }
2725 }
2727 private void validateDocumented(Symbol container, Symbol contained, DiagnosticPosition pos) {
2728 if (contained.attribute(syms.documentedType.tsym) != null) {
2729 if (container.attribute(syms.documentedType.tsym) == null) {
2730 log.error(pos, "invalid.containedby.annotation.not.documented", container, contained);
2731 }
2732 }
2733 }
2735 private void validateInherited(Symbol container, Symbol contained, DiagnosticPosition pos) {
2736 if (contained.attribute(syms.inheritedType.tsym) != null) {
2737 if (container.attribute(syms.inheritedType.tsym) == null) {
2738 log.error(pos, "invalid.containedby.annotation.not.inherited", container, contained);
2739 }
2740 }
2741 }
2743 private void validateTarget(Symbol container, Symbol contained, DiagnosticPosition pos) {
2744 Attribute.Array containedTarget = getAttributeTargetAttribute(contained);
2746 // If contained has no Target, we are done
2747 if (containedTarget == null) {
2748 return;
2749 }
2751 // If contained has Target m1, container must have a Target
2752 // annotation, m2, and m2 must be a subset of m1. (This is
2753 // trivially true if contained has no target as per above).
2755 // contained has target, but container has not, error
2756 Attribute.Array containerTarget = getAttributeTargetAttribute(container);
2757 if (containerTarget == null) {
2758 log.error(pos, "invalid.containedby.annotation.incompatible.target", container, contained);
2759 return;
2760 }
2762 Set<Name> containerTargets = new HashSet<Name>();
2763 for (Attribute app : containerTarget.values) {
2764 if (!(app instanceof Attribute.Enum)) {
2765 continue; // recovery
2766 }
2767 Attribute.Enum e = (Attribute.Enum)app;
2768 containerTargets.add(e.value.name);
2769 }
2771 Set<Name> containedTargets = new HashSet<Name>();
2772 for (Attribute app : containedTarget.values) {
2773 if (!(app instanceof Attribute.Enum)) {
2774 continue; // recovery
2775 }
2776 Attribute.Enum e = (Attribute.Enum)app;
2777 containedTargets.add(e.value.name);
2778 }
2780 if (!isTargetSubset(containedTargets, containerTargets)) {
2781 log.error(pos, "invalid.containedby.annotation.incompatible.target", container, contained);
2782 }
2783 }
2785 /** Checks that t is a subset of s, with respect to ElementType
2786 * semantics, specifically {ANNOTATION_TYPE} is a subset of {TYPE}
2787 */
2788 private boolean isTargetSubset(Set<Name> s, Set<Name> t) {
2789 // Check that all elements in t are present in s
2790 for (Name n2 : t) {
2791 boolean currentElementOk = false;
2792 for (Name n1 : s) {
2793 if (n1 == n2) {
2794 currentElementOk = true;
2795 break;
2796 } else if (n1 == names.TYPE && n2 == names.ANNOTATION_TYPE) {
2797 currentElementOk = true;
2798 break;
2799 }
2800 }
2801 if (!currentElementOk)
2802 return false;
2803 }
2804 return true;
2805 }
2807 private void validateDefault(Symbol container, Symbol contained, DiagnosticPosition pos) {
2808 // validate that all other elements of containing type has defaults
2809 Scope scope = container.members();
2810 for(Symbol elm : scope.getElements()) {
2811 if (elm.name != names.value &&
2812 elm.kind == Kinds.MTH &&
2813 ((MethodSymbol)elm).defaultValue == null) {
2814 log.error(pos,
2815 "invalid.containedby.annotation.elem.nondefault",
2816 container,
2817 elm);
2818 }
2819 }
2820 }
2822 /** Is s a method symbol that overrides a method in a superclass? */
2823 boolean isOverrider(Symbol s) {
2824 if (s.kind != MTH || s.isStatic())
2825 return false;
2826 MethodSymbol m = (MethodSymbol)s;
2827 TypeSymbol owner = (TypeSymbol)m.owner;
2828 for (Type sup : types.closure(owner.type)) {
2829 if (sup == owner.type)
2830 continue; // skip "this"
2831 Scope scope = sup.tsym.members();
2832 for (Scope.Entry e = scope.lookup(m.name); e.scope != null; e = e.next()) {
2833 if (!e.sym.isStatic() && m.overrides(e.sym, owner, types, true))
2834 return true;
2835 }
2836 }
2837 return false;
2838 }
2840 /** Is the annotation applicable to the symbol? */
2841 boolean annotationApplicable(JCAnnotation a, Symbol s) {
2842 Attribute.Array arr = getAttributeTargetAttribute(a.annotationType.type.tsym);
2843 if (arr == null) {
2844 return true;
2845 }
2846 for (Attribute app : arr.values) {
2847 if (!(app instanceof Attribute.Enum)) return true; // recovery
2848 Attribute.Enum e = (Attribute.Enum) app;
2849 if (e.value.name == names.TYPE)
2850 { if (s.kind == TYP) return true; }
2851 else if (e.value.name == names.FIELD)
2852 { if (s.kind == VAR && s.owner.kind != MTH) return true; }
2853 else if (e.value.name == names.METHOD)
2854 { if (s.kind == MTH && !s.isConstructor()) return true; }
2855 else if (e.value.name == names.PARAMETER)
2856 { if (s.kind == VAR &&
2857 s.owner.kind == MTH &&
2858 (s.flags() & PARAMETER) != 0)
2859 return true;
2860 }
2861 else if (e.value.name == names.CONSTRUCTOR)
2862 { if (s.kind == MTH && s.isConstructor()) return true; }
2863 else if (e.value.name == names.LOCAL_VARIABLE)
2864 { if (s.kind == VAR && s.owner.kind == MTH &&
2865 (s.flags() & PARAMETER) == 0)
2866 return true;
2867 }
2868 else if (e.value.name == names.ANNOTATION_TYPE)
2869 { if (s.kind == TYP && (s.flags() & ANNOTATION) != 0)
2870 return true;
2871 }
2872 else if (e.value.name == names.PACKAGE)
2873 { if (s.kind == PCK) return true; }
2874 else if (e.value.name == names.TYPE_USE)
2875 { if (s.kind == TYP ||
2876 s.kind == VAR ||
2877 (s.kind == MTH && !s.isConstructor() &&
2878 !s.type.getReturnType().hasTag(VOID)))
2879 return true;
2880 }
2881 else
2882 return true; // recovery
2883 }
2884 return false;
2885 }
2888 Attribute.Array getAttributeTargetAttribute(Symbol s) {
2889 Attribute.Compound atTarget =
2890 s.attribute(syms.annotationTargetType.tsym);
2891 if (atTarget == null) return null; // ok, is applicable
2892 Attribute atValue = atTarget.member(names.value);
2893 if (!(atValue instanceof Attribute.Array)) return null; // error recovery
2894 return (Attribute.Array) atValue;
2895 }
2897 /** Check an annotation value.
2898 *
2899 * @param a The annotation tree to check
2900 * @return true if this annotation tree is valid, otherwise false
2901 */
2902 public boolean validateAnnotationDeferErrors(JCAnnotation a) {
2903 boolean res = false;
2904 final Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log);
2905 try {
2906 res = validateAnnotation(a);
2907 } finally {
2908 log.popDiagnosticHandler(diagHandler);
2909 }
2910 return res;
2911 }
2913 private boolean validateAnnotation(JCAnnotation a) {
2914 boolean isValid = true;
2915 // collect an inventory of the annotation elements
2916 Set<MethodSymbol> members = new LinkedHashSet<MethodSymbol>();
2917 for (Scope.Entry e = a.annotationType.type.tsym.members().elems;
2918 e != null;
2919 e = e.sibling)
2920 if (e.sym.kind == MTH)
2921 members.add((MethodSymbol) e.sym);
2923 // remove the ones that are assigned values
2924 for (JCTree arg : a.args) {
2925 if (!arg.hasTag(ASSIGN)) continue; // recovery
2926 JCAssign assign = (JCAssign) arg;
2927 Symbol m = TreeInfo.symbol(assign.lhs);
2928 if (m == null || m.type.isErroneous()) continue;
2929 if (!members.remove(m)) {
2930 isValid = false;
2931 log.error(assign.lhs.pos(), "duplicate.annotation.member.value",
2932 m.name, a.type);
2933 }
2934 }
2936 // all the remaining ones better have default values
2937 List<Name> missingDefaults = List.nil();
2938 for (MethodSymbol m : members) {
2939 if (m.defaultValue == null && !m.type.isErroneous()) {
2940 missingDefaults = missingDefaults.append(m.name);
2941 }
2942 }
2943 missingDefaults = missingDefaults.reverse();
2944 if (missingDefaults.nonEmpty()) {
2945 isValid = false;
2946 String key = (missingDefaults.size() > 1)
2947 ? "annotation.missing.default.value.1"
2948 : "annotation.missing.default.value";
2949 log.error(a.pos(), key, a.type, missingDefaults);
2950 }
2952 // special case: java.lang.annotation.Target must not have
2953 // repeated values in its value member
2954 if (a.annotationType.type.tsym != syms.annotationTargetType.tsym ||
2955 a.args.tail == null)
2956 return isValid;
2958 if (!a.args.head.hasTag(ASSIGN)) return false; // error recovery
2959 JCAssign assign = (JCAssign) a.args.head;
2960 Symbol m = TreeInfo.symbol(assign.lhs);
2961 if (m.name != names.value) return false;
2962 JCTree rhs = assign.rhs;
2963 if (!rhs.hasTag(NEWARRAY)) return false;
2964 JCNewArray na = (JCNewArray) rhs;
2965 Set<Symbol> targets = new HashSet<Symbol>();
2966 for (JCTree elem : na.elems) {
2967 if (!targets.add(TreeInfo.symbol(elem))) {
2968 isValid = false;
2969 log.error(elem.pos(), "repeated.annotation.target");
2970 }
2971 }
2972 return isValid;
2973 }
2975 void checkDeprecatedAnnotation(DiagnosticPosition pos, Symbol s) {
2976 if (allowAnnotations &&
2977 lint.isEnabled(LintCategory.DEP_ANN) &&
2978 (s.flags() & DEPRECATED) != 0 &&
2979 !syms.deprecatedType.isErroneous() &&
2980 s.attribute(syms.deprecatedType.tsym) == null) {
2981 log.warning(LintCategory.DEP_ANN,
2982 pos, "missing.deprecated.annotation");
2983 }
2984 }
2986 void checkDeprecated(final DiagnosticPosition pos, final Symbol other, final Symbol s) {
2987 if ((s.flags() & DEPRECATED) != 0 &&
2988 (other.flags() & DEPRECATED) == 0 &&
2989 s.outermostClass() != other.outermostClass()) {
2990 deferredLintHandler.report(new DeferredLintHandler.LintLogger() {
2991 @Override
2992 public void report() {
2993 warnDeprecated(pos, s);
2994 }
2995 });
2996 }
2997 }
2999 void checkSunAPI(final DiagnosticPosition pos, final Symbol s) {
3000 if ((s.flags() & PROPRIETARY) != 0) {
3001 deferredLintHandler.report(new DeferredLintHandler.LintLogger() {
3002 public void report() {
3003 if (enableSunApiLintControl)
3004 warnSunApi(pos, "sun.proprietary", s);
3005 else
3006 log.mandatoryWarning(pos, "sun.proprietary", s);
3007 }
3008 });
3009 }
3010 }
3012 void checkProfile(final DiagnosticPosition pos, final Symbol s) {
3013 if (profile != Profile.DEFAULT && (s.flags() & NOT_IN_PROFILE) != 0) {
3014 log.error(pos, "not.in.profile", s, profile);
3015 }
3016 }
3018 /* *************************************************************************
3019 * Check for recursive annotation elements.
3020 **************************************************************************/
3022 /** Check for cycles in the graph of annotation elements.
3023 */
3024 void checkNonCyclicElements(JCClassDecl tree) {
3025 if ((tree.sym.flags_field & ANNOTATION) == 0) return;
3026 Assert.check((tree.sym.flags_field & LOCKED) == 0);
3027 try {
3028 tree.sym.flags_field |= LOCKED;
3029 for (JCTree def : tree.defs) {
3030 if (!def.hasTag(METHODDEF)) continue;
3031 JCMethodDecl meth = (JCMethodDecl)def;
3032 checkAnnotationResType(meth.pos(), meth.restype.type);
3033 }
3034 } finally {
3035 tree.sym.flags_field &= ~LOCKED;
3036 tree.sym.flags_field |= ACYCLIC_ANN;
3037 }
3038 }
3040 void checkNonCyclicElementsInternal(DiagnosticPosition pos, TypeSymbol tsym) {
3041 if ((tsym.flags_field & ACYCLIC_ANN) != 0)
3042 return;
3043 if ((tsym.flags_field & LOCKED) != 0) {
3044 log.error(pos, "cyclic.annotation.element");
3045 return;
3046 }
3047 try {
3048 tsym.flags_field |= LOCKED;
3049 for (Scope.Entry e = tsym.members().elems; e != null; e = e.sibling) {
3050 Symbol s = e.sym;
3051 if (s.kind != Kinds.MTH)
3052 continue;
3053 checkAnnotationResType(pos, ((MethodSymbol)s).type.getReturnType());
3054 }
3055 } finally {
3056 tsym.flags_field &= ~LOCKED;
3057 tsym.flags_field |= ACYCLIC_ANN;
3058 }
3059 }
3061 void checkAnnotationResType(DiagnosticPosition pos, Type type) {
3062 switch (type.getTag()) {
3063 case CLASS:
3064 if ((type.tsym.flags() & ANNOTATION) != 0)
3065 checkNonCyclicElementsInternal(pos, type.tsym);
3066 break;
3067 case ARRAY:
3068 checkAnnotationResType(pos, types.elemtype(type));
3069 break;
3070 default:
3071 break; // int etc
3072 }
3073 }
3075 /* *************************************************************************
3076 * Check for cycles in the constructor call graph.
3077 **************************************************************************/
3079 /** Check for cycles in the graph of constructors calling other
3080 * constructors.
3081 */
3082 void checkCyclicConstructors(JCClassDecl tree) {
3083 Map<Symbol,Symbol> callMap = new HashMap<Symbol, Symbol>();
3085 // enter each constructor this-call into the map
3086 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
3087 JCMethodInvocation app = TreeInfo.firstConstructorCall(l.head);
3088 if (app == null) continue;
3089 JCMethodDecl meth = (JCMethodDecl) l.head;
3090 if (TreeInfo.name(app.meth) == names._this) {
3091 callMap.put(meth.sym, TreeInfo.symbol(app.meth));
3092 } else {
3093 meth.sym.flags_field |= ACYCLIC;
3094 }
3095 }
3097 // Check for cycles in the map
3098 Symbol[] ctors = new Symbol[0];
3099 ctors = callMap.keySet().toArray(ctors);
3100 for (Symbol caller : ctors) {
3101 checkCyclicConstructor(tree, caller, callMap);
3102 }
3103 }
3105 /** Look in the map to see if the given constructor is part of a
3106 * call cycle.
3107 */
3108 private void checkCyclicConstructor(JCClassDecl tree, Symbol ctor,
3109 Map<Symbol,Symbol> callMap) {
3110 if (ctor != null && (ctor.flags_field & ACYCLIC) == 0) {
3111 if ((ctor.flags_field & LOCKED) != 0) {
3112 log.error(TreeInfo.diagnosticPositionFor(ctor, tree),
3113 "recursive.ctor.invocation");
3114 } else {
3115 ctor.flags_field |= LOCKED;
3116 checkCyclicConstructor(tree, callMap.remove(ctor), callMap);
3117 ctor.flags_field &= ~LOCKED;
3118 }
3119 ctor.flags_field |= ACYCLIC;
3120 }
3121 }
3123 /* *************************************************************************
3124 * Miscellaneous
3125 **************************************************************************/
3127 /**
3128 * Return the opcode of the operator but emit an error if it is an
3129 * error.
3130 * @param pos position for error reporting.
3131 * @param operator an operator
3132 * @param tag a tree tag
3133 * @param left type of left hand side
3134 * @param right type of right hand side
3135 */
3136 int checkOperator(DiagnosticPosition pos,
3137 OperatorSymbol operator,
3138 JCTree.Tag tag,
3139 Type left,
3140 Type right) {
3141 if (operator.opcode == ByteCodes.error) {
3142 log.error(pos,
3143 "operator.cant.be.applied.1",
3144 treeinfo.operatorName(tag),
3145 left, right);
3146 }
3147 return operator.opcode;
3148 }
3151 /**
3152 * Check for division by integer constant zero
3153 * @param pos Position for error reporting.
3154 * @param operator The operator for the expression
3155 * @param operand The right hand operand for the expression
3156 */
3157 void checkDivZero(DiagnosticPosition pos, Symbol operator, Type operand) {
3158 if (operand.constValue() != null
3159 && lint.isEnabled(LintCategory.DIVZERO)
3160 && (operand.getTag().isSubRangeOf(LONG))
3161 && ((Number) (operand.constValue())).longValue() == 0) {
3162 int opc = ((OperatorSymbol)operator).opcode;
3163 if (opc == ByteCodes.idiv || opc == ByteCodes.imod
3164 || opc == ByteCodes.ldiv || opc == ByteCodes.lmod) {
3165 log.warning(LintCategory.DIVZERO, pos, "div.zero");
3166 }
3167 }
3168 }
3170 /**
3171 * Check for empty statements after if
3172 */
3173 void checkEmptyIf(JCIf tree) {
3174 if (tree.thenpart.hasTag(SKIP) && tree.elsepart == null &&
3175 lint.isEnabled(LintCategory.EMPTY))
3176 log.warning(LintCategory.EMPTY, tree.thenpart.pos(), "empty.if");
3177 }
3179 /** Check that symbol is unique in given scope.
3180 * @param pos Position for error reporting.
3181 * @param sym The symbol.
3182 * @param s The scope.
3183 */
3184 boolean checkUnique(DiagnosticPosition pos, Symbol sym, Scope s) {
3185 if (sym.type.isErroneous())
3186 return true;
3187 if (sym.owner.name == names.any) return false;
3188 for (Scope.Entry e = s.lookup(sym.name); e.scope == s; e = e.next()) {
3189 if (sym != e.sym &&
3190 (e.sym.flags() & CLASH) == 0 &&
3191 sym.kind == e.sym.kind &&
3192 sym.name != names.error &&
3193 (sym.kind != MTH || types.hasSameArgs(types.erasure(sym.type), types.erasure(e.sym.type)))) {
3194 if ((sym.flags() & VARARGS) != (e.sym.flags() & VARARGS)) {
3195 varargsDuplicateError(pos, sym, e.sym);
3196 return true;
3197 } else if (sym.kind == MTH && !types.hasSameArgs(sym.type, e.sym.type, false)) {
3198 duplicateErasureError(pos, sym, e.sym);
3199 sym.flags_field |= CLASH;
3200 return true;
3201 } else {
3202 duplicateError(pos, e.sym);
3203 return false;
3204 }
3205 }
3206 }
3207 return true;
3208 }
3210 /** Report duplicate declaration error.
3211 */
3212 void duplicateErasureError(DiagnosticPosition pos, Symbol sym1, Symbol sym2) {
3213 if (!sym1.type.isErroneous() && !sym2.type.isErroneous()) {
3214 log.error(pos, "name.clash.same.erasure", sym1, sym2);
3215 }
3216 }
3218 /** Check that single-type import is not already imported or top-level defined,
3219 * but make an exception for two single-type imports which denote the same type.
3220 * @param pos Position for error reporting.
3221 * @param sym The symbol.
3222 * @param s The scope
3223 */
3224 boolean checkUniqueImport(DiagnosticPosition pos, Symbol sym, Scope s) {
3225 return checkUniqueImport(pos, sym, s, false);
3226 }
3228 /** Check that static single-type import is not already imported or top-level defined,
3229 * but make an exception for two single-type imports which denote the same type.
3230 * @param pos Position for error reporting.
3231 * @param sym The symbol.
3232 * @param s The scope
3233 */
3234 boolean checkUniqueStaticImport(DiagnosticPosition pos, Symbol sym, Scope s) {
3235 return checkUniqueImport(pos, sym, s, true);
3236 }
3238 /** Check that single-type import is not already imported or top-level defined,
3239 * but make an exception for two single-type imports which denote the same type.
3240 * @param pos Position for error reporting.
3241 * @param sym The symbol.
3242 * @param s The scope.
3243 * @param staticImport Whether or not this was a static import
3244 */
3245 private boolean checkUniqueImport(DiagnosticPosition pos, Symbol sym, Scope s, boolean staticImport) {
3246 for (Scope.Entry e = s.lookup(sym.name); e.scope != null; e = e.next()) {
3247 // is encountered class entered via a class declaration?
3248 boolean isClassDecl = e.scope == s;
3249 if ((isClassDecl || sym != e.sym) &&
3250 sym.kind == e.sym.kind &&
3251 sym.name != names.error) {
3252 if (!e.sym.type.isErroneous()) {
3253 String what = e.sym.toString();
3254 if (!isClassDecl) {
3255 if (staticImport)
3256 log.error(pos, "already.defined.static.single.import", what);
3257 else
3258 log.error(pos, "already.defined.single.import", what);
3259 }
3260 else if (sym != e.sym)
3261 log.error(pos, "already.defined.this.unit", what);
3262 }
3263 return false;
3264 }
3265 }
3266 return true;
3267 }
3269 /** Check that a qualified name is in canonical form (for import decls).
3270 */
3271 public void checkCanonical(JCTree tree) {
3272 if (!isCanonical(tree))
3273 log.error(tree.pos(), "import.requires.canonical",
3274 TreeInfo.symbol(tree));
3275 }
3276 // where
3277 private boolean isCanonical(JCTree tree) {
3278 while (tree.hasTag(SELECT)) {
3279 JCFieldAccess s = (JCFieldAccess) tree;
3280 if (s.sym.owner != TreeInfo.symbol(s.selected))
3281 return false;
3282 tree = s.selected;
3283 }
3284 return true;
3285 }
3287 /** Check that an auxiliary class is not accessed from any other file than its own.
3288 */
3289 void checkForBadAuxiliaryClassAccess(DiagnosticPosition pos, Env<AttrContext> env, ClassSymbol c) {
3290 if (lint.isEnabled(Lint.LintCategory.AUXILIARYCLASS) &&
3291 (c.flags() & AUXILIARY) != 0 &&
3292 rs.isAccessible(env, c) &&
3293 !fileManager.isSameFile(c.sourcefile, env.toplevel.sourcefile))
3294 {
3295 log.warning(pos, "auxiliary.class.accessed.from.outside.of.its.source.file",
3296 c, c.sourcefile);
3297 }
3298 }
3300 private class ConversionWarner extends Warner {
3301 final String uncheckedKey;
3302 final Type found;
3303 final Type expected;
3304 public ConversionWarner(DiagnosticPosition pos, String uncheckedKey, Type found, Type expected) {
3305 super(pos);
3306 this.uncheckedKey = uncheckedKey;
3307 this.found = found;
3308 this.expected = expected;
3309 }
3311 @Override
3312 public void warn(LintCategory lint) {
3313 boolean warned = this.warned;
3314 super.warn(lint);
3315 if (warned) return; // suppress redundant diagnostics
3316 switch (lint) {
3317 case UNCHECKED:
3318 Check.this.warnUnchecked(pos(), "prob.found.req", diags.fragment(uncheckedKey), found, expected);
3319 break;
3320 case VARARGS:
3321 if (method != null &&
3322 method.attribute(syms.trustMeType.tsym) != null &&
3323 isTrustMeAllowedOnMethod(method) &&
3324 !types.isReifiable(method.type.getParameterTypes().last())) {
3325 Check.this.warnUnsafeVararg(pos(), "varargs.unsafe.use.varargs.param", method.params.last());
3326 }
3327 break;
3328 default:
3329 throw new AssertionError("Unexpected lint: " + lint);
3330 }
3331 }
3332 }
3334 public Warner castWarner(DiagnosticPosition pos, Type found, Type expected) {
3335 return new ConversionWarner(pos, "unchecked.cast.to.type", found, expected);
3336 }
3338 public Warner convertWarner(DiagnosticPosition pos, Type found, Type expected) {
3339 return new ConversionWarner(pos, "unchecked.assign", found, expected);
3340 }
3341 }