### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java,v retrieving revision 1.95 diff -u -r1.95 ASTNode.java --- compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java 9 Sep 2008 10:00:42 -0000 1.95 +++ compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java 30 Sep 2008 13:18:32 -0000 @@ -41,20 +41,20 @@ public final static int Bit16 = 0x8000; // in javadoc comment (name ref, type ref, msg) public final static int Bit17 = 0x10000; // compound assigned (reference lhs) public final static int Bit18 = 0x20000; // non null (expression) | onDemand (import reference) - public final static int Bit19 = 0x40000; // didResolve (parameterized qualified type ref/parameterized single type ref) | empty (javadoc return statement) + public final static int Bit19 = 0x40000; // didResolve (parameterized qualified type ref/parameterized single type ref) | empty (javadoc return statement) | needReceiverGenericCast (msg/fieldref) public final static int Bit20 = 0x80000; public final static int Bit21 = 0x100000; - public final static int Bit22 = 0x200000; // parenthesis count (expression) | used (import reference) - public final static int Bit23 = 0x400000; // parenthesis count (expression) - public final static int Bit24 = 0x800000; // parenthesis count (expression) + public final static int Bit22 = 0x200000; // parenthesis count (expression) | used (import reference) + public final static int Bit23 = 0x400000; // parenthesis count (expression) + public final static int Bit24 = 0x800000; // parenthesis count (expression) public final static int Bit25 = 0x1000000; // parenthesis count (expression) public final static int Bit26 = 0x2000000; // parenthesis count (expression) public final static int Bit27 = 0x4000000; // parenthesis count (expression) public final static int Bit28 = 0x8000000; // parenthesis count (expression) - public final static int Bit29 = 0x10000000; // parenthesis count (expression) - public final static int Bit30 = 0x20000000; // elseif (if statement) | try block exit (try statement) | fall-through (case statement) | ignore no effect assign (expression ref) | needScope (for statement) | isAnySubRoutineEscaping (return statement) | blockExit (synchronized statement) - public final static int Bit31 = 0x40000000; // local declaration reachable (local decl) | ignore raw type check (type ref) | discard entire assignment (assignment) | isSynchronized (return statement) | thenExit (if statement) - public final static int Bit32 = 0x80000000; // reachable (statement) + public final static int Bit29 = 0x10000000; // parenthesis count (expression) + public final static int Bit30 = 0x20000000; // elseif (if statement) | try block exit (try statement) | fall-through (case statement) | ignore no effect assign (expression ref) | needScope (for statement) | isAnySubRoutineEscaping (return statement) | blockExit (synchronized statement) + public final static int Bit31 = 0x40000000; // local declaration reachable (local decl) | ignore raw type check (type ref) | discard entire assignment (assignment) | isSynchronized (return statement) | thenExit (if statement) + public final static int Bit32 = 0x80000000; // reachable (statement) public final static long Bit32L = 0x80000000L; public final static long Bit33L = 0x100000000L; @@ -112,6 +112,9 @@ // for name refs or local decls public static final int FirstAssignmentToLocal = Bit4; + // for msg or field references + public static final int NeedReceiverGenericCast = Bit19; + // for this reference public static final int IsImplicitThis = Bit3; Index: compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java,v retrieving revision 1.121 diff -u -r1.121 FieldReference.java --- compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java 25 Sep 2008 23:10:29 -0000 1.121 +++ compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java 30 Sep 2008 13:18:32 -0000 @@ -210,6 +210,9 @@ || ((this.implicitConversion & TypeIds.UNBOXING) != 0) || (this.genericCast != null)) { this.receiver.generateCode(currentScope, codeStream, !isStatic); + if ((this.bits & NeedReceiverGenericCast) != 0) { + codeStream.checkcast(this.actualReceiverType); + } pc = codeStream.position; if (codegenBinding.declaringClass == null) { // array length codeStream.arraylength(); @@ -545,13 +548,14 @@ scope.problemReporter().invalidField(this, this.actualReceiverType); return null; } - TypeBinding receiverErasure = this.actualReceiverType.erasure(); - if (receiverErasure instanceof ReferenceBinding) { - if (receiverErasure.findSuperTypeOriginatingFrom(fieldBinding.declaringClass) == null) { - this.actualReceiverType = fieldBinding.declaringClass; // handle indirect inheritance thru variable secondary bound - } - } + // handle indirect inheritance thru variable secondary bound + // receiver may receive generic cast, as part of implicit conversion + TypeBinding oldReceiverType = this.actualReceiverType; + this.actualReceiverType = this.actualReceiverType.getErasureCompatibleType(fieldBinding.declaringClass); this.receiver.computeConversion(scope, this.actualReceiverType, this.actualReceiverType); + if (this.actualReceiverType != oldReceiverType && this.receiver.postConversionType(scope) != this.actualReceiverType) { // record need for explicit cast at codegen since receiver could not handle it + this.bits |= NeedReceiverGenericCast; + } if (isFieldUseDeprecated(fieldBinding, scope, (this.bits & ASTNode.IsStrictlyAssigned) !=0)) { scope.problemReporter().deprecatedField(fieldBinding, this); } Index: compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java,v retrieving revision 1.135 diff -u -r1.135 MessageSend.java --- compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java 25 Sep 2008 23:10:29 -0000 1.135 +++ compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java 30 Sep 2008 13:18:33 -0000 @@ -50,7 +50,6 @@ public long nameSourcePosition ; //(start<<32)+end public TypeBinding actualReceiverType; - public TypeBinding receiverGenericCast; // extra reference type cast to perform on generic receiver public TypeBinding valueCast; // extra reference type cast to perform on method returned value public TypeReference[] typeArguments; public TypeBinding[] genericTypeArguments; @@ -123,9 +122,7 @@ * @param valueRequired boolean */ public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { - int pc = codeStream.position; - // generate receiver/enclosing instance access MethodBinding codegenBinding = this.binding.original(); boolean isStatic = codegenBinding.isStatic(); @@ -139,8 +136,9 @@ codeStream.generateOuterAccess(path, this, targetType, currentScope); } else { this.receiver.generateCode(currentScope, codeStream, true); - if (this.receiverGenericCast != null) - codeStream.checkcast(this.receiverGenericCast); + if ((this.bits & NeedReceiverGenericCast) != 0) { + codeStream.checkcast(this.actualReceiverType); + } codeStream.recordPositionsFrom(pc, this.sourceStart); } @@ -149,7 +147,7 @@ // actual message invocation if (this.syntheticAccessor == null){ - TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis(), this.receiverGenericCast != null); + TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis()); if (isStatic){ codeStream.invoke(Opcodes.OPC_invokestatic, codegenBinding, constantPoolDeclaringClass); } else if( (this.receiver.isSuper()) || codegenBinding.isPrivate()){ @@ -454,13 +452,13 @@ scope.problemReporter().rawTypeReference(this.receiver, this.actualReceiverType); } } else { + // handle indirect inheritance thru variable secondary bound + // receiver may receive generic cast, as part of implicit conversion + TypeBinding oldReceiverType = this.actualReceiverType; + this.actualReceiverType = this.actualReceiverType.getErasureCompatibleType(this.binding.declaringClass); this.receiver.computeConversion(scope, this.actualReceiverType, this.actualReceiverType); - // compute generic cast if necessary - TypeBinding receiverErasure = this.actualReceiverType.erasure(); - if (receiverErasure instanceof ReferenceBinding) { - if (receiverErasure.findSuperTypeOriginatingFrom(this.binding.declaringClass) == null) { - this.receiverGenericCast = this.binding.declaringClass; // handle indirect inheritance thru variable secondary bound - } + if (this.actualReceiverType != oldReceiverType && this.receiver.postConversionType(scope) != this.actualReceiverType) { // record need for explicit cast at codegen since receiver could not handle it + this.bits |= NeedReceiverGenericCast; } } } else { Index: compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java,v retrieving revision 1.133 diff -u -r1.133 QualifiedNameReference.java --- compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java 26 Sep 2008 16:37:13 -0000 1.133 +++ compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java 30 Sep 2008 13:18:33 -0000 @@ -737,16 +737,12 @@ // set generic cast of for previous field (if any) if (previousField != null) { TypeBinding fieldReceiverType = type; - TypeBinding receiverErasure = type.erasure(); - if (receiverErasure instanceof ReferenceBinding) { - if (receiverErasure.findSuperTypeOriginatingFrom(field.declaringClass) == null) { - fieldReceiverType = field.declaringClass; // handle indirect inheritance thru variable secondary bound - } - } + TypeBinding oldReceiverType = fieldReceiverType; + fieldReceiverType = fieldReceiverType.getErasureCompatibleType(field.declaringClass);// handle indirect inheritance thru variable secondary bound FieldBinding originalBinding = previousField.original(); - if (originalBinding.type.leafComponentType().isTypeVariable()) { + if (fieldReceiverType != oldReceiverType || originalBinding.type.leafComponentType().isTypeVariable()) { // record need for explicit cast at codegen setGenericCast(index-1,originalBinding.type.genericCast(fieldReceiverType)); // type cannot be base-type even in boxing case - } + } } // only last field is actually a write access if any if (isFieldUseDeprecated(field, scope, (this.bits & ASTNode.IsStrictlyAssigned) !=0 && index+1 == length)) { Index: compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java,v retrieving revision 1.168 diff -u -r1.168 CodeStream.java --- compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java 25 Sep 2008 23:10:29 -0000 1.168 +++ compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java 30 Sep 2008 13:18:34 -0000 @@ -2932,10 +2932,9 @@ * @param codegenBinding * @param actualReceiverType * @param isImplicitThisReceiver - * @param hasGenericCast * @return the receiver type to use in constant pool */ -public static TypeBinding getConstantPoolDeclaringClass(Scope currentScope, MethodBinding codegenBinding, TypeBinding actualReceiverType, boolean isImplicitThisReceiver, boolean hasGenericCast) { +public static TypeBinding getConstantPoolDeclaringClass(Scope currentScope, MethodBinding codegenBinding, TypeBinding actualReceiverType, boolean isImplicitThisReceiver) { TypeBinding constantPoolDeclaringClass = codegenBinding.declaringClass; // Post 1.4.0 target, array clone() invocations are qualified with array type // This is handled in array type #clone method binding resolution (see Scope and UpdatedMethodBinding) @@ -2949,7 +2948,7 @@ // for runtime compatibility on 1.2 VMs : change the declaring class of the binding // NOTE: from target 1.2 on, method's declaring class is touched if any different from receiver type // and not from Object or implicit static method call. - if (constantPoolDeclaringClass != actualReceiverType.erasure() && !hasGenericCast && !actualReceiverType.isArrayType()) { + if (constantPoolDeclaringClass != actualReceiverType.erasure() && !actualReceiverType.isArrayType()) { CompilerOptions options = currentScope.compilerOptions(); if ((options.targetJDK >= ClassFileConstants.JDK1_2 && (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(isImplicitThisReceiver && codegenBinding.isStatic())) Index: eval/org/eclipse/jdt/internal/eval/CodeSnippetMessageSend.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetMessageSend.java,v retrieving revision 1.59 diff -u -r1.59 CodeSnippetMessageSend.java --- eval/org/eclipse/jdt/internal/eval/CodeSnippetMessageSend.java 25 Sep 2008 23:10:29 -0000 1.59 +++ eval/org/eclipse/jdt/internal/eval/CodeSnippetMessageSend.java 30 Sep 2008 13:18:34 -0000 @@ -67,14 +67,15 @@ } } else { this.receiver.generateCode(currentScope, codeStream, !isStatic); - if (this.receiverGenericCast != null) - codeStream.checkcast(this.receiverGenericCast); + if ((this.bits & NeedReceiverGenericCast) != 0) { + codeStream.checkcast(this.actualReceiverType); + } codeStream.recordPositionsFrom(pc, this.sourceStart); } // generate arguments generateArguments(this.binding, this.arguments, currentScope, codeStream); // actual message invocation - TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis(), this.receiverGenericCast != null); + TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis()); if (isStatic) { codeStream.invoke(Opcodes.OPC_invokestatic, codegenBinding, constantPoolDeclaringClass); } else if( (this.receiver.isSuper()) || codegenBinding.isPrivate()){ @@ -96,8 +97,9 @@ currentScope.problemReporter().needImplementation(this); } else { this.receiver.generateCode(currentScope, codeStream, !isStatic); - if (this.receiverGenericCast != null) - codeStream.checkcast(this.receiverGenericCast); + if ((this.bits & NeedReceiverGenericCast) != 0) { + codeStream.checkcast(this.actualReceiverType); + } codeStream.recordPositionsFrom(pc, this.sourceStart); } if (isStatic) { @@ -299,14 +301,14 @@ && (((NameReference) this.receiver).bits & Binding.TYPE) != 0) { scope.problemReporter().mustUseAStaticMethod(this, this.binding); } else { - // compute generic cast if necessary - TypeBinding receiverErasure = this.actualReceiverType.erasure(); - if (receiverErasure instanceof ReferenceBinding) { - if (receiverErasure.findSuperTypeOriginatingFrom(this.binding.declaringClass) == null) { - this.actualReceiverType = this.binding.declaringClass; // handle indirect inheritance thru variable secondary bound - } - } + // handle indirect inheritance thru variable secondary bound + // receiver may receive generic cast, as part of implicit conversion + TypeBinding oldReceiverType = this.actualReceiverType; + this.actualReceiverType = this.actualReceiverType.getErasureCompatibleType(this.binding.declaringClass); this.receiver.computeConversion(scope, this.actualReceiverType, this.actualReceiverType); + if (this.actualReceiverType != oldReceiverType && this.receiver.postConversionType(scope) != this.actualReceiverType) { // record need for explicit cast at codegen since receiver could not handle it + this.bits |= NeedReceiverGenericCast; + } } } checkInvocationArguments(scope, this.receiver, this.actualReceiverType, this.binding, this.arguments, argumentTypes, argsContainCast, this); Index: compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java,v retrieving revision 1.101 diff -u -r1.101 TypeBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java 9 Sep 2008 18:40:56 -0000 1.101 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java 30 Sep 2008 13:18:34 -0000 @@ -358,6 +358,51 @@ return signature(); } +/** + * Return the supertype which would erase as a subtype of a given declaring class. + * If the receiver is already erasure compatible, then it will returned. If not, then will return the alternate lowest + * upper bound compatible with declaring class. + * NOTE: the declaringClass is already know to be compatible with the receiver + * @param declaringClass to look for + * @return the lowest erasure compatible type (considering alternate bounds) + */ +public TypeBinding getErasureCompatibleType(TypeBinding declaringClass) { + switch(kind()) { + case Binding.TYPE_PARAMETER : + TypeVariableBinding variable = (TypeVariableBinding) this; + if (variable.erasure().findSuperTypeOriginatingFrom(declaringClass) != null) { + return this; // no need for alternate receiver type + } + if (variable.superclass != null && variable.superclass.findSuperTypeOriginatingFrom(declaringClass) != null) { + return variable.superclass.getErasureCompatibleType(declaringClass); + } + for (int i = 0, otherLength = variable.superInterfaces.length; i < otherLength; i++) { + ReferenceBinding superInterface = variable.superInterfaces[i]; + if (superInterface.findSuperTypeOriginatingFrom(declaringClass) != null) { + return superInterface.getErasureCompatibleType(declaringClass); + } + } + return this; // only occur if passed null declaringClass for arraylength + case Binding.INTERSECTION_TYPE : + WildcardBinding intersection = (WildcardBinding) this; + if (intersection.erasure().findSuperTypeOriginatingFrom(declaringClass) != null) { + return this; // no need for alternate receiver type + } + if (intersection.superclass != null && intersection.superclass.findSuperTypeOriginatingFrom(declaringClass) != null) { + return intersection.superclass.getErasureCompatibleType(declaringClass); + } + for (int i = 0, otherLength = intersection.superInterfaces.length; i < otherLength; i++) { + ReferenceBinding superInterface = intersection.superInterfaces[i]; + if (superInterface.findSuperTypeOriginatingFrom(declaringClass) != null) { + return superInterface.getErasureCompatibleType(declaringClass); + } + } + return this; // only occur if passed null declaringClass for arraylength + default : + return this; + } +} + public abstract PackageBinding getPackage(); void initializeForStaticImports() { #P org.eclipse.jdt.core.tests.compiler Index: src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java,v retrieving revision 1.757 diff -u -r1.757 GenericTypeTest.java --- src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java 23 Sep 2008 13:00:52 -0000 1.757 +++ src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java 30 Sep 2008 13:18:42 -0000 @@ -46336,7 +46336,7 @@ "----------\n"); } //https://bugs.eclipse.org/bugs/show_bug.cgi?id=247953 -public void _test1381() throws Exception { +public void test1381() throws Exception { this.runConformTest( new String[] { "X.java", @@ -46361,30 +46361,28 @@ "}\n", "p/IB.java", // ===================== "package p;\n" + - "interface IA {\n" + + "interface IA {\n" + // non visible " void baz();\n" + "}\n" + "public interface IB extends IA {\n" + "}\n", }, "done"); - // check #baz() invocation declaring class is IA + // check #baz() invocation declaring class is IB String expectedOutput = - " // Method descriptor #21 (LX;)V\n" + - " // Signature: (LX;)V\n" + - " // Stack: 1, Locals: 2\n" + - " void foo(X xt);\n" + - " 0 aload_1 [xt]\n" + - " 1 invokevirtual X.get() : AA [23]\n" + - " 4 checkcast p.IA [25]\n" + - " 7 invokeinterface p.IA.baz() : void [27] [nargs: 1]\n" + + " // Method descriptor #10 ()V\n" + + " // Stack: 1, Locals: 1\n" + + " void foo();\n" + + " 0 aload_0 [this]\n" + + " 1 getfield X.t : AA [21]\n" + + " 4 checkcast p.IB [23]\n" + + " 7 invokeinterface p.IB.baz() : void [25] [nargs: 1]\n" + " 12 return\n" + " Line numbers:\n" + - " [pc: 0, line: 5]\n" + - " [pc: 12, line: 6]\n" + + " [pc: 0, line: 4]\n" + + " [pc: 12, line: 5]\n" + " Local variable table:\n" + - " [pc: 0, pc: 13] local: this index: 0 type: X\n" + - " [pc: 0, pc: 13] local: xt index: 1 type: X\n"; + " [pc: 0, pc: 13] local: this index: 0 type: X\n"; File f = new File(OUTPUT_DIR + File.separator + "X.class"); byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(f); @@ -46399,7 +46397,7 @@ } } //https://bugs.eclipse.org/bugs/show_bug.cgi?id=247953 - variation -public void _test1382() throws Exception { +public void test1382() throws Exception { this.runConformTest( new String[] { "X.java", @@ -46452,7 +46450,7 @@ } } //https://bugs.eclipse.org/bugs/show_bug.cgi?id=247953 - variation -public void _test1383() throws Exception { +public void test1383() throws Exception { this.runConformTest( new String[] { "X.java", @@ -46507,7 +46505,7 @@ } } //https://bugs.eclipse.org/bugs/show_bug.cgi?id=247953 - variation -public void _test1384() throws Exception { +public void test1384() throws Exception { this.runConformTest( new String[] { "X.java", @@ -46561,7 +46559,7 @@ } } //https://bugs.eclipse.org/bugs/show_bug.cgi?id=247953 - variation -public void _test1385() throws Exception { +public void test1385() throws Exception { this.runConformTest( new String[] { "X.java", @@ -46613,7 +46611,7 @@ } } //https://bugs.eclipse.org/bugs/show_bug.cgi?id=247953 - variation -public void _test1386() throws Exception { +public void test1386() throws Exception { this.runConformTest( new String[] { "X.java", @@ -46635,7 +46633,7 @@ "public interface IB extends IA {\n" + "}\n", }, - "111"); + ""); // check #baz() invocation declaring class is not IA String expectedOutput = " // Method descriptor #21 (LX;)V\n" + @@ -46667,7 +46665,7 @@ } } //https://bugs.eclipse.org/bugs/show_bug.cgi?id=247953 - variation -public void _test1387() throws Exception { +public void test1387() throws Exception { this.runConformTest( new String[] { "X.java", @@ -46698,21 +46696,22 @@ "done"); // check #baz declaring class is not IA String expectedOutput = - " // Method descriptor #21 (LX;)V\n" + - " // Signature: (LX;)V\n" + - " // Stack: 1, Locals: 2\n" + - " void foo(X xt);\n" + - " 0 aload_1 [xt]\n" + - " 1 invokevirtual X.get() : AA [23]\n" + - " 4 checkcast p.IB [25]\n" + - " 7 invokeinterface p.IB.baz() : void [27] [nargs: 1]\n" + - " 12 return\n" + + " // Method descriptor #10 ()V\n" + + " // Stack: 2, Locals: 1\n" + + " void foo();\n" + + " 0 getstatic java.lang.System.out : java.io.PrintStream [21]\n" + + " 3 aload_0 [this]\n" + + " 4 getfield X.t : AA [27]\n" + + " 7 checkcast p.IB [29]\n" + + " 10 pop\n" + + " 11 getstatic p.IB.baz : java.lang.Object [31]\n" + + " 14 invokevirtual java.io.PrintStream.println(java.lang.Object) : void [35]\n" + + " 17 return\n" + " Line numbers:\n" + - " [pc: 0, line: 5]\n" + - " [pc: 12, line: 6]\n" + + " [pc: 0, line: 4]\n" + + " [pc: 17, line: 5]\n" + " Local variable table:\n" + - " [pc: 0, pc: 13] local: this index: 0 type: X\n" + - " [pc: 0, pc: 13] local: xt index: 1 type: X\n"; + " [pc: 0, pc: 18] local: this index: 0 type: X\n"; File f = new File(OUTPUT_DIR + File.separator + "X.class"); byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(f); @@ -46727,7 +46726,7 @@ } } //https://bugs.eclipse.org/bugs/show_bug.cgi?id=247953 - variation -public void _test1388() throws Exception { +public void test1388() throws Exception { this.runConformTest( new String[] { "X.java", @@ -46758,21 +46757,22 @@ "done"); // check #baz declaring class is not IA String expectedOutput = - " // Method descriptor #21 (LX;)V\n" + - " // Signature: (LX;)V\n" + - " // Stack: 1, Locals: 2\n" + - " void foo(X xt);\n" + - " 0 aload_1 [xt]\n" + - " 1 invokevirtual X.get() : AA [23]\n" + - " 4 checkcast p.IB [25]\n" + - " 7 invokeinterface p.IB.baz() : void [27] [nargs: 1]\n" + - " 12 return\n" + + " // Method descriptor #10 ()V\n" + + " // Stack: 2, Locals: 1\n" + + " void foo();\n" + + " 0 getstatic java.lang.System.out : java.io.PrintStream [21]\n" + + " 3 aload_0 [this]\n" + + " 4 getfield X.t : AA [27]\n" + + " 7 checkcast p.IB [29]\n" + + " 10 pop\n" + + " 11 getstatic p.IB.baz : java.lang.Object [31]\n" + + " 14 invokevirtual java.io.PrintStream.println(java.lang.Object) : void [35]\n" + + " 17 return\n" + " Line numbers:\n" + - " [pc: 0, line: 5]\n" + - " [pc: 12, line: 6]\n" + + " [pc: 0, line: 4]\n" + + " [pc: 17, line: 5]\n" + " Local variable table:\n" + - " [pc: 0, pc: 13] local: this index: 0 type: X\n" + - " [pc: 0, pc: 13] local: xt index: 1 type: X\n"; + " [pc: 0, pc: 18] local: this index: 0 type: X\n"; File f = new File(OUTPUT_DIR + File.separator + "X.class"); byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(f); @@ -46787,7 +46787,7 @@ } } //https://bugs.eclipse.org/bugs/show_bug.cgi?id=247953 - variation -public void _test1389() throws Exception { +public void test1389() throws Exception { this.runConformTest( new String[] { "X.java", @@ -47136,4 +47136,58 @@ assertEquals("Wrong contents", expectedOutput, result); } } +public void test1396() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "public class X> {\n" + + " T sx1;\n" + + " void foo(T t) {\n" + + " t.sx2.t.getClass();\n" + + " }\n" + + "}\n" + + "interface X1> {\n" + + "}\n" + + "abstract class SubX1> implements X1 {\n" + + " T sx2;\n" + + "}\n" + + "interface X2> extends X1{\n" + + "}\n" + + "abstract class SubX2> extends SubX1 implements X2 {\n" + + " T t;\n" + + "}\n", + }, + ""); + String expectedOutput = + " // Method descriptor #21 (LSubX2;)V\n" + + " // Signature: (TT;)V\n" + + " // Stack: 1, Locals: 2\n" + + " void foo(SubX2 t);\n" + + " 0 aload_1 [t]\n" + + " 1 getfield SubX2.sx2 : X2 [23]\n" + + " 4 checkcast SubX2 [24]\n" + + " 7 getfield SubX2.t : X2 [29]\n" + + " 10 checkcast SubX2 [24]\n" + + " 13 invokevirtual java.lang.Object.getClass() : java.lang.Class [32]\n" + + " 16 pop\n" + + " 17 return\n" + + " Line numbers:\n" + + " [pc: 0, line: 4]\n" + + " [pc: 17, line: 5]\n" + + " Local variable table:\n" + + " [pc: 0, pc: 18] local: this index: 0 type: X\n" + + " [pc: 0, pc: 18] local: t index: 1 type: SubX2\n"; + + File f = new File(OUTPUT_DIR + File.separator + "X.class"); + byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(f); + ClassFileBytesDisassembler disassembler = ToolFactory.createDefaultClassFileBytesDisassembler(); + String result = disassembler.disassemble(classFileBytes, "\n", ClassFileBytesDisassembler.DETAILED); + int index = result.indexOf(expectedOutput); + if (index == -1 || expectedOutput.length() == 0) { + System.out.println(Util.displayString(result, 3)); + } + if (index == -1) { + assertEquals("Wrong contents", expectedOutput, result); + } +} } \ No newline at end of file