6313164: javac generates code that fails byte code verification for the varargs feature
authormcimadamore
Fri, 28 Jan 2011 12:03:49 +0000
changeset 8229 39266c1b1b0e
parent 8228 4e6ee38974b2
child 8230 b761a23e78d8
6313164: javac generates code that fails byte code verification for the varargs feature Summary: method applicability check should fail if formal varargs element type is not accessible Reviewed-by: jjg
langtools/src/share/classes/com/sun/tools/javac/comp/Check.java
langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java
langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java
langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties
langtools/test/tools/javac/diags/examples.not-yet.txt
langtools/test/tools/javac/diags/examples/InaccessibleVarargsType/InaccessibleVarargsType.java
langtools/test/tools/javac/diags/examples/InaccessibleVarargsType/p1/A.java
langtools/test/tools/javac/diags/examples/InaccessibleVarargsType/p1/B.java
langtools/test/tools/javac/generics/inference/6638712/T6638712c.out
langtools/test/tools/javac/generics/inference/6638712/T6638712d.out
langtools/test/tools/javac/varargs/6313164/T6313164.java
langtools/test/tools/javac/varargs/6313164/T6313164.out
langtools/test/tools/javac/varargs/6313164/p1/A.java
langtools/test/tools/javac/varargs/6313164/p1/B.java
langtools/test/tools/javac/varargs/6313164/p1/C.java
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Fri Jan 28 12:01:07 2011 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Fri Jan 28 12:03:49 2011 +0000
@@ -60,6 +60,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;
@@ -91,6 +92,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);
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java	Fri Jan 28 12:01:07 2011 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java	Fri Jan 28 12:03:49 2011 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -485,11 +485,8 @@
                 @Override
                 public Type inst(List<Type> inferred, Types types) throws NoInstanceException {
                     List<Type> formals = types.subst(mt2.argtypes, tvars, inferred);
-                    if (!rs.argumentsAcceptable(capturedArgs, formals,
-                           allowBoxing, useVarargs, warn)) {
-                      // inferred method is not applicable
-                      throw invalidInstanceException.setMessage("inferred.do.not.conform.to.params", formals, argtypes);
-                    }
+                    // check that actuals conform to inferred formals
+                    checkArgumentsAcceptable(env, capturedArgs, formals, allowBoxing, useVarargs, warn);
                     // check that inferred bounds conform to their bounds
                     checkWithinBounds(all_tvars,
                            types.subst(inferredTypes, tvars, inferred), warn);
@@ -500,17 +497,27 @@
             }};
             return mt2;
         }
-        else if (!rs.argumentsAcceptable(capturedArgs, mt.getParameterTypes(), allowBoxing, useVarargs, warn)) {
-            // inferred method is not applicable
-            throw invalidInstanceException.setMessage("inferred.do.not.conform.to.params", mt.getParameterTypes(), argtypes);
-        }
         else {
+            // check that actuals conform to inferred formals
+            checkArgumentsAcceptable(env, capturedArgs, mt.getParameterTypes(), allowBoxing, useVarargs, warn);
             // return instantiated version of method type
             return mt;
         }
     }
     //where
 
+        private void checkArgumentsAcceptable(Env<AttrContext> env, List<Type> actuals, List<Type> formals,
+                boolean allowBoxing, boolean useVarargs, Warner warn) {
+            try {
+                rs.checkRawArgumentsAcceptable(env, actuals, formals,
+                       allowBoxing, useVarargs, warn);
+            }
+            catch (Resolve.InapplicableMethodException ex) {
+                // inferred method is not applicable
+                throw invalidInstanceException.setMessage(ex.getDiagnostic());
+            }
+        }
+
         /** Try to instantiate argument type `that' to given type `to'.
          *  If this fails, try to insantiate `that' to `to' where
          *  every occurrence of a type variable in `tvars' is replaced
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Fri Jan 28 12:01:07 2011 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Fri Jan 28 12:03:49 2011 +0000
@@ -331,7 +331,7 @@
         throws Infer.InferenceException {
         boolean polymorphicSignature = m.isPolymorphicSignatureGeneric() && allowMethodHandles;
         if (useVarargs && (m.flags() & VARARGS) == 0)
-            throw inapplicableMethodException.setMessage(null);
+            throw inapplicableMethodException.setMessage();
         Type mt = types.memberType(site, m);
 
         // tvars is the list of formal type variables for which type arguments
@@ -386,7 +386,7 @@
                                     useVarargs,
                                     warn);
 
-        checkRawArgumentsAcceptable(argtypes, mt.getParameterTypes(),
+        checkRawArgumentsAcceptable(env, argtypes, mt.getParameterTypes(),
                                 allowBoxing, useVarargs, warn);
         return mt;
     }
@@ -411,19 +411,21 @@
 
     /** Check if a parameter list accepts a list of args.
      */
