--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Tue Mar 06 13:26:36 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Tue Mar 06 13:28:05 2012 +0000
@@ -63,6 +63,7 @@
private final Names names;
private final Log log;
+ private final Resolve rs;
private final Symtab syms;
private final Enter enter;
private final Infer infer;
@@ -95,6 +96,7 @@
names = Names.instance(context);
log = Log.instance(context);
+ rs = Resolve.instance(context);
syms = Symtab.instance(context);
enter = Enter.instance(context);
infer = Infer.instance(context);
@@ -106,6 +108,7 @@
Source source = Source.instance(context);
allowGenerics = source.allowGenerics();
+ allowVarargs = source.allowVarargs();
allowAnnotations = source.allowAnnotations();
allowCovariantReturns = source.allowCovariantReturns();
allowSimplifiedVarargs = source.allowSimplifiedVarargs();
@@ -137,6 +140,10 @@
*/
boolean allowGenerics;
+ /** Switch: varargs enabled?
+ */
+ boolean allowVarargs;
+
/** Switch: annotations enabled?
*/
boolean allowAnnotations;
@@ -743,22 +750,105 @@
(s.flags() & (STATIC | FINAL)) != 0);
}
- /**
- * Check that vararg method call is sound
- * @param pos Position to be used for error reporting.
- * @param argtypes Actual arguments supplied to vararg method.
- */
- void checkVararg(DiagnosticPosition pos, List<Type> argtypes, Symbol msym) {
- Type argtype = argtypes.last();
- if (!types.isReifiable(argtype) &&
- (!allowSimplifiedVarargs ||
- msym.attribute(syms.trustMeType.tsym) == null ||
- !isTrustMeAllowedOnMethod(msym))) {
- warnUnchecked(pos,
- "unchecked.generic.array.creation",
- argtype);
+ Type checkMethod(Type owntype,
+ Symbol sym,
+ Env<AttrContext> env,
+ final List<JCExpression> argtrees,
+ List<Type> argtypes,
+ boolean useVarargs) {
+ boolean warned = false;
+ // System.out.println("call : " + env.tree);
+ // System.out.println("method : " + owntype);
+ // System.out.println("actuals: " + argtypes);
+ List<Type> formals = owntype.getParameterTypes();
+ Type last = useVarargs ? formals.last() : null;
+ if (sym.name==names.init &&
+ sym.owner == syms.enumSym)
+ formals = formals.tail.tail;
+ List<JCExpression> args = argtrees;
+ while (formals.head != last) {
+ JCTree arg = args.head;
+ Warner warn = convertWarner(arg.pos(), arg.type, formals.head);
+ assertConvertible(arg, arg.type, formals.head, warn);
+ warned |= warn.hasNonSilentLint(LintCategory.UNCHECKED);
+ args = args.tail;
+ formals = formals.tail;
+ }
+ if (useVarargs) {
+ Type varArg = types.elemtype(last);
+ while (args.tail != null) {
+ JCTree arg = args.head;
+ Warner warn = convertWarner(arg.pos(), arg.type, varArg);
+ assertConvertible(arg, arg.type, varArg, warn);
+ warned |= warn.hasNonSilentLint(LintCategory.UNCHECKED);
+ args = args.tail;
+ }
+ } else if ((sym.flags() & VARARGS) != 0 && allowVarargs) {
+ // non-varargs call to varargs method
+ Type varParam = owntype.getParameterTypes().last();
+ Type lastArg = argtypes.last();
+ if (types.isSubtypeUnchecked(lastArg, types.elemtype(varParam)) &&
+ !types.isSameType(types.erasure(varParam), types.erasure(lastArg)))
+ log.warning(argtrees.last().pos(), "inexact.non-varargs.call",
+ types.elemtype(varParam), varParam);
}
+ if (warned) {
+ warnUnchecked(env.tree.pos(),
+ "unchecked.meth.invocation.applied",
+ kindName(sym),
+ sym.name,
+ rs.methodArguments(sym.type.getParameterTypes()),
+ rs.methodArguments(argtypes),
+ kindName(sym.location()),
+ sym.location());
+ owntype = new MethodType(owntype.getParameterTypes(),
+ types.erasure(owntype.getReturnType()),
+ types.erasure(owntype.getThrownTypes()),
+ syms.methodClass);
+ }
+ if (useVarargs) {
+ JCTree tree = env.tree;
+ Type argtype = owntype.getParameterTypes().last();
+ if (!types.isReifiable(argtype) &&
+ (!allowSimplifiedVarargs ||
+ sym.attribute(syms.trustMeType.tsym) == null ||
+ !isTrustMeAllowedOnMethod(sym))) {
+ warnUnchecked(env.tree.pos(),
+ "unchecked.generic.array.creation",
+ argtype);
+ }
+ Type elemtype = types.elemtype(argtype);
+ switch (tree.getTag()) {
+ case APPLY:
+ ((JCMethodInvocation) tree).varargsElement = elemtype;
+ break;
+ case NEWCLASS:
+ ((JCNewClass) tree).varargsElement = elemtype;
+ break;
+ default:
+ throw new AssertionError(""+tree);
+ }
+ }
+ return owntype;
}
+ //where
+ private void assertConvertible(JCTree tree, Type actual, Type formal, Warner warn) {
+ if (types.isConvertible(actual, formal, warn))
+ return;
+
+ if (formal.isCompound()
+ && types.isSubtype(actual, types.supertype(formal))
+ && types.isSubtypeUnchecked(actual, types.interfaces(formal), warn))
+ return;
+
+ if (false) {
+ // TODO: make assertConvertible work
+ typeError(tree.pos(), diags.fragment("incompatible.types"), actual, formal);
+ throw new AssertionError("Tree: " + tree
+ + " actual:" + actual
+ + " formal: " + formal);
+ }
+ }
/**
* Check that type 't' is a valid instantiation of a generic class