diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CastTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CastTest.java index f251fed..cef41ac 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CastTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CastTest.java @@ -2374,53 +2374,6 @@ "SUCCESS" ); } -// https://bugs.eclipse.org/bugs/show_bug.cgi?id=359284 -// Verify that needless checkcast is not emitted. -public void test062() throws Exception { - String source = - "public class X {\n" + - "public X() {\n" + - " Object[] x = null;\n" + - "}\n" + - "}\n"; - this.runConformTest( - new String[] { - "X.java", - source - }, - "" - ); - String expectedOutput = - "public class X {\n" + - " \n" + - " // Method descriptor #6 ()V\n" + - " // Stack: 1, Locals: 2\n" + - " public X();\n" + - " 0 aload_0 [this]\n" + - " 1 invokespecial java.lang.Object() [8]\n" + - " 4 aconst_null\n" + - " 5 astore_1 [x]\n" + - " 6 return\n" + - " Line numbers:\n" + - " [pc: 0, line: 2]\n" + - " [pc: 4, line: 3]\n" + - " [pc: 6, line: 4]\n" + - " Local variable table:\n" + - " [pc: 0, pc: 7] local: this index: 0 type: X\n" + - " [pc: 6, pc: 7] local: x index: 1 type: java.lang.Object[]\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); - } -} public static Class testClass() { return CastTest.class; } diff --git a/org.eclipse.jdt.core/buildnotes_jdt-core.html b/org.eclipse.jdt.core/buildnotes_jdt-core.html index 7be1a35..6068df6 100644 --- a/org.eclipse.jdt.core/buildnotes_jdt-core.html +++ b/org.eclipse.jdt.core/buildnotes_jdt-core.html @@ -246,9 +246,7 @@

Problem Reports Fixed

-359284 -Unnecessary checkast from null -
359943 +359943 invokedynamic in generated class file is not correctly recognized by the eclipse compiler
360644 Scope.isDefinedInSameUnit(ReferenceBinding) fails for a ParameterizedTypeBinding diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java index 2e7ebef..9b12104 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java @@ -53,6 +53,10 @@ public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) { int pc = codeStream.position; this.receiver.generateCode(currentScope, codeStream, true); + if (this.receiver instanceof CastExpression // ((type[])null)[0] + && ((CastExpression)this.receiver).innermostCastedExpression().resolvedType == TypeBinding.NULL){ + codeStream.checkcast(this.receiver.resolvedType); + } codeStream.recordPositionsFrom(pc, this.sourceStart); this.position.generateCode(currentScope, codeStream, true); assignment.expression.generateCode(currentScope, codeStream, true); @@ -68,6 +72,10 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { int pc = codeStream.position; this.receiver.generateCode(currentScope, codeStream, true); + if (this.receiver instanceof CastExpression // ((type[])null)[0] + && ((CastExpression)this.receiver).innermostCastedExpression().resolvedType == TypeBinding.NULL){ + codeStream.checkcast(this.receiver.resolvedType); + } this.position.generateCode(currentScope, codeStream, true); codeStream.arrayAt(this.resolvedType.id); // Generating code for the potential runtime type checking @@ -91,6 +99,10 @@ public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) { this.receiver.generateCode(currentScope, codeStream, true); + if (this.receiver instanceof CastExpression // ((type[])null)[0] + && ((CastExpression)this.receiver).innermostCastedExpression().resolvedType == TypeBinding.NULL){ + codeStream.checkcast(this.receiver.resolvedType); + } this.position.generateCode(currentScope, codeStream, true); codeStream.dup2(); codeStream.arrayAt(this.resolvedType.id); @@ -120,6 +132,10 @@ public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) { this.receiver.generateCode(currentScope, codeStream, true); + if (this.receiver instanceof CastExpression // ((type[])null)[0] + && ((CastExpression)this.receiver).innermostCastedExpression().resolvedType == TypeBinding.NULL){ + codeStream.checkcast(this.receiver.resolvedType); + } this.position.generateCode(currentScope, codeStream, true); codeStream.dup2(); codeStream.arrayAt(this.resolvedType.id); @@ -155,6 +171,10 @@ public TypeBinding resolveType(BlockScope scope) { this.constant = Constant.NotAConstant; + if (this.receiver instanceof CastExpression // no cast check for ((type[])null)[0] + && ((CastExpression)this.receiver).innermostCastedExpression() instanceof NullLiteral) { + this.receiver.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on + } TypeBinding arrayType = this.receiver.resolveType(scope); if (arrayType != null) { this.receiver.computeConversion(scope, arrayType, arrayType); diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java index 567deaf..b11e476 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java @@ -133,6 +133,13 @@ break generateInit; } this.initialization.generateCode(currentScope, codeStream, true); + // 26903, need extra cast to store null in array local var + if (this.binding.type.isArrayType() + && (this.initialization.resolvedType == TypeBinding.NULL // arrayLoc = null + || ((this.initialization instanceof CastExpression) // arrayLoc = (type[])null + && (((CastExpression)this.initialization).innermostCastedExpression().resolvedType == TypeBinding.NULL)))){ + codeStream.checkcast(this.binding.type); + } codeStream.store(this.binding, false); if ((this.bits & ASTNode.FirstAssignmentToLocal) != 0) { /* Variable may have been initialized during the code initializing it diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java index 058e218..a2cdd89 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java @@ -350,6 +350,14 @@ } return; } + // 26903, need extra cast to store null in array local var + if (localBinding.type.isArrayType() + && (assignment.expression.resolvedType == TypeBinding.NULL // arrayLoc = null + || ((assignment.expression instanceof CastExpression) // arrayLoc = (type[])null + && (((CastExpression)assignment.expression).innermostCastedExpression().resolvedType == TypeBinding.NULL)))){ + codeStream.checkcast(localBinding.type); + } + // normal local assignment (since cannot store in outer local which are final locations) codeStream.store(localBinding, valueRequired); if ((this.bits & ASTNode.FirstAssignmentToLocal) != 0) { // for local variable debug attributes