-    boolean argumentsAcceptable(List<Type> argtypes,
+    boolean argumentsAcceptable(Env<AttrContext> env,
+                                List<Type> argtypes,
                                 List<Type> formals,
                                 boolean allowBoxing,
                                 boolean useVarargs,
                                 Warner warn) {
         try {
-            checkRawArgumentsAcceptable(argtypes, formals, allowBoxing, useVarargs, warn);
+            checkRawArgumentsAcceptable(env, argtypes, formals, allowBoxing, useVarargs, warn);
             return true;
         } catch (InapplicableMethodException ex) {
             return false;
         }
     }
-    void checkRawArgumentsAcceptable(List<Type> argtypes,
+    void checkRawArgumentsAcceptable(Env<AttrContext> env,
+                                List<Type> argtypes,
                                 List<Type> formals,
                                 boolean allowBoxing,
                                 boolean useVarargs,
@@ -460,6 +462,14 @@
                             elt);
                 argtypes = argtypes.tail;
             }
+            //check varargs element type accessibility
+            if (!isAccessible(env, elt)) {
+                Symbol location = env.enclClass.sym;
+                throw inapplicableMethodException.setMessage("inaccessible.varargs.type",
+                            elt,
+                            Kinds.kindName(location),
+                            location);
+            }
         }
         return;
     }
@@ -474,6 +484,10 @@
                 this.diagnostic = null;
                 this.diags = diags;
             }
+            InapplicableMethodException setMessage() {
+                this.diagnostic = null;
+                return this;
+            }
             InapplicableMethodException setMessage(String key) {
                 this.diagnostic = key != null ? diags.fragment(key) : null;
                 return this;
@@ -482,6 +496,10 @@
                 this.diagnostic = key != null ? diags.fragment(key, args) : null;
                 return this;
             }
