### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java,v retrieving revision 1.114 diff -u -r1.114 TryStatement.java --- compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java 19 Nov 2009 15:57:21 -0000 1.114 +++ compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java 17 Dec 2010 07:20:15 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. + * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 332637 - Dead Code detection removing code that isn't dead *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -126,15 +127,15 @@ addPotentialInitializationsFrom( handlingContext.initsOnReturn)); } else { + FlowInfo initsOnException = handlingContext.initsOnException(this.caughtExceptionTypes[i]); catchInfo = - flowInfo.unconditionalCopy(). - addPotentialInitializationsFrom( - handlingContext.initsOnException( - this.caughtExceptionTypes[i])) - .addPotentialInitializationsFrom(tryInfo.unconditionalCopy()) + flowInfo.nullInfoLessUnconditionalCopy() + .addPotentialInitializationsFrom(initsOnException) + .addNullInfoFrom(initsOnException) // null info only from here, this is the only way to enter the catch block .addPotentialInitializationsFrom( - handlingContext.initsOnReturn. - nullInfoLessUnconditionalCopy()); + tryInfo.nullInfoLessUnconditionalCopy()) + .addPotentialInitializationsFrom( + handlingContext.initsOnReturn.nullInfoLessUnconditionalCopy()); } // catch var is always set @@ -235,15 +236,15 @@ addPotentialInitializationsFrom( handlingContext.initsOnReturn)); }else { + FlowInfo initsOnException = handlingContext.initsOnException(this.caughtExceptionTypes[i]); catchInfo = - flowInfo.unconditionalCopy() + flowInfo.nullInfoLessUnconditionalCopy() + .addPotentialInitializationsFrom(initsOnException) + .addNullInfoFrom(initsOnException) // null info only from here, this is the only way to enter the catch block .addPotentialInitializationsFrom( - handlingContext.initsOnException( - this.caughtExceptionTypes[i])) - .addPotentialInitializationsFrom(tryInfo.unconditionalCopy()) + tryInfo.nullInfoLessUnconditionalCopy()) .addPotentialInitializationsFrom( - handlingContext.initsOnReturn. - nullInfoLessUnconditionalCopy()); + handlingContext.initsOnReturn.nullInfoLessUnconditionalCopy()); } // catch var is always set Index: compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java,v retrieving revision 1.30 diff -u -r1.30 ConditionalFlowInfo.java --- compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java 24 Feb 2010 20:12:41 -0000 1.30 +++ compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java 17 Dec 2010 07:20:15 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 332637 - Dead Code detection removing code that isn't dead *******************************************************************************/ package org.eclipse.jdt.internal.compiler.flow; @@ -35,6 +36,13 @@ return this; } +public FlowInfo addNullInfoFrom(FlowInfo otherInits) { + + this.initsWhenTrue.addNullInfoFrom(otherInits); + this.initsWhenFalse.addNullInfoFrom(otherInits); + return this; +} + public FlowInfo addPotentialInitializationsFrom(FlowInfo otherInits) { this.initsWhenTrue.addPotentialInitializationsFrom(otherInits); Index: compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java,v retrieving revision 1.41.2.1 diff -u -r1.41.2.1 FlowInfo.java --- compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java 21 Jul 2010 09:33:31 -0000 1.41.2.1 +++ compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java 17 Dec 2010 07:20:15 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 332637 - Dead Code detection removing code that isn't dead *******************************************************************************/ package org.eclipse.jdt.internal.compiler.flow; @@ -41,6 +42,13 @@ */ abstract public FlowInfo addInitializationsFrom(FlowInfo otherInits); +/** + * Add all null information from otherInits to this flow info and return this. + * The operation models the effect of an unconditional sequence of this flow info + * and otherInits. + */ +abstract public FlowInfo addNullInfoFrom(FlowInfo otherInits); + /** * Compose other inits over this flow info, then return this. The operation Index: compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java,v retrieving revision 1.65 diff -u -r1.65 UnconditionalFlowInfo.java --- compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java 24 Feb 2010 20:12:40 -0000 1.65 +++ compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java 17 Dec 2010 07:20:15 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 332637 *******************************************************************************/ package org.eclipse.jdt.internal.compiler.flow; @@ -87,16 +88,25 @@ public int[] nullStatusChangedInAssert; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=303448 public FlowInfo addInitializationsFrom(FlowInfo inits) { + return addInfoFrom(inits, true); +} +public FlowInfo addNullInfoFrom(FlowInfo inits) { + return addInfoFrom(inits, false); +} +private FlowInfo addInfoFrom(FlowInfo inits, boolean handleInits) { if (this == DEAD_END) return this; if (inits == DEAD_END) return this; UnconditionalFlowInfo otherInits = inits.unconditionalInits(); - // union of definitely assigned variables, - this.definiteInits |= otherInits.definiteInits; - // union of potentially set ones - this.potentialInits |= otherInits.potentialInits; + if (handleInits) { + // union of definitely assigned variables, + this.definiteInits |= otherInits.definiteInits; + // union of potentially set ones + this.potentialInits |= otherInits.potentialInits; + } + // combine null information boolean thisHadNulls = (this.tagBits & NULL_FLAG_MASK) != 0, otherHasNulls = (otherInits.tagBits & NULL_FLAG_MASK) != 0; @@ -218,14 +228,17 @@ } } int i; - // manage definite assignment info - for (i = 0; i < mergeLimit; i++) { - this.extra[0][i] |= otherInits.extra[0][i]; - this.extra[1][i] |= otherInits.extra[1][i]; - } - for (; i < copyLimit; i++) { - this.extra[0][i] = otherInits.extra[0][i]; - this.extra[1][i] = otherInits.extra[1][i]; + if (handleInits) { + // manage definite assignment info + for (i = 0; i < mergeLimit; i++) { + this.extra[0][i] |= otherInits.extra[0][i]; + this.extra[1][i] |= otherInits.extra[1][i]; + } + for (; i < copyLimit; i++) { + this.extra[0][i] = otherInits.extra[0][i]; + this.extra[1][i] = otherInits.extra[1][i]; + + } } // tweak limits for nulls if (!thisHadNulls) { #P org.eclipse.jdt.core.tests.compiler Index: src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java,v retrieving revision 1.95.2.2 diff -u -r1.95.2.2 NullReferenceTest.java --- src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java 23 Aug 2010 08:47:08 -0000 1.95.2.2 +++ src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java 17 Dec 2010 07:20:19 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 332637 *******************************************************************************/ package org.eclipse.jdt.core.tests.compiler.regression; @@ -749,12 +750,12 @@ " o.toString();\n" + " }\n" + "}\n"}, - "----------\n" + + "----------\n" + "1. ERROR in X.java (at line 4)\n" + - " o.toString();\n" + - " ^\n" + + " o.toString();\n" + + " ^\n" + "The variable o may be null\n" + - "----------\n"); + "----------\n"); } // null analysis -- conditional expression @@ -5598,7 +5599,7 @@ // null analysis - try/catch public void test0554_try_catch() { - this.runConformTest( + this.runNegativeTest( new String[] { "X.java", "public class X {\n" + @@ -5622,14 +5623,18 @@ " throw new LocalException();\n" + " }\n" + "}\n"}, - "" - // conservative flow analysis suppresses the warning -// "----------\n" + -// "1. ERROR in X.java (at line 10)\n" + -// " if (o != null) {\n" + -// " ^\n" + -// "Redundant null check: The variable o can only be null at this location\n" + -// "----------\n" + "----------\n" + + "1. ERROR in X.java (at line 10)\n" + + " if (o != null) {\n" + + " ^\n" + + "Null comparison always yields false: The variable o can only be null at this location\n" + + "----------\n" + + "2. WARNING in X.java (at line 10)\n" + + " if (o != null) {\n" + + " }\n" + + " ^^^^^^^\n" + + "Dead code\n" + + "----------\n" ); } @@ -5748,9 +5753,7 @@ "1. ERROR in X.java (at line 13)\n" + " o.toString();\n" + " ^\n" + -// "Null pointer access: The variable o can only be null at this location\n" + - "Potential null pointer access: The variable o may be null at this location\n" + - // conservative flow analysis softens the error + "Null pointer access: The variable o can only be null at this location\n" + "----------\n", JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); } @@ -5785,9 +5788,7 @@ "1. ERROR in X.java (at line 12)\n" + " o.toString();\n" + " ^\n" + -// "Null pointer access: The variable o can only be null at this location\n" + - "Potential null pointer access: The variable o may be null at this location\n" + - // conservative flow analysis softens the error + "Null pointer access: The variable o can only be null at this location\n" + "----------\n", JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); } @@ -12664,4 +12665,135 @@ "}"}, "Compiler good Compiler good"); } +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=332637 +// Dead Code detection removing code that isn't dead +public void testBug332637() { + if (this.complianceLevel < ClassFileConstants.JDK1_5) + return; + this.runConformTest( + new String[] { + "DeadCodeExample.java", + "public class DeadCodeExample {\n" + + "\n" + + " private class CanceledException extends Exception {\n" + + " }\n" + + "\n" + + " private interface ProgressMonitor {\n" + + " boolean isCanceled();\n" + + " }\n" + + "\n" + + " private void checkForCancellation(ProgressMonitor monitor)\n" + + " throws CanceledException {\n" + + " if (monitor.isCanceled()) {\n" + + " throw new CanceledException();\n" + + " }\n" + + " }\n" + + "\n" + + " private int run() {\n" + + "\n" + + " ProgressMonitor monitor = new ProgressMonitor() {\n" + + " private int i = 0;\n" + + "\n" + + " public boolean isCanceled() {\n" + + " return (++i == 5);\n" + + " }\n" + + " };\n" + + "\n" + + " Integer number = null;\n" + + "\n" + + " try {\n" + + " checkForCancellation(monitor);\n" + + "\n" + + " number = Integer.valueOf(0);\n" + + "\n" + + " for (String s : new String[10]) {\n" + + " checkForCancellation(monitor);\n" + + " number++;\n" + + " }\n" + + " return 0;\n" + + " } catch (CanceledException e) {\n" + + " System.out.println(\"Canceled after \" + number\n" + + " + \" times through the loop\");\n" + + " if (number != null) {\n" + + " System.out.println(\"number = \" + number);\n" + + " }\n" + + " return -1;\n" + + " }\n" + + " }\n" + + "\n" + + " public static void main(String[] args) {\n" + + " System.out.println(new DeadCodeExample().run());\n" + + " }\n" + + "}\n" + }); +} + +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=332637 +//Dead Code detection removing code that isn't dead +public void testBug332637b() { + if (this.complianceLevel < ClassFileConstants.JDK1_5) + return; + this.runConformTest( + new String[] { + "DeadCodeExample.java", + "public class DeadCodeExample {\n" + + "\n" + + " private class CanceledException extends Exception {\n" + + " }\n" + + "\n" + + " private interface ProgressMonitor {\n" + + " boolean isCanceled();\n" + + " }\n" + + "\n" + + " private void checkForCancellation(ProgressMonitor monitor)\n" + + " throws CanceledException {\n" + + " if (monitor.isCanceled()) {\n" + + " throw new CanceledException();\n" + + " }\n" + + " }\n" + + "\n" + + " private int run() {\n" + + "\n" + + " ProgressMonitor monitor = new ProgressMonitor() {\n" + + " private int i = 0;\n" + + "\n" + + " public boolean isCanceled() {\n" + + " return (++i == 5);\n" + + " }\n" + + " };\n" + + "\n" + + " Integer number = null;\n" + + "\n" + + " try {\n" + + " checkForCancellation(monitor);\n" + + "\n" + + " number = Integer.valueOf(0);\n" + + "\n" + + " for (String s : new String[10]) {\n" + + " checkForCancellation(monitor);\n" + + " number++;\n" + + " }\n" + + " return 0;\n" + + " } catch (CanceledException e) {\n" + + " System.out.println(\"Canceled after \" + number\n" + + " + \" times through the loop\");\n" + + " if (number != null) {\n" + + " System.out.println(\"number = \" + number);\n" + + " }\n" + + " return -1;\n" + + " } finally {\n" + + " System.out.println(\"Done\");\n" + + " }\n" + + " }\n" + + "\n" + + " public static void main(String[] args) {\n" + + " System.out.println(new DeadCodeExample().run());\n" + + " }\n" + + "}\n" + }, + "Canceled after 3 times through the loop\n" + + "number = 3\n" + + "Done\n" + + "-1"); +} } \ No newline at end of file