langtools/src/share/classes/com/sun/tools/javac/comp/Check.java
changeset 12080 23101f54df44
parent 12079 e1739a771470
child 12087 31eeebc3ef49
--- 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