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

changeset 1219
48ee63caaa93
parent 1218
dda6a5b15580
child 1226
97bec6ab1227
     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

mercurial