langtools/src/share/classes/com/sun/tools/javac/comp/Check.java
changeset 7643 a067a0cda531
parent 7628 e7baeb97d164
child 7681 1f0819a3341f
equal deleted inserted replaced
7642:9ca5d29b34f7 7643:a067a0cda531
    73     // The set of lint options currently in effect. It is initialized
    73     // The set of lint options currently in effect. It is initialized
    74     // from the context, and then is set/reset as needed by Attr as it
    74     // from the context, and then is set/reset as needed by Attr as it
    75     // visits all the various parts of the trees during attribution.
    75     // visits all the various parts of the trees during attribution.
    76     private Lint lint;
    76     private Lint lint;
    77 
    77 
       
    78     // The method being analyzed in Attr - it is set/reset as needed by
       
    79     // Attr as it visits new method declarations.
       
    80     private MethodSymbol method;
       
    81 
    78     public static Check instance(Context context) {
    82     public static Check instance(Context context) {
    79         Check instance = context.get(checkKey);
    83         Check instance = context.get(checkKey);
    80         if (instance == null)
    84         if (instance == null)
    81             instance = new Check(context);
    85             instance = new Check(context);
    82         return instance;
    86         return instance;
    98 
   102 
    99         Source source = Source.instance(context);
   103         Source source = Source.instance(context);
   100         allowGenerics = source.allowGenerics();
   104         allowGenerics = source.allowGenerics();
   101         allowAnnotations = source.allowAnnotations();
   105         allowAnnotations = source.allowAnnotations();
   102         allowCovariantReturns = source.allowCovariantReturns();
   106         allowCovariantReturns = source.allowCovariantReturns();
       
   107         allowSimplifiedVarargs = source.allowSimplifiedVarargs();
   103         complexInference = options.isSet(COMPLEXINFERENCE);
   108         complexInference = options.isSet(COMPLEXINFERENCE);
   104         skipAnnotations = options.isSet("skipAnnotations");
   109         skipAnnotations = options.isSet("skipAnnotations");
   105         warnOnSyntheticConflicts = options.isSet("warnOnSyntheticConflicts");
   110         warnOnSyntheticConflicts = options.isSet("warnOnSyntheticConflicts");
   106         suppressAbortOnBadClassFile = options.isSet("suppressAbortOnBadClassFile");
   111         suppressAbortOnBadClassFile = options.isSet("suppressAbortOnBadClassFile");
   107 
   112 
   134 
   139 
   135     /** Switch: covariant returns enabled?
   140     /** Switch: covariant returns enabled?
   136      */
   141      */
   137     boolean allowCovariantReturns;
   142     boolean allowCovariantReturns;
   138 
   143 
       
   144     /** Switch: simplified varargs enabled?
       
   145      */
       
   146     boolean allowSimplifiedVarargs;
       
   147 
   139     /** Switch: -complexinference option set?
   148     /** Switch: -complexinference option set?
   140      */
   149      */
   141     boolean complexInference;
   150     boolean complexInference;
   142 
   151 
   143     /** Character for synthetic names
   152     /** Character for synthetic names
   173         Lint prev = lint;
   182         Lint prev = lint;
   174         lint = newLint;
   183         lint = newLint;
   175         return prev;
   184         return prev;
   176     }
   185     }
   177 
   186 
       
   187     MethodSymbol setMethod(MethodSymbol newMethod) {
       
   188         MethodSymbol prev = method;
       
   189         method = newMethod;
       
   190         return prev;
       
   191     }
       
   192 
   178     /** Warn about deprecated symbol.
   193     /** Warn about deprecated symbol.
   179      *  @param pos        Position to be used for error reporting.
   194      *  @param pos        Position to be used for error reporting.
   180      *  @param sym        The deprecated symbol.
   195      *  @param sym        The deprecated symbol.
   181      */
   196      */
   182     void warnDeprecated(DiagnosticPosition pos, Symbol sym) {
   197     void warnDeprecated(DiagnosticPosition pos, Symbol sym) {
   195 
   210 
   196     /** Warn about unsafe vararg method decl.
   211     /** Warn about unsafe vararg method decl.
   197      *  @param pos        Position to be used for error reporting.
   212      *  @param pos        Position to be used for error reporting.
   198      *  @param sym        The deprecated symbol.
   213      *  @param sym        The deprecated symbol.
   199      */
   214      */
   200     void warnUnsafeVararg(DiagnosticPosition pos, Type elemType) {
   215     void warnUnsafeVararg(DiagnosticPosition pos, String key, Object... args) {
   201         if (!lint.isSuppressed(LintCategory.VARARGS))
   216         if (lint.isEnabled(LintCategory.VARARGS) && allowSimplifiedVarargs)
   202             unsafeVarargsHandler.report(pos, "varargs.non.reifiable.type", elemType);
   217             log.warning(LintCategory.VARARGS, pos, key, args);
   203     }
   218     }
   204 
   219 
   205     /** Warn about using proprietary API.
   220     /** Warn about using proprietary API.
   206      *  @param pos        Position to be used for error reporting.
   221      *  @param pos        Position to be used for error reporting.
   207      *  @param msg        A string describing the problem.
   222      *  @param msg        A string describing the problem.
   220      * Report any deferred diagnostics.
   235      * Report any deferred diagnostics.
   221      */
   236      */
   222     public void reportDeferredDiagnostics() {
   237     public void reportDeferredDiagnostics() {
   223         deprecationHandler.reportDeferredDiagnostic();
   238         deprecationHandler.reportDeferredDiagnostic();
   224         uncheckedHandler.reportDeferredDiagnostic();
   239         uncheckedHandler.reportDeferredDiagnostic();
   225         unsafeVarargsHandler.reportDeferredDiagnostic();
       
   226         sunApiHandler.reportDeferredDiagnostic();
   240         sunApiHandler.reportDeferredDiagnostic();
   227     }
   241     }
   228 
   242 
   229 
   243 
   230     /** Report a failure to complete a class.
   244     /** Report a failure to complete a class.
   703         public Boolean visitCapturedType(CapturedType t, Void s) {
   717         public Boolean visitCapturedType(CapturedType t, Void s) {
   704             return false;
   718             return false;
   705         }
   719         }
   706     }
   720     }
   707 
   721 
   708     void checkVarargMethodDecl(JCMethodDecl tree) {
   722     void checkVarargsMethodDecl(Env<AttrContext> env, JCMethodDecl tree) {
   709         MethodSymbol m = tree.sym;
   723         MethodSymbol m = tree.sym;
   710         //check the element type of the vararg
   724         if (!allowSimplifiedVarargs) return;
       
   725         boolean hasTrustMeAnno = m.attribute(syms.trustMeType.tsym) != null;
       
   726         Type varargElemType = null;
   711         if (m.isVarArgs()) {
   727         if (m.isVarArgs()) {
   712             Type varargElemType = types.elemtype(tree.params.last().type);
   728             varargElemType = types.elemtype(tree.params.last().type);
   713             if (!types.isReifiable(varargElemType)) {
   729         }
   714                 warnUnsafeVararg(tree.params.head.pos(), varargElemType);
   730         if (hasTrustMeAnno && !isTrustMeAllowedOnMethod(m)) {
   715             }
   731             if (varargElemType != null) {
   716         }
   732                 log.error(tree,
   717     }
   733                         "varargs.invalid.trustme.anno",
       
   734                         syms.trustMeType.tsym,
       
   735                         diags.fragment("varargs.trustme.on.virtual.varargs", m));
       
   736             } else {
       
   737                 log.error(tree,
       
   738                             "varargs.invalid.trustme.anno",
       
   739                             syms.trustMeType.tsym,
       
   740                             diags.fragment("varargs.trustme.on.non.varargs.meth", m));
       
   741             }
       
   742         } else if (hasTrustMeAnno && varargElemType != null &&
       
   743                             types.isReifiable(varargElemType)) {
       
   744             warnUnsafeVararg(tree,
       
   745                             "varargs.redundant.trustme.anno",
       
   746                             syms.trustMeType.tsym,
       
   747                             diags.fragment("varargs.trustme.on.reifiable.varargs", varargElemType));
       
   748         }
       
   749         else if (!hasTrustMeAnno && varargElemType != null &&
       
   750                 !types.isReifiable(varargElemType)) {
       
   751             warnUnchecked(tree.params.head.pos(), "unchecked.varargs.non.reifiable.type", varargElemType);
       
   752         }
       
   753     }
       
   754     //where
       
   755         private boolean isTrustMeAllowedOnMethod(Symbol s) {
       
   756             return (s.flags() & VARARGS) != 0 &&
       
   757                 (s.isConstructor() ||
       
   758                     (s.flags() & (STATIC | FINAL)) != 0);
       
   759         }
   718 
   760 
   719     /**
   761     /**
   720      * Check that vararg method call is sound
   762      * Check that vararg method call is sound
   721      * @param pos Position to be used for error reporting.
   763      * @param pos Position to be used for error reporting.
   722      * @param argtypes Actual arguments supplied to vararg method.
   764      * @param argtypes Actual arguments supplied to vararg method.
   723      */
   765      */
   724     void checkVararg(DiagnosticPosition pos, List<Type> argtypes, Symbol msym, Env<AttrContext> env) {
   766     void checkVararg(DiagnosticPosition pos, List<Type> argtypes, Symbol msym) {
   725         Env<AttrContext> calleeLintEnv = env;
       
   726         while (calleeLintEnv.info.lint == null)
       
   727             calleeLintEnv = calleeLintEnv.next;
       
   728         Lint calleeLint = calleeLintEnv.info.lint.augment(msym.attributes_field, msym.flags());
       
   729         Type argtype = argtypes.last();
   767         Type argtype = argtypes.last();
   730         if (!types.isReifiable(argtype) && !calleeLint.isSuppressed(Lint.LintCategory.VARARGS)) {
   768         if (!types.isReifiable(argtype) &&
       
   769                 (!allowSimplifiedVarargs ||
       
   770                 msym.attribute(syms.trustMeType.tsym) == null ||
       
   771                 !isTrustMeAllowedOnMethod(msym))) {
   731             warnUnchecked(pos,
   772             warnUnchecked(pos,
   732                               "unchecked.generic.array.creation",
   773                               "unchecked.generic.array.creation",
   733                               argtype);
   774                               argtype);
   734         }
   775         }
   735     }
   776     }
  1073             for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail)
  1114             for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail)
  1074                 validateTree(l.head, checkRaw, isOuter);
  1115                 validateTree(l.head, checkRaw, isOuter);
  1075         }
  1116         }
  1076 
  1117 
  1077         void checkRaw(JCTree tree, Env<AttrContext> env) {
  1118         void checkRaw(JCTree tree, Env<AttrContext> env) {
  1078             if (lint.isEnabled(Lint.LintCategory.RAW) &&
  1119             if (lint.isEnabled(LintCategory.RAW) &&
  1079                 tree.type.tag == CLASS &&
  1120                 tree.type.tag == CLASS &&
  1080                 !TreeInfo.isDiamond(tree) &&
  1121                 !TreeInfo.isDiamond(tree) &&
  1081                 !env.enclClass.name.isEmpty() &&  //anonymous or intersection
  1122                 !env.enclClass.name.isEmpty() &&  //anonymous or intersection
  1082                 tree.type.isRaw()) {
  1123                 tree.type.isRaw()) {
  1083                 log.warning(Lint.LintCategory.RAW,
  1124                 log.warning(LintCategory.RAW,
  1084                         tree.pos(), "raw.class.use", tree.type, tree.type.tsym.type);
  1125                         tree.pos(), "raw.class.use", tree.type, tree.type.tsym.type);
  1085             }
  1126             }
  1086         }
  1127         }
  1087     }
  1128     }
  1088 
  1129 
  1345         List<Type> mtvars = mt.getTypeArguments();
  1386         List<Type> mtvars = mt.getTypeArguments();
  1346         List<Type> otvars = ot.getTypeArguments();
  1387         List<Type> otvars = ot.getTypeArguments();
  1347         Type mtres = mt.getReturnType();
  1388         Type mtres = mt.getReturnType();
  1348         Type otres = types.subst(ot.getReturnType(), otvars, mtvars);
  1389         Type otres = types.subst(ot.getReturnType(), otvars, mtvars);
  1349 
  1390 
  1350         overrideWarner.warned = false;
  1391         overrideWarner.clear();
  1351         boolean resultTypesOK =
  1392         boolean resultTypesOK =
  1352             types.returnTypeSubstitutable(mt, ot, otres, overrideWarner);
  1393             types.returnTypeSubstitutable(mt, ot, otres, overrideWarner);
  1353         if (!resultTypesOK) {
  1394         if (!resultTypesOK) {
  1354             if (!allowCovariantReturns &&
  1395             if (!allowCovariantReturns &&
  1355                 m.owner != origin &&
  1396                 m.owner != origin &&
  1360                           "override.incompatible.ret",
  1401                           "override.incompatible.ret",
  1361                           cannotOverride(m, other),
  1402                           cannotOverride(m, other),
  1362                           mtres, otres);
  1403                           mtres, otres);
  1363                 return;
  1404                 return;
  1364             }
  1405             }
  1365         } else if (overrideWarner.warned) {
  1406         } else if (overrideWarner.hasNonSilentLint(LintCategory.UNCHECKED)) {
  1366             warnUnchecked(TreeInfo.diagnosticPositionFor(m, tree),
  1407             warnUnchecked(TreeInfo.diagnosticPositionFor(m, tree),
  1367                     "override.unchecked.ret",
  1408                     "override.unchecked.ret",
  1368                     uncheckedOverrides(m, other),
  1409                     uncheckedOverrides(m, other),
  1369                     mtres, otres);
  1410                     mtres, otres);
  1370         }
  1411         }
  1389             return;
  1430             return;
  1390         }
  1431         }
  1391 
  1432 
  1392         // Optional warning if varargs don't agree
  1433         // Optional warning if varargs don't agree
  1393         if ((((m.flags() ^ other.flags()) & Flags.VARARGS) != 0)
  1434         if ((((m.flags() ^ other.flags()) & Flags.VARARGS) != 0)
  1394             && lint.isEnabled(Lint.LintCategory.OVERRIDES)) {
  1435             && lint.isEnabled(LintCategory.OVERRIDES)) {
  1395             log.warning(TreeInfo.diagnosticPositionFor(m, tree),
  1436             log.warning(TreeInfo.diagnosticPositionFor(m, tree),
  1396                         ((m.flags() & Flags.VARARGS) != 0)
  1437                         ((m.flags() & Flags.VARARGS) != 0)
  1397                         ? "override.varargs.missing"
  1438                         ? "override.varargs.missing"
  1398                         : "override.varargs.extra",
  1439                         : "override.varargs.extra",
  1399                         varargsOverrides(m, other));
  1440                         varargsOverrides(m, other));
  2378         }
  2419         }
  2379     }
  2420     }
  2380 
  2421 
  2381     void checkDeprecatedAnnotation(DiagnosticPosition pos, Symbol s) {
  2422     void checkDeprecatedAnnotation(DiagnosticPosition pos, Symbol s) {
  2382         if (allowAnnotations &&
  2423         if (allowAnnotations &&
  2383             lint.isEnabled(Lint.LintCategory.DEP_ANN) &&
  2424             lint.isEnabled(LintCategory.DEP_ANN) &&
  2384             (s.flags() & DEPRECATED) != 0 &&
  2425             (s.flags() & DEPRECATED) != 0 &&
  2385             !syms.deprecatedType.isErroneous() &&
  2426             !syms.deprecatedType.isErroneous() &&
  2386             s.attribute(syms.deprecatedType.tsym) == null) {
  2427             s.attribute(syms.deprecatedType.tsym) == null) {
  2387             log.warning(Lint.LintCategory.DEP_ANN,
  2428             log.warning(LintCategory.DEP_ANN,
  2388                     pos, "missing.deprecated.annotation");
  2429                     pos, "missing.deprecated.annotation");
  2389         }
  2430         }
  2390     }
  2431     }
  2391 
  2432 
  2392 /* *************************************************************************
  2433 /* *************************************************************************
  2528      *  @param operator      The operator for the expression
  2569      *  @param operator      The operator for the expression
  2529      *  @param operand       The right hand operand for the expression
  2570      *  @param operand       The right hand operand for the expression
  2530      */
  2571      */
  2531     void checkDivZero(DiagnosticPosition pos, Symbol operator, Type operand) {
  2572     void checkDivZero(DiagnosticPosition pos, Symbol operator, Type operand) {
  2532         if (operand.constValue() != null
  2573         if (operand.constValue() != null
  2533             && lint.isEnabled(Lint.LintCategory.DIVZERO)
  2574             && lint.isEnabled(LintCategory.DIVZERO)
  2534             && operand.tag <= LONG
  2575             && operand.tag <= LONG
  2535             && ((Number) (operand.constValue())).longValue() == 0) {
  2576             && ((Number) (operand.constValue())).longValue() == 0) {
  2536             int opc = ((OperatorSymbol)operator).opcode;
  2577             int opc = ((OperatorSymbol)operator).opcode;
  2537             if (opc == ByteCodes.idiv || opc == ByteCodes.imod
  2578             if (opc == ByteCodes.idiv || opc == ByteCodes.imod
  2538                 || opc == ByteCodes.ldiv || opc == ByteCodes.lmod) {
  2579                 || opc == ByteCodes.ldiv || opc == ByteCodes.lmod) {
  2539                 log.warning(Lint.LintCategory.DIVZERO, pos, "div.zero");
  2580                 log.warning(LintCategory.DIVZERO, pos, "div.zero");
  2540             }
  2581             }
  2541         }
  2582         }
  2542     }
  2583     }
  2543 
  2584 
  2544     /**
  2585     /**
  2545      * Check for empty statements after if
  2586      * Check for empty statements after if
  2546      */
  2587      */
  2547     void checkEmptyIf(JCIf tree) {
  2588     void checkEmptyIf(JCIf tree) {
  2548         if (tree.thenpart.getTag() == JCTree.SKIP && tree.elsepart == null && lint.isEnabled(Lint.LintCategory.EMPTY))
  2589         if (tree.thenpart.getTag() == JCTree.SKIP && tree.elsepart == null && lint.isEnabled(LintCategory.EMPTY))
  2549             log.warning(Lint.LintCategory.EMPTY, tree.thenpart.pos(), "empty.if");
  2590             log.warning(LintCategory.EMPTY, tree.thenpart.pos(), "empty.if");
  2550     }
  2591     }
  2551 
  2592 
  2552     /** Check that symbol is unique in given scope.
  2593     /** Check that symbol is unique in given scope.
  2553      *  @param pos           Position for error reporting.
  2594      *  @param pos           Position for error reporting.
  2554      *  @param sym           The symbol.
  2595      *  @param sym           The symbol.
  2652             }
  2693             }
  2653             return true;
  2694             return true;
  2654         }
  2695         }
  2655 
  2696 
  2656     private class ConversionWarner extends Warner {
  2697     private class ConversionWarner extends Warner {
  2657         final String key;
  2698         final String uncheckedKey;
  2658         final Type found;
  2699         final Type found;
  2659         final Type expected;
  2700         final Type expected;
  2660         public ConversionWarner(DiagnosticPosition pos, String key, Type found, Type expected) {
  2701         public ConversionWarner(DiagnosticPosition pos, String uncheckedKey, Type found, Type expected) {
  2661             super(pos);
  2702             super(pos);
  2662             this.key = key;
  2703             this.uncheckedKey = uncheckedKey;
  2663             this.found = found;
  2704             this.found = found;
  2664             this.expected = expected;
  2705             this.expected = expected;
  2665         }
  2706         }
  2666 
  2707 
  2667         @Override
  2708         @Override
  2668         public void warnUnchecked() {
  2709         public void warn(LintCategory lint) {
  2669             boolean warned = this.warned;
  2710             boolean warned = this.warned;
  2670             super.warnUnchecked();
  2711             super.warn(lint);
  2671             if (warned) return; // suppress redundant diagnostics
  2712             if (warned) return; // suppress redundant diagnostics
  2672             Object problem = diags.fragment(key);
  2713             switch (lint) {
  2673             Check.this.warnUnchecked(pos(), "prob.found.req", problem, found, expected);
  2714                 case UNCHECKED:
       
  2715                     Check.this.warnUnchecked(pos(), "prob.found.req", diags.fragment(uncheckedKey), found, expected);
       
  2716                     break;
       
  2717                 case VARARGS:
       
  2718                     if (method != null &&
       
  2719                             method.attribute(syms.trustMeType.tsym) != null &&
       
  2720                             isTrustMeAllowedOnMethod(method) &&
       
  2721                             !types.isReifiable(method.type.getParameterTypes().last())) {
       
  2722                         Check.this.warnUnsafeVararg(pos(), "varargs.unsafe.use.varargs.param", method.params.last());
       
  2723                     }
       
  2724                     break;
       
  2725                 default:
       
  2726                     throw new AssertionError("Unexpected lint: " + lint);
       
  2727             }
  2674         }
  2728         }
  2675     }
  2729     }
  2676 
  2730 
  2677     public Warner castWarner(DiagnosticPosition pos, Type found, Type expected) {
  2731     public Warner castWarner(DiagnosticPosition pos, Type found, Type expected) {
  2678         return new ConversionWarner(pos, "unchecked.cast.to.type", found, expected);
  2732         return new ConversionWarner(pos, "unchecked.cast.to.type", found, expected);