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

changeset 795
7b99f98b3035
parent 780
1d625fbe6c22
child 798
4868a36f6fd8
     1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Check.java	Mon Dec 13 14:08:01 2010 -0800
     1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java	Mon Dec 13 15:11:00 2010 -0800
     1.3 @@ -75,6 +75,10 @@
     1.4      // visits all the various parts of the trees during attribution.
     1.5      private Lint lint;
     1.6  
     1.7 +    // The method being analyzed in Attr - it is set/reset as needed by
     1.8 +    // Attr as it visits new method declarations.
     1.9 +    private MethodSymbol method;
    1.10 +
    1.11      public static Check instance(Context context) {
    1.12          Check instance = context.get(checkKey);
    1.13          if (instance == null)
    1.14 @@ -100,6 +104,7 @@
    1.15          allowGenerics = source.allowGenerics();
    1.16          allowAnnotations = source.allowAnnotations();
    1.17          allowCovariantReturns = source.allowCovariantReturns();
    1.18 +        allowSimplifiedVarargs = source.allowSimplifiedVarargs();
    1.19          complexInference = options.isSet(COMPLEXINFERENCE);
    1.20          skipAnnotations = options.isSet("skipAnnotations");
    1.21          warnOnSyntheticConflicts = options.isSet("warnOnSyntheticConflicts");
    1.22 @@ -136,6 +141,10 @@
    1.23       */
    1.24      boolean allowCovariantReturns;
    1.25  
    1.26 +    /** Switch: simplified varargs enabled?
    1.27 +     */
    1.28 +    boolean allowSimplifiedVarargs;
    1.29 +
    1.30      /** Switch: -complexinference option set?
    1.31       */
    1.32      boolean complexInference;
    1.33 @@ -175,6 +184,12 @@
    1.34          return prev;
    1.35      }
    1.36  
    1.37 +    MethodSymbol setMethod(MethodSymbol newMethod) {
    1.38 +        MethodSymbol prev = method;
    1.39 +        method = newMethod;
    1.40 +        return prev;
    1.41 +    }
    1.42 +
    1.43      /** Warn about deprecated symbol.
    1.44       *  @param pos        Position to be used for error reporting.
    1.45       *  @param sym        The deprecated symbol.
    1.46 @@ -197,9 +212,9 @@
    1.47       *  @param pos        Position to be used for error reporting.
    1.48       *  @param sym        The deprecated symbol.
    1.49       */
    1.50 -    void warnUnsafeVararg(DiagnosticPosition pos, Type elemType) {
    1.51 -        if (!lint.isSuppressed(LintCategory.VARARGS))
    1.52 -            unsafeVarargsHandler.report(pos, "varargs.non.reifiable.type", elemType);
    1.53 +    void warnUnsafeVararg(DiagnosticPosition pos, String key, Object... args) {
    1.54 +        if (lint.isEnabled(LintCategory.VARARGS) && allowSimplifiedVarargs)
    1.55 +            log.warning(LintCategory.VARARGS, pos, key, args);
    1.56      }
    1.57  
    1.58      /** Warn about using proprietary API.
    1.59 @@ -222,7 +237,6 @@
    1.60      public void reportDeferredDiagnostics() {
    1.61          deprecationHandler.reportDeferredDiagnostic();
    1.62          uncheckedHandler.reportDeferredDiagnostic();
    1.63 -        unsafeVarargsHandler.reportDeferredDiagnostic();
    1.64          sunApiHandler.reportDeferredDiagnostic();
    1.65      }
    1.66  
    1.67 @@ -705,29 +719,56 @@
    1.68          }
    1.69      }
    1.70  
    1.71 -    void checkVarargMethodDecl(JCMethodDecl tree) {
    1.72 +    void checkVarargsMethodDecl(Env<AttrContext> env, JCMethodDecl tree) {
    1.73          MethodSymbol m = tree.sym;
    1.74 -        //check the element type of the vararg
    1.75 +        if (!allowSimplifiedVarargs) return;
    1.76 +        boolean hasTrustMeAnno = m.attribute(syms.trustMeType.tsym) != null;
    1.77 +        Type varargElemType = null;
    1.78          if (m.isVarArgs()) {
    1.79 -            Type varargElemType = types.elemtype(tree.params.last().type);
    1.80 -            if (!types.isReifiable(varargElemType)) {
    1.81 -                warnUnsafeVararg(tree.params.head.pos(), varargElemType);
    1.82 +            varargElemType = types.elemtype(tree.params.last().type);
    1.83 +        }
    1.84 +        if (hasTrustMeAnno && !isTrustMeAllowedOnMethod(m)) {
    1.85 +            if (varargElemType != null) {
    1.86 +                log.error(tree,
    1.87 +                        "varargs.invalid.trustme.anno",
    1.88 +                        syms.trustMeType.tsym,
    1.89 +                        diags.fragment("varargs.trustme.on.virtual.varargs", m));
    1.90 +            } else {
    1.91 +                log.error(tree,
    1.92 +                            "varargs.invalid.trustme.anno",
    1.93 +                            syms.trustMeType.tsym,
    1.94 +                            diags.fragment("varargs.trustme.on.non.varargs.meth", m));
    1.95              }
    1.96 +        } else if (hasTrustMeAnno && varargElemType != null &&
    1.97 +                            types.isReifiable(varargElemType)) {
    1.98 +            warnUnsafeVararg(tree,
    1.99 +                            "varargs.redundant.trustme.anno",
   1.100 +                            syms.trustMeType.tsym,
   1.101 +                            diags.fragment("varargs.trustme.on.reifiable.varargs", varargElemType));
   1.102 +        }
   1.103 +        else if (!hasTrustMeAnno && varargElemType != null &&
   1.104 +                !types.isReifiable(varargElemType)) {
   1.105 +            warnUnchecked(tree.params.head.pos(), "unchecked.varargs.non.reifiable.type", varargElemType);
   1.106          }
   1.107      }
   1.108 +    //where
   1.109 +        private boolean isTrustMeAllowedOnMethod(Symbol s) {
   1.110 +            return (s.flags() & VARARGS) != 0 &&
   1.111 +                (s.isConstructor() ||
   1.112 +                    (s.flags() & (STATIC | FINAL)) != 0);
   1.113 +        }
   1.114  
   1.115      /**
   1.116       * Check that vararg method call is sound
   1.117       * @param pos Position to be used for error reporting.
   1.118       * @param argtypes Actual arguments supplied to vararg method.
   1.119       */
   1.120 -    void checkVararg(DiagnosticPosition pos, List<Type> argtypes, Symbol msym, Env<AttrContext> env) {
   1.121 -        Env<AttrContext> calleeLintEnv = env;
   1.122 -        while (calleeLintEnv.info.lint == null)
   1.123 -            calleeLintEnv = calleeLintEnv.next;
   1.124 -        Lint calleeLint = calleeLintEnv.info.lint.augment(msym.attributes_field, msym.flags());
   1.125 +    void checkVararg(DiagnosticPosition pos, List<Type> argtypes, Symbol msym) {
   1.126          Type argtype = argtypes.last();
   1.127 -        if (!types.isReifiable(argtype) && !calleeLint.isSuppressed(Lint.LintCategory.VARARGS)) {
   1.128 +        if (!types.isReifiable(argtype) &&
   1.129 +                (!allowSimplifiedVarargs ||
   1.130 +                msym.attribute(syms.trustMeType.tsym) == null ||
   1.131 +                !isTrustMeAllowedOnMethod(msym))) {
   1.132              warnUnchecked(pos,
   1.133                                "unchecked.generic.array.creation",
   1.134                                argtype);
   1.135 @@ -1075,12 +1116,12 @@
   1.136          }
   1.137  
   1.138          void checkRaw(JCTree tree, Env<AttrContext> env) {
   1.139 -            if (lint.isEnabled(Lint.LintCategory.RAW) &&
   1.140 +            if (lint.isEnabled(LintCategory.RAW) &&
   1.141                  tree.type.tag == CLASS &&
   1.142                  !TreeInfo.isDiamond(tree) &&
   1.143                  !env.enclClass.name.isEmpty() &&  //anonymous or intersection
   1.144                  tree.type.isRaw()) {
   1.145 -                log.warning(Lint.LintCategory.RAW,
   1.146 +                log.warning(LintCategory.RAW,
   1.147                          tree.pos(), "raw.class.use", tree.type, tree.type.tsym.type);
   1.148              }
   1.149          }
   1.150 @@ -1347,7 +1388,7 @@
   1.151          Type mtres = mt.getReturnType();
   1.152          Type otres = types.subst(ot.getReturnType(), otvars, mtvars);
   1.153  
   1.154 -        overrideWarner.warned = false;
   1.155 +        overrideWarner.clear();
   1.156          boolean resultTypesOK =
   1.157              types.returnTypeSubstitutable(mt, ot, otres, overrideWarner);
   1.158          if (!resultTypesOK) {
   1.159 @@ -1362,7 +1403,7 @@
   1.160                            mtres, otres);
   1.161                  return;
   1.162              }
   1.163 -        } else if (overrideWarner.warned) {
   1.164 +        } else if (overrideWarner.hasNonSilentLint(LintCategory.UNCHECKED)) {
   1.165              warnUnchecked(TreeInfo.diagnosticPositionFor(m, tree),
   1.166                      "override.unchecked.ret",
   1.167                      uncheckedOverrides(m, other),
   1.168 @@ -1391,7 +1432,7 @@
   1.169  
   1.170          // Optional warning if varargs don't agree
   1.171          if ((((m.flags() ^ other.flags()) & Flags.VARARGS) != 0)
   1.172 -            && lint.isEnabled(Lint.LintCategory.OVERRIDES)) {
   1.173 +            && lint.isEnabled(LintCategory.OVERRIDES)) {
   1.174              log.warning(TreeInfo.diagnosticPositionFor(m, tree),
   1.175                          ((m.flags() & Flags.VARARGS) != 0)
   1.176                          ? "override.varargs.missing"
   1.177 @@ -2380,11 +2421,11 @@
   1.178  
   1.179      void checkDeprecatedAnnotation(DiagnosticPosition pos, Symbol s) {
   1.180          if (allowAnnotations &&
   1.181 -            lint.isEnabled(Lint.LintCategory.DEP_ANN) &&
   1.182 +            lint.isEnabled(LintCategory.DEP_ANN) &&
   1.183              (s.flags() & DEPRECATED) != 0 &&
   1.184              !syms.deprecatedType.isErroneous() &&
   1.185              s.attribute(syms.deprecatedType.tsym) == null) {
   1.186 -            log.warning(Lint.LintCategory.DEP_ANN,
   1.187 +            log.warning(LintCategory.DEP_ANN,
   1.188                      pos, "missing.deprecated.annotation");
   1.189          }
   1.190      }
   1.191 @@ -2530,13 +2571,13 @@
   1.192       */
   1.193      void checkDivZero(DiagnosticPosition pos, Symbol operator, Type operand) {
   1.194          if (operand.constValue() != null
   1.195 -            && lint.isEnabled(Lint.LintCategory.DIVZERO)
   1.196 +            && lint.isEnabled(LintCategory.DIVZERO)
   1.197              && operand.tag <= LONG
   1.198              && ((Number) (operand.constValue())).longValue() == 0) {
   1.199              int opc = ((OperatorSymbol)operator).opcode;
   1.200              if (opc == ByteCodes.idiv || opc == ByteCodes.imod
   1.201                  || opc == ByteCodes.ldiv || opc == ByteCodes.lmod) {
   1.202 -                log.warning(Lint.LintCategory.DIVZERO, pos, "div.zero");
   1.203 +                log.warning(LintCategory.DIVZERO, pos, "div.zero");
   1.204              }
   1.205          }
   1.206      }
   1.207 @@ -2545,8 +2586,8 @@
   1.208       * Check for empty statements after if
   1.209       */
   1.210      void checkEmptyIf(JCIf tree) {
   1.211 -        if (tree.thenpart.getTag() == JCTree.SKIP && tree.elsepart == null && lint.isEnabled(Lint.LintCategory.EMPTY))
   1.212 -            log.warning(Lint.LintCategory.EMPTY, tree.thenpart.pos(), "empty.if");
   1.213 +        if (tree.thenpart.getTag() == JCTree.SKIP && tree.elsepart == null && lint.isEnabled(LintCategory.EMPTY))
   1.214 +            log.warning(LintCategory.EMPTY, tree.thenpart.pos(), "empty.if");
   1.215      }
   1.216  
   1.217      /** Check that symbol is unique in given scope.
   1.218 @@ -2654,23 +2695,36 @@
   1.219          }
   1.220  
   1.221      private class ConversionWarner extends Warner {
   1.222 -        final String key;
   1.223 +        final String uncheckedKey;
   1.224          final Type found;
   1.225          final Type expected;
   1.226 -        public ConversionWarner(DiagnosticPosition pos, String key, Type found, Type expected) {
   1.227 +        public ConversionWarner(DiagnosticPosition pos, String uncheckedKey, Type found, Type expected) {
   1.228              super(pos);
   1.229 -            this.key = key;
   1.230 +            this.uncheckedKey = uncheckedKey;
   1.231              this.found = found;
   1.232              this.expected = expected;
   1.233          }
   1.234  
   1.235          @Override
   1.236 -        public void warnUnchecked() {
   1.237 +        public void warn(LintCategory lint) {
   1.238              boolean warned = this.warned;
   1.239 -            super.warnUnchecked();
   1.240 +            super.warn(lint);
   1.241              if (warned) return; // suppress redundant diagnostics
   1.242 -            Object problem = diags.fragment(key);
   1.243 -            Check.this.warnUnchecked(pos(), "prob.found.req", problem, found, expected);
   1.244 +            switch (lint) {
   1.245 +                case UNCHECKED:
   1.246 +                    Check.this.warnUnchecked(pos(), "prob.found.req", diags.fragment(uncheckedKey), found, expected);
   1.247 +                    break;
   1.248 +                case VARARGS:
   1.249 +                    if (method != null &&
   1.250 +                            method.attribute(syms.trustMeType.tsym) != null &&
   1.251 +                            isTrustMeAllowedOnMethod(method) &&
   1.252 +                            !types.isReifiable(method.type.getParameterTypes().last())) {
   1.253 +                        Check.this.warnUnsafeVararg(pos(), "varargs.unsafe.use.varargs.param", method.params.last());
   1.254 +                    }
   1.255 +                    break;
   1.256 +                default:
   1.257 +                    throw new AssertionError("Unexpected lint: " + lint);
   1.258 +            }
   1.259          }
   1.260      }
   1.261  

mercurial