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