src/share/classes/com/sun/tools/javac/comp/Check.java

Print this page




  25 
  26 package com.sun.tools.javac.comp;
  27 
  28 import java.util.*;
  29 import java.util.Set;
  30 
  31 import com.sun.tools.javac.code.*;
  32 import com.sun.tools.javac.jvm.*;
  33 import com.sun.tools.javac.tree.*;
  34 import com.sun.tools.javac.util.*;
  35 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
  36 import com.sun.tools.javac.util.List;
  37 
  38 import com.sun.tools.javac.tree.JCTree.*;
  39 import com.sun.tools.javac.code.Lint;
  40 import com.sun.tools.javac.code.Lint.LintCategory;
  41 import com.sun.tools.javac.code.Type.*;
  42 import com.sun.tools.javac.code.Symbol.*;
  43 
  44 import static com.sun.tools.javac.code.Flags.*;


  45 import static com.sun.tools.javac.code.Kinds.*;
  46 import static com.sun.tools.javac.code.TypeTags.*;

  47 
  48 import static com.sun.tools.javac.main.OptionName.*;

  49 
  50 /** Type checking helper class for the attribution phase.
  51  *
  52  *  <p><b>This is NOT part of any supported API.
  53  *  If you write code that depends on this, you do so at your own risk.
  54  *  This code and its internal interfaces are subject to change or
  55  *  deletion without notice.</b>
  56  */
  57 public class Check {
  58     protected static final Context.Key<Check> checkKey =
  59         new Context.Key<Check>();
  60 
  61     private final Names names;
  62     private final Log log;
  63     private final Symtab syms;
  64     private final Enter enter;
  65     private final Infer infer;
  66     private final Types types;
  67     private final JCDiagnostic.Factory diags;
  68     private final boolean skipAnnotations;


 970                                VOLATILE)
 971                  &&
 972                  (sym.kind == TYP ||
 973                   checkDisjoint(pos, flags,
 974                                 ABSTRACT | NATIVE,
 975                                 STRICTFP))) {
 976             // skip
 977         }
 978         return flags & (mask | ~StandardFlags) | implicit;
 979     }
 980 
 981 
 982     /** Determine if this enum should be implicitly final.
 983      *
 984      *  If the enum has no specialized enum contants, it is final.
 985      *
 986      *  If the enum does have specialized enum contants, it is
 987      *  <i>not</i> final.
 988      */
 989     private long implicitEnumFinalFlag(JCTree tree) {
 990         if (tree.getTag() != JCTree.CLASSDEF) return 0;
 991         class SpecialTreeVisitor extends JCTree.Visitor {
 992             boolean specialized;
 993             SpecialTreeVisitor() {
 994                 this.specialized = false;
 995             };
 996 
 997             @Override
 998             public void visitTree(JCTree tree) { /* no-op */ }
 999 
1000             @Override
1001             public void visitVarDef(JCVariableDecl tree) {
1002                 if ((tree.mods.flags & ENUM) != 0) {
1003                     if (tree.init instanceof JCNewClass &&
1004                         ((JCNewClass) tree.init).def != null) {
1005                         specialized = true;
1006                     }
1007                 }
1008             }
1009         }
1010 


1082                  }
1083 
1084                 forms = tree.type.tsym.type.getTypeArguments();
1085 
1086                 boolean is_java_lang_Class = tree.type.tsym.flatName() == names.java_lang_Class;
1087 
1088                 // For matching pairs of actual argument types `a' and
1089                 // formal type parameters with declared bound `b' ...
1090                 while (args.nonEmpty() && forms.nonEmpty()) {
1091                     validateTree(args.head,
1092                             !(isOuter && is_java_lang_Class),
1093                             false);
1094                     args = args.tail;
1095                     forms = forms.tail;
1096                 }
1097 
1098                 // Check that this type is either fully parameterized, or
1099                 // not parameterized at all.
1100                 if (tree.type.getEnclosingType().isRaw())
1101                     log.error(tree.pos(), "improperly.formed.type.inner.raw.param");
1102                 if (tree.clazz.getTag() == JCTree.SELECT)
1103                     visitSelectInternal((JCFieldAccess)tree.clazz);
1104             }
1105         }
1106 
1107         @Override
1108         public void visitTypeParameter(JCTypeParameter tree) {
1109             validateTrees(tree.bounds, true, isOuter);
1110             checkClassBounds(tree.pos(), tree.type);
1111         }
1112 
1113         @Override
1114         public void visitWildcard(JCWildcard tree) {
1115             if (tree.inner != null)
1116                 validateTree(tree.inner, true, isOuter);
1117         }
1118 
1119         @Override
1120         public void visitSelect(JCFieldAccess tree) {
1121             if (tree.type.tag == CLASS) {
1122                 visitSelectInternal(tree);


2396         return false;
2397     }
2398 
2399     /** Check an annotation value.
2400      */
2401     public void validateAnnotation(JCAnnotation a) {
2402         // collect an inventory of the members (sorted alphabetically)
2403         Set<MethodSymbol> members = new TreeSet<MethodSymbol>(new Comparator<Symbol>() {
2404             public int compare(Symbol t, Symbol t1) {
2405                 return t.name.compareTo(t1.name);
2406             }
2407         });
2408         for (Scope.Entry e = a.annotationType.type.tsym.members().elems;
2409              e != null;
2410              e = e.sibling)
2411             if (e.sym.kind == MTH)
2412                 members.add((MethodSymbol) e.sym);
2413 
2414         // count them off as they're annotated
2415         for (JCTree arg : a.args) {
2416             if (arg.getTag() != JCTree.ASSIGN) continue; // recovery
2417             JCAssign assign = (JCAssign) arg;
2418             Symbol m = TreeInfo.symbol(assign.lhs);
2419             if (m == null || m.type.isErroneous()) continue;
2420             if (!members.remove(m))
2421                 log.error(assign.lhs.pos(), "duplicate.annotation.member.value",
2422                           m.name, a.type);
2423         }
2424 
2425         // all the remaining ones better have default values
2426         ListBuffer<Name> missingDefaults = ListBuffer.lb();
2427         for (MethodSymbol m : members) {
2428             if (m.defaultValue == null && !m.type.isErroneous()) {
2429                 missingDefaults.append(m.name);
2430             }
2431         }
2432         if (missingDefaults.nonEmpty()) {
2433             String key = (missingDefaults.size() > 1)
2434                     ? "annotation.missing.default.value.1"
2435                     : "annotation.missing.default.value";
2436             log.error(a.pos(), key, a.type, missingDefaults);
2437         }
2438 
2439         // special case: java.lang.annotation.Target must not have
2440         // repeated values in its value member
2441         if (a.annotationType.type.tsym != syms.annotationTargetType.tsym ||
2442             a.args.tail == null)
2443             return;
2444 
2445         if (a.args.head.getTag() != JCTree.ASSIGN) return; // error recovery
2446         JCAssign assign = (JCAssign) a.args.head;
2447         Symbol m = TreeInfo.symbol(assign.lhs);
2448         if (m.name != names.value) return;
2449         JCTree rhs = assign.rhs;
2450         if (rhs.getTag() != JCTree.NEWARRAY) return;
2451         JCNewArray na = (JCNewArray) rhs;
2452         Set<Symbol> targets = new HashSet<Symbol>();
2453         for (JCTree elem : na.elems) {
2454             if (!targets.add(TreeInfo.symbol(elem))) {
2455                 log.error(elem.pos(), "repeated.annotation.target");
2456             }
2457         }
2458     }
2459 
2460     void checkDeprecatedAnnotation(DiagnosticPosition pos, Symbol s) {
2461         if (allowAnnotations &&
2462             lint.isEnabled(LintCategory.DEP_ANN) &&
2463             (s.flags() & DEPRECATED) != 0 &&
2464             !syms.deprecatedType.isErroneous() &&
2465             s.attribute(syms.deprecatedType.tsym) == null) {
2466             log.warning(LintCategory.DEP_ANN,
2467                     pos, "missing.deprecated.annotation");
2468         }
2469     }
2470 


2489                       warnSunApi(pos, "sun.proprietary", s);
2490                     else
2491                       log.strictWarning(pos, "sun.proprietary", s);
2492                 }
2493             });
2494         }
2495     }
2496 
2497 /* *************************************************************************
2498  * Check for recursive annotation elements.
2499  **************************************************************************/
2500 
2501     /** Check for cycles in the graph of annotation elements.
2502      */
2503     void checkNonCyclicElements(JCClassDecl tree) {
2504         if ((tree.sym.flags_field & ANNOTATION) == 0) return;
2505         Assert.check((tree.sym.flags_field & LOCKED) == 0);
2506         try {
2507             tree.sym.flags_field |= LOCKED;
2508             for (JCTree def : tree.defs) {
2509                 if (def.getTag() != JCTree.METHODDEF) continue;
2510                 JCMethodDecl meth = (JCMethodDecl)def;
2511                 checkAnnotationResType(meth.pos(), meth.restype.type);
2512             }
2513         } finally {
2514             tree.sym.flags_field &= ~LOCKED;
2515             tree.sym.flags_field |= ACYCLIC_ANN;
2516         }
2517     }
2518 
2519     void checkNonCyclicElementsInternal(DiagnosticPosition pos, TypeSymbol tsym) {
2520         if ((tsym.flags_field & ACYCLIC_ANN) != 0)
2521             return;
2522         if ((tsym.flags_field & LOCKED) != 0) {
2523             log.error(pos, "cyclic.annotation.element");
2524             return;
2525         }
2526         try {
2527             tsym.flags_field |= LOCKED;
2528             for (Scope.Entry e = tsym.members().elems; e != null; e = e.sibling) {
2529                 Symbol s = e.sym;


2597             }
2598             ctor.flags_field |= ACYCLIC;
2599         }
2600     }
2601 
2602 /* *************************************************************************
2603  * Miscellaneous
2604  **************************************************************************/
2605 
2606     /**
2607      * Return the opcode of the operator but emit an error if it is an
2608      * error.
2609      * @param pos        position for error reporting.
2610      * @param operator   an operator
2611      * @param tag        a tree tag
2612      * @param left       type of left hand side
2613      * @param right      type of right hand side
2614      */
2615     int checkOperator(DiagnosticPosition pos,
2616                        OperatorSymbol operator,
2617                        int tag,
2618                        Type left,
2619                        Type right) {
2620         if (operator.opcode == ByteCodes.error) {
2621             log.error(pos,
2622                       "operator.cant.be.applied.1",
2623                       treeinfo.operatorName(tag),
2624                       left, right);
2625         }
2626         return operator.opcode;
2627     }
2628 
2629 
2630     /**
2631      *  Check for division by integer constant zero
2632      *  @param pos           Position for error reporting.
2633      *  @param operator      The operator for the expression
2634      *  @param operand       The right hand operand for the expression
2635      */
2636     void checkDivZero(DiagnosticPosition pos, Symbol operator, Type operand) {
2637         if (operand.constValue() != null
2638             && lint.isEnabled(LintCategory.DIVZERO)
2639             && operand.tag <= LONG
2640             && ((Number) (operand.constValue())).longValue() == 0) {
2641             int opc = ((OperatorSymbol)operator).opcode;
2642             if (opc == ByteCodes.idiv || opc == ByteCodes.imod
2643                 || opc == ByteCodes.ldiv || opc == ByteCodes.lmod) {
2644                 log.warning(LintCategory.DIVZERO, pos, "div.zero");
2645             }
2646         }
2647     }
2648 
2649     /**
2650      * Check for empty statements after if
2651      */
2652     void checkEmptyIf(JCIf tree) {
2653         if (tree.thenpart.getTag() == JCTree.SKIP && tree.elsepart == null && lint.isEnabled(LintCategory.EMPTY))

2654             log.warning(LintCategory.EMPTY, tree.thenpart.pos(), "empty.if");
2655     }
2656 
2657     /** Check that symbol is unique in given scope.
2658      *  @param pos           Position for error reporting.
2659      *  @param sym           The symbol.
2660      *  @param s             The scope.
2661      */
2662     boolean checkUnique(DiagnosticPosition pos, Symbol sym, Scope s) {
2663         if (sym.type.isErroneous())
2664             return true;
2665         if (sym.owner.name == names.any) return false;
2666         for (Scope.Entry e = s.lookup(sym.name); e.scope == s; e = e.next()) {
2667             if (sym != e.sym &&
2668                     (e.sym.flags() & CLASH) == 0 &&
2669                     sym.kind == e.sym.kind &&
2670                     sym.name != names.error &&
2671                     (sym.kind != MTH || types.hasSameArgs(types.erasure(sym.type), types.erasure(e.sym.type)))) {
2672                 if ((sym.flags() & VARARGS) != (e.sym.flags() & VARARGS)) {
2673                     varargsDuplicateError(pos, sym, e.sym);


2737                             log.error(pos, "already.defined.single.import", what);
2738                     }
2739                     else if (sym != e.sym)
2740                         log.error(pos, "already.defined.this.unit", what);
2741                 }
2742                 return false;
2743             }
2744         }
2745         return true;
2746     }
2747 
2748     /** Check that a qualified name is in canonical form (for import decls).
2749      */
2750     public void checkCanonical(JCTree tree) {
2751         if (!isCanonical(tree))
2752             log.error(tree.pos(), "import.requires.canonical",
2753                       TreeInfo.symbol(tree));
2754     }
2755         // where
2756         private boolean isCanonical(JCTree tree) {
2757             while (tree.getTag() == JCTree.SELECT) {
2758                 JCFieldAccess s = (JCFieldAccess) tree;
2759                 if (s.sym.owner != TreeInfo.symbol(s.selected))
2760                     return false;
2761                 tree = s.selected;
2762             }
2763             return true;
2764         }
2765 
2766     private class ConversionWarner extends Warner {
2767         final String uncheckedKey;
2768         final Type found;
2769         final Type expected;
2770         public ConversionWarner(DiagnosticPosition pos, String uncheckedKey, Type found, Type expected) {
2771             super(pos);
2772             this.uncheckedKey = uncheckedKey;
2773             this.found = found;
2774             this.expected = expected;
2775         }
2776 
2777         @Override




  25 
  26 package com.sun.tools.javac.comp;
  27 
  28 import java.util.*;
  29 import java.util.Set;
  30 
  31 import com.sun.tools.javac.code.*;
  32 import com.sun.tools.javac.jvm.*;
  33 import com.sun.tools.javac.tree.*;
  34 import com.sun.tools.javac.util.*;
  35 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
  36 import com.sun.tools.javac.util.List;
  37 
  38 import com.sun.tools.javac.tree.JCTree.*;
  39 import com.sun.tools.javac.code.Lint;
  40 import com.sun.tools.javac.code.Lint.LintCategory;
  41 import com.sun.tools.javac.code.Type.*;
  42 import com.sun.tools.javac.code.Symbol.*;
  43 
  44 import static com.sun.tools.javac.code.Flags.*;
  45 import static com.sun.tools.javac.code.Flags.SYNCHRONIZED;
  46 import static com.sun.tools.javac.code.Flags.ANNOTATION;
  47 import static com.sun.tools.javac.code.Kinds.*;
  48 import static com.sun.tools.javac.code.TypeTags.*;
  49 import static com.sun.tools.javac.code.TypeTags.WILDCARD;
  50 
  51 import static com.sun.tools.javac.main.OptionName.*;
  52 import static com.sun.tools.javac.tree.JCTree.Tag.*;
  53 
  54 /** Type checking helper class for the attribution phase.
  55  *
  56  *  <p><b>This is NOT part of any supported API.
  57  *  If you write code that depends on this, you do so at your own risk.
  58  *  This code and its internal interfaces are subject to change or
  59  *  deletion without notice.</b>
  60  */
  61 public class Check {
  62     protected static final Context.Key<Check> checkKey =
  63         new Context.Key<Check>();
  64 
  65     private final Names names;
  66     private final Log log;
  67     private final Symtab syms;
  68     private final Enter enter;
  69     private final Infer infer;
  70     private final Types types;
  71     private final JCDiagnostic.Factory diags;
  72     private final boolean skipAnnotations;


 974                                VOLATILE)
 975                  &&
 976                  (sym.kind == TYP ||
 977                   checkDisjoint(pos, flags,
 978                                 ABSTRACT | NATIVE,
 979                                 STRICTFP))) {
 980             // skip
 981         }
 982         return flags & (mask | ~StandardFlags) | implicit;
 983     }
 984 
 985 
 986     /** Determine if this enum should be implicitly final.
 987      *
 988      *  If the enum has no specialized enum contants, it is final.
 989      *
 990      *  If the enum does have specialized enum contants, it is
 991      *  <i>not</i> final.
 992      */
 993     private long implicitEnumFinalFlag(JCTree tree) {
 994         if (!tree.hasTag(CLASSDEF)) return 0;
 995         class SpecialTreeVisitor extends JCTree.Visitor {
 996             boolean specialized;
 997             SpecialTreeVisitor() {
 998                 this.specialized = false;
 999             };
1000 
1001             @Override
1002             public void visitTree(JCTree tree) { /* no-op */ }
1003 
1004             @Override
1005             public void visitVarDef(JCVariableDecl tree) {
1006                 if ((tree.mods.flags & ENUM) != 0) {
1007                     if (tree.init instanceof JCNewClass &&
1008                         ((JCNewClass) tree.init).def != null) {
1009                         specialized = true;
1010                     }
1011                 }
1012             }
1013         }
1014 


1086                  }
1087 
1088                 forms = tree.type.tsym.type.getTypeArguments();
1089 
1090                 boolean is_java_lang_Class = tree.type.tsym.flatName() == names.java_lang_Class;
1091 
1092                 // For matching pairs of actual argument types `a' and
1093                 // formal type parameters with declared bound `b' ...
1094                 while (args.nonEmpty() && forms.nonEmpty()) {
1095                     validateTree(args.head,
1096                             !(isOuter && is_java_lang_Class),
1097                             false);
1098                     args = args.tail;
1099                     forms = forms.tail;
1100                 }
1101 
1102                 // Check that this type is either fully parameterized, or
1103                 // not parameterized at all.
1104                 if (tree.type.getEnclosingType().isRaw())
1105                     log.error(tree.pos(), "improperly.formed.type.inner.raw.param");
1106                 if (tree.clazz.hasTag(SELECT))
1107                     visitSelectInternal((JCFieldAccess)tree.clazz);
1108             }
1109         }
1110 
1111         @Override
1112         public void visitTypeParameter(JCTypeParameter tree) {
1113             validateTrees(tree.bounds, true, isOuter);
1114             checkClassBounds(tree.pos(), tree.type);
1115         }
1116 
1117         @Override
1118         public void visitWildcard(JCWildcard tree) {
1119             if (tree.inner != null)
1120                 validateTree(tree.inner, true, isOuter);
1121         }
1122 
1123         @Override
1124         public void visitSelect(JCFieldAccess tree) {
1125             if (tree.type.tag == CLASS) {
1126                 visitSelectInternal(tree);


2400         return false;
2401     }
2402 
2403     /** Check an annotation value.
2404      */
2405     public void validateAnnotation(JCAnnotation a) {
2406         // collect an inventory of the members (sorted alphabetically)
2407         Set<MethodSymbol> members = new TreeSet<MethodSymbol>(new Comparator<Symbol>() {
2408             public int compare(Symbol t, Symbol t1) {
2409                 return t.name.compareTo(t1.name);
2410             }
2411         });
2412         for (Scope.Entry e = a.annotationType.type.tsym.members().elems;
2413              e != null;
2414              e = e.sibling)
2415             if (e.sym.kind == MTH)
2416                 members.add((MethodSymbol) e.sym);
2417 
2418         // count them off as they're annotated
2419         for (JCTree arg : a.args) {
2420             if (!arg.hasTag(ASSIGN)) continue; // recovery
2421             JCAssign assign = (JCAssign) arg;
2422             Symbol m = TreeInfo.symbol(assign.lhs);
2423             if (m == null || m.type.isErroneous()) continue;
2424             if (!members.remove(m))
2425                 log.error(assign.lhs.pos(), "duplicate.annotation.member.value",
2426                           m.name, a.type);
2427         }
2428 
2429         // all the remaining ones better have default values
2430         ListBuffer<Name> missingDefaults = ListBuffer.lb();
2431         for (MethodSymbol m : members) {
2432             if (m.defaultValue == null && !m.type.isErroneous()) {
2433                 missingDefaults.append(m.name);
2434             }
2435         }
2436         if (missingDefaults.nonEmpty()) {
2437             String key = (missingDefaults.size() > 1)
2438                     ? "annotation.missing.default.value.1"
2439                     : "annotation.missing.default.value";
2440             log.error(a.pos(), key, a.type, missingDefaults);
2441         }
2442 
2443         // special case: java.lang.annotation.Target must not have
2444         // repeated values in its value member
2445         if (a.annotationType.type.tsym != syms.annotationTargetType.tsym ||
2446             a.args.tail == null)
2447             return;
2448 
2449         if (!a.args.head.hasTag(ASSIGN)) return; // error recovery
2450         JCAssign assign = (JCAssign) a.args.head;
2451         Symbol m = TreeInfo.symbol(assign.lhs);
2452         if (m.name != names.value) return;
2453         JCTree rhs = assign.rhs;
2454         if (!rhs.hasTag(NEWARRAY)) return;
2455         JCNewArray na = (JCNewArray) rhs;
2456         Set<Symbol> targets = new HashSet<Symbol>();
2457         for (JCTree elem : na.elems) {
2458             if (!targets.add(TreeInfo.symbol(elem))) {
2459                 log.error(elem.pos(), "repeated.annotation.target");
2460             }
2461         }
2462     }
2463 
2464     void checkDeprecatedAnnotation(DiagnosticPosition pos, Symbol s) {
2465         if (allowAnnotations &&
2466             lint.isEnabled(LintCategory.DEP_ANN) &&
2467             (s.flags() & DEPRECATED) != 0 &&
2468             !syms.deprecatedType.isErroneous() &&
2469             s.attribute(syms.deprecatedType.tsym) == null) {
2470             log.warning(LintCategory.DEP_ANN,
2471                     pos, "missing.deprecated.annotation");
2472         }
2473     }
2474 


2493                       warnSunApi(pos, "sun.proprietary", s);
2494                     else
2495                       log.strictWarning(pos, "sun.proprietary", s);
2496                 }
2497             });
2498         }
2499     }
2500 
2501 /* *************************************************************************
2502  * Check for recursive annotation elements.
2503  **************************************************************************/
2504 
2505     /** Check for cycles in the graph of annotation elements.
2506      */
2507     void checkNonCyclicElements(JCClassDecl tree) {
2508         if ((tree.sym.flags_field & ANNOTATION) == 0) return;
2509         Assert.check((tree.sym.flags_field & LOCKED) == 0);
2510         try {
2511             tree.sym.flags_field |= LOCKED;
2512             for (JCTree def : tree.defs) {
2513                 if (!def.hasTag(METHODDEF)) continue;
2514                 JCMethodDecl meth = (JCMethodDecl)def;
2515                 checkAnnotationResType(meth.pos(), meth.restype.type);
2516             }
2517         } finally {
2518             tree.sym.flags_field &= ~LOCKED;
2519             tree.sym.flags_field |= ACYCLIC_ANN;
2520         }
2521     }
2522 
2523     void checkNonCyclicElementsInternal(DiagnosticPosition pos, TypeSymbol tsym) {
2524         if ((tsym.flags_field & ACYCLIC_ANN) != 0)
2525             return;
2526         if ((tsym.flags_field & LOCKED) != 0) {
2527             log.error(pos, "cyclic.annotation.element");
2528             return;
2529         }
2530         try {
2531             tsym.flags_field |= LOCKED;
2532             for (Scope.Entry e = tsym.members().elems; e != null; e = e.sibling) {
2533                 Symbol s = e.sym;


2601             }
2602             ctor.flags_field |= ACYCLIC;
2603         }
2604     }
2605 
2606 /* *************************************************************************
2607  * Miscellaneous
2608  **************************************************************************/
2609 
2610     /**
2611      * Return the opcode of the operator but emit an error if it is an
2612      * error.
2613      * @param pos        position for error reporting.
2614      * @param operator   an operator
2615      * @param tag        a tree tag
2616      * @param left       type of left hand side
2617      * @param right      type of right hand side
2618      */
2619     int checkOperator(DiagnosticPosition pos,
2620                        OperatorSymbol operator,
2621                        JCTree.Tag tag,
2622                        Type left,
2623                        Type right) {
2624         if (operator.opcode == ByteCodes.error) {
2625             log.error(pos,
2626                       "operator.cant.be.applied.1",
2627                       treeinfo.operatorName(tag),
2628                       left, right);
2629         }
2630         return operator.opcode;
2631     }
2632 
2633 
2634     /**
2635      *  Check for division by integer constant zero
2636      *  @param pos           Position for error reporting.
2637      *  @param operator      The operator for the expression
2638      *  @param operand       The right hand operand for the expression
2639      */
2640     void checkDivZero(DiagnosticPosition pos, Symbol operator, Type operand) {
2641         if (operand.constValue() != null
2642             && lint.isEnabled(LintCategory.DIVZERO)
2643             && operand.tag <= LONG
2644             && ((Number) (operand.constValue())).longValue() == 0) {
2645             int opc = ((OperatorSymbol)operator).opcode;
2646             if (opc == ByteCodes.idiv || opc == ByteCodes.imod
2647                 || opc == ByteCodes.ldiv || opc == ByteCodes.lmod) {
2648                 log.warning(LintCategory.DIVZERO, pos, "div.zero");
2649             }
2650         }
2651     }
2652 
2653     /**
2654      * Check for empty statements after if
2655      */
2656     void checkEmptyIf(JCIf tree) {
2657         if (tree.thenpart.hasTag(SKIP) && tree.elsepart == null && 
2658                 lint.isEnabled(LintCategory.EMPTY))
2659             log.warning(LintCategory.EMPTY, tree.thenpart.pos(), "empty.if");
2660     }
2661 
2662     /** Check that symbol is unique in given scope.
2663      *  @param pos           Position for error reporting.
2664      *  @param sym           The symbol.
2665      *  @param s             The scope.
2666      */
2667     boolean checkUnique(DiagnosticPosition pos, Symbol sym, Scope s) {
2668         if (sym.type.isErroneous())
2669             return true;
2670         if (sym.owner.name == names.any) return false;
2671         for (Scope.Entry e = s.lookup(sym.name); e.scope == s; e = e.next()) {
2672             if (sym != e.sym &&
2673                     (e.sym.flags() & CLASH) == 0 &&
2674                     sym.kind == e.sym.kind &&
2675                     sym.name != names.error &&
2676                     (sym.kind != MTH || types.hasSameArgs(types.erasure(sym.type), types.erasure(e.sym.type)))) {
2677                 if ((sym.flags() & VARARGS) != (e.sym.flags() & VARARGS)) {
2678                     varargsDuplicateError(pos, sym, e.sym);


2742                             log.error(pos, "already.defined.single.import", what);
2743                     }
2744                     else if (sym != e.sym)
2745                         log.error(pos, "already.defined.this.unit", what);
2746                 }
2747                 return false;
2748             }
2749         }
2750         return true;
2751     }
2752 
2753     /** Check that a qualified name is in canonical form (for import decls).
2754      */
2755     public void checkCanonical(JCTree tree) {
2756         if (!isCanonical(tree))
2757             log.error(tree.pos(), "import.requires.canonical",
2758                       TreeInfo.symbol(tree));
2759     }
2760         // where
2761         private boolean isCanonical(JCTree tree) {
2762             while (tree.hasTag(SELECT)) {
2763                 JCFieldAccess s = (JCFieldAccess) tree;
2764                 if (s.sym.owner != TreeInfo.symbol(s.selected))
2765                     return false;
2766                 tree = s.selected;
2767             }
2768             return true;
2769         }
2770 
2771     private class ConversionWarner extends Warner {
2772         final String uncheckedKey;
2773         final Type found;
2774         final Type expected;
2775         public ConversionWarner(DiagnosticPosition pos, String uncheckedKey, Type found, Type expected) {
2776             super(pos);
2777             this.uncheckedKey = uncheckedKey;
2778             this.found = found;
2779             this.expected = expected;
2780         }
2781 
2782         @Override