+            InapplicableMethodException setMessage(JCDiagnostic diag) {
+                this.diagnostic = diag;
+                return this;
+            }
 
             public JCDiagnostic getDiagnostic() {
                 return diagnostic;
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Fri Jan 28 12:01:07 2011 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Fri Jan 28 12:03:49 2011 +0000
@@ -831,6 +831,10 @@
 compiler.misc.varargs.trustme.on.virtual.varargs=\
     Instance method {0} is not final.
 
+# 0: type, 1: kind, 2: symbol
+compiler.misc.inaccessible.varargs.type=\
+    formal varargs element type {0} is not accessible from {1} {2}
+
 # In the following string, {1} will always be the detail message from
 # java.io.IOException.
 # 0: symbol, 1: string
@@ -1564,11 +1568,6 @@
     inferred: {0}\n\
     bound(s): {1}
 
-compiler.misc.inferred.do.not.conform.to.params=\
-    actual arguments do not conform to inferred formal arguments\n\
-    required: {0}\n\
-    found: {1}
-
 # 0: symbol
 compiler.misc.diamond=\
     {0}<>
--- a/langtools/test/tools/javac/diags/examples.not-yet.txt	Fri Jan 28 12:01:07 2011 +0000
+++ b/langtools/test/tools/javac/diags/examples.not-yet.txt	Fri Jan 28 12:03:49 2011 +0000
@@ -63,7 +63,6 @@
 compiler.misc.fatal.err.cant.close.loader               # JavacProcessingEnvironment
 compiler.misc.file.does.not.contain.package
 compiler.misc.illegal.start.of.class.file
-compiler.misc.inferred.do.not.conform.to.params         # UNUSED (hard to see if very complex inference scenario might require this though, so leaving it in, as per JLS3)
 compiler.misc.kindname.annotation
 compiler.misc.kindname.enum
 compiler.misc.kindname.package
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/InaccessibleVarargsType/InaccessibleVarargsType.java	Fri Jan 28 12:03:49 2011 +0000
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.misc.inaccessible.varargs.type
+// key: compiler.err.cant.apply.symbol.1
+
+import p1.B;
+
+class InaccessibleVarargsType {
+    { new B().foo(new B(), new B()); }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/InaccessibleVarargsType/p1/A.java	Fri Jan 28 12:03:49 2011 +0000
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package p1;
+
+class A {
+    A() { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/InaccessibleVarargsType/p1/B.java	Fri Jan 28 12:03:49 2011 +0000
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package p1;
+
+public class B extends A {
+    public B() {}
+    public void foo(A... args) { }
+}
--- a/langtools/test/tools/javac/generics/inference/6638712/T6638712c.out	Fri Jan 28 12:01:07 2011 +0000
+++ b/langtools/test/tools/javac/generics/inference/6638712/T6638712c.out	Fri Jan 28 12:03:49 2011 +0000
@@ -1,2 +1,2 @@
-T6638712c.java:16:9: compiler.err.cant.apply.symbol.1: kindname.method, sort, T[],java.util.Comparator<? super T>, java.lang.Enum[],java.util.Comparator<java.lang.Enum<?>>, kindname.class, T6638712c, (compiler.misc.inferred.do.not.conform.to.params: java.lang.Enum[],java.util.Comparator<? super java.lang.Enum>, java.lang.Enum[],java.util.Comparator<java.lang.Enum<?>>)
+T6638712c.java:16:9: compiler.err.cant.apply.symbol.1: kindname.method, sort, T[],java.util.Comparator<? super T>, java.lang.Enum[],java.util.Comparator<java.lang.Enum<?>>, kindname.class, T6638712c, (compiler.misc.no.conforming.assignment.exists: java.util.Comparator<java.lang.Enum<?>>, java.util.Comparator<? super java.lang.Enum>)
 1 error
--- a/langtools/test/tools/javac/generics/inference/6638712/T6638712d.out	Fri Jan 28 12:01:07 2011 +0000
+++ b/langtools/test/tools/javac/generics/inference/6638712/T6638712d.out	Fri Jan 28 12:03:49 2011 +0000
@@ -1,2 +1,2 @@
-T6638712d.java:16:9: compiler.err.cant.apply.symbol.1: kindname.method, m, U,java.util.List<java.util.List<U>>, int,java.util.List<java.util.List<java.lang.String>>, kindname.class, T6638712d, (compiler.misc.inferred.do.not.conform.to.params: java.lang.String,java.util.List<java.util.List<java.lang.String>>, int,java.util.List<java.util.List<java.lang.String>>)
+T6638712d.java:16:9: compiler.err.cant.apply.symbol.1: kindname.method, m, U,java.util.List<java.util.List<U>>, int,java.util.List<java.util.List<java.lang.String>>, kindname.class, T6638712d, (compiler.misc.no.conforming.assignment.exists: int, java.lang.String)
 1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/varargs/6313164/T6313164.java	Fri Jan 28 12:03:49 2011 +0000
@@ -0,0 +1,18 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug     6313164
+ * @author mcimadamore
+ * @summary  javac generates code that fails byte code verification for the varargs feature
+ * @compile/fail/ref=T6313164.out -XDrawDiagnostics T6313164.java
+ */
+import p1.*;
+
+class T6313164 {
+    { B b = new B();
+      b.foo1(new B(), new B()); //error - A not accesible
+      b.foo2(new B(), new B()); //ok - A not accessible, but foo2(Object...) applicable
+      b.foo3(null, null); //error - A (inferred) not accesible
+      b.foo4(null, null); //error - A (inferred in 15.12.2.8 - no resolution backtrack) not accesible
+      b.foo4(new B(), new C()); //ok - A (inferred in 15.12.2.7) not accessible, but foo4(Object...) applicable
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/varargs/6313164/T6313164.out	Fri Jan 28 12:03:49 2011 +0000
@@ -0,0 +1,6 @@
+T6313164.java:12:8: compiler.err.cant.apply.symbol.1: kindname.method, foo1, p1.A[], p1.B,p1.B, kindname.class, p1.B, (compiler.misc.inaccessible.varargs.type: p1.A, kindname.class, T6313164)
+T6313164.java:14:13: compiler.err.invalid.inferred.types: X, (compiler.misc.inaccessible.varargs.type: p1.A, kindname.class, T6313164)
+T6313164.java:15:13: compiler.err.invalid.inferred.types: X, (compiler.misc.inaccessible.varargs.type: p1.A, kindname.class, T6313164)
+- compiler.note.unchecked.filename: B.java
+- compiler.note.unchecked.recompile
+3 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/varargs/6313164/p1/A.java	Fri Jan 28 12:03:49 2011 +0000
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package p1;
+
+class A {
+    A() { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/varargs/6313164/p1/B.java	Fri Jan 28 12:03:49 2011 +0000
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package p1;
+
+public class B extends A {
+    public B() {}
+    public void foo1(A... args) { }
+    public void foo2(A... args) { }
+    public void foo2(Object... args) { }
+    public <X extends A> void foo3(X... args) { }
+    public <X extends A> void foo4(X... args) { }
+    public void foo4(Object... args) { }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/varargs/6313164/p1/C.java	Fri Jan 28 12:03:49 2011 +0000
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package p1;
+
+public class C extends A { }