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

Print this page




 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




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


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