### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java,v retrieving revision 1.109 diff -u -r1.109 AbstractMethodDeclaration.java --- compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java 6 Nov 2010 16:16:58 -0000 1.109 +++ compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java 9 Nov 2010 19:59:06 -0000 @@ -173,36 +173,48 @@ classFile.addProblemMethod(this, this.binding, problemsCopy); return; } + boolean restart = false; + boolean abort = false; // regular code generation - try { - problemResetPC = classFile.contentsOffset; - this.generateCode(classFile); - } catch (AbortMethod e) { - // a fatal error was detected during code generation, need to restart code gen if possible - if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) { - // a branch target required a goto_w, restart code gen in wide mode. - try { + do { + try { + problemResetPC = classFile.contentsOffset; + this.generateCode(classFile); + restart = false; + } catch (AbortMethod e) { + // a fatal error was detected during code generation, need to restart code gen if possible + if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) { + // a branch target required a goto_w, restart code gen in wide mode. + if (!restart) { + classFile.contentsOffset = problemResetPC; + classFile.methodCount--; + classFile.codeStream.resetInWideMode(); // request wide mode + restart = true; + } else { + // after restarting in wide mode, code generation failed again + // report a problem + restart = false; + abort = true; + } + } else if (e.compilationResult == CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE) { classFile.contentsOffset = problemResetPC; classFile.methodCount--; - classFile.codeStream.resetInWideMode(); // request wide mode - this.generateCode(classFile); // restart method generation - } catch (AbortMethod e2) { - int problemsLength; - CategorizedProblem[] problems = - this.scope.referenceCompilationUnit().compilationResult.getAllProblems(); - CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length]; - System.arraycopy(problems, 0, problemsCopy, 0, problemsLength); - classFile.addProblemMethod(this, this.binding, problemsCopy, problemResetPC); + classFile.codeStream.resetForCodeGenUnusedLocals(); + restart = true; + } else { + restart = false; + abort = true; } - } else { - // produce a problem method accounting for this fatal error - int problemsLength; - CategorizedProblem[] problems = - this.scope.referenceCompilationUnit().compilationResult.getAllProblems(); - CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length]; - System.arraycopy(problems, 0, problemsCopy, 0, problemsLength); - classFile.addProblemMethod(this, this.binding, problemsCopy, problemResetPC); } + } while (restart); + // produce a problem method accounting for this fatal error + if (abort) { + int problemsLength; + CategorizedProblem[] problems = + this.scope.referenceCompilationUnit().compilationResult.getAllProblems(); + CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length]; + System.arraycopy(problems, 0, problemsCopy, 0, problemsLength); + classFile.addProblemMethod(this, this.binding, problemsCopy, problemResetPC); } } Index: compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java,v retrieving revision 1.60 diff -u -r1.60 Clinit.java --- compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java 6 Nov 2010 16:16:58 -0000 1.60 +++ compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java 9 Nov 2010 19:59:06 -0000 @@ -100,35 +100,46 @@ // should never have to add any problem method return; } - try { - clinitOffset = classFile.contentsOffset; - this.generateCode(classScope, classFile, clinitOffset); - } catch (AbortMethod e) { - // should never occur - // the clinit referenceContext is the type declaration - // All clinit problems will be reported against the type: AbortType instead of AbortMethod - // reset the contentsOffset to the value before generating the clinit code - // decrement the number of method info as well. - // This is done in the addProblemMethod and addProblemConstructor for other - // cases. - if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) { - // a branch target required a goto_w, restart code gen in wide mode. - try { + boolean restart = false; + do { + try { + clinitOffset = classFile.contentsOffset; + this.generateCode(classScope, classFile, clinitOffset); + restart = false; + } catch (AbortMethod e) { + // should never occur + // the clinit referenceContext is the type declaration + // All clinit problems will be reported against the type: AbortType instead of AbortMethod + // reset the contentsOffset to the value before generating the clinit code + // decrement the number of method info as well. + // This is done in the addProblemMethod and addProblemConstructor for other + // cases. + if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) { + // a branch target required a goto_w, restart code gen in wide mode. + if (!restart) { + classFile.contentsOffset = clinitOffset; + classFile.methodCount--; + classFile.codeStream.resetInWideMode(); // request wide mode + // restart method generation + restart = true; + } else { + classFile.contentsOffset = clinitOffset; + classFile.methodCount--; + } + } else if (e.compilationResult == CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE) { classFile.contentsOffset = clinitOffset; classFile.methodCount--; - classFile.codeStream.resetInWideMode(); // request wide mode - this.generateCode(classScope, classFile, clinitOffset); + classFile.codeStream.resetForCodeGenUnusedLocals(); // restart method generation - } catch (AbortMethod e2) { + restart = true; + } else { + // produce a problem method accounting for this fatal error classFile.contentsOffset = clinitOffset; classFile.methodCount--; + restart = false; } - } else { - // produce a problem method accounting for this fatal error - classFile.contentsOffset = clinitOffset; - classFile.methodCount--; } - } + } while (restart); } /** Index: compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java,v retrieving revision 1.111 diff -u -r1.111 ConstructorDeclaration.java --- compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java 6 Nov 2010 16:16:58 -0000 1.111 +++ compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java 9 Nov 2010 19:59:06 -0000 @@ -209,33 +209,43 @@ classFile.addProblemConstructor(this, this.binding, problemsCopy); return; } - try { - problemResetPC = classFile.contentsOffset; - internalGenerateCode(classScope, classFile); - } catch (AbortMethod e) { - if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) { - // a branch target required a goto_w, restart code gen in wide mode. - try { + boolean restart = false; + boolean abort = false; + do { + try { + problemResetPC = classFile.contentsOffset; + internalGenerateCode(classScope, classFile); + restart = false; + } catch (AbortMethod e) { + if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) { + // a branch target required a goto_w, restart code gen in wide mode. + if (!restart) { + classFile.contentsOffset = problemResetPC; + classFile.methodCount--; + classFile.codeStream.resetInWideMode(); // request wide mode + restart = true; + } else { + restart = false; + abort = true; + } + } else if (e.compilationResult == CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE) { classFile.contentsOffset = problemResetPC; classFile.methodCount--; - classFile.codeStream.resetInWideMode(); // request wide mode - internalGenerateCode(classScope, classFile); // restart method generation - } catch (AbortMethod e2) { - int problemsLength; - CategorizedProblem[] problems = - this.scope.referenceCompilationUnit().compilationResult.getAllProblems(); - CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length]; - System.arraycopy(problems, 0, problemsCopy, 0, problemsLength); - classFile.addProblemConstructor(this, this.binding, problemsCopy, problemResetPC); + classFile.codeStream.resetForCodeGenUnusedLocals(); + restart = true; + } else { + restart = false; + abort = true; } - } else { - int problemsLength; - CategorizedProblem[] problems = - this.scope.referenceCompilationUnit().compilationResult.getAllProblems(); - CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length]; - System.arraycopy(problems, 0, problemsCopy, 0, problemsLength); - classFile.addProblemConstructor(this, this.binding, problemsCopy, problemResetPC); } + } while (restart); + if (abort) { + int problemsLength; + CategorizedProblem[] problems = + this.scope.referenceCompilationUnit().compilationResult.getAllProblems(); + CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length]; + System.arraycopy(problems, 0, problemsCopy, 0, problemsLength); + classFile.addProblemConstructor(this, this.binding, problemsCopy, problemResetPC); } } Index: compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java,v retrieving revision 1.127 diff -u -r1.127 SingleNameReference.java --- compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java 6 Nov 2010 16:16:58 -0000 1.127 +++ compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java 9 Nov 2010 19:59:06 -0000 @@ -39,6 +39,7 @@ import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.eclipse.jdt.internal.compiler.lookup.VariableBinding; +import org.eclipse.jdt.internal.compiler.problem.AbortMethod; import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; public class SingleNameReference extends NameReference implements OperatorIds { @@ -422,6 +423,15 @@ break; case Binding.LOCAL : // reading a local LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; + if (localBinding.resolvedPosition == -1) { + if (valueRequired) { + // restart code gen + localBinding.useFlag = LocalVariableBinding.USED; + throw new AbortMethod(CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE, null); + } + codeStream.recordPositionsFrom(pc, this.sourceStart); + return; + } if (!valueRequired && (this.implicitConversion & TypeIds.UNBOXING) == 0) { // if no valueRequired, optimize out entire gen codeStream.recordPositionsFrom(pc, this.sourceStart); @@ -525,6 +535,7 @@ case Binding.LOCAL : // assigning to a local variable (cannot assign to outer local) LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; // using incr bytecode if possible + Constant assignConstant; switch (localBinding.type.id) { case T_JavaLangString : codeStream.generateStringConcatenationAppend(currentScope, this, expression); @@ -534,10 +545,25 @@ codeStream.store(localBinding, false); return; case T_int : - Constant assignConstant; - if (((assignConstant = expression.constant) != Constant.NotAConstant) + assignConstant = expression.constant; + if (localBinding.resolvedPosition == -1) { + if (valueRequired) { + /* + * restart code gen because we either: + * - need the value + * - the constant can have potential side-effect + */ + localBinding.useFlag = LocalVariableBinding.USED; + throw new AbortMethod(CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE, null); + } else if (assignConstant == Constant.NotAConstant) { + // we only need to generate the value of the expression's constant if it is not a constant expression + expression.generateCode(currentScope, codeStream, false); + } + return; + } + if ((assignConstant != Constant.NotAConstant) && (assignConstant.typeID() != TypeIds.T_float) // only for integral types - && (assignConstant.typeID() != TypeIds.T_double)) {// TODO (philippe) is this test needed ? + && (assignConstant.typeID() != TypeIds.T_double)) { // TODO (philippe) is this test needed ? switch (operator) { case PLUS : int increment = assignConstant.intValue(); @@ -559,6 +585,22 @@ } //$FALL-THROUGH$ default : + if (localBinding.resolvedPosition == -1) { + assignConstant = expression.constant; + if (valueRequired) { + /* + * restart code gen because we either: + * - need the value + * - the constant can have potential side-effect + */ + localBinding.useFlag = LocalVariableBinding.USED; + throw new AbortMethod(CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE, null); + } else if (assignConstant == Constant.NotAConstant) { + // we only need to generate the value of the expression's constant if it is not a constant expression + expression.generateCode(currentScope, codeStream, false); + } + return; + } codeStream.load(localBinding); } } @@ -687,6 +729,14 @@ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=185682 // check if postIncrement is the only usage of this local Reference.reportOnlyUselesslyReadLocal(currentScope, localBinding, valueRequired); + if (localBinding.resolvedPosition == -1) { + if (valueRequired) { + // restart code gen + localBinding.useFlag = LocalVariableBinding.USED; + throw new AbortMethod(CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE, null); + } + return; + } // using incr bytecode if possible if (localBinding.type == TypeBinding.INT) { 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.178 diff -u -r1.178 CodeStream.java --- compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java 6 Nov 2010 16:16:58 -0000 1.178 +++ compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java 9 Nov 2010 19:59:06 -0000 @@ -41,7 +41,8 @@ static LocalVariableBinding[] noLocals = new LocalVariableBinding[LOCALS_INCREMENT]; static LocalVariableBinding[] noVisibleLocals = new LocalVariableBinding[LOCALS_INCREMENT]; public static final CompilationResult RESTART_IN_WIDE_MODE = new CompilationResult((char[])null, 0, 0, 0); - + public static final CompilationResult RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE = new CompilationResult((char[])null, 0, 0, 0); + public int allLocalsCounter; public byte[] bCodeStream; public ClassFile classFile; // The current classfile it is associated to. @@ -6197,7 +6198,9 @@ public void resetInWideMode() { this.wideMode = true; } - +public void resetForCodeGenUnusedLocals() { + // nothing to do in standard code stream +} private final void resizeByteArray() { int length = this.bCodeStream.length; int requiredSize = length + length; Index: compiler/org/eclipse/jdt/internal/compiler/codegen/StackMapFrameCodeStream.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/StackMapFrameCodeStream.java,v retrieving revision 1.28 diff -u -r1.28 StackMapFrameCodeStream.java --- compiler/org/eclipse/jdt/internal/compiler/codegen/StackMapFrameCodeStream.java 7 Mar 2009 01:08:07 -0000 1.28 +++ compiler/org/eclipse/jdt/internal/compiler/codegen/StackMapFrameCodeStream.java 9 Nov 2010 19:59:06 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2009 IBM Corporation and others. + * Copyright (c) 2006, 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 @@ -539,6 +539,10 @@ this.resetSecretLocals(); super.resetInWideMode(); } +public void resetForCodeGenUnusedLocals() { + this.resetSecretLocals(); + super.resetForCodeGenUnusedLocals(); +} public void resetSecretLocals() { for (int i = 0, max = this.locals.length; i < max; i++) { LocalVariableBinding localVariableBinding = this.locals[i]; Index: compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java,v retrieving revision 1.121 diff -u -r1.121 BlockScope.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java 6 Nov 2010 16:16:58 -0000 1.121 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java 9 Nov 2010 19:59:06 -0000 @@ -191,7 +191,7 @@ LocalVariableBinding local = this.locals[ilocal]; // if no local at all, will be locals[ilocal]==null // check if variable is actually used, and may force it to be preserved - boolean generateCurrentLocalVar = (local.useFlag != LocalVariableBinding.UNUSED && local.constant() == Constant.NotAConstant); + boolean generateCurrentLocalVar = (local.useFlag > LocalVariableBinding.UNUSED && local.constant() == Constant.NotAConstant); // do not report fake used variable if (local.useFlag == LocalVariableBinding.UNUSED @@ -206,7 +206,8 @@ if (!generateCurrentLocalVar) { if (local.declaration != null && compilerOptions().preserveAllLocalVariables) { generateCurrentLocalVar = true; // force it to be preserved in the generated code - local.useFlag = LocalVariableBinding.USED; + if (local.useFlag == LocalVariableBinding.UNUSED) + local.useFlag = LocalVariableBinding.USED; } } Index: eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java,v retrieving revision 1.61 diff -u -r1.61 CodeSnippetSingleNameReference.java --- eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java 6 Nov 2010 16:16:58 -0000 1.61 +++ eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java 9 Nov 2010 19:59:06 -0000 @@ -38,6 +38,7 @@ import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.eclipse.jdt.internal.compiler.lookup.VariableBinding; +import org.eclipse.jdt.internal.compiler.problem.AbortMethod; /** * A single name reference inside a code snippet can denote a field of a remote @@ -270,6 +271,15 @@ break; case Binding.LOCAL : // reading a local LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; + if (localBinding.resolvedPosition == -1) { + if (valueRequired) { + // restart code gen + localBinding.useFlag = LocalVariableBinding.USED; + throw new AbortMethod(CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE, null); + } + codeStream.recordPositionsFrom(pc, this.sourceStart); + return; + } if (!valueRequired) break; // outer local? @@ -341,6 +351,7 @@ case Binding.LOCAL : // assigning to a local variable (cannot assign to outer local) LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; // using incr bytecode if possible + Constant assignConstant; switch (localBinding.type.id) { case T_JavaLangString : codeStream.generateStringConcatenationAppend(currentScope, this, expression); @@ -350,8 +361,23 @@ codeStream.store(localBinding, false); return; case T_int : - Constant assignConstant; - if (((assignConstant = expression.constant) != Constant.NotAConstant) + assignConstant = expression.constant; + if (localBinding.resolvedPosition == -1) { + if (valueRequired) { + /* + * restart code gen because we either: + * - need the value + * - the constant can have potential side-effect + */ + localBinding.useFlag = LocalVariableBinding.USED; + throw new AbortMethod(CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE, null); + } else if (assignConstant == Constant.NotAConstant) { + // we only need to generate the value of the expression's constant if it is not a constant expression + expression.generateCode(currentScope, codeStream, false); + } + return; + } + if ((assignConstant != Constant.NotAConstant) && (assignConstant.typeID() != TypeIds.T_float) // only for integral types && (assignConstant.typeID() != TypeIds.T_double)) { // TODO (philippe) is this test needed ? switch (operator) { @@ -375,6 +401,22 @@ } //$FALL-THROUGH$ default : + if (localBinding.resolvedPosition == -1) { + assignConstant = expression.constant; + if (valueRequired) { + /* + * restart code gen because we either: + * - need the value + * - the constant can have potential side-effect + */ + localBinding.useFlag = LocalVariableBinding.USED; + throw new AbortMethod(CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE, null); + } else if (assignConstant == Constant.NotAConstant) { + // we only need to generate the value of the expression's constant if it is not a constant expression + expression.generateCode(currentScope, codeStream, false); + } + return; + } codeStream.load(localBinding); } } #P org.eclipse.jdt.core.tests.compiler Index: src/org/eclipse/jdt/core/tests/compiler/regression/EnumTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/EnumTest.java,v retrieving revision 1.154 diff -u -r1.154 EnumTest.java --- src/org/eclipse/jdt/core/tests/compiler/regression/EnumTest.java 13 Sep 2010 13:26:19 -0000 1.154 +++ src/org/eclipse/jdt/core/tests/compiler/regression/EnumTest.java 9 Nov 2010 19:59:06 -0000 @@ -33,7 +33,7 @@ // All specified tests which does not belong to the class are skipped... static { // TESTS_NAMES = new String[] { "test000" }; -// TESTS_NUMBERS = new int[] { 181 }; +// TESTS_NUMBERS = new int[] { 182 }; // TESTS_RANGE = new int[] { 21, 50 }; } public static Test suite() { @@ -6542,4 +6542,126 @@ }, "SUCCESS"); } +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=328519 +public void test182() throws Exception { + Map customOptions = getCompilerOptions(); + customOptions.put(CompilerOptions.OPTION_ReportUnusedLocal, CompilerOptions.ERROR); + customOptions.put(CompilerOptions.OPTION_PreserveUnusedLocal, CompilerOptions.OPTIMIZE_OUT); + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " public static void main(String argv[]) {\n" + + " foo();\n" + + " }\n" + + " public static void foo() {\n" + + " int n = 0;\n" + + " for (E e : E.values()) {\n" + + " if (e.val() == E.VALUES[n++] ) {\n" + + " System.out.print(e.val());\n" + + " }\n" + + " }\n" + + " }\n" + + "}", + "E.java", + "enum E {\n" + + " a1(1), a2(2);\n" + + " static int[] VALUES = { 1, 2 };\n" + + " private int value;\n" + + " E(int v) {\n" + + " this.value = v;\n" + + " }\n" + + " public int val() {\n" + + " return this.value;\n" + + " }\n" + + "}" + }, + "12", + null/*classLibraries*/, + true/*shouldFlushOutputDirectory*/, + null, + customOptions, + null); +} +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=328519 +public void test183() throws Exception { + Map customOptions = getCompilerOptions(); + customOptions.put(CompilerOptions.OPTION_ReportUnusedLocal, CompilerOptions.ERROR); + customOptions.put(CompilerOptions.OPTION_PreserveUnusedLocal, CompilerOptions.OPTIMIZE_OUT); + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " public static void main(String argv[]) {\n" + + " }\n" + + " static {\n" + + " int n = 0;\n" + + " for (E e : E.values()) {\n" + + " if (e.val() == E.VALUES[n++] ) {\n" + + " System.out.print(e.val());\n" + + " }\n" + + " }\n" + + " }\n" + + "}", + "E.java", + "enum E {\n" + + " a1(1), a2(2);\n" + + " static int[] VALUES = { 1, 2 };\n" + + " private int value;\n" + + " E(int v) {\n" + + " this.value = v;\n" + + " }\n" + + " public int val() {\n" + + " return this.value;\n" + + " }\n" + + "}" + }, + "12", + null/*classLibraries*/, + true/*shouldFlushOutputDirectory*/, + null, + customOptions, + null); +} +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=328519 +public void test184() throws Exception { + Map customOptions = getCompilerOptions(); + customOptions.put(CompilerOptions.OPTION_ReportUnusedLocal, CompilerOptions.ERROR); + customOptions.put(CompilerOptions.OPTION_PreserveUnusedLocal, CompilerOptions.OPTIMIZE_OUT); + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " public static void main(String argv[]) {\n" + + " new X();\n" + + " }\n" + + " X() {\n" + + " int n = 0;\n" + + " for (E e : E.values()) {\n" + + " if (e.val() == E.VALUES[n++] ) {\n" + + " System.out.print(e.val());\n" + + " }\n" + + " }\n" + + " }\n" + + "}", + "E.java", + "enum E {\n" + + " a1(1), a2(2);\n" + + " static int[] VALUES = { 1, 2 };\n" + + " private int value;\n" + + " E(int v) {\n" + + " this.value = v;\n" + + " }\n" + + " public int val() {\n" + + " return this.value;\n" + + " }\n" + + "}" + }, + "12", + null/*classLibraries*/, + true/*shouldFlushOutputDirectory*/, + null, + customOptions, + null); +} } Index: src/org/eclipse/jdt/core/tests/compiler/regression/ProgrammingProblemsTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProgrammingProblemsTest.java,v retrieving revision 1.28 diff -u -r1.28 ProgrammingProblemsTest.java --- src/org/eclipse/jdt/core/tests/compiler/regression/ProgrammingProblemsTest.java 6 Nov 2010 16:16:57 -0000 1.28 +++ src/org/eclipse/jdt/core/tests/compiler/regression/ProgrammingProblemsTest.java 9 Nov 2010 19:59:06 -0000 @@ -11,6 +11,7 @@ *******************************************************************************/ package org.eclipse.jdt.core.tests.compiler.regression; +import java.io.File; import java.util.HashMap; import java.util.Map; @@ -35,8 +36,8 @@ // Only the highest compliance level is run; add the VM argument // -Dcompliance=1.4 (for example) to lower it if needed static { -// TESTS_NAMES = new String[] { "test001" }; -// TESTS_NUMBERS = new int[] { 43 }; +// TESTS_NAMES = new String[] { "test0055" }; +// TESTS_NUMBERS = new int[] { 56 }; // TESTS_RANGE = new int[] { 1, -1 }; } @@ -47,7 +48,11 @@ public static Class testClass() { return ProgrammingProblemsTest.class; } - +protected Map getCompilerOptions() { + Map compilerOptions = super.getCompilerOptions(); + compilerOptions.put(CompilerOptions.OPTION_PreserveUnusedLocal, CompilerOptions.OPTIMIZE_OUT); + return compilerOptions; +} void runTest( String[] testFiles, String[] errorOptions, @@ -141,8 +146,8 @@ null /* ignoreOptions */, false /* expectingCompilerErrors */, "----------\n" + - "1. WARNING in X.java (at line 2)\r\n" + - " public void foo(boolean b) {\r\n" + + "1. WARNING in X.java (at line 2)\n" + + " public void foo(boolean b) {\n" + " ^\n" + "The value of the parameter b is not used\n" + "----------\n" /* expectedCompilerLog */, @@ -277,8 +282,8 @@ null /* ignoreOptions */, true /* expectingCompilerErrors */, "----------\n" + - "1. ERROR in X.java (at line 2)\r\n" + - " public void foo(boolean b) {\r\n" + + "1. ERROR in X.java (at line 2)\n" + + " public void foo(boolean b) {\n" + " ^\n" + "The value of the parameter b is not used\n" + "----------\n" /* expectedCompilerLog */, @@ -2120,5 +2125,158 @@ true/*shouldFlushOutputDirectory*/, customOptions); } - +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=328519 +public void test0053() throws Exception { + Map customOptions = getCompilerOptions(); + customOptions.put(CompilerOptions.OPTION_ReportUnusedLocal, CompilerOptions.WARNING); + this.runConformTest( + new String[] { + "X.java", + "class X {\n" + + " int foo() {\n" + + " int i=1;\n" + + " i++;\n" + // value after increment is still not used + " return 0;\n" + + " }\n" + + "}" + }, + "", + null/*classLibraries*/, + true/*shouldFlushOutputDirectory*/, + null, + customOptions, + null); + String expectedOutput = + " // Method descriptor #15 ()I\n" + + " // Stack: 1, Locals: 1\n" + + " int foo();\n" + + " 0 iconst_0\n" + + " 1 ireturn\n" + + " Line numbers:\n" + + " [pc: 0, line: 5]\n" + + " Local variable table:\n" + + " [pc: 0, pc: 2] local: this index: 0 type: X\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=328519 +public void test0054() throws Exception { + Map customOptions = getCompilerOptions(); + customOptions.put(CompilerOptions.OPTION_ReportUnusedLocal, CompilerOptions.ERROR); + this.runConformTest( + new String[] { + "X.java", + "class X {\n" + + " int foo() {\n" + + " int i=1;\n" + + " return i+=1;\n" + // value is used as it is returned + " }\n" + + "}" + }, + "", + null/*classLibraries*/, + true/*shouldFlushOutputDirectory*/, + null, + customOptions, + null); + String expectedOutput = + " // Method descriptor #15 ()I\n" + + " // Stack: 1, Locals: 2\n" + + " int foo();\n" + + " 0 iconst_1\n" + + " 1 istore_1 [i]\n" + + " 2 iinc 1 1 [i]\n" + + " 5 iload_1 [i]\n" + + " 6 ireturn\n" + + " Line numbers:\n" + + " [pc: 0, line: 3]\n" + + " [pc: 2, line: 4]\n" + + " Local variable table:\n" + + " [pc: 0, pc: 7] local: this index: 0 type: X\n" + + " [pc: 2, pc: 7] local: i index: 1 type: int\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput); +} + +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=329613 +// regression caused by https://bugs.eclipse.org/bugs/show_bug.cgi?id=328519 +public void test0055() { + Map customOptions = getCompilerOptions(); + customOptions.put(CompilerOptions.OPTION_ReportUnusedPrivateMember, CompilerOptions.IGNORE); + customOptions.put(CompilerOptions.OPTION_ReportUnusedLocal, CompilerOptions.WARNING); + customOptions.put(CompilerOptions.OPTION_PreserveUnusedLocal, CompilerOptions.PRESERVE); + this.runNegativeTest( + new String[] { + "test1/E.java", + "package test1;\n" + + "public class E {\n" + + " private void foo() {\n" + + " int a= 10;\n" + + " a++;\n" + + " a--;\n" + + " --a;\n" + + " ++a;\n" + + " for ( ; ; a++) {\n" + + " }\n" + + " }\n" + + "}" + }, + "----------\n" + + "1. WARNING in test1\\E.java (at line 4)\n" + + " int a= 10;\n" + + " ^\n" + + "The value of the local variable a is not used\n" + + "----------\n", + null/*classLibraries*/, + true/*shouldFlushOutputDirectory*/, + customOptions); +} +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=328519 +public void test0056() throws Exception { + Map customOptions = getCompilerOptions(); + customOptions.put(CompilerOptions.OPTION_ReportUnusedLocal, CompilerOptions.ERROR); + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " static int foo() {\n" + + " int i = 2;\n" + + " int j = 3;\n" + + " return (i += j *= 3);\n" + // value is used as it is returned + " }\n" + + " public static void main(String[] args) {\n" + + " System.out.println(foo());\n" + + " }\n" + + "}" + }, + "11", + null/*classLibraries*/, + true/*shouldFlushOutputDirectory*/, + null, + customOptions, + null); +} +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=328519 +public void test0057() throws Exception { + Map customOptions = getCompilerOptions(); + customOptions.put(CompilerOptions.OPTION_ReportUnusedLocal, CompilerOptions.IGNORE); + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " public static void main (String args[]) {\n" + + " int i = 0;\n" + + " i += 4 + foo();\n" + + " }\n" + + " public static int foo() {\n" + + " System.out.println(\"OK\");\n" + + " return 0;\n" + + " }\n" + + "}" + }, + "OK", + null/*classLibraries*/, + true/*shouldFlushOutputDirectory*/, + null, + customOptions, + null); +} } \ No newline at end of file