0001: /*
0002: * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
0003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004: *
0005: * This code is free software; you can redistribute it and/or modify it
0006: * under the terms of the GNU General Public License version 2 only, as
0007: * published by the Free Software Foundation. Sun designates this
0008: * particular file as subject to the "Classpath" exception as provided
0009: * by Sun in the LICENSE file that accompanied this code.
0010: *
0011: * This code is distributed in the hope that it will be useful, but WITHOUT
0012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014: * version 2 for more details (a copy is included in the LICENSE file that
0015: * accompanied this code).
0016: *
0017: * You should have received a copy of the GNU General Public License version
0018: * 2 along with this work; if not, write to the Free Software Foundation,
0019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020: *
0021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022: * CA 95054 USA or visit www.sun.com if you need additional information or
0023: * have any questions.
0024: */
0025:
0026: package com.sun.tools.javac.comp;
0027:
0028: import java.util.*;
0029: import java.util.Set;
0030:
0031: import com.sun.tools.javac.code.*;
0032: import com.sun.tools.javac.jvm.*;
0033: import com.sun.tools.javac.tree.*;
0034: import com.sun.tools.javac.util.*;
0035: import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
0036: import com.sun.tools.javac.util.List;
0037:
0038: import com.sun.tools.javac.tree.JCTree.*;
0039: import com.sun.tools.javac.code.Lint;
0040: import com.sun.tools.javac.code.Lint.LintCategory;
0041: import com.sun.tools.javac.code.Type.*;
0042: import com.sun.tools.javac.code.Symbol.*;
0043:
0044: import static com.sun.tools.javac.code.Flags.*;
0045: import static com.sun.tools.javac.code.Kinds.*;
0046: import static com.sun.tools.javac.code.TypeTags.*;
0047:
0048: /** Type checking helper class for the attribution phase.
0049: *
0050: * <p><b>This is NOT part of any API supported by Sun Microsystems. If
0051: * you write code that depends on this, you do so at your own risk.
0052: * This code and its internal interfaces are subject to change or
0053: * deletion without notice.</b>
0054: */
0055: @Version("@(#)Check.java 1.174 07/06/14")
0056: public class Check {
0057: protected static final Context.Key<Check> checkKey = new Context.Key<Check>();
0058:
0059: private final Name.Table names;
0060: private final Log log;
0061: private final Symtab syms;
0062: private final Infer infer;
0063: private final Target target;
0064: private final Source source;
0065: private final Types types;
0066: private final boolean skipAnnotations;
0067: private final TreeInfo treeinfo;
0068:
0069: // The set of lint options currently in effect. It is initialized
0070: // from the context, and then is set/reset as needed by Attr as it
0071: // visits all the various parts of the trees during attribution.
0072: private Lint lint;
0073:
0074: public static Check instance(Context context) {
0075: Check instance = context.get(checkKey);
0076: if (instance == null)
0077: instance = new Check(context);
0078: return instance;
0079: }
0080:
0081: protected Check(Context context) {
0082: context.put(checkKey, this );
0083:
0084: names = Name.Table.instance(context);
0085: log = Log.instance(context);
0086: syms = Symtab.instance(context);
0087: infer = Infer.instance(context);
0088: this .types = Types.instance(context);
0089: Options options = Options.instance(context);
0090: target = Target.instance(context);
0091: source = Source.instance(context);
0092: lint = Lint.instance(context);
0093: treeinfo = TreeInfo.instance(context);
0094:
0095: Source source = Source.instance(context);
0096: allowGenerics = source.allowGenerics();
0097: allowAnnotations = source.allowAnnotations();
0098: complexInference = options.get("-complexinference") != null;
0099: skipAnnotations = options.get("skipAnnotations") != null;
0100:
0101: boolean verboseDeprecated = lint
0102: .isEnabled(LintCategory.DEPRECATION);
0103: boolean verboseUnchecked = lint
0104: .isEnabled(LintCategory.UNCHECKED);
0105:
0106: deprecationHandler = new MandatoryWarningHandler(log,
0107: verboseDeprecated, "deprecated");
0108: uncheckedHandler = new MandatoryWarningHandler(log,
0109: verboseUnchecked, "unchecked");
0110: }
0111:
0112: /** Switch: generics enabled?
0113: */
0114: boolean allowGenerics;
0115:
0116: /** Switch: annotations enabled?
0117: */
0118: boolean allowAnnotations;
0119:
0120: /** Switch: -complexinference option set?
0121: */
0122: boolean complexInference;
0123:
0124: /** A table mapping flat names of all compiled classes in this run to their
0125: * symbols; maintained from outside.
0126: */
0127: public Map<Name, ClassSymbol> compiled = new HashMap<Name, ClassSymbol>();
0128:
0129: /** A handler for messages about deprecated usage.
0130: */
0131: private MandatoryWarningHandler deprecationHandler;
0132:
0133: /** A handler for messages about unchecked or unsafe usage.
0134: */
0135: private MandatoryWarningHandler uncheckedHandler;
0136:
0137: /* *************************************************************************
0138: * Errors and Warnings
0139: **************************************************************************/
0140:
0141: Lint setLint(Lint newLint) {
0142: Lint prev = lint;
0143: lint = newLint;
0144: return prev;
0145: }
0146:
0147: /** Warn about deprecated symbol.
0148: * @param pos Position to be used for error reporting.
0149: * @param sym The deprecated symbol.
0150: */
0151: void warnDeprecated(DiagnosticPosition pos, Symbol sym) {
0152: if (!lint.isSuppressed(LintCategory.DEPRECATION))
0153: deprecationHandler.report(pos, "has.been.deprecated", sym,
0154: sym.location());
0155: }
0156:
0157: /** Warn about unchecked operation.
0158: * @param pos Position to be used for error reporting.
0159: * @param msg A string describing the problem.
0160: */
0161: public void warnUnchecked(DiagnosticPosition pos, String msg,
0162: Object... args) {
0163: if (!lint.isSuppressed(LintCategory.UNCHECKED))
0164: uncheckedHandler.report(pos, msg, args);
0165: }
0166:
0167: /**
0168: * Report any deferred diagnostics.
0169: */
0170: public void reportDeferredDiagnostics() {
0171: deprecationHandler.reportDeferredDiagnostic();
0172: uncheckedHandler.reportDeferredDiagnostic();
0173: }
0174:
0175: /** Report a failure to complete a class.
0176: * @param pos Position to be used for error reporting.
0177: * @param ex The failure to report.
0178: */
0179: public Type completionError(DiagnosticPosition pos,
0180: CompletionFailure ex) {
0181: log.error(pos, "cant.access", ex.sym, ex.errmsg);
0182: if (ex instanceof ClassReader.BadClassFile)
0183: throw new Abort();
0184: else
0185: return syms.errType;
0186: }
0187:
0188: /** Report a type error.
0189: * @param pos Position to be used for error reporting.
0190: * @param problem A string describing the error.
0191: * @param found The type that was found.
0192: * @param req The type that was required.
0193: */
0194: Type typeError(DiagnosticPosition pos, Object problem, Type found,
0195: Type req) {
0196: log.error(pos, "prob.found.req", problem, found, req);
0197: return syms.errType;
0198: }
0199:
0200: Type typeError(DiagnosticPosition pos, String problem, Type found,
0201: Type req, Object explanation) {
0202: log.error(pos, "prob.found.req.1", problem, found, req,
0203: explanation);
0204: return syms.errType;
0205: }
0206:
0207: /** Report an error that wrong type tag was found.
0208: * @param pos Position to be used for error reporting.
0209: * @param required An internationalized string describing the type tag
0210: * required.
0211: * @param found The type that was found.
0212: */
0213: Type typeTagError(DiagnosticPosition pos, Object required,
0214: Object found) {
0215: log.error(pos, "type.found.req", found, required);
0216: return syms.errType;
0217: }
0218:
0219: /** Report an error that symbol cannot be referenced before super
0220: * has been called.
0221: * @param pos Position to be used for error reporting.
0222: * @param sym The referenced symbol.
0223: */
0224: void earlyRefError(DiagnosticPosition pos, Symbol sym) {
0225: log.error(pos, "cant.ref.before.ctor.called", sym);
0226: }
0227:
0228: /** Report duplicate declaration error.
0229: */
0230: void duplicateError(DiagnosticPosition pos, Symbol sym) {
0231: if (!sym.type.isErroneous()) {
0232: log.error(pos, "already.defined", sym, sym.location());
0233: }
0234: }
0235:
0236: /** Report array/varargs duplicate declaration
0237: */
0238: void varargsDuplicateError(DiagnosticPosition pos, Symbol sym1,
0239: Symbol sym2) {
0240: if (!sym1.type.isErroneous() && !sym2.type.isErroneous()) {
0241: log.error(pos, "array.and.varargs", sym1, sym2, sym2
0242: .location());
0243: }
0244: }
0245:
0246: /* ************************************************************************
0247: * duplicate declaration checking
0248: *************************************************************************/
0249:
0250: /** Check that variable does not hide variable with same name in
0251: * immediately enclosing local scope.
0252: * @param pos Position for error reporting.
0253: * @param v The symbol.
0254: * @param s The scope.
0255: */
0256: void checkTransparentVar(DiagnosticPosition pos, VarSymbol v,
0257: Scope s) {
0258: if (s.next != null) {
0259: for (Scope.Entry e = s.next.lookup(v.name); e.scope != null
0260: && e.sym.owner == v.owner; e = e.next()) {
0261: if (e.sym.kind == VAR
0262: && (e.sym.owner.kind & (VAR | MTH)) != 0
0263: && v.name != names.error) {
0264: duplicateError(pos, e.sym);
0265: return;
0266: }
0267: }
0268: }
0269: }
0270:
0271: /** Check that a class or interface does not hide a class or
0272: * interface with same name in immediately enclosing local scope.
0273: * @param pos Position for error reporting.
0274: * @param c The symbol.
0275: * @param s The scope.
0276: */
0277: void checkTransparentClass(DiagnosticPosition pos, ClassSymbol c,
0278: Scope s) {
0279: if (s.next != null) {
0280: for (Scope.Entry e = s.next.lookup(c.name); e.scope != null
0281: && e.sym.owner == c.owner; e = e.next()) {
0282: if (e.sym.kind == TYP
0283: && (e.sym.owner.kind & (VAR | MTH)) != 0
0284: && c.name != names.error) {
0285: duplicateError(pos, e.sym);
0286: return;
0287: }
0288: }
0289: }
0290: }
0291:
0292: /** Check that class does not have the same name as one of
0293: * its enclosing classes, or as a class defined in its enclosing scope.
0294: * return true if class is unique in its enclosing scope.
0295: * @param pos Position for error reporting.
0296: * @param name The class name.
0297: * @param s The enclosing scope.
0298: */
0299: boolean checkUniqueClassName(DiagnosticPosition pos, Name name,
0300: Scope s) {
0301: for (Scope.Entry e = s.lookup(name); e.scope == s; e = e.next()) {
0302: if (e.sym.kind == TYP && e.sym.name != names.error) {
0303: duplicateError(pos, e.sym);
0304: return false;
0305: }
0306: }
0307: for (Symbol sym = s.owner; sym != null; sym = sym.owner) {
0308: if (sym.kind == TYP && sym.name == name
0309: && sym.name != names.error) {
0310: duplicateError(pos, sym);
0311: return true;
0312: }
0313: }
0314: return true;
0315: }
0316:
0317: /* *************************************************************************
0318: * Class name generation
0319: **************************************************************************/
0320:
0321: /** Return name of local class.
0322: * This is of the form <enclClass> $ n <classname>
0323: * where
0324: * enclClass is the flat name of the enclosing class,
0325: * classname is the simple name of the local class
0326: */
0327: Name localClassName(ClassSymbol c) {
0328: for (int i = 1;; i++) {
0329: Name flatname = names.fromString(""
0330: + c.owner.enclClass().flatname
0331: + target.syntheticNameChar() + i + c.name);
0332: if (compiled.get(flatname) == null)
0333: return flatname;
0334: }
0335: }
0336:
0337: /* *************************************************************************
0338: * Type Checking
0339: **************************************************************************/
0340:
0341: /** Check that a given type is assignable to a given proto-type.
0342: * If it is, return the type, otherwise return errType.
0343: * @param pos Position to be used for error reporting.
0344: * @param found The type that was found.
0345: * @param req The type that was required.
0346: */
0347: Type checkType(DiagnosticPosition pos, Type found, Type req) {
0348: if (req.tag == ERROR)
0349: return req;
0350: if (found.tag == FORALL)
0351: return instantiatePoly(pos, (ForAll) found, req,
0352: convertWarner(pos, found, req));
0353: if (req.tag == NONE)
0354: return found;
0355: if (types.isAssignable(found, req, convertWarner(pos, found,
0356: req)))
0357: return found;
0358: if (found.tag <= DOUBLE && req.tag <= DOUBLE)
0359: return typeError(pos, JCDiagnostic
0360: .fragment("possible.loss.of.precision"), found, req);
0361: if (found.isSuperBound()) {
0362: log.error(pos, "assignment.from.super-bound", found);
0363: return syms.errType;
0364: }
0365: if (req.isExtendsBound()) {
0366: log.error(pos, "assignment.to.extends-bound", req);
0367: return syms.errType;
0368: }
0369: return typeError(pos, JCDiagnostic
0370: .fragment("incompatible.types"), found, req);
0371: }
0372:
0373: /** Instantiate polymorphic type to some prototype, unless
0374: * prototype is `anyPoly' in which case polymorphic type
0375: * is returned unchanged.
0376: */
0377: Type instantiatePoly(DiagnosticPosition pos, ForAll t, Type pt,
0378: Warner warn) {
0379: if (pt == Infer.anyPoly && complexInference) {
0380: return t;
0381: } else if (pt == Infer.anyPoly || pt.tag == NONE) {
0382: Type newpt = t.qtype.tag <= VOID ? t.qtype
0383: : syms.objectType;
0384: return instantiatePoly(pos, t, newpt, warn);
0385: } else if (pt.tag == ERROR) {
0386: return pt;
0387: } else {
0388: try {
0389: return infer.instantiateExpr(t, pt, warn);
0390: } catch (Infer.NoInstanceException ex) {
0391: if (ex.isAmbiguous) {
0392: JCDiagnostic d = ex.getDiagnostic();
0393: log.error(pos, "undetermined.type"
0394: + (d != null ? ".1" : ""), t, d);
0395: return syms.errType;
0396: } else {
0397: JCDiagnostic d = ex.getDiagnostic();
0398: return typeError(pos, JCDiagnostic.fragment(
0399: "incompatible.types"
0400: + (d != null ? ".1" : ""), d), t,
0401: pt);
0402: }
0403: }
0404: }
0405: }
0406:
0407: /** Check that a given type can be cast to a given target type.
0408: * Return the result of the cast.
0409: * @param pos Position to be used for error reporting.
0410: * @param found The type that is being cast.
0411: * @param req The target type of the cast.
0412: */
0413: Type checkCastable(DiagnosticPosition pos, Type found, Type req) {
0414: if (found.tag == FORALL) {
0415: instantiatePoly(pos, (ForAll) found, req, castWarner(pos,
0416: found, req));
0417: return req;
0418: } else if (types.isCastable(found, req, castWarner(pos, found,
0419: req))) {
0420: return req;
0421: } else {
0422: return typeError(pos, JCDiagnostic
0423: .fragment("inconvertible.types"), found, req);
0424: }
0425: }
0426:
0427: //where
0428: /** Is type a type variable, or a (possibly multi-dimensional) array of
0429: * type variables?
0430: */
0431: boolean isTypeVar(Type t) {
0432: return t.tag == TYPEVAR || t.tag == ARRAY
0433: && isTypeVar(types.elemtype(t));
0434: }
0435:
0436: /** Check that a type is within some bounds.
0437: *
0438: * Used in TypeApply to verify that, e.g., X in V<X> is a valid
0439: * type argument.
0440: * @param pos Position to be used for error reporting.
0441: * @param a The type that should be bounded by bs.
0442: * @param bs The bound.
0443: */
0444: private void checkExtends(DiagnosticPosition pos, Type a, TypeVar bs) {
0445: if (a.isUnbound()) {
0446: return;
0447: } else if (a.tag != WILDCARD) {
0448: a = types.upperBound(a);
0449: for (List<Type> l = types.getBounds(bs); l.nonEmpty(); l = l.tail) {
0450: if (!types.isSubtype(a, l.head)) {
0451: log.error(pos, "not.within.bounds", a);
0452: return;
0453: }
0454: }
0455: } else if (a.isExtendsBound()) {
0456: if (!types.isCastable(bs.getUpperBound(), types
0457: .upperBound(a), Warner.noWarnings))
0458: log.error(pos, "not.within.bounds", a);
0459: } else if (a.isSuperBound()) {
0460: if (types.notSoftSubtype(types.lowerBound(a), bs
0461: .getUpperBound()))
0462: log.error(pos, "not.within.bounds", a);
0463: }
0464: }
0465:
0466: /** Check that type is different from 'void'.
0467: * @param pos Position to be used for error reporting.
0468: * @param t The type to be checked.
0469: */
0470: Type checkNonVoid(DiagnosticPosition pos, Type t) {
0471: if (t.tag == VOID) {
0472: log.error(pos, "void.not.allowed.here");
0473: return syms.errType;
0474: } else {
0475: return t;
0476: }
0477: }
0478:
0479: /** Check that type is a class or interface type.
0480: * @param pos Position to be used for error reporting.
0481: * @param t The type to be checked.
0482: */
0483: Type checkClassType(DiagnosticPosition pos, Type t) {
0484: if (t.tag != CLASS && t.tag != ERROR)
0485: return typeTagError(pos, JCDiagnostic
0486: .fragment("type.req.class"),
0487: (t.tag == TYPEVAR) ? JCDiagnostic.fragment(
0488: "type.parameter", t) : t);
0489: else
0490: return t;
0491: }
0492:
0493: /** Check that type is a class or interface type.
0494: * @param pos Position to be used for error reporting.
0495: * @param t The type to be checked.
0496: * @param noBounds True if type bounds are illegal here.
0497: */
0498: Type checkClassType(DiagnosticPosition pos, Type t, boolean noBounds) {
0499: t = checkClassType(pos, t);
0500: if (noBounds && t.isParameterized()) {
0501: List<Type> args = t.getTypeArguments();
0502: while (args.nonEmpty()) {
0503: if (args.head.tag == WILDCARD)
0504: return typeTagError(pos, log
0505: .getLocalizedString("type.req.exact"),
0506: args.head);
0507: args = args.tail;
0508: }
0509: }
0510: return t;
0511: }
0512:
0513: /** Check that type is a reifiable class, interface or array type.
0514: * @param pos Position to be used for error reporting.
0515: * @param t The type to be checked.
0516: */
0517: Type checkReifiableReferenceType(DiagnosticPosition pos, Type t) {
0518: if (t.tag != CLASS && t.tag != ARRAY && t.tag != ERROR) {
0519: return typeTagError(pos, JCDiagnostic
0520: .fragment("type.req.class.array"), t);
0521: } else if (!types.isReifiable(t)) {
0522: log.error(pos, "illegal.generic.type.for.instof");
0523: return syms.errType;
0524: } else {
0525: return t;
0526: }
0527: }
0528:
0529: /** Check that type is a reference type, i.e. a class, interface or array type
0530: * or a type variable.
0531: * @param pos Position to be used for error reporting.
0532: * @param t The type to be checked.
0533: */
0534: Type checkRefType(DiagnosticPosition pos, Type t) {
0535: switch (t.tag) {
0536: case CLASS:
0537: case ARRAY:
0538: case TYPEVAR:
0539: case WILDCARD:
0540: case ERROR:
0541: return t;
0542: default:
0543: return typeTagError(pos, JCDiagnostic
0544: .fragment("type.req.ref"), t);
0545: }
0546: }
0547:
0548: /** Check that type is a null or reference type.
0549: * @param pos Position to be used for error reporting.
0550: * @param t The type to be checked.
0551: */
0552: Type checkNullOrRefType(DiagnosticPosition pos, Type t) {
0553: switch (t.tag) {
0554: case CLASS:
0555: case ARRAY:
0556: case TYPEVAR:
0557: case WILDCARD:
0558: case BOT:
0559: case ERROR:
0560: return t;
0561: default:
0562: return typeTagError(pos, JCDiagnostic
0563: .fragment("type.req.ref"), t);
0564: }
0565: }
0566:
0567: /** Check that flag set does not contain elements of two conflicting sets. s
0568: * Return true if it doesn't.
0569: * @param pos Position to be used for error reporting.
0570: * @param flags The set of flags to be checked.
0571: * @param set1 Conflicting flags set #1.
0572: * @param set2 Conflicting flags set #2.
0573: */
0574: boolean checkDisjoint(DiagnosticPosition pos, long flags,
0575: long set1, long set2) {
0576: if ((flags & set1) != 0 && (flags & set2) != 0) {
0577: log
0578: .error(pos, "illegal.combination.of.modifiers",
0579: TreeInfo.flagNames(TreeInfo.firstFlag(flags
0580: & set1)), TreeInfo
0581: .flagNames(TreeInfo.firstFlag(flags
0582: & set2)));
0583: return false;
0584: } else
0585: return true;
0586: }
0587:
0588: /** Check that given modifiers are legal for given symbol and
0589: * return modifiers together with any implicit modififiers for that symbol.
0590: * Warning: we can't use flags() here since this method
0591: * is called during class enter, when flags() would cause a premature
0592: * completion.
0593: * @param pos Position to be used for error reporting.
0594: * @param flags The set of modifiers given in a definition.
0595: * @param sym The defined symbol.
0596: */
0597: long checkFlags(DiagnosticPosition pos, long flags, Symbol sym,
0598: JCTree tree) {
0599: long mask;
0600: long implicit = 0;
0601: switch (sym.kind) {
0602: case VAR:
0603: if (sym.owner.kind != TYP)
0604: mask = LocalVarFlags;
0605: else if ((sym.owner.flags_field & INTERFACE) != 0)
0606: mask = implicit = InterfaceVarFlags;
0607: else
0608: mask = VarFlags;
0609: break;
0610: case MTH:
0611: if (sym.name == names.init) {
0612: if ((sym.owner.flags_field & ENUM) != 0) {
0613: // enum constructors cannot be declared public or
0614: // protected and must be implicitly or explicitly
0615: // private
0616: implicit = PRIVATE;
0617: mask = PRIVATE;
0618: } else
0619: mask = ConstructorFlags;
0620: } else if ((sym.owner.flags_field & INTERFACE) != 0)
0621: mask = implicit = InterfaceMethodFlags;
0622: else {
0623: mask = MethodFlags;
0624: }
0625: // Imply STRICTFP if owner has STRICTFP set.
0626: if (((flags | implicit) & Flags.ABSTRACT) == 0)
0627: implicit |= sym.owner.flags_field & STRICTFP;
0628: break;
0629: case TYP:
0630: if (sym.isLocal()) {
0631: mask = LocalClassFlags;
0632: if (sym.name.len == 0) { // Anonymous class
0633: // Anonymous classes in static methods are themselves static;
0634: // that's why we admit STATIC here.
0635: mask |= STATIC;
0636: // JLS: Anonymous classes are final.
0637: implicit |= FINAL;
0638: }
0639: if ((sym.owner.flags_field & STATIC) == 0
0640: && (flags & ENUM) != 0)
0641: log.error(pos, "enums.must.be.static");
0642: } else if (sym.owner.kind == TYP) {
0643: mask = MemberClassFlags;
0644: if (sym.owner.owner.kind == PCK
0645: || (sym.owner.flags_field & STATIC) != 0)
0646: mask |= STATIC;
0647: else if ((flags & ENUM) != 0)
0648: log.error(pos, "enums.must.be.static");
0649: // Nested interfaces and enums are always STATIC (Spec ???)
0650: if ((flags & (INTERFACE | ENUM)) != 0)
0651: implicit = STATIC;
0652: } else {
0653: mask = ClassFlags;
0654: }
0655: // Interfaces are always ABSTRACT
0656: if ((flags & INTERFACE) != 0)
0657: implicit |= ABSTRACT;
0658:
0659: if ((flags & ENUM) != 0) {
0660: // enums can't be declared abstract or final
0661: mask &= ~(ABSTRACT | FINAL);
0662: implicit |= implicitEnumFinalFlag(tree);
0663: }
0664: // Imply STRICTFP if owner has STRICTFP set.
0665: implicit |= sym.owner.flags_field & STRICTFP;
0666: break;
0667: default:
0668: throw new AssertionError();
0669: }
0670: long illegal = flags & StandardFlags & ~mask;
0671: if (illegal != 0) {
0672: if ((illegal & INTERFACE) != 0) {
0673: log.error(pos, "intf.not.allowed.here");
0674: mask |= INTERFACE;
0675: } else {
0676: log.error(pos, "mod.not.allowed.here", TreeInfo
0677: .flagNames(illegal));
0678: }
0679: } else if ((sym.kind == TYP ||
0680: // ISSUE: Disallowing abstract&private is no longer appropriate
0681: // in the presence of inner classes. Should it be deleted here?
0682: checkDisjoint(pos, flags, ABSTRACT, PRIVATE | STATIC))
0683: && checkDisjoint(pos, flags, ABSTRACT | INTERFACE,
0684: FINAL | NATIVE | SYNCHRONIZED)
0685: && checkDisjoint(pos, flags, PUBLIC, PRIVATE
0686: | PROTECTED)
0687: && checkDisjoint(pos, flags, PRIVATE, PUBLIC
0688: | PROTECTED)
0689: && checkDisjoint(pos, flags, FINAL, VOLATILE)
0690: && (sym.kind == TYP || checkDisjoint(pos, flags,
0691: ABSTRACT | NATIVE, STRICTFP))) {
0692: // skip
0693: }
0694: return flags & (mask | ~StandardFlags) | implicit;
0695: }
0696:
0697: /** Determine if this enum should be implicitly final.
0698: *
0699: * If the enum has no specialized enum contants, it is final.
0700: *
0701: * If the enum does have specialized enum contants, it is
0702: * <i>not</i> final.
0703: */
0704: private long implicitEnumFinalFlag(JCTree tree) {
0705: if (tree.getTag() != JCTree.CLASSDEF)
0706: return 0;
0707: class SpecialTreeVisitor extends JCTree.Visitor {
0708: boolean specialized;
0709:
0710: SpecialTreeVisitor() {
0711: this .specialized = false;
0712: };
0713:
0714: public void visitTree(JCTree tree) { /* no-op */
0715: }
0716:
0717: public void visitVarDef(JCVariableDecl tree) {
0718: if ((tree.mods.flags & ENUM) != 0) {
0719: if (tree.init instanceof JCNewClass
0720: && ((JCNewClass) tree.init).def != null) {
0721: specialized = true;
0722: }
0723: }
0724: }
0725: }
0726:
0727: SpecialTreeVisitor sts = new SpecialTreeVisitor();
0728: JCClassDecl cdef = (JCClassDecl) tree;
0729: for (JCTree defs : cdef.defs) {
0730: defs.accept(sts);
0731: if (sts.specialized)
0732: return 0;
0733: }
0734: return FINAL;
0735: }
0736:
0737: /* *************************************************************************
0738: * Type Validation
0739: **************************************************************************/
0740:
0741: /** Validate a type expression. That is,
0742: * check that all type arguments of a parametric type are within
0743: * their bounds. This must be done in a second phase after type attributon
0744: * since a class might have a subclass as type parameter bound. E.g:
0745: *
0746: * class B<A extends C> { ... }
0747: * class C extends B<C> { ... }
0748: *
0749: * and we can't make sure that the bound is already attributed because
0750: * of possible cycles.
0751: */
0752: private Validator validator = new Validator();
0753:
0754: /** Visitor method: Validate a type expression, if it is not null, catching
0755: * and reporting any completion failures.
0756: */
0757: void validate(JCTree tree) {
0758: try {
0759: if (tree != null)
0760: tree.accept(validator);
0761: } catch (CompletionFailure ex) {
0762: completionError(tree.pos(), ex);
0763: }
0764: }
0765:
0766: /** Visitor method: Validate a list of type expressions.
0767: */
0768: void validate(List<? extends JCTree> trees) {
0769: for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail)
0770: validate(l.head);
0771: }
0772:
0773: /** Visitor method: Validate a list of type parameters.
0774: */
0775: void validateTypeParams(List<JCTypeParameter> trees) {
0776: for (List<JCTypeParameter> l = trees; l.nonEmpty(); l = l.tail)
0777: validate(l.head);
0778: }
0779:
0780: /** A visitor class for type validation.
0781: */
0782: class Validator extends JCTree.Visitor {
0783:
0784: public void visitTypeArray(JCArrayTypeTree tree) {
0785: validate(tree.elemtype);
0786: }
0787:
0788: public void visitTypeApply(JCTypeApply tree) {
0789: if (tree.type.tag == CLASS) {
0790: List<Type> formals = tree.type.tsym.type
0791: .getTypeArguments();
0792: List<Type> actuals = tree.type.getTypeArguments();
0793: List<JCExpression> args = tree.arguments;
0794: List<Type> forms = formals;
0795: ListBuffer<TypeVar> tvars_buf = new ListBuffer<TypeVar>();
0796:
0797: // For matching pairs of actual argument types `a' and
0798: // formal type parameters with declared bound `b' ...
0799: while (args.nonEmpty() && forms.nonEmpty()) {
0800: validate(args.head);
0801:
0802: // exact type arguments needs to know their
0803: // bounds (for upper and lower bound
0804: // calculations). So we create new TypeVars with
0805: // bounds substed with actuals.
0806: tvars_buf.append(types.substBound(
0807: ((TypeVar) forms.head), formals, Type
0808: .removeBounds(actuals)));
0809:
0810: args = args.tail;
0811: forms = forms.tail;
0812: }
0813:
0814: args = tree.arguments;
0815: List<TypeVar> tvars = tvars_buf.toList();
0816: while (args.nonEmpty() && tvars.nonEmpty()) {
0817: // Let the actual arguments know their bound
0818: args.head.type.withTypeVar(tvars.head);
0819: args = args.tail;
0820: tvars = tvars.tail;
0821: }
0822:
0823: args = tree.arguments;
0824: tvars = tvars_buf.toList();
0825: while (args.nonEmpty() && tvars.nonEmpty()) {
0826: checkExtends(args.head.pos(), args.head.type,
0827: tvars.head);
0828: args = args.tail;
0829: tvars = tvars.tail;
0830: }
0831:
0832: // Check that this type is either fully parameterized, or
0833: // not parameterized at all.
0834: if (tree.type.getEnclosingType().isRaw())
0835: log.error(tree.pos(),
0836: "improperly.formed.type.inner.raw.param");
0837: if (tree.clazz.getTag() == JCTree.SELECT)
0838: visitSelectInternal((JCFieldAccess) tree.clazz);
0839: }
0840: }
0841:
0842: public void visitTypeParameter(JCTypeParameter tree) {
0843: validate(tree.bounds);
0844: checkClassBounds(tree.pos(), tree.type);
0845: }
0846:
0847: @Override
0848: public void visitWildcard(JCWildcard tree) {
0849: if (tree.inner != null)
0850: validate(tree.inner);
0851: }
0852:
0853: public void visitSelect(JCFieldAccess tree) {
0854: if (tree.type.tag == CLASS) {
0855: visitSelectInternal(tree);
0856:
0857: // Check that this type is either fully parameterized, or
0858: // not parameterized at all.
0859: if (tree.selected.type.isParameterized()
0860: && tree.type.tsym.type.getTypeArguments()
0861: .nonEmpty())
0862: log.error(tree.pos(),
0863: "improperly.formed.type.param.missing");
0864: }
0865: }
0866:
0867: public void visitSelectInternal(JCFieldAccess tree) {
0868: if (tree.type.getEnclosingType().tag != CLASS
0869: && tree.selected.type.isParameterized()) {
0870: // The enclosing type is not a class, so we are
0871: // looking at a static member type. However, the
0872: // qualifying expression is parameterized.
0873: log.error(tree.pos(),
0874: "cant.select.static.class.from.param.type");
0875: } else {
0876: // otherwise validate the rest of the expression
0877: validate(tree.selected);
0878: }
0879: }
0880:
0881: /** Default visitor method: do nothing.
0882: */
0883: public void visitTree(JCTree tree) {
0884: }
0885: }
0886:
0887: /* *************************************************************************
0888: * Exception checking
0889: **************************************************************************/
0890:
0891: /* The following methods treat classes as sets that contain
0892: * the class itself and all their subclasses
0893: */
0894:
0895: /** Is given type a subtype of some of the types in given list?
0896: */
0897: boolean subset(Type t, List<Type> ts) {
0898: for (List<Type> l = ts; l.nonEmpty(); l = l.tail)
0899: if (types.isSubtype(t, l.head))
0900: return true;
0901: return false;
0902: }
0903:
0904: /** Is given type a subtype or supertype of
0905: * some of the types in given list?
0906: */
0907: boolean intersects(Type t, List<Type> ts) {
0908: for (List<Type> l = ts; l.nonEmpty(); l = l.tail)
0909: if (types.isSubtype(t, l.head)
0910: || types.isSubtype(l.head, t))
0911: return true;
0912: return false;
0913: }
0914:
0915: /** Add type set to given type list, unless it is a subclass of some class
0916: * in the list.
0917: */
0918: List<Type> incl(Type t, List<Type> ts) {
0919: return subset(t, ts) ? ts : excl(t, ts).prepend(t);
0920: }
0921:
0922: /** Remove type set from type set list.
0923: */
0924: List<Type> excl(Type t, List<Type> ts) {
0925: if (ts.isEmpty()) {
0926: return ts;
0927: } else {
0928: List<Type> ts1 = excl(t, ts.tail);
0929: if (types.isSubtype(ts.head, t))
0930: return ts1;
0931: else if (ts1 == ts.tail)
0932: return ts;
0933: else
0934: return ts1.prepend(ts.head);
0935: }
0936: }
0937:
0938: /** Form the union of two type set lists.
0939: */
0940: List<Type> union(List<Type> ts1, List<Type> ts2) {
0941: List<Type> ts = ts1;
0942: for (List<Type> l = ts2; l.nonEmpty(); l = l.tail)
0943: ts = incl(l.head, ts);
0944: return ts;
0945: }
0946:
0947: /** Form the difference of two type lists.
0948: */
0949: List<Type> diff(List<Type> ts1, List<Type> ts2) {
0950: List<Type> ts = ts1;
0951: for (List<Type> l = ts2; l.nonEmpty(); l = l.tail)
0952: ts = excl(l.head, ts);
0953: return ts;
0954: }
0955:
0956: /** Form the intersection of two type lists.
0957: */
0958: public List<Type> intersect(List<Type> ts1, List<Type> ts2) {
0959: List<Type> ts = List.nil();
0960: for (List<Type> l = ts1; l.nonEmpty(); l = l.tail)
0961: if (subset(l.head, ts2))
0962: ts = incl(l.head, ts);
0963: for (List<Type> l = ts2; l.nonEmpty(); l = l.tail)
0964: if (subset(l.head, ts1))
0965: ts = incl(l.head, ts);
0966: return ts;
0967: }
0968:
0969: /** Is exc an exception symbol that need not be declared?
0970: */
0971: boolean isUnchecked(ClassSymbol exc) {
0972: return exc.kind == ERR
0973: || exc.isSubClass(syms.errorType.tsym, types)
0974: || exc
0975: .isSubClass(syms.runtimeExceptionType.tsym,
0976: types);
0977: }
0978:
0979: /** Is exc an exception type that need not be declared?
0980: */
0981: boolean isUnchecked(Type exc) {
0982: return (exc.tag == TYPEVAR) ? isUnchecked(types.super type(exc))
0983: : (exc.tag == CLASS) ? isUnchecked((ClassSymbol) exc.tsym)
0984: : exc.tag == BOT;
0985: }
0986:
0987: /** Same, but handling completion failures.
0988: */
0989: boolean isUnchecked(DiagnosticPosition pos, Type exc) {
0990: try {
0991: return isUnchecked(exc);
0992: } catch (CompletionFailure ex) {
0993: completionError(pos, ex);
0994: return true;
0995: }
0996: }
0997:
0998: /** Is exc handled by given exception list?
0999: */
1000: boolean isHandled(Type exc, List<Type> handled) {
1001: return isUnchecked(exc) || subset(exc, handled);
1002: }
1003:
1004: /** Return all exceptions in thrown list that are not in handled list.
1005: * @param thrown The list of thrown exceptions.
1006: * @param handled The list of handled exceptions.
1007: */
1008: List<Type> unHandled(List<Type> thrown, List<Type> handled) {
1009: List<Type> unhandled = List.nil();
1010: for (List<Type> l = thrown; l.nonEmpty(); l = l.tail)
1011: if (!isHandled(l.head, handled))
1012: unhandled = unhandled.prepend(l.head);
1013: return unhandled;
1014: }
1015:
1016: /* *************************************************************************
1017: * Overriding/Implementation checking
1018: **************************************************************************/
1019:
1020: /** The level of access protection given by a flag set,
1021: * where PRIVATE is highest and PUBLIC is lowest.
1022: */
1023: static int protection(long flags) {
1024: switch ((short) (flags & AccessFlags)) {
1025: case PRIVATE:
1026: return 3;
1027: case PROTECTED:
1028: return 1;
1029: default:
1030: case PUBLIC:
1031: return 0;
1032: case 0:
1033: return 2;
1034: }
1035: }
1036:
1037: /** A string describing the access permission given by a flag set.
1038: * This always returns a space-separated list of Java Keywords.
1039: */
1040: private static String protectionString(long flags) {
1041: long flags1 = flags & AccessFlags;
1042: return (flags1 == 0) ? "package" : TreeInfo.flagNames(flags1);
1043: }
1044:
1045: /** A customized "cannot override" error message.
1046: * @param m The overriding method.
1047: * @param other The overridden method.
1048: * @return An internationalized string.
1049: */
1050: static Object cannotOverride(MethodSymbol m, MethodSymbol other) {
1051: String key;
1052: if ((other.owner.flags() & INTERFACE) == 0)
1053: key = "cant.override";
1054: else if ((m.owner.flags() & INTERFACE) == 0)
1055: key = "cant.implement";
1056: else
1057: key = "clashes.with";
1058: return JCDiagnostic.fragment(key, m, m.location(), other, other
1059: .location());
1060: }
1061:
1062: /** A customized "override" warning message.
1063: * @param m The overriding method.
1064: * @param other The overridden method.
1065: * @return An internationalized string.
1066: */
1067: static Object uncheckedOverrides(MethodSymbol m, MethodSymbol other) {
1068: String key;
1069: if ((other.owner.flags() & INTERFACE) == 0)
1070: key = "unchecked.override";
1071: else if ((m.owner.flags() & INTERFACE) == 0)
1072: key = "unchecked.implement";
1073: else
1074: key = "unchecked.clash.with";
1075: return JCDiagnostic.fragment(key, m, m.location(), other, other
1076: .location());
1077: }
1078:
1079: /** A customized "override" warning message.
1080: * @param m The overriding method.
1081: * @param other The overridden method.
1082: * @return An internationalized string.
1083: */
1084: static Object varargsOverrides(MethodSymbol m, MethodSymbol other) {
1085: String key;
1086: if ((other.owner.flags() & INTERFACE) == 0)
1087: key = "varargs.override";
1088: else if ((m.owner.flags() & INTERFACE) == 0)
1089: key = "varargs.implement";
1090: else
1091: key = "varargs.clash.with";
1092: return JCDiagnostic.fragment(key, m, m.location(), other, other
1093: .location());
1094: }
1095:
1096: /** Check that this method conforms with overridden method 'other'.
1097: * where `origin' is the class where checking started.
1098: * Complications:
1099: * (1) Do not check overriding of synthetic methods
1100: * (reason: they might be final).
1101: * todo: check whether this is still necessary.
1102: * (2) Admit the case where an interface proxy throws fewer exceptions
1103: * than the method it implements. Augment the proxy methods with the
1104: * undeclared exceptions in this case.
1105: * (3) When generics are enabled, admit the case where an interface proxy
1106: * has a result type
1107: * extended by the result type of the method it implements.
1108: * Change the proxies result type to the smaller type in this case.
1109: *
1110: * @param tree The tree from which positions
1111: * are extracted for errors.
1112: * @param m The overriding method.
1113: * @param other The overridden method.
1114: * @param origin The class of which the overriding method
1115: * is a member.
1116: */
1117: void checkOverride(JCTree tree, MethodSymbol m, MethodSymbol other,
1118: ClassSymbol origin) {
1119: // Don't check overriding of synthetic methods or by bridge methods.
1120: if ((m.flags() & (SYNTHETIC | BRIDGE)) != 0
1121: || (other.flags() & SYNTHETIC) != 0) {
1122: return;
1123: }
1124:
1125: // Error if static method overrides instance method (JLS 8.4.6.2).
1126: if ((m.flags() & STATIC) != 0 && (other.flags() & STATIC) == 0) {
1127: log.error(TreeInfo.diagnosticPositionFor(m, tree),
1128: "override.static", cannotOverride(m, other));
1129: return;
1130: }
1131:
1132: // Error if instance method overrides static or final
1133: // method (JLS 8.4.6.1).
1134: if ((other.flags() & FINAL) != 0 || (m.flags() & STATIC) == 0
1135: && (other.flags() & STATIC) != 0) {
1136: log
1137: .error(TreeInfo.diagnosticPositionFor(m, tree),
1138: "override.meth", cannotOverride(m, other),
1139: TreeInfo.flagNames(other.flags()
1140: & (FINAL | STATIC)));
1141: return;
1142: }
1143:
1144: if ((m.owner.flags() & ANNOTATION) != 0) {
1145: // handled in validateAnnotationMethod
1146: return;
1147: }
1148:
1149: // Error if overriding method has weaker access (JLS 8.4.6.3).
1150: if ((origin.flags() & INTERFACE) == 0
1151: && protection(m.flags()) > protection(other.flags())) {
1152: log.error(TreeInfo.diagnosticPositionFor(m, tree),
1153: "override.weaker.access", cannotOverride(m, other),
1154: protectionString(other.flags()));
1155: return;
1156:
1157: }
1158:
1159: Type mt = types.memberType(origin.type, m);
1160: Type ot = types.memberType(origin.type, other);
1161: // Error if overriding result type is different
1162: // (or, in the case of generics mode, not a subtype) of
1163: // overridden result type. We have to rename any type parameters
1164: // before comparing types.
1165: List<Type> mtvars = mt.getTypeArguments();
1166: List<Type> otvars = ot.getTypeArguments();
1167: Type mtres = mt.getReturnType();
1168: Type otres = types.subst(ot.getReturnType(), otvars, mtvars);
1169:
1170: overrideWarner.warned = false;
1171: boolean resultTypesOK = types.returnTypeSubstitutable(mt, ot,
1172: otres, overrideWarner);
1173: if (!resultTypesOK) {
1174: if (!source.allowCovariantReturns() && m.owner != origin
1175: && m.owner.isSubClass(other.owner, types)) {
1176: // allow limited interoperability with covariant returns
1177: } else {
1178: typeError(TreeInfo.diagnosticPositionFor(m, tree),
1179: JCDiagnostic.fragment(
1180: "override.incompatible.ret",
1181: cannotOverride(m, other)), mtres, otres);
1182: return;
1183: }
1184: } else if (overrideWarner.warned) {
1185: warnUnchecked(TreeInfo.diagnosticPositionFor(m, tree),
1186: "prob.found.req", JCDiagnostic.fragment(
1187: "override.unchecked.ret",
1188: uncheckedOverrides(m, other)), mtres, otres);
1189: }
1190:
1191: // Error if overriding method throws an exception not reported
1192: // by overridden method.
1193: List<Type> otthrown = types.subst(ot.getThrownTypes(), otvars,
1194: mtvars);
1195: List<Type> unhandled = unHandled(mt.getThrownTypes(), otthrown);
1196: if (unhandled.nonEmpty()) {
1197: log.error(TreeInfo.diagnosticPositionFor(m, tree),
1198: "override.meth.doesnt.throw", cannotOverride(m,
1199: other), unhandled.head);
1200: return;
1201: }
1202:
1203: // Optional warning if varargs don't agree
1204: if ((((m.flags() ^ other.flags()) & Flags.VARARGS) != 0)
1205: && lint.isEnabled(Lint.LintCategory.OVERRIDES)) {
1206: log
1207: .warning(
1208: TreeInfo.diagnosticPositionFor(m, tree),
1209: ((m.flags() & Flags.VARARGS) != 0) ? "override.varargs.missing"
1210: : "override.varargs.extra",
1211: varargsOverrides(m, other));
1212: }
1213:
1214: // Warn if instance method overrides bridge method (compiler spec ??)
1215: if ((other.flags() & BRIDGE) != 0) {
1216: log.warning(TreeInfo.diagnosticPositionFor(m, tree),
1217: "override.bridge", uncheckedOverrides(m, other));
1218: }
1219:
1220: // Warn if a deprecated method overridden by a non-deprecated one.
1221: if ((other.flags() & DEPRECATED) != 0
1222: && (m.flags() & DEPRECATED) == 0
1223: && m.outermostClass() != other.outermostClass()
1224: && !isDeprecatedOverrideIgnorable(other, origin)) {
1225: warnDeprecated(TreeInfo.diagnosticPositionFor(m, tree),
1226: other);
1227: }
1228: }
1229:
1230: // where
1231: private boolean isDeprecatedOverrideIgnorable(MethodSymbol m,
1232: ClassSymbol origin) {
1233: // If the method, m, is defined in an interface, then ignore the issue if the method
1234: // is only inherited via a supertype and also implemented in the supertype,
1235: // because in that case, we will rediscover the issue when examining the method
1236: // in the supertype.
1237: // If the method, m, is not defined in an interface, then the only time we need to
1238: // address the issue is when the method is the supertype implemementation: any other
1239: // case, we will have dealt with when examining the supertype classes
1240: ClassSymbol mc = m.enclClass();
1241: Type st = types.super type(origin.type);
1242: if (st.tag != CLASS)
1243: return true;
1244: MethodSymbol stimpl = m.implementation((ClassSymbol) st.tsym,
1245: types, false);
1246:
1247: if (mc != null && ((mc.flags() & INTERFACE) != 0)) {
1248: List<Type> intfs = types.interfaces(origin.type);
1249: return (intfs.contains(mc.type) ? false : (stimpl != null));
1250: } else
1251: return (stimpl != m);
1252: }
1253:
1254: // used to check if there were any unchecked conversions
1255: Warner overrideWarner = new Warner();
1256:
1257: /** Check that a class does not inherit two concrete methods
1258: * with the same signature.
1259: * @param pos Position to be used for error reporting.
1260: * @param site The class type to be checked.
1261: */
1262: public void checkCompatibleConcretes(DiagnosticPosition pos,
1263: Type site) {
1264: Type sup = types.super type(site);
1265: if (sup.tag != CLASS)
1266: return;
1267:
1268: for (Type t1 = sup; t1.tsym.type.isParameterized(); t1 = types
1269: .super type(t1)) {
1270: for (Scope.Entry e1 = t1.tsym.members().elems; e1 != null; e1 = e1.sibling) {
1271: Symbol s1 = e1.sym;
1272: if (s1.kind != MTH
1273: || (s1.flags() & (STATIC | SYNTHETIC | BRIDGE)) != 0
1274: || !s1.isInheritedIn(site.tsym, types)
1275: || ((MethodSymbol) s1).implementation(
1276: site.tsym, types, true) != s1)
1277: continue;
1278: Type st1 = types.memberType(t1, s1);
1279: int s1ArgsLength = st1.getParameterTypes().length();
1280: if (st1 == s1.type)
1281: continue;
1282:
1283: for (Type t2 = sup; t2.tag == CLASS; t2 = types
1284: .super type(t2)) {
1285: for (Scope.Entry e2 = t1.tsym.members().lookup(
1286: s1.name); e2.scope != null; e2 = e2.next()) {
1287: Symbol s2 = e2.sym;
1288: if (s2 == s1
1289: || s2.kind != MTH
1290: || (s2.flags() & (STATIC | SYNTHETIC | BRIDGE)) != 0
1291: || s2.type.getParameterTypes().length() != s1ArgsLength
1292: || !s2.isInheritedIn(site.tsym, types)
1293: || ((MethodSymbol) s2).implementation(
1294: site.tsym, types, true) != s2)
1295: continue;
1296: Type st2 = types.memberType(t2, s2);
1297: if (types.overrideEquivalent(st1, st2))
1298: log.error(pos,
1299: "concrete.inheritance.conflict",
1300: s1, t1, s2, t2, sup);
1301: }
1302: }
1303: }
1304: }
1305: }
1306:
1307: /** Check that classes (or interfaces) do not each define an abstract
1308: * method with same name and arguments but incompatible return types.
1309: * @param pos Position to be used for error reporting.
1310: * @param t1 The first argument type.
1311: * @param t2 The second argument type.
1312: */
1313: public boolean checkCompatibleAbstracts(DiagnosticPosition pos,
1314: Type t1, Type t2) {
1315: return checkCompatibleAbstracts(pos, t1, t2, types
1316: .makeCompoundType(t1, t2));
1317: }
1318:
1319: public boolean checkCompatibleAbstracts(DiagnosticPosition pos,
1320: Type t1, Type t2, Type site) {
1321: Symbol sym = firstIncompatibility(t1, t2, site);
1322: if (sym != null) {
1323: log.error(pos, "types.incompatible.diff.ret", t1, t2,
1324: sym.name
1325: + "("
1326: + types.memberType(t2, sym)
1327: .getParameterTypes() + ")");
1328: return false;
1329: }
1330: return true;
1331: }
1332:
1333: /** Return the first method which is defined with same args
1334: * but different return types in two given interfaces, or null if none
1335: * exists.
1336: * @param t1 The first type.
1337: * @param t2 The second type.
1338: * @param site The most derived type.
1339: * @returns symbol from t2 that conflicts with one in t1.
1340: */
1341: private Symbol firstIncompatibility(Type t1, Type t2, Type site) {
1342: Map<TypeSymbol, Type> interfaces1 = new HashMap<TypeSymbol, Type>();
1343: closure(t1, interfaces1);
1344: Map<TypeSymbol, Type> interfaces2;
1345: if (t1 == t2)
1346: interfaces2 = interfaces1;
1347: else
1348: closure(t2, interfaces1,
1349: interfaces2 = new HashMap<TypeSymbol, Type>());
1350:
1351: for (Type t3 : interfaces1.values()) {
1352: for (Type t4 : interfaces2.values()) {
1353: Symbol s = firstDirectIncompatibility(t3, t4, site);
1354: if (s != null)
1355: return s;
1356: }
1357: }
1358: return null;
1359: }
1360:
1361: /** Compute all the supertypes of t, indexed by type symbol. */
1362: private void closure(Type t, Map<TypeSymbol, Type> typeMap) {
1363: if (t.tag != CLASS)
1364: return;
1365: if (typeMap.put(t.tsym, t) == null) {
1366: closure(types.super type(t), typeMap);
1367: for (Type i : types.interfaces(t))
1368: closure(i, typeMap);
1369: }
1370: }
1371:
1372: /** Compute all the supertypes of t, indexed by type symbol (except thise in typesSkip). */
1373: private void closure(Type t, Map<TypeSymbol, Type> typesSkip,
1374: Map<TypeSymbol, Type> typeMap) {
1375: if (t.tag != CLASS)
1376: return;
1377: if (typesSkip.get(t.tsym) != null)
1378: return;
1379: if (typeMap.put(t.tsym, t) == null) {
1380: closure(types.super type(t), typesSkip, typeMap);
1381: for (Type i : types.interfaces(t))
1382: closure(i, typesSkip, typeMap);
1383: }
1384: }
1385:
1386: /** Return the first method in t2 that conflicts with a method from t1. */
1387: private Symbol firstDirectIncompatibility(Type t1, Type t2,
1388: Type site) {
1389: for (Scope.Entry e1 = t1.tsym.members().elems; e1 != null; e1 = e1.sibling) {
1390: Symbol s1 = e1.sym;
1391: Type st1 = null;
1392: if (s1.kind != MTH || !s1.isInheritedIn(site.tsym, types))
1393: continue;
1394: Symbol impl = ((MethodSymbol) s1).implementation(site.tsym,
1395: types, false);
1396: if (impl != null && (impl.flags() & ABSTRACT) == 0)
1397: continue;
1398: for (Scope.Entry e2 = t2.tsym.members().lookup(s1.name); e2.scope != null; e2 = e2
1399: .next()) {
1400: Symbol s2 = e2.sym;
1401: if (s1 == s2)
1402: continue;
1403: if (s2.kind != MTH
1404: || !s2.isInheritedIn(site.tsym, types))
1405: continue;
1406: if (st1 == null)
1407: st1 = types.memberType(t1, s1);
1408: Type st2 = types.memberType(t2, s2);
1409: if (types.overrideEquivalent(st1, st2)) {
1410: List<Type> tvars1 = st1.getTypeArguments();
1411: List<Type> tvars2 = st2.getTypeArguments();
1412: Type rt1 = st1.getReturnType();
1413: Type rt2 = types.subst(st2.getReturnType(), tvars2,
1414: tvars1);
1415: boolean compat = types.isSameType(rt1, rt2)
1416: || rt1.tag >= CLASS
1417: && rt2.tag >= CLASS
1418: && (types.covariantReturnType(rt1, rt2,
1419: Warner.noWarnings) || types
1420: .covariantReturnType(rt2, rt1,
1421: Warner.noWarnings));
1422: if (!compat)
1423: return s2;
1424: }
1425: }
1426: }
1427: return null;
1428: }
1429:
1430: /** Check that a given method conforms with any method it overrides.
1431: * @param tree The tree from which positions are extracted
1432: * for errors.
1433: * @param m The overriding method.
1434: */
1435: void checkOverride(JCTree tree, MethodSymbol m) {
1436: ClassSymbol origin = (ClassSymbol) m.owner;
1437: if ((origin.flags() & ENUM) != 0
1438: && names.finalize.equals(m.name))
1439: if (m.overrides(syms.enumFinalFinalize, origin, types,
1440: false)) {
1441: log.error(tree.pos(), "enum.no.finalize");
1442: return;
1443: }
1444: for (Type t = types.super type(origin.type); t.tag == CLASS; t = types
1445: .super type(t)) {
1446: TypeSymbol c = t.tsym;
1447: Scope.Entry e = c.members().lookup(m.name);
1448: while (e.scope != null) {
1449: if (m.overrides(e.sym, origin, types, false))
1450: checkOverride(tree, m, (MethodSymbol) e.sym, origin);
1451: e = e.next();
1452: }
1453: }
1454: }
1455:
1456: /** Check that all abstract members of given class have definitions.
1457: * @param pos Position to be used for error reporting.
1458: * @param c The class.
1459: */
1460: void checkAllDefined(DiagnosticPosition pos, ClassSymbol c) {
1461: try {
1462: MethodSymbol undef = firstUndef(c, c);
1463: if (undef != null) {
1464: if ((c.flags() & ENUM) != 0
1465: && types.super type(c.type).tsym == syms.enumSym
1466: && (c.flags() & FINAL) == 0) {
1467: // add the ABSTRACT flag to an enum
1468: c.flags_field |= ABSTRACT;
1469: } else {
1470: MethodSymbol undef1 = new MethodSymbol(undef
1471: .flags(), undef.name, types.memberType(
1472: c.type, undef), undef.owner);
1473: log.error(pos, "does.not.override.abstract", c,
1474: undef1, undef1.location());
1475: }
1476: }
1477: } catch (CompletionFailure ex) {
1478: completionError(pos, ex);
1479: }
1480: }
1481:
1482: //where
1483: /** Return first abstract member of class `c' that is not defined
1484: * in `impl', null if there is none.
1485: */
1486: private MethodSymbol firstUndef(ClassSymbol impl, ClassSymbol c) {
1487: MethodSymbol undef = null;
1488: // Do not bother to search in classes that are not abstract,
1489: // since they cannot have abstract members.
1490: if (c == impl || (c.flags() & (ABSTRACT | INTERFACE)) != 0) {
1491: Scope s = c.members();
1492: for (Scope.Entry e = s.elems; undef == null && e != null; e = e.sibling) {
1493: if (e.sym.kind == MTH
1494: && (e.sym.flags() & (ABSTRACT | IPROXY)) == ABSTRACT) {
1495: MethodSymbol absmeth = (MethodSymbol) e.sym;
1496: MethodSymbol implmeth = absmeth.implementation(
1497: impl, types, true);
1498: if (implmeth == null || implmeth == absmeth)
1499: undef = absmeth;
1500: }
1501: }
1502: if (undef == null) {
1503: Type st = types.super type(c.type);
1504: if (st.tag == CLASS)
1505: undef = firstUndef(impl, (ClassSymbol) st.tsym);
1506: }
1507: for (List<Type> l = types.interfaces(c.type); undef == null
1508: && l.nonEmpty(); l = l.tail) {
1509: undef = firstUndef(impl, (ClassSymbol) l.head.tsym);
1510: }
1511: }
1512: return undef;
1513: }
1514:
1515: /** Check for cyclic references. Issue an error if the
1516: * symbol of the type referred to has a LOCKED flag set.
1517: *
1518: * @param pos Position to be used for error reporting.
1519: * @param t The type referred to.
1520: */
1521: void checkNonCyclic(DiagnosticPosition pos, Type t) {
1522: checkNonCyclicInternal(pos, t);
1523: }
1524:
1525: void checkNonCyclic(DiagnosticPosition pos, TypeVar t) {
1526: checkNonCyclic1(pos, t, new HashSet<TypeVar>());
1527: }
1528:
1529: private void checkNonCyclic1(DiagnosticPosition pos, Type t,
1530: Set<TypeVar> seen) {
1531: final TypeVar tv;
1532: if (seen.contains(t)) {
1533: tv = (TypeVar) t;
1534: tv.bound = new ErrorType();
1535: log.error(pos, "cyclic.inheritance", t);
1536: } else if (t.tag == TYPEVAR) {
1537: tv = (TypeVar) t;
1538: seen.add(tv);
1539: for (Type b : types.getBounds(tv))
1540: checkNonCyclic1(pos, b, seen);
1541: }
1542: }
1543:
1544: /** Check for cyclic references. Issue an error if the
1545: * symbol of the type referred to has a LOCKED flag set.
1546: *
1547: * @param pos Position to be used for error reporting.
1548: * @param t The type referred to.
1549: * @returns True if the check completed on all attributed classes
1550: */
1551: private boolean checkNonCyclicInternal(DiagnosticPosition pos,
1552: Type t) {
1553: boolean complete = true; // was the check complete?
1554: //- System.err.println("checkNonCyclicInternal("+t+");");//DEBUG
1555: Symbol c = t.tsym;
1556: if ((c.flags_field & ACYCLIC) != 0)
1557: return true;
1558:
1559: if ((c.flags_field & LOCKED) != 0) {
1560: noteCyclic(pos, (ClassSymbol) c);
1561: } else if (!c.type.isErroneous()) {
1562: try {
1563: c.flags_field |= LOCKED;
1564: if (c.type.tag == CLASS) {
1565: ClassType clazz = (ClassType) c.type;
1566: if (clazz.interfaces_field != null)
1567: for (List<Type> l = clazz.interfaces_field; l
1568: .nonEmpty(); l = l.tail)
1569: complete &= checkNonCyclicInternal(pos,
1570: l.head);
1571: if (clazz.super type_field != null) {
1572: Type st = clazz.super type_field;
1573: if (st != null && st.tag == CLASS)
1574: complete &= checkNonCyclicInternal(pos, st);
1575: }
1576: if (c.owner.kind == TYP)
1577: complete &= checkNonCyclicInternal(pos,
1578: c.owner.type);
1579: }
1580: } finally {
1581: c.flags_field &= ~LOCKED;
1582: }
1583: }
1584: if (complete)
1585: complete = ((c.flags_field & UNATTRIBUTED) == 0)
1586: && c.completer == null;
1587: if (complete)
1588: c.flags_field |= ACYCLIC;
1589: return complete;
1590: }
1591:
1592: /** Note that we found an inheritance cycle. */
1593: private void noteCyclic(DiagnosticPosition pos, ClassSymbol c) {
1594: log.error(pos, "cyclic.inheritance", c);
1595: for (List<Type> l = types.interfaces(c.type); l.nonEmpty(); l = l.tail)
1596: l.head = new ErrorType((ClassSymbol) l.head.tsym);
1597: Type st = types.super type(c.type);
1598: if (st.tag == CLASS)
1599: ((ClassType) c.type).super type_field = new ErrorType(
1600: (ClassSymbol) st.tsym);
1601: c.type = new ErrorType(c);
1602: c.flags_field |= ACYCLIC;
1603: }
1604:
1605: /** Check that all methods which implement some
1606: * method conform to the method they implement.
1607: * @param tree The class definition whose members are checked.
1608: */
1609: void checkImplementations(JCClassDecl tree) {
1610: checkImplementations(tree, tree.sym);
1611: }
1612:
1613: //where
1614: /** Check that all methods which implement some
1615: * method in `ic' conform to the method they implement.
1616: */
1617: void checkImplementations(JCClassDecl tree, ClassSymbol ic) {
1618: ClassSymbol origin = tree.sym;
1619: for (List<Type> l = types.closure(ic.type); l.nonEmpty(); l = l.tail) {
1620: ClassSymbol lc = (ClassSymbol) l.head.tsym;
1621: if ((allowGenerics || origin != lc)
1622: && (lc.flags() & ABSTRACT) != 0) {
1623: for (Scope.Entry e = lc.members().elems; e != null; e = e.sibling) {
1624: if (e.sym.kind == MTH
1625: && (e.sym.flags() & (STATIC | ABSTRACT)) == ABSTRACT) {
1626: MethodSymbol absmeth = (MethodSymbol) e.sym;
1627: MethodSymbol implmeth = absmeth.implementation(
1628: origin, types, false);
1629: if (implmeth != null
1630: && implmeth != absmeth
1631: && (implmeth.owner.flags() & INTERFACE) == (origin
1632: .flags() & INTERFACE)) {
1633: // don't check if implmeth is in a class, yet
1634: // origin is an interface. This case arises only
1635: // if implmeth is declared in Object. The reason is
1636: // that interfaces really don't inherit from
1637: // Object it's just that the compiler represents
1638: // things that way.
1639: checkOverride(tree, implmeth, absmeth,
1640: origin);
1641: }
1642: }
1643: }
1644: }
1645: }
1646: }
1647:
1648: /** Check that all abstract methods implemented by a class are
1649: * mutually compatible.
1650: * @param pos Position to be used for error reporting.
1651: * @param c The class whose interfaces are checked.
1652: */
1653: void checkCompatibleSupertypes(DiagnosticPosition pos, Type c) {
1654: List<Type> super types = types.interfaces(c);
1655: Type super type = types.super type(c);
1656: if (super type.tag == CLASS
1657: && (super type.tsym.flags() & ABSTRACT) != 0)
1658: super types = super types.prepend(super type);
1659: for (List<Type> l = super types; l.nonEmpty(); l = l.tail) {
1660: if (allowGenerics
1661: && !l.head.getTypeArguments().isEmpty()
1662: && !checkCompatibleAbstracts(pos, l.head, l.head, c))
1663: return;
1664: for (List<Type> m = super types; m != l; m = m.tail)
1665: if (!checkCompatibleAbstracts(pos, l.head, m.head, c))
1666: return;
1667: }
1668: checkCompatibleConcretes(pos, c);
1669: }
1670:
1671: /** Check that class c does not implement directly or indirectly
1672: * the same parameterized interface with two different argument lists.
1673: * @param pos Position to be used for error reporting.
1674: * @param type The type whose interfaces are checked.
1675: */
1676: void checkClassBounds(DiagnosticPosition pos, Type type) {
1677: checkClassBounds(pos, new HashMap<TypeSymbol, Type>(), type);
1678: }
1679:
1680: //where
1681: /** Enter all interfaces of type `type' into the hash table `seensofar'
1682: * with their class symbol as key and their type as value. Make
1683: * sure no class is entered with two different types.
1684: */
1685: void checkClassBounds(DiagnosticPosition pos,
1686: Map<TypeSymbol, Type> seensofar, Type type) {
1687: if (type.isErroneous())
1688: return;
1689: for (List<Type> l = types.interfaces(type); l.nonEmpty(); l = l.tail) {
1690: Type it = l.head;
1691: Type oldit = seensofar.put(it.tsym, it);
1692: if (oldit != null) {
1693: List<Type> oldparams = oldit.allparams();
1694: List<Type> newparams = it.allparams();
1695: if (!types.containsTypeEquivalent(oldparams, newparams))
1696: log.error(pos, "cant.inherit.diff.arg", it.tsym,
1697: Type.toString(oldparams), Type
1698: .toString(newparams));
1699: }
1700: checkClassBounds(pos, seensofar, it);
1701: }
1702: Type st = types.super type(type);
1703: if (st != null)
1704: checkClassBounds(pos, seensofar, st);
1705: }
1706:
1707: /** Enter interface into into set.
1708: * If it existed already, issue a "repeated interface" error.
1709: */
1710: void checkNotRepeated(DiagnosticPosition pos, Type it, Set<Type> its) {
1711: if (its.contains(it))
1712: log.error(pos, "repeated.interface");
1713: else {
1714: its.add(it);
1715: }
1716: }
1717:
1718: /* *************************************************************************
1719: * Check annotations
1720: **************************************************************************/
1721:
1722: /** Annotation types are restricted to primitives, String, an
1723: * enum, an annotation, Class, Class<?>, Class<? extends
1724: * Anything>, arrays of the preceding.
1725: */
1726: void validateAnnotationType(JCTree restype) {
1727: // restype may be null if an error occurred, so don't bother validating it
1728: if (restype != null) {
1729: validateAnnotationType(restype.pos(), restype.type);
1730: }
1731: }
1732:
1733: void validateAnnotationType(DiagnosticPosition pos, Type type) {
1734: if (type.isPrimitive())
1735: return;
1736: if (types.isSameType(type, syms.stringType))
1737: return;
1738: if ((type.tsym.flags() & Flags.ENUM) != 0)
1739: return;
1740: if ((type.tsym.flags() & Flags.ANNOTATION) != 0)
1741: return;
1742: if (types.lowerBound(type).tsym == syms.classType.tsym)
1743: return;
1744: if (types.isArray(type) && !types.isArray(types.elemtype(type))) {
1745: validateAnnotationType(pos, types.elemtype(type));
1746: return;
1747: }
1748: log.error(pos, "invalid.annotation.member.type");
1749: }
1750:
1751: /**
1752: * "It is also a compile-time error if any method declared in an
1753: * annotation type has a signature that is override-equivalent to
1754: * that of any public or protected method declared in class Object
1755: * or in the interface annotation.Annotation."
1756: *
1757: * @jls3 9.6 Annotation Types
1758: */
1759: void validateAnnotationMethod(DiagnosticPosition pos, MethodSymbol m) {
1760: for (Type sup = syms.annotationType; sup.tag == CLASS; sup = types
1761: .super type(sup)) {
1762: Scope s = sup.tsym.members();
1763: for (Scope.Entry e = s.lookup(m.name); e.scope != null; e = e
1764: .next()) {
1765: if (e.sym.kind == MTH
1766: && (e.sym.flags() & (PUBLIC | PROTECTED)) != 0
1767: && types.overrideEquivalent(m.type, e.sym.type))
1768: log.error(pos, "intf.annotation.member.clash",
1769: e.sym, sup);
1770: }
1771: }
1772: }
1773:
1774: /** Check the annotations of a symbol.
1775: */
1776: public void validateAnnotations(List<JCAnnotation> annotations,
1777: Symbol s) {
1778: if (skipAnnotations)
1779: return;
1780: for (JCAnnotation a : annotations)
1781: validateAnnotation(a, s);
1782: }
1783:
1784: /** Check an annotation of a symbol.
1785: */
1786: public void validateAnnotation(JCAnnotation a, Symbol s) {
1787: validateAnnotation(a);
1788:
1789: if (!annotationApplicable(a, s))
1790: log.error(a.pos(), "annotation.type.not.applicable");
1791:
1792: if (a.annotationType.type.tsym == syms.overrideType.tsym) {
1793: if (!isOverrider(s))
1794: log.error(a.pos(),
1795: "method.does.not.override.superclass");
1796: }
1797: }
1798:
1799: /** Is s a method symbol that overrides a method in a superclass? */
1800: boolean isOverrider(Symbol s) {
1801: if (s.kind != MTH || s.isStatic())
1802: return false;
1803: MethodSymbol m = (MethodSymbol) s;
1804: TypeSymbol owner = (TypeSymbol) m.owner;
1805: for (Type sup : types.closure(owner.type)) {
1806: if (sup == owner.type)
1807: continue; // skip "this"
1808: Scope scope = sup.tsym.members();
1809: for (Scope.Entry e = scope.lookup(m.name); e.scope != null; e = e
1810: .next()) {
1811: if (!e.sym.isStatic()
1812: && m.overrides(e.sym, owner, types, true))
1813: return true;
1814: }
1815: }
1816: return false;
1817: }
1818:
1819: /** Is the annotation applicable to the symbol? */
1820: boolean annotationApplicable(JCAnnotation a, Symbol s) {
1821: Attribute.Compound atTarget = a.annotationType.type.tsym
1822: .attribute(syms.annotationTargetType.tsym);
1823: if (atTarget == null)
1824: return true;
1825: Attribute atValue = atTarget.member(names.value);
1826: if (!(atValue instanceof Attribute.Array))
1827: return true; // error recovery
1828: Attribute.Array arr = (Attribute.Array) atValue;
1829: for (Attribute app : arr.values) {
1830: if (!(app instanceof Attribute.Enum))
1831: return true; // recovery
1832: Attribute.Enum e = (Attribute.Enum) app;
1833: if (e.value.name == names.TYPE) {
1834: if (s.kind == TYP)
1835: return true;
1836: } else if (e.value.name == names.FIELD) {
1837: if (s.kind == VAR && s.owner.kind != MTH)
1838: return true;
1839: } else if (e.value.name == names.METHOD) {
1840: if (s.kind == MTH && !s.isConstructor())
1841: return true;
1842: } else if (e.value.name == names.PARAMETER) {
1843: if (s.kind == VAR && s.owner.kind == MTH
1844: && (s.flags() & PARAMETER) != 0)
1845: return true;
1846: } else if (e.value.name == names.CONSTRUCTOR) {
1847: if (s.kind == MTH && s.isConstructor())
1848: return true;
1849: } else if (e.value.name == names.LOCAL_VARIABLE) {
1850: if (s.kind == VAR && s.owner.kind == MTH
1851: && (s.flags() & PARAMETER) == 0)
1852: return true;
1853: } else if (e.value.name == names.ANNOTATION_TYPE) {
1854: if (s.kind == TYP && (s.flags() & ANNOTATION) != 0)
1855: return true;
1856: } else if (e.value.name == names.PACKAGE) {
1857: if (s.kind == PCK)
1858: return true;
1859: } else
1860: return true; // recovery
1861: }
1862: return false;
1863: }
1864:
1865: /** Check an annotation value.
1866: */
1867: public void validateAnnotation(JCAnnotation a) {
1868: if (a.type.isErroneous())
1869: return;
1870:
1871: // collect an inventory of the members
1872: Set<MethodSymbol> members = new HashSet<MethodSymbol>();
1873: for (Scope.Entry e = a.annotationType.type.tsym.members().elems; e != null; e = e.sibling)
1874: if (e.sym.kind == MTH)
1875: members.add((MethodSymbol) e.sym);
1876:
1877: // count them off as they're annotated
1878: for (JCTree arg : a.args) {
1879: if (arg.getTag() != JCTree.ASSIGN)
1880: continue; // recovery
1881: JCAssign assign = (JCAssign) arg;
1882: Symbol m = TreeInfo.symbol(assign.lhs);
1883: if (m == null || m.type.isErroneous())
1884: continue;
1885: if (!members.remove(m))
1886: log.error(arg.pos(),
1887: "duplicate.annotation.member.value", m.name,
1888: a.type);
1889: if (assign.rhs.getTag() == ANNOTATION)
1890: validateAnnotation((JCAnnotation) assign.rhs);
1891: }
1892:
1893: // all the remaining ones better have default values
1894: for (MethodSymbol m : members)
1895: if (m.defaultValue == null && !m.type.isErroneous())
1896: log.error(a.pos(), "annotation.missing.default.value",
1897: a.type, m.name);
1898:
1899: // special case: java.lang.annotation.Target must not have
1900: // repeated values in its value member
1901: if (a.annotationType.type.tsym != syms.annotationTargetType.tsym
1902: || a.args.tail == null)
1903: return;
1904:
1905: if (a.args.head.getTag() != JCTree.ASSIGN)
1906: return; // error recovery
1907: JCAssign assign = (JCAssign) a.args.head;
1908: Symbol m = TreeInfo.symbol(assign.lhs);
1909: if (m.name != names.value)
1910: return;
1911: JCTree rhs = assign.rhs;
1912: if (rhs.getTag() != JCTree.NEWARRAY)
1913: return;
1914: JCNewArray na = (JCNewArray) rhs;
1915: Set<Symbol> targets = new HashSet<Symbol>();
1916: for (JCTree elem : na.elems) {
1917: if (!targets.add(TreeInfo.symbol(elem))) {
1918: log.error(elem.pos(), "repeated.annotation.target");
1919: }
1920: }
1921: }
1922:
1923: void checkDeprecatedAnnotation(DiagnosticPosition pos, Symbol s) {
1924: if (allowAnnotations
1925: && lint.isEnabled(Lint.LintCategory.DEP_ANN)
1926: && (s.flags() & DEPRECATED) != 0
1927: && !syms.deprecatedType.isErroneous()
1928: && s.attribute(syms.deprecatedType.tsym) == null) {
1929: log.warning(pos, "missing.deprecated.annotation");
1930: }
1931: }
1932:
1933: /* *************************************************************************
1934: * Check for recursive annotation elements.
1935: **************************************************************************/
1936:
1937: /** Check for cycles in the graph of annotation elements.
1938: */
1939: void checkNonCyclicElements(JCClassDecl tree) {
1940: if ((tree.sym.flags_field & ANNOTATION) == 0)
1941: return;
1942: assert (tree.sym.flags_field & LOCKED) == 0;
1943: try {
1944: tree.sym.flags_field |= LOCKED;
1945: for (JCTree def : tree.defs) {
1946: if (def.getTag() != JCTree.METHODDEF)
1947: continue;
1948: JCMethodDecl meth = (JCMethodDecl) def;
1949: checkAnnotationResType(meth.pos(), meth.restype.type);
1950: }
1951: } finally {
1952: tree.sym.flags_field &= ~LOCKED;
1953: tree.sym.flags_field |= ACYCLIC_ANN;
1954: }
1955: }
1956:
1957: void checkNonCyclicElementsInternal(DiagnosticPosition pos,
1958: TypeSymbol tsym) {
1959: if ((tsym.flags_field & ACYCLIC_ANN) != 0)
1960: return;
1961: if ((tsym.flags_field & LOCKED) != 0) {
1962: log.error(pos, "cyclic.annotation.element");
1963: return;
1964: }
1965: try {
1966: tsym.flags_field |= LOCKED;
1967: for (Scope.Entry e = tsym.members().elems; e != null; e = e.sibling) {
1968: Symbol s = e.sym;
1969: if (s.kind != Kinds.MTH)
1970: continue;
1971: checkAnnotationResType(pos, ((MethodSymbol) s).type
1972: .getReturnType());
1973: }
1974: } finally {
1975: tsym.flags_field &= ~LOCKED;
1976: tsym.flags_field |= ACYCLIC_ANN;
1977: }
1978: }
1979:
1980: void checkAnnotationResType(DiagnosticPosition pos, Type type) {
1981: switch (type.tag) {
1982: case TypeTags.CLASS:
1983: if ((type.tsym.flags() & ANNOTATION) != 0)
1984: checkNonCyclicElementsInternal(pos, type.tsym);
1985: break;
1986: case TypeTags.ARRAY:
1987: checkAnnotationResType(pos, types.elemtype(type));
1988: break;
1989: default:
1990: break; // int etc
1991: }
1992: }
1993:
1994: /* *************************************************************************
1995: * Check for cycles in the constructor call graph.
1996: **************************************************************************/
1997:
1998: /** Check for cycles in the graph of constructors calling other
1999: * constructors.
2000: */
2001: void checkCyclicConstructors(JCClassDecl tree) {
2002: Map<Symbol, Symbol> callMap = new HashMap<Symbol, Symbol>();
2003:
2004: // enter each constructor this-call into the map
2005: for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
2006: JCMethodInvocation app = TreeInfo
2007: .firstConstructorCall(l.head);
2008: if (app == null)
2009: continue;
2010: JCMethodDecl meth = (JCMethodDecl) l.head;
2011: if (TreeInfo.name(app.meth) == names._this ) {
2012: callMap.put(meth.sym, TreeInfo.symbol(app.meth));
2013: } else {
2014: meth.sym.flags_field |= ACYCLIC;
2015: }
2016: }
2017:
2018: // Check for cycles in the map
2019: Symbol[] ctors = new Symbol[0];
2020: ctors = callMap.keySet().toArray(ctors);
2021: for (Symbol caller : ctors) {
2022: checkCyclicConstructor(tree, caller, callMap);
2023: }
2024: }
2025:
2026: /** Look in the map to see if the given constructor is part of a
2027: * call cycle.
2028: */
2029: private void checkCyclicConstructor(JCClassDecl tree, Symbol ctor,
2030: Map<Symbol, Symbol> callMap) {
2031: if (ctor != null && (ctor.flags_field & ACYCLIC) == 0) {
2032: if ((ctor.flags_field & LOCKED) != 0) {
2033: log.error(TreeInfo.diagnosticPositionFor(ctor, tree),
2034: "recursive.ctor.invocation");
2035: } else {
2036: ctor.flags_field |= LOCKED;
2037: checkCyclicConstructor(tree, callMap.remove(ctor),
2038: callMap);
2039: ctor.flags_field &= ~LOCKED;
2040: }
2041: ctor.flags_field |= ACYCLIC;
2042: }
2043: }
2044:
2045: /* *************************************************************************
2046: * Miscellaneous
2047: **************************************************************************/
2048:
2049: /**
2050: * Return the opcode of the operator but emit an error if it is an
2051: * error.
2052: * @param pos position for error reporting.
2053: * @param operator an operator
2054: * @param tag a tree tag
2055: * @param left type of left hand side
2056: * @param right type of right hand side
2057: */
2058: int checkOperator(DiagnosticPosition pos, OperatorSymbol operator,
2059: int tag, Type left, Type right) {
2060: if (operator.opcode == ByteCodes.error) {
2061: log.error(pos, "operator.cant.be.applied", treeinfo
2062: .operatorName(tag), left + "," + right);
2063: }
2064: return operator.opcode;
2065: }
2066:
2067: /**
2068: * Check for division by integer constant zero
2069: * @param pos Position for error reporting.
2070: * @param operator The operator for the expression
2071: * @param operand The right hand operand for the expression
2072: */
2073: void checkDivZero(DiagnosticPosition pos, Symbol operator,
2074: Type operand) {
2075: if (operand.constValue() != null
2076: && lint.isEnabled(Lint.LintCategory.DIVZERO)
2077: && operand.tag <= LONG
2078: && ((Number) (operand.constValue())).longValue() == 0) {
2079: int opc = ((OperatorSymbol) operator).opcode;
2080: if (opc == ByteCodes.idiv || opc == ByteCodes.imod
2081: || opc == ByteCodes.ldiv || opc == ByteCodes.lmod) {
2082: log.warning(pos, "div.zero");
2083: }
2084: }
2085: }
2086:
2087: /**
2088: * Check for empty statements after if
2089: */
2090: void checkEmptyIf(JCIf tree) {
2091: if (tree.thenpart.getTag() == JCTree.SKIP
2092: && tree.elsepart == null
2093: && lint.isEnabled(Lint.LintCategory.EMPTY))
2094: log.warning(tree.thenpart.pos(), "empty.if");
2095: }
2096:
2097: /** Check that symbol is unique in given scope.
2098: * @param pos Position for error reporting.
2099: * @param sym The symbol.
2100: * @param s The scope.
2101: */
2102: boolean checkUnique(DiagnosticPosition pos, Symbol sym, Scope s) {
2103: if (sym.type.isErroneous())
2104: return true;
2105: if (sym.owner.name == names.any)
2106: return false;
2107: for (Scope.Entry e = s.lookup(sym.name); e.scope == s; e = e
2108: .next()) {
2109: if (sym != e.sym
2110: && sym.kind == e.sym.kind
2111: && sym.name != names.error
2112: && (sym.kind != MTH || types.overrideEquivalent(
2113: sym.type, e.sym.type))) {
2114: if ((sym.flags() & VARARGS) != (e.sym.flags() & VARARGS))
2115: varargsDuplicateError(pos, sym, e.sym);
2116: else
2117: duplicateError(pos, e.sym);
2118: return false;
2119: }
2120: }
2121: return true;
2122: }
2123:
2124: /** Check that single-type import is not already imported or top-level defined,
2125: * but make an exception for two single-type imports which denote the same type.
2126: * @param pos Position for error reporting.
2127: * @param sym The symbol.
2128: * @param s The scope
2129: */
2130: boolean checkUniqueImport(DiagnosticPosition pos, Symbol sym,
2131: Scope s) {
2132: return checkUniqueImport(pos, sym, s, false);
2133: }
2134:
2135: /** Check that static single-type import is not already imported or top-level defined,
2136: * but make an exception for two single-type imports which denote the same type.
2137: * @param pos Position for error reporting.
2138: * @param sym The symbol.
2139: * @param s The scope
2140: * @param staticImport Whether or not this was a static import
2141: */
2142: boolean checkUniqueStaticImport(DiagnosticPosition pos, Symbol sym,
2143: Scope s) {
2144: return checkUniqueImport(pos, sym, s, true);
2145: }
2146:
2147: /** Check that single-type import is not already imported or top-level defined,
2148: * but make an exception for two single-type imports which denote the same type.
2149: * @param pos Position for error reporting.
2150: * @param sym The symbol.
2151: * @param s The scope.
2152: * @param staticImport Whether or not this was a static import
2153: */
2154: private boolean checkUniqueImport(DiagnosticPosition pos,
2155: Symbol sym, Scope s, boolean staticImport) {
2156: for (Scope.Entry e = s.lookup(sym.name); e.scope != null; e = e
2157: .next()) {
2158: // is encountered class entered via a class declaration?
2159: boolean isClassDecl = e.scope == s;
2160: if ((isClassDecl || sym != e.sym) && sym.kind == e.sym.kind
2161: && sym.name != names.error) {
2162: if (!e.sym.type.isErroneous()) {
2163: String what = e.sym.toString();
2164: if (!isClassDecl) {
2165: if (staticImport)
2166: log
2167: .error(
2168: pos,
2169: "already.defined.static.single.import",
2170: what);
2171: else
2172: log.error(pos,
2173: "already.defined.single.import",
2174: what);
2175: } else if (sym != e.sym)
2176: log.error(pos, "already.defined.this.unit",
2177: what);
2178: }
2179: return false;
2180: }
2181: }
2182: return true;
2183: }
2184:
2185: /** Check that a qualified name is in canonical form (for import decls).
2186: */
2187: public void checkCanonical(JCTree tree) {
2188: if (!isCanonical(tree))
2189: log.error(tree.pos(), "import.requires.canonical", TreeInfo
2190: .symbol(tree));
2191: }
2192:
2193: // where
2194: private boolean isCanonical(JCTree tree) {
2195: while (tree.getTag() == JCTree.SELECT) {
2196: JCFieldAccess s = (JCFieldAccess) tree;
2197: if (s.sym.owner != TreeInfo.symbol(s.selected))
2198: return false;
2199: tree = s.selected;
2200: }
2201: return true;
2202: }
2203:
2204: private class ConversionWarner extends Warner {
2205: final String key;
2206: final Type found;
2207: final Type expected;
2208:
2209: public ConversionWarner(DiagnosticPosition pos, String key,
2210: Type found, Type expected) {
2211: super (pos);
2212: this .key = key;
2213: this .found = found;
2214: this .expected = expected;
2215: }
2216:
2217: public void warnUnchecked() {
2218: boolean warned = this .warned;
2219: super .warnUnchecked();
2220: if (warned)
2221: return; // suppress redundant diagnostics
2222: Object problem = JCDiagnostic.fragment(key);
2223: Check.this .warnUnchecked(pos(), "prob.found.req", problem,
2224: found, expected);
2225: }
2226: }
2227:
2228: public Warner castWarner(DiagnosticPosition pos, Type found,
2229: Type expected) {
2230: return new ConversionWarner(pos, "unchecked.cast.to.type",
2231: found, expected);
2232: }
2233:
2234: public Warner convertWarner(DiagnosticPosition pos, Type found,
2235: Type expected) {
2236: return new ConversionWarner(pos, "unchecked.assign", found,
2237: expected);
2238: }
2239: }
|