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