8160928: javac incorrectly copies over interior type annotations to bridge method
authorsadayapalam
Mon, 11 Jul 2016 18:13:42 +0530
changeset 39600 83ea7c12c164
parent 39599 3c7da4996d8c
child 39601 5b37e511ae4b
8160928: javac incorrectly copies over interior type annotations to bridge method Reviewed-by: mcimadamore
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/SymbolMetadata.java
langtools/test/tools/javac/annotations/typeAnnotations/classfile/BridgeShouldHaveNoInteriorAnnotationsTest.java
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/SymbolMetadata.java	Fri Jul 08 16:47:13 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/SymbolMetadata.java	Mon Jul 11 18:13:42 2016 +0530
@@ -26,8 +26,11 @@
 package com.sun.tools.javac.code;
 
 
+import com.sun.tools.javac.code.Attribute.TypeCompound;
+import com.sun.tools.javac.code.Kinds.Kind;
 import com.sun.tools.javac.util.Assert;
 import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
 
 /**
  * Container for all annotations (attributes in javac) on a Symbol.
@@ -142,9 +145,22 @@
             throw new NullPointerException();
         }
         setDeclarationAttributes(other.getDeclarationAttributes());
-        setTypeAttributes(other.getTypeAttributes());
-        setInitTypeAttributes(other.getInitTypeAttributes());
-        setClassInitTypeAttributes(other.getClassInitTypeAttributes());
+        if ((sym.flags() & Flags.BRIDGE) != 0) {
+            Assert.check(other.sym.kind == Kind.MTH);
+            ListBuffer<TypeCompound> typeAttributes = new ListBuffer<>();
+            for (TypeCompound tc : other.getTypeAttributes()) {
+                // Carry over only contractual type annotations: i.e nothing interior to method body.
+                if (!tc.position.type.isLocal())
+                    typeAttributes.append(tc);
+            }
+            setTypeAttributes(typeAttributes.toList());
+        } else {
+            setTypeAttributes(other.getTypeAttributes());
+        }
+        if (sym.kind == Kind.TYP) {
+            setInitTypeAttributes(other.getInitTypeAttributes());
+            setClassInitTypeAttributes(other.getClassInitTypeAttributes());
+        }
     }
 
     public SymbolMetadata reset() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/BridgeShouldHaveNoInteriorAnnotationsTest.java	Mon Jul 11 18:13:42 2016 +0530
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2016, 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 8160928
+ * @summary javac incorrectly copies over interior type annotations to bridge method
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
+ * @build toolbox.ToolBox toolbox.JavapTask
+ * @run compile -g BridgeShouldHaveNoInteriorAnnotationsTest.java
+ * @run main BridgeShouldHaveNoInteriorAnnotationsTest
+ */
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+import toolbox.JavapTask;
+import toolbox.Task;
+import toolbox.ToolBox;
+
+class Pair_8160928<T1, T2> {
+}
+
+public class BridgeShouldHaveNoInteriorAnnotationsTest
+                   implements java.util.Iterator<Pair_8160928<Object, Object>> {
+
+    @Override
+    public boolean hasNext() {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public Pair_8160928<@NonNull Object, Object> next() {
+        Comparable<@NonNull Object> cble1 = (Comparable<@NonNull Object>) null;
+        return null;
+    }
+
+    @Override
+    public void remove() {
+        throw new UnsupportedOperationException();
+    }
+
+
+    @Target(ElementType.TYPE_USE)
+    public @interface NonNull {
+    };
+
+
+    // Expected output can't be directly encoded into NestedLambdasCastedTest !!!
+    static class OutputExpectedOnceHolder {
+        public String[] outputs = {
+            "0: #61(): CAST, offset=1, type_index=0, location=[TYPE_ARGUMENT(0)]",
+            "1: #61(): LOCAL_VARIABLE, {start_pc=5, length=2, index=1}, location=[TYPE_ARGUMENT(0)]",
+        };
+    }
+
+    static class OutputExpectedTwiceHolder {
+        public String[] outputs = {
+            "0: #61(): METHOD_RETURN, location=[TYPE_ARGUMENT(0)]",
+        };
+    }
+
+    public static strictfp void main(String args[]) throws Exception {
+        ToolBox tb = new ToolBox();
+        Path classPath = Paths.get(ToolBox.testClasses, "BridgeShouldHaveNoInteriorAnnotationsTest.class");
+        String javapOut = new JavapTask(tb)
+                .options("-v", "-p")
+                .classes(classPath.toString())
+                .run()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        OutputExpectedOnceHolder holder = new OutputExpectedOnceHolder();
+        for (String s : holder.outputs) {
+            String newOutput = javapOut.replace(s, "");
+            if (((javapOut.length() - newOutput.length()) / s.length()) != 1)
+                throw new AssertionError("Interior annotations carried over to bridge ?");
+        }
+        OutputExpectedTwiceHolder holder2 = new OutputExpectedTwiceHolder();
+        for (String s : holder2.outputs) {
+            String newOutput = javapOut.replace(s, "");
+            if (((javapOut.length() - newOutput.length()) / s.length()) != 2)
+                throw new AssertionError("Exterior annotations not properly carried over to bridge");
+        }
+    }
+}