diff options
| author | Andrew Clement | 2013-08-07 13:00:56 +0000 |
|---|---|---|
| committer | Jayaprakash Arthanareeswaran | 2013-08-08 02:50:55 +0000 |
| commit | 21d3c1ac784a9ef78a64389e4df817ec0452ce19 (patch) | |
| tree | 685d07e9c03e0588ace06b1bb43aea14aae33231 | |
| parent | 4ddddb5424dafb4b8650d4349863e03fece6ac06 (diff) | |
| download | eclipse.jdt.core-21d3c1ac784a9ef78a64389e4df817ec0452ce19.tar.gz eclipse.jdt.core-21d3c1ac784a9ef78a64389e4df817ec0452ce19.tar.xz eclipse.jdt.core-21d3c1ac784a9ef78a64389e4df817ec0452ce19.zip | |
Fix for Bug 409236- [1.8][compiler] Type annotations on intersection
cast types dropped by code generator
Signed-off-by: Andrew Clement <aclement@gopivotal.com>
6 files changed, 270 insertions, 12 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TypeAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TypeAnnotationTest.java index ccb9fde6a0..da190f934b 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TypeAnnotationTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TypeAnnotationTest.java @@ -13,6 +13,7 @@ * IBM Corporation - initial API and implementation * Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for * Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work) + * Bug 409236 - [1.8][compiler] Type annotations on intersection cast types dropped by code generator *******************************************************************************/ package org.eclipse.jdt.core.tests.compiler.regression; @@ -3060,6 +3061,244 @@ public class TypeAnnotationTest extends AbstractRegressionTest { checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); } + public void test070a_codeblocks_castWithIntersectionCast() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "import java.io.*;\n" + + "public class X {\n" + + " public void foo(Object o) {\n" + + " I i = (@B(1) I & J) o;\n" + + " J j = (I & @B(2) J) o;\n" + + " }\n" + + "}\n" + + "interface I {}\n" + + "interface J {}\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B {\n" + + " int value() default 1;\n" + + "}\n", + }, + ""); + String expectedOutput = + " // Method descriptor #15 (Ljava/lang/Object;)V\n" + + " // Stack: 1, Locals: 4\n" + + " public void foo(java.lang.Object o);\n" + + " 0 aload_1 [o]\n" + + " 1 checkcast I [16]\n" + + " 4 checkcast J [18]\n" + + " 7 astore_2 [i]\n" + + " 8 aload_1 [o]\n" + + " 9 checkcast I [16]\n" + + " 12 checkcast J [18]\n" + + " 15 astore_3 [j]\n" + + " 16 return\n" + + " Line numbers:\n" + + " [pc: 0, line: 4]\n" + + " [pc: 8, line: 5]\n" + + " [pc: 16, line: 6]\n" + + " Local variable table:\n" + + " [pc: 0, pc: 17] local: this index: 0 type: X\n" + + " [pc: 0, pc: 17] local: o index: 1 type: java.lang.Object\n" + + " [pc: 8, pc: 17] local: i index: 2 type: I\n" + + " [pc: 16, pc: 17] local: j index: 3 type: J\n" + + " RuntimeVisibleTypeAnnotations: \n" + + " #27 @B(\n" + + " #28 value=(int) 1 (constant type)\n" + + " target type = 0x47 CAST\n" + + " offset = 1\n" + + " type argument index = 0\n" + + " )\n" + + " #27 @B(\n" + + " #28 value=(int) 2 (constant type)\n" + + " target type = 0x47 CAST\n" + + " offset = 9\n" + + " type argument index = 1\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test070b_codeblocks_castWithIntersectionCast() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "import java.io.*;\n" + + "public class X {\n" + + " public void foo(Object o) {\n" + + " System.out.println(123);\n" + + " I<String> i = (I<@B(1) String> & @B(2) J<String>) o;\n" + + " }\n" + + "}\n" + + "interface I<T> {}\n" + + "interface J<T> {}\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B {\n" + + " int value() default 1;\n" + + "}\n", + }, + ""); + String expectedOutput = + " public void foo(java.lang.Object o);\n" + + " 0 getstatic java.lang.System.out : java.io.PrintStream [16]\n" + + " 3 bipush 123\n" + + " 5 invokevirtual java.io.PrintStream.println(int) : void [22]\n" + + " 8 aload_1 [o]\n" + + " 9 checkcast I [28]\n" + + " 12 checkcast J [30]\n" + + " 15 astore_2 [i]\n" + + " 16 return\n" + + " Line numbers:\n" + + " [pc: 0, line: 4]\n" + + " [pc: 8, line: 5]\n" + + " [pc: 16, line: 6]\n" + + " Local variable table:\n" + + " [pc: 0, pc: 17] local: this index: 0 type: X\n" + + " [pc: 0, pc: 17] local: o index: 1 type: java.lang.Object\n" + + " [pc: 16, pc: 17] local: i index: 2 type: I\n" + + " Local variable type table:\n" + + " [pc: 16, pc: 17] local: i index: 2 type: I<java.lang.String>\n" + + " RuntimeVisibleTypeAnnotations: \n" + + " #39 @B(\n" + + " #40 value=(int) 1 (constant type)\n" + + " target type = 0x47 CAST\n" + + " offset = 9\n" + + " type argument index = 0\n" + + " location = [TYPE_ARGUMENT(0)]\n" + + " )\n" + + " #39 @B(\n" + + " #40 value=(int) 2 (constant type)\n" + + " target type = 0x47 CAST\n" + + " offset = 9\n" + + " type argument index = 1\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test070c_codeblocks_castTwiceInExpression() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "import java.io.*;\n" + + "public class X {\n" + + " public void foo(Object o) {\n" + + " System.out.println(123);\n" + + " I i = (@B(1) I)(@B(2) J) o;\n" + + " }\n" + + "}\n" + + "interface I {}\n" + + "interface J {}\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B {\n" + + " int value() default 1;\n" + + "}\n", + }, + ""); + String expectedOutput = + " 0 getstatic java.lang.System.out : java.io.PrintStream [16]\n" + + " 3 bipush 123\n" + + " 5 invokevirtual java.io.PrintStream.println(int) : void [22]\n" + + " 8 aload_1 [o]\n" + + " 9 checkcast J [28]\n" + + " 12 checkcast I [30]\n" + + " 15 astore_2 [i]\n" + + " 16 return\n" + + " Line numbers:\n" + + " [pc: 0, line: 4]\n" + + " [pc: 8, line: 5]\n" + + " [pc: 16, line: 6]\n" + + " Local variable table:\n" + + " [pc: 0, pc: 17] local: this index: 0 type: X\n" + + " [pc: 0, pc: 17] local: o index: 1 type: java.lang.Object\n" + + " [pc: 16, pc: 17] local: i index: 2 type: I\n" + + " RuntimeVisibleTypeAnnotations: \n" + + " #37 @B(\n" + + " #38 value=(int) 2 (constant type)\n" + + " target type = 0x47 CAST\n" + + " offset = 9\n" + + " type argument index = 0\n" + + " )\n" + + " #37 @B(\n" + + " #38 value=(int) 1 (constant type)\n" + + " target type = 0x47 CAST\n" + + " offset = 12\n" + + " type argument index = 0\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test070d_codeblocks_castDoubleIntersectionCastInExpression() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "import java.io.*;\n" + + "public class X {\n" + + " public void foo(Object o) {\n" + + " System.out.println(123);\n" + + " I i = (@B(1) I & J)(K & @B(2) L) o;\n" + + " }\n" + + "}\n" + + "interface I {}\n" + + "interface J {}\n" + + "interface K {}\n" + + "interface L {}\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B {\n" + + " int value() default 1;\n" + + "}\n", + }, + ""); + String expectedOutput = + " public void foo(java.lang.Object o);\n" + + " 0 getstatic java.lang.System.out : java.io.PrintStream [16]\n" + + " 3 bipush 123\n" + + " 5 invokevirtual java.io.PrintStream.println(int) : void [22]\n" + + " 8 aload_1 [o]\n" + + " 9 checkcast K [28]\n" + + " 12 checkcast L [30]\n" + + " 15 checkcast I [32]\n" + + " 18 checkcast J [34]\n" + + " 21 astore_2 [i]\n" + + " 22 return\n" + + " Line numbers:\n" + + " [pc: 0, line: 4]\n" + + " [pc: 8, line: 5]\n" + + " [pc: 22, line: 6]\n" + + " Local variable table:\n" + + " [pc: 0, pc: 23] local: this index: 0 type: X\n" + + " [pc: 0, pc: 23] local: o index: 1 type: java.lang.Object\n" + + " [pc: 22, pc: 23] local: i index: 2 type: I\n" + + " RuntimeVisibleTypeAnnotations: \n" + + " #41 @B(\n" + + " #42 value=(int) 2 (constant type)\n" + + " target type = 0x47 CAST\n" + + " offset = 9\n" + + " type argument index = 1\n" + + " )\n" + + " #41 @B(\n" + + " #42 value=(int) 1 (constant type)\n" + + " target type = 0x47 CAST\n" + + " offset = 15\n" + + " type argument index = 0\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + public void test071_codeblocks_constructorInvocationTypeArgument() throws Exception { this.runConformTest( new String[] { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java index b3547fb297..a7d3b6199c 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java @@ -15,6 +15,7 @@ * Bug 405066 - [1.8][compiler][codegen] Implement code generation infrastructure for JSR335 * Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for * Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work) + * Bug 409236 - [1.8][compiler] Type annotations on intersection cast types dropped by code generator *******************************************************************************/ package org.eclipse.jdt.internal.compiler; @@ -2190,8 +2191,7 @@ public class ClassFile implements TypeConstants, TypeIds { // bytecode offset this.contents[this.contentsOffset++] = (byte) (annotationContext.info >> 8); this.contents[this.contentsOffset++] = (byte) annotationContext.info; - // type_argument_index not set for cast - this.contents[this.contentsOffset++] = (byte)0; + this.contents[this.contentsOffset++] = (byte) annotationContext.info2; break; case AnnotationTargetTypeConstants.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT : diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IntersectionCastTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IntersectionCastTypeReference.java index f4020cb8b9..27da4692c2 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IntersectionCastTypeReference.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IntersectionCastTypeReference.java @@ -11,6 +11,8 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for + * Bug 409236 - [1.8][compiler] Type annotations on intersection cast types dropped by code generator *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -30,6 +32,12 @@ public class IntersectionCastTypeReference extends TypeReference { this.sourceStart = typeReferences[0].sourceStart; int length = typeReferences.length; this.sourceEnd = typeReferences[length - 1].sourceEnd; + for (int i = 0, max = typeReferences.length; i < max; i++) { + if ((typeReferences[i].bits & ASTNode.HasTypeAnnotations) != 0) { + this.bits |= ASTNode.HasTypeAnnotations; + break; + } + } } public TypeReference copyDims(int dim) { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java index 3a2d918748..3ab3e2d141 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java @@ -16,6 +16,7 @@ * bug 392862 - [1.8][compiler][null] Evaluate null annotations on array types * Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for * Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work) + * Bug 409236 - [1.8][compiler] Type annotations on intersection cast types dropped by code generator *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -51,8 +52,8 @@ static class AnnotationCollector extends ASTVisitor { TypeReference typeReference; int targetType; Annotation[] primaryAnnotations; - int info = -1; - int info2 = -1; + int info = 0; + int info2 = 0; LocalVariableBinding localVariable; Annotation[][] annotationsOnDimensions; int dimensions; @@ -183,12 +184,6 @@ static class AnnotationCollector extends ASTVisitor { case AnnotationTargetTypeConstants.NEW : case AnnotationTargetTypeConstants.CONSTRUCTOR_REFERENCE : case AnnotationTargetTypeConstants.METHOD_REFERENCE : - case AnnotationTargetTypeConstants.CAST: - annotationContext.info = this.info; - break; - case AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER_BOUND : - case AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER_BOUND : - annotationContext.info2 = this.info2; annotationContext.info = this.info; break; case AnnotationTargetTypeConstants.LOCAL_VARIABLE : @@ -199,6 +194,9 @@ static class AnnotationCollector extends ASTVisitor { case AnnotationTargetTypeConstants.METHOD_INVOCATION_TYPE_ARGUMENT : case AnnotationTargetTypeConstants.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT : case AnnotationTargetTypeConstants.METHOD_REFERENCE_TYPE_ARGUMENT : + case AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER_BOUND : + case AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER_BOUND : + case AnnotationTargetTypeConstants.CAST: annotationContext.info2 = this.info2; annotationContext.info = this.info; break; @@ -225,6 +223,14 @@ static class AnnotationCollector extends ASTVisitor { this.currentWildcard = wildcard; return true; } + public boolean visit(IntersectionCastTypeReference intersectionCastTypeReference, BlockScope scope) { + int length = intersectionCastTypeReference.typeReferences == null ? 0 : intersectionCastTypeReference.typeReferences.length; + for (int i = 0; i < length; i++) { + this.info2 = i; + intersectionCastTypeReference.typeReferences[i].traverse(this, scope); + } + return false; // iteration was done here, do not repeat in the caller + } public boolean visit(Argument argument, BlockScope scope) { if ((argument.bits & ASTNode.IsUnionType) == 0) { return true; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java index b44dd65eb1..1422f74db4 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java @@ -19,6 +19,7 @@ * Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for * Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work) * Bug 409247 - [1.8][compiler] Verify error with code allocating multidimensional array + * Bug 409236 - [1.8][compiler] Type annotations on intersection cast types dropped by code generator *******************************************************************************/ package org.eclipse.jdt.internal.compiler.codegen; @@ -657,7 +658,7 @@ public void checkcast(TypeReference typeReference, TypeBinding typeBinding) { reality this should not matter. In its intended use form such as (I & Serializable) () -> {}, no cast is emitted at all */ TypeBinding [] types = typeBinding instanceof IntersectionCastTypeBinding ? typeBinding.getIntersectingTypes() : new TypeBinding [] { typeBinding }; - for (int i = types.length - 1; i >=0; i--) { + for (int i = 0, max = types.length; i < max; i++) { this.countLabels = 0; if (this.classFileOffset + 2 >= this.bCodeStream.length) { resizeByteArray(); diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ExtendedAnnotation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ExtendedAnnotation.java index 902b329678..634a1dc335 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ExtendedAnnotation.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ExtendedAnnotation.java @@ -13,6 +13,7 @@ * IBM Corporation - initial API and implementation * Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for * Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work) + * Bug 409236 - [1.8][compiler] Type annotations on intersection cast types dropped by code generator *******************************************************************************/ package org.eclipse.jdt.internal.core.util; @@ -209,7 +210,10 @@ public class ExtendedAnnotation extends ClassFileStruct implements IExtendedAnno case IExtendedAnnotationConstants.CAST : this.offset = u2At(classFileBytes, this.readOffset, localOffset); - this.readOffset += 3; // skipping the 3rd byte which will be 0 for CAST + this.readOffset += 2; + // read type_argument_index + this.annotationTypeIndex = u1At(classFileBytes, this.readOffset, localOffset); + this.readOffset++; break; case IExtendedAnnotationConstants.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT : |
