8144185: javac produces incorrect RuntimeInvisibleTypeAnnotations length attribute
Reviewed-by: sadayapalam
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Sat Jun 17 00:15:44 2017 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Mon Jun 12 12:25:40 2017 -0700
@@ -2056,7 +2056,7 @@
Assert.error(skind.name());
throw new AssertionError();
}
- if (ret != sym) {
+ if (ret != sym && skind.propagateAnnotations()) {
ret.setDeclarationAttributes(sym.getRawAttributes());
ret.setTypeAttributes(sym.getRawTypeAttributes());
}
@@ -2092,7 +2092,6 @@
if (m.containsKey(lambdaIdent.sym)) {
Symbol tSym = m.get(lambdaIdent.sym);
JCTree t = make.Ident(tSym).setType(lambdaIdent.type);
- tSym.setTypeAttributes(lambdaIdent.sym.getRawTypeAttributes());
return t;
}
break;
@@ -2101,7 +2100,6 @@
// Transform outer instance variable references anchoring them to the captured synthetic.
Symbol tSym = m.get(lambdaIdent.sym.owner);
JCExpression t = make.Ident(tSym).setType(lambdaIdent.sym.owner.type);
- tSym.setTypeAttributes(lambdaIdent.sym.owner.getRawTypeAttributes());
t = make.Select(t, lambdaIdent.name);
t.setType(lambdaIdent.type);
TreeInfo.setSymbol(t, lambdaIdent.sym);
@@ -2122,7 +2120,6 @@
if (m.containsKey(fieldAccess.sym.owner)) {
Symbol tSym = m.get(fieldAccess.sym.owner);
JCExpression t = make.Ident(tSym).setType(fieldAccess.sym.owner.type);
- tSym.setTypeAttributes(fieldAccess.sym.owner.getRawTypeAttributes());
return t;
}
return null;
@@ -2322,7 +2319,18 @@
CAPTURED_VAR, // variables in enclosing scope to translated synthetic parameters
CAPTURED_THIS, // class symbols to translated synthetic parameters (for captured member access)
CAPTURED_OUTER_THIS, // used when `this' capture is illegal, but outer this capture is legit (JDK-8129740)
- TYPE_VAR // original to translated lambda type variables
+ TYPE_VAR; // original to translated lambda type variables
+
+ boolean propagateAnnotations() {
+ switch (this) {
+ case CAPTURED_VAR:
+ case CAPTURED_THIS:
+ case CAPTURED_OUTER_THIS:
+ return false;
+ default:
+ return true;
+ }
+ }
}
/**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/TypeAnnotationPropagationTest.java Mon Jun 12 12:25:40 2017 -0700
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2017, Google Inc. 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 8144185
+ * @summary javac produces incorrect RuntimeInvisibleTypeAnnotations length attribute
+ * @modules jdk.jdeps/com.sun.tools.classfile
+ */
+
+import static java.lang.annotation.ElementType.TYPE_USE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.sun.tools.classfile.Attribute;
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.Code_attribute;
+import com.sun.tools.classfile.Method;
+import com.sun.tools.classfile.RuntimeVisibleTypeAnnotations_attribute;
+import com.sun.tools.classfile.TypeAnnotation;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.util.Arrays;
+import java.util.Objects;
+
+public class TypeAnnotationPropagationTest extends ClassfileTestHelper {
+ public static void main(String[] args) throws Exception {
+ new TypeAnnotationPropagationTest().run();
+ }
+
+ public void run() throws Exception {
+ ClassFile cf = getClassFile("TypeAnnotationPropagationTest$Test.class");
+
+ Method f = null;
+ for (Method m : cf.methods) {
+ if (m.getName(cf.constant_pool).contains("f")) {
+ f = m;
+ break;
+ }
+ }
+
+ int idx = f.attributes.getIndex(cf.constant_pool, Attribute.Code);
+ Code_attribute cattr = (Code_attribute) f.attributes.get(idx);
+ idx = cattr.attributes.getIndex(cf.constant_pool, Attribute.RuntimeVisibleTypeAnnotations);
+ RuntimeVisibleTypeAnnotations_attribute attr =
+ (RuntimeVisibleTypeAnnotations_attribute) cattr.attributes.get(idx);
+
+ TypeAnnotation anno = attr.annotations[0];
+ assertEquals(anno.position.lvarOffset, new int[] {3}, "start_pc");
+ assertEquals(anno.position.lvarLength, new int[] {8}, "length");
+ assertEquals(anno.position.lvarIndex, new int[] {1}, "index");
+ }
+
+ void assertEquals(int[] actual, int[] expected, String message) {
+ if (!Arrays.equals(actual, expected)) {
+ throw new AssertionError(
+ String.format(
+ "actual: %s, expected: %s, %s",
+ Arrays.toString(actual), Arrays.toString(expected), message));
+ }
+ }
+
+ /** ********************* Test class ************************ */
+ static class Test {
+ void f() {
+ @A String s = "";
+ Runnable r =
+ () -> {
+ Objects.requireNonNull(s);
+ Objects.requireNonNull(s);
+ Objects.requireNonNull(s);
+ Objects.requireNonNull(s);
+ Objects.requireNonNull(s);
+ Objects.requireNonNull(s);
+ };
+ }
+
+ @Retention(RUNTIME)
+ @Target(TYPE_USE)
+ @interface A {}
+ }
+}
+