1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Check.java Tue Mar 06 13:26:36 2012 +0000 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java Tue Mar 06 13:28:05 2012 +0000 1.3 @@ -63,6 +63,7 @@ 1.4 1.5 private final Names names; 1.6 private final Log log; 1.7 + private final Resolve rs; 1.8 private final Symtab syms; 1.9 private final Enter enter; 1.10 private final Infer infer; 1.11 @@ -95,6 +96,7 @@ 1.12 1.13 names = Names.instance(context); 1.14 log = Log.instance(context); 1.15 + rs = Resolve.instance(context); 1.16 syms = Symtab.instance(context); 1.17 enter = Enter.instance(context); 1.18 infer = Infer.instance(context); 1.19 @@ -106,6 +108,7 @@ 1.20 1.21 Source source = Source.instance(context); 1.22 allowGenerics = source.allowGenerics(); 1.23 + allowVarargs = source.allowVarargs(); 1.24 allowAnnotations = source.allowAnnotations(); 1.25 allowCovariantReturns = source.allowCovariantReturns(); 1.26 allowSimplifiedVarargs = source.allowSimplifiedVarargs(); 1.27 @@ -137,6 +140,10 @@ 1.28 */ 1.29 boolean allowGenerics; 1.30 1.31 + /** Switch: varargs enabled? 1.32 + */ 1.33 + boolean allowVarargs; 1.34 + 1.35 /** Switch: annotations enabled? 1.36 */ 1.37 boolean allowAnnotations; 1.38 @@ -743,22 +750,105 @@ 1.39 (s.flags() & (STATIC | FINAL)) != 0); 1.40 } 1.41 1.42 - /** 1.43 - * Check that vararg method call is sound 1.44 - * @param pos Position to be used for error reporting. 1.45 - * @param argtypes Actual arguments supplied to vararg method. 1.46 - */ 1.47 - void checkVararg(DiagnosticPosition pos, List<Type> argtypes, Symbol msym) { 1.48 - Type argtype = argtypes.last(); 1.49 - if (!types.isReifiable(argtype) && 1.50 - (!allowSimplifiedVarargs || 1.51 - msym.attribute(syms.trustMeType.tsym) == null || 1.52 - !isTrustMeAllowedOnMethod(msym))) { 1.53 - warnUnchecked(pos, 1.54 - "unchecked.generic.array.creation", 1.55 - argtype); 1.56 + Type checkMethod(Type owntype, 1.57 + Symbol sym, 1.58 + Env<AttrContext> env, 1.59 + final List<JCExpression> argtrees, 1.60 + List<Type> argtypes, 1.61 + boolean useVarargs) { 1.62 + boolean warned = false; 1.63 + // System.out.println("call : " + env.tree); 1.64 + // System.out.println("method : " + owntype); 1.65 + // System.out.println("actuals: " + argtypes); 1.66 + List<Type> formals = owntype.getParameterTypes(); 1.67 + Type last = useVarargs ? formals.last() : null; 1.68 + if (sym.name==names.init && 1.69 + sym.owner == syms.enumSym) 1.70 + formals = formals.tail.tail; 1.71 + List<JCExpression> args = argtrees; 1.72 + while (formals.head != last) { 1.73 + JCTree arg = args.head; 1.74 + Warner warn = convertWarner(arg.pos(), arg.type, formals.head); 1.75 + assertConvertible(arg, arg.type, formals.head, warn); 1.76 + warned |= warn.hasNonSilentLint(LintCategory.UNCHECKED); 1.77 + args = args.tail; 1.78 + formals = formals.tail; 1.79 } 1.80 + if (useVarargs) { 1.81 + Type varArg = types.elemtype(last); 1.82 + while (args.tail != null) { 1.83 + JCTree arg = args.head; 1.84 + Warner warn = convertWarner(arg.pos(), arg.type, varArg); 1.85 + assertConvertible(arg, arg.type, varArg, warn); 1.86 + warned |= warn.hasNonSilentLint(LintCategory.UNCHECKED); 1.87 + args = args.tail; 1.88 + } 1.89 + } else if ((sym.flags() & VARARGS) != 0 && allowVarargs) { 1.90 + // non-varargs call to varargs method 1.91 + Type varParam = owntype.getParameterTypes().last(); 1.92 + Type lastArg = argtypes.last(); 1.93 + if (types.isSubtypeUnchecked(lastArg, types.elemtype(varParam)) && 1.94 + !types.isSameType(types.erasure(varParam), types.erasure(lastArg))) 1.95 + log.warning(argtrees.last().pos(), "inexact.non-varargs.call", 1.96 + types.elemtype(varParam), varParam); 1.97 + } 1.98 + if (warned) { 1.99 + warnUnchecked(env.tree.pos(), 1.100 + "unchecked.meth.invocation.applied", 1.101 + kindName(sym), 1.102 + sym.name, 1.103 + rs.methodArguments(sym.type.getParameterTypes()), 1.104 + rs.methodArguments(argtypes), 1.105 + kindName(sym.location()), 1.106 + sym.location()); 1.107 + owntype = new MethodType(owntype.getParameterTypes(), 1.108 + types.erasure(owntype.getReturnType()), 1.109 + types.erasure(owntype.getThrownTypes()), 1.110 + syms.methodClass); 1.111 + } 1.112 + if (useVarargs) { 1.113 + JCTree tree = env.tree; 1.114 + Type argtype = owntype.getParameterTypes().last(); 1.115 + if (!types.isReifiable(argtype) && 1.116 + (!allowSimplifiedVarargs || 1.117 + sym.attribute(syms.trustMeType.tsym) == null || 1.118 + !isTrustMeAllowedOnMethod(sym))) { 1.119 + warnUnchecked(env.tree.pos(), 1.120 + "unchecked.generic.array.creation", 1.121 + argtype); 1.122 + } 1.123 + Type elemtype = types.elemtype(argtype); 1.124 + switch (tree.getTag()) { 1.125 + case APPLY: 1.126 + ((JCMethodInvocation) tree).varargsElement = elemtype; 1.127 + break; 1.128 + case NEWCLASS: 1.129 + ((JCNewClass) tree).varargsElement = elemtype; 1.130 + break; 1.131 + default: 1.132 + throw new AssertionError(""+tree); 1.133 + } 1.134 + } 1.135 + return owntype; 1.136 } 1.137 + //where 1.138 + private void assertConvertible(JCTree tree, Type actual, Type formal, Warner warn) { 1.139 + if (types.isConvertible(actual, formal, warn)) 1.140 + return; 1.141 + 1.142 + if (formal.isCompound() 1.143 + && types.isSubtype(actual, types.supertype(formal)) 1.144 + && types.isSubtypeUnchecked(actual, types.interfaces(formal), warn)) 1.145 + return; 1.146 + 1.147 + if (false) { 1.148 + // TODO: make assertConvertible work 1.149 + typeError(tree.pos(), diags.fragment("incompatible.types"), actual, formal); 1.150 + throw new AssertionError("Tree: " + tree 1.151 + + " actual:" + actual 1.152 + + " formal: " + formal); 1.153 + } 1.154 + } 1.155 1.156 /** 1.157 * Check that type 't' is a valid instantiation of a generic class