changeset 1995:04b56f4312b6 jdk7u80-b04

6695379: Copy method annotations and parameter annotations to synthetic bridge methods Reviewed-by: mcimadamore
author vromero
date Thu, 11 Dec 2014 18:06:50 +0000
parents 979f55cda0e2
children 072aeca12bf3 08c11954963e
files src/share/classes/com/sun/tools/javac/comp/TransTypes.java test/tools/javac/6889255/T6889255.java test/tools/javac/T6695379/AnnotationsAreNotCopiedToBridgeMethodsTest.java
diffstat 3 files changed, 133 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/comp/TransTypes.java	Wed Nov 26 17:03:13 2014 +0000
+++ b/src/share/classes/com/sun/tools/javac/comp/TransTypes.java	Thu Dec 11 18:06:50 2014 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2014, 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
@@ -223,6 +223,12 @@
                                                meth.name,
                                                bridgeType,
                                                origin);
+        /* once JDK-6996415 is solved it should be checked if this approach can
+         * be applied to method addOverrideBridgesIfNeeded
+         */
+        bridge.params = createBridgeParams(impl, bridge, bridgeType);
+        bridge.attributes_field = impl.attributes_field;
+
         if (!hypothetical) {
             JCMethodDecl md = make.MethodDef(bridge, null);
 
@@ -257,6 +263,26 @@
         overridden.put(bridge, meth);
     }
 
+    private List<VarSymbol> createBridgeParams(MethodSymbol impl, MethodSymbol bridge,
+            Type bridgeType) {
+        List<VarSymbol> bridgeParams = null;
+        if (impl.params != null) {
+            bridgeParams = List.nil();
+            List<VarSymbol> implParams = impl.params;
+            Type.MethodType mType = (Type.MethodType)bridgeType;
+            List<Type> argTypes = mType.argtypes;
+            while (implParams.nonEmpty() && argTypes.nonEmpty()) {
+                VarSymbol param = new VarSymbol(implParams.head.flags() | SYNTHETIC | PARAMETER,
+                        implParams.head.name, argTypes.head, bridge);
+                param.attributes_field = implParams.head.attributes_field;
+                bridgeParams = bridgeParams.append(param);
+                implParams = implParams.tail;
+                argTypes = argTypes.tail;
+            }
+        }
+        return bridgeParams;
+    }
+
     /** Add bridge if given symbol is a non-private, non-static member
      *  of the given class, which is either defined in the class or non-final
      *  inherited, and one of the two following conditions holds:
--- a/test/tools/javac/6889255/T6889255.java	Wed Nov 26 17:03:13 2014 +0000
+++ b/test/tools/javac/6889255/T6889255.java	Thu Dec 11 18:06:50 2014 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2014, 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
@@ -429,9 +429,9 @@
         // -- no Code attribute for the LocalVariableTable attribute
         if ((v.owner.flags() & Flags.ABSTRACT) != 0)
             return "arg" + (i - 1);
-        // bridge methods use xN
+        // bridge methods use argN. No LVT for them anymore
         if ((v.owner.flags() & Flags.BRIDGE) != 0)
-            return "x" + (i - 1);
+            return "arg" + (i - 1);
 
         // The rest of this method assumes the local conventions in the test program
         Type t = v.type;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/T6695379/AnnotationsAreNotCopiedToBridgeMethodsTest.java	Thu Dec 11 18:06:50 2014 +0000
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+/*
+ * @test
+ * @bug 6695379
+ * @summary Copy method annotations and parameter annotations to synthetic
+ * bridge methods
+ * @run main AnnotationsAreNotCopiedToBridgeMethodsTest
+ */
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+import java.io.BufferedInputStream;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import com.sun.tools.classfile.AccessFlags;
+import com.sun.tools.classfile.Attribute;
+import com.sun.tools.classfile.Attributes;
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.Method;
+import com.sun.tools.javac.util.Assert;
+
+public class AnnotationsAreNotCopiedToBridgeMethodsTest {
+
+    public static void main(String[] args) throws Exception {
+        new AnnotationsAreNotCopiedToBridgeMethodsTest().run();
+    }
+
+    void run() throws Exception {
+        checkClassFile(Paths.get(System.getProperty("test.classes"),
+                this.getClass().getSimpleName() + "$CovariantReturnType.class"));
+        checkClassFile(Paths.get(System.getProperty("test.classes"),
+                this.getClass().getSimpleName() +
+                "$CovariantReturnType$VisibilityChange.class"));
+    }
+
+    void checkClassFile(final Path cfilePath) throws Exception {
+        ClassFile classFile = ClassFile.read(
+                new BufferedInputStream(Files.newInputStream(cfilePath)));
+        for (Method method : classFile.methods) {
+            if (method.access_flags.is(AccessFlags.ACC_BRIDGE)) {
+                checkForAttr(method.attributes,
+                        "Annotations hasn't been copied to bridge method",
+                        Attribute.RuntimeVisibleAnnotations,
+                        Attribute.RuntimeVisibleParameterAnnotations);
+            }
+        }
+    }
+
+    void checkForAttr(Attributes attrs, String errorMsg, String... attrNames) {
+        for (String attrName : attrNames) {
+            Assert.checkNonNull(attrs.get(attrName), errorMsg);
+        }
+    }
+
+    @Target(value = {ElementType.PARAMETER})
+    @Retention(RetentionPolicy.RUNTIME)
+    @interface ParamAnnotation {}
+
+    @Target(value = {ElementType.METHOD})
+    @Retention(RetentionPolicy.RUNTIME)
+    @interface MethodAnnotation {}
+
+    abstract class T<A,B> {
+        B m(A a){return null;}
+    }
+
+    class CovariantReturnType extends T<Integer, Integer> {
+        @MethodAnnotation
+        Integer m(@ParamAnnotation Integer i) {
+            return i;
+        }
+
+        public class VisibilityChange extends CovariantReturnType {}
+
+    }
+
+}