View | Details | Raw Unified | Return to bug 328519 | Differences between
and this patch

Collapse All | Expand All

(-)compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java (+4 lines)
Lines 194-199 Link Here
194
					System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
194
					System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
195
					classFile.addProblemMethod(this, this.binding, problemsCopy, problemResetPC);
195
					classFile.addProblemMethod(this, this.binding, problemsCopy, problemResetPC);
196
				}
196
				}
197
			} else if (e.compilationResult == CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE) {
198
				classFile.contentsOffset = problemResetPC;
199
				classFile.methodCount--;
200
				this.generateCode(classFile); // restart method generation
197
			} else {
201
			} else {
198
				// produce a problem method accounting for this fatal error
202
				// produce a problem method accounting for this fatal error
199
				int problemsLength;
203
				int problemsLength;
(-)compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java (+4 lines)
Lines 123-128 Link Here
123
					classFile.contentsOffset = clinitOffset;
123
					classFile.contentsOffset = clinitOffset;
124
					classFile.methodCount--;
124
					classFile.methodCount--;
125
				}
125
				}
126
			} else if (e.compilationResult == CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE) {
127
				classFile.contentsOffset = clinitOffset;
128
				classFile.methodCount--;
129
				this.generateCode(classFile); // restart method generation
126
			} else {
130
			} else {
127
				// produce a problem method accounting for this fatal error
131
				// produce a problem method accounting for this fatal error
128
				classFile.contentsOffset = clinitOffset;
132
				classFile.contentsOffset = clinitOffset;
(-)compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java (+4 lines)
Lines 228-233 Link Here
228
				System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
228
				System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
229
				classFile.addProblemConstructor(this, this.binding, problemsCopy, problemResetPC);
229
				classFile.addProblemConstructor(this, this.binding, problemsCopy, problemResetPC);
230
			}
230
			}
231
		} else if (e.compilationResult == CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE) {
232
			classFile.contentsOffset = problemResetPC;
233
			classFile.methodCount--;
234
			this.generateCode(classFile); // restart method generation
231
		} else {
235
		} else {
232
			int problemsLength;
236
			int problemsLength;
233
			CategorizedProblem[] problems =
237
			CategorizedProblem[] problems =
(-)compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java (+26 lines)
Lines 39-44 Link Here
39
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
39
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
40
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
40
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
41
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
41
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
42
import org.eclipse.jdt.internal.compiler.problem.AbortMethod;
42
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
43
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
43
44
44
public class SingleNameReference extends NameReference implements OperatorIds {
45
public class SingleNameReference extends NameReference implements OperatorIds {
Lines 422-427 Link Here
422
				break;
423
				break;
423
			case Binding.LOCAL : // reading a local
424
			case Binding.LOCAL : // reading a local
424
				LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
425
				LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
426
				if (localBinding.resolvedPosition == -1) {
427
					if (valueRequired) {
428
						// restart code gen
429
						localBinding.useFlag = LocalVariableBinding.USED;
430
						throw new AbortMethod(CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE, null);
431
					}
432
					codeStream.recordPositionsFrom(pc, this.sourceStart);
433
					return;
434
				}
425
				if (!valueRequired && (this.implicitConversion & TypeIds.UNBOXING) == 0) {
435
				if (!valueRequired && (this.implicitConversion & TypeIds.UNBOXING) == 0) {
426
					// if no valueRequired, optimize out entire gen
436
					// if no valueRequired, optimize out entire gen
427
					codeStream.recordPositionsFrom(pc, this.sourceStart);
437
					codeStream.recordPositionsFrom(pc, this.sourceStart);
Lines 525-530 Link Here
525
		case Binding.LOCAL : // assigning to a local variable (cannot assign to outer local)
535
		case Binding.LOCAL : // assigning to a local variable (cannot assign to outer local)
526
			LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
536
			LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
527
			// using incr bytecode if possible
537
			// using incr bytecode if possible
538
			if (localBinding.resolvedPosition == -1) {
539
				if (valueRequired) {
540
					// restart code gen
541
					localBinding.useFlag = LocalVariableBinding.USED;
542
					throw new AbortMethod(CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE, null);
543
				}
544
				return;
545
			}
528
			switch (localBinding.type.id) {
546
			switch (localBinding.type.id) {
529
				case T_JavaLangString :
547
				case T_JavaLangString :
530
					codeStream.generateStringConcatenationAppend(currentScope, this, expression);
548
					codeStream.generateStringConcatenationAppend(currentScope, this, expression);
Lines 687-692 Link Here
687
			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=185682
705
			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=185682
688
			// check if postIncrement is the only usage of this local
706
			// check if postIncrement is the only usage of this local
689
			Reference.reportOnlyUselesslyReadLocal(currentScope, localBinding, valueRequired);
707
			Reference.reportOnlyUselesslyReadLocal(currentScope, localBinding, valueRequired);
708
			if (localBinding.resolvedPosition == -1) {
709
				if (valueRequired) {
710
					// restart code gen
711
					localBinding.useFlag = LocalVariableBinding.USED;
712
					throw new AbortMethod(CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE, null);
713
				}
714
				return;
715
			}
690
716
691
			// using incr bytecode if possible
717
			// using incr bytecode if possible
692
			if (localBinding.type == TypeBinding.INT) {
718
			if (localBinding.type == TypeBinding.INT) {
(-)compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java (-1 / +2 lines)
Lines 41-47 Link Here
41
	static LocalVariableBinding[] noLocals = new LocalVariableBinding[LOCALS_INCREMENT];
41
	static LocalVariableBinding[] noLocals = new LocalVariableBinding[LOCALS_INCREMENT];
42
	static LocalVariableBinding[] noVisibleLocals = new LocalVariableBinding[LOCALS_INCREMENT];
42
	static LocalVariableBinding[] noVisibleLocals = new LocalVariableBinding[LOCALS_INCREMENT];
43
	public static final CompilationResult RESTART_IN_WIDE_MODE = new CompilationResult((char[])null, 0, 0, 0);
43
	public static final CompilationResult RESTART_IN_WIDE_MODE = new CompilationResult((char[])null, 0, 0, 0);
44
	
44
	public static final CompilationResult RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE = new CompilationResult((char[])null, 0, 0, 0);
45
45
	public int allLocalsCounter;
46
	public int allLocalsCounter;
46
	public byte[] bCodeStream;
47
	public byte[] bCodeStream;
47
	public ClassFile classFile; // The current classfile it is associated to.
48
	public ClassFile classFile; // The current classfile it is associated to.
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java (-2 / +3 lines)
Lines 191-197 Link Here
191
			LocalVariableBinding local = this.locals[ilocal]; // if no local at all, will be locals[ilocal]==null
191
			LocalVariableBinding local = this.locals[ilocal]; // if no local at all, will be locals[ilocal]==null
192
192
193
			// check if variable is actually used, and may force it to be preserved
193
			// check if variable is actually used, and may force it to be preserved
194
			boolean generateCurrentLocalVar = (local.useFlag != LocalVariableBinding.UNUSED && local.constant() == Constant.NotAConstant);
194
			boolean generateCurrentLocalVar = (local.useFlag > LocalVariableBinding.UNUSED && local.constant() == Constant.NotAConstant);
195
195
196
			// do not report fake used variable
196
			// do not report fake used variable
197
			if (local.useFlag == LocalVariableBinding.UNUSED
197
			if (local.useFlag == LocalVariableBinding.UNUSED
Lines 206-212 Link Here
206
			if (!generateCurrentLocalVar) {
206
			if (!generateCurrentLocalVar) {
207
				if (local.declaration != null && compilerOptions().preserveAllLocalVariables) {
207
				if (local.declaration != null && compilerOptions().preserveAllLocalVariables) {
208
					generateCurrentLocalVar = true; // force it to be preserved in the generated code
208
					generateCurrentLocalVar = true; // force it to be preserved in the generated code
209
					local.useFlag = LocalVariableBinding.USED;
209
					if (local.useFlag == LocalVariableBinding.UNUSED)
210
						local.useFlag = LocalVariableBinding.USED;
210
				}
211
				}
211
			}
212
			}
212
213
(-)eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java (+18 lines)
Lines 38-43 Link Here
38
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
38
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
39
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
39
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
40
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
40
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
41
import org.eclipse.jdt.internal.compiler.problem.AbortMethod;
41
42
42
/**
43
/**
43
 * A single name reference inside a code snippet can denote a field of a remote
44
 * A single name reference inside a code snippet can denote a field of a remote
Lines 270-275 Link Here
270
				break;
271
				break;
271
			case Binding.LOCAL : // reading a local
272
			case Binding.LOCAL : // reading a local
272
				LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
273
				LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
274
				if (localBinding.resolvedPosition == -1) {
275
					if (valueRequired) {
276
						// restart code gen
277
						localBinding.useFlag = LocalVariableBinding.USED;
278
						throw new AbortMethod(CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE, null);
279
					}
280
					codeStream.recordPositionsFrom(pc, this.sourceStart);
281
					return;
282
				}
273
				if (!valueRequired)
283
				if (!valueRequired)
274
					break;
284
					break;
275
				// outer local?
285
				// outer local?
Lines 340-345 Link Here
340
			break;
350
			break;
341
		case Binding.LOCAL : // assigning to a local variable (cannot assign to outer local)
351
		case Binding.LOCAL : // assigning to a local variable (cannot assign to outer local)
342
			LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
352
			LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
353
			if (localBinding.resolvedPosition == -1) {
354
				if (valueRequired) {
355
					// restart code gen
356
					localBinding.useFlag = LocalVariableBinding.USED;
357
					throw new AbortMethod(CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE, null);
358
				}
359
				return;
360
			}
343
			// using incr bytecode if possible
361
			// using incr bytecode if possible
344
			switch (localBinding.type.id) {
362
			switch (localBinding.type.id) {
345
				case T_JavaLangString :
363
				case T_JavaLangString :
(-)src/org/eclipse/jdt/core/tests/compiler/regression/ProgrammingProblemsTest.java (-3 / +111 lines)
Lines 11-16 Link Here
11
 *******************************************************************************/
11
 *******************************************************************************/
12
package org.eclipse.jdt.core.tests.compiler.regression;
12
package org.eclipse.jdt.core.tests.compiler.regression;
13
13
14
import java.io.File;
14
import java.util.HashMap;
15
import java.util.HashMap;
15
import java.util.Map;
16
import java.util.Map;
16
17
Lines 35-41 Link Here
35
  	// Only the highest compliance level is run; add the VM argument
36
  	// Only the highest compliance level is run; add the VM argument
36
  	// -Dcompliance=1.4 (for example) to lower it if needed
37
  	// -Dcompliance=1.4 (for example) to lower it if needed
37
  	static {
38
  	static {
38
//    	TESTS_NAMES = new String[] { "test001" };
39
//    	TESTS_NAMES = new String[] { "test0055" };
39
//		TESTS_NUMBERS = new int[] { 43 };
40
//		TESTS_NUMBERS = new int[] { 43 };
40
//  	TESTS_RANGE = new int[] { 1, -1 };
41
//  	TESTS_RANGE = new int[] { 1, -1 };
41
  	}
42
  	}
Lines 47-53 Link Here
47
public static Class testClass() {
48
public static Class testClass() {
48
    return ProgrammingProblemsTest.class;
49
    return ProgrammingProblemsTest.class;
49
}
50
}
50
51
protected Map getCompilerOptions() {
52
	Map compilerOptions = super.getCompilerOptions();
53
	compilerOptions.put(CompilerOptions.OPTION_PreserveUnusedLocal,  CompilerOptions.OPTIMIZE_OUT);
54
	return compilerOptions;
55
}
51
void runTest(
56
void runTest(
52
		String[] testFiles,
57
		String[] testFiles,
53
		String[] errorOptions,
58
		String[] errorOptions,
Lines 2120-2124 Link Here
2120
			true/*shouldFlushOutputDirectory*/,
2125
			true/*shouldFlushOutputDirectory*/,
2121
			customOptions);
2126
			customOptions);
2122
}
2127
}
2123
2128
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=328519
2129
public void test0053() throws Exception {
2130
	Map customOptions = getCompilerOptions();
2131
	customOptions.put(CompilerOptions.OPTION_ReportUnusedLocal, CompilerOptions.WARNING);
2132
	this.runConformTest(
2133
		new String[] {
2134
			"X.java",
2135
			"class X {\n" + 
2136
			"    int foo() {\n" + 
2137
			"        int i=1;\n" +
2138
			"        i++;\n" + 	// value after increment is still not used
2139
			"        return 0;\n" + 
2140
			"    }\n" + 
2141
			"}"
2142
		},
2143
		"",
2144
		null/*classLibraries*/,
2145
		true/*shouldFlushOutputDirectory*/,
2146
		null,
2147
		customOptions,
2148
		null);
2149
	String expectedOutput =
2150
		"  // Method descriptor #15 ()I\n" + 
2151
		"  // Stack: 1, Locals: 1\n" + 
2152
		"  int foo();\n" + 
2153
		"    0  iconst_0\n" + 
2154
		"    1  ireturn\n" + 
2155
		"      Line numbers:\n" + 
2156
		"        [pc: 0, line: 5]\n" + 
2157
		"      Local variable table:\n" + 
2158
		"        [pc: 0, pc: 2] local: this index: 0 type: X\n";
2159
	checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput);
2160
}
2161
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=328519
2162
public void test0054() throws Exception {
2163
	Map customOptions = getCompilerOptions();
2164
	customOptions.put(CompilerOptions.OPTION_ReportUnusedLocal, CompilerOptions.ERROR);
2165
	this.runConformTest(
2166
		new String[] {
2167
			"X.java",
2168
			"class X {\n" + 
2169
			"    int foo() {\n" + 
2170
			"        int i=1;\n" +
2171
			"        return i+=1;\n" + 	// value is used as it is returned
2172
			"    }\n" + 
2173
			"}"
2174
		},
2175
		"",
2176
		null/*classLibraries*/,
2177
		true/*shouldFlushOutputDirectory*/,
2178
		null,
2179
		customOptions,
2180
		null);
2181
	String expectedOutput =
2182
		"  // Method descriptor #15 ()I\n" + 
2183
		"  // Stack: 1, Locals: 2\n" + 
2184
		"  int foo();\n" + 
2185
		"    0  iconst_1\n" + 
2186
		"    1  istore_1 [i]\n" + 
2187
		"    2  iinc 1 1 [i]\n" + 
2188
		"    5  iload_1 [i]\n" + 
2189
		"    6  ireturn\n" + 
2190
		"      Line numbers:\n" + 
2191
		"        [pc: 0, line: 3]\n" + 
2192
		"        [pc: 2, line: 4]\n" + 
2193
		"      Local variable table:\n" + 
2194
		"        [pc: 0, pc: 7] local: this index: 0 type: X\n" + 
2195
		"        [pc: 2, pc: 7] local: i index: 1 type: int\n";
2196
	checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput);
2197
}
2198
2199
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=329613
2200
// regression caused by https://bugs.eclipse.org/bugs/show_bug.cgi?id=328519
2201
public void test0055() {
2202
	Map customOptions = getCompilerOptions();
2203
	customOptions.put(CompilerOptions.OPTION_ReportUnusedPrivateMember, CompilerOptions.IGNORE);
2204
	customOptions.put(CompilerOptions.OPTION_ReportUnusedLocal, CompilerOptions.WARNING);
2205
	customOptions.put(CompilerOptions.OPTION_PreserveUnusedLocal, CompilerOptions.PRESERVE);
2206
	this.runNegativeTest(
2207
			new String[] {
2208
					"test1/E.java",
2209
					"package test1;\n" +
2210
					"public class E {\n" +
2211
						"    private void foo() {\n" +
2212
						"        int a= 10;\n" +
2213
						"        a++;\n" +
2214
						"        a--;\n" +
2215
						"        --a;\n" +
2216
						"        ++a;\n" +
2217
						"        for ( ; ; a++) {\n" +
2218
							"        }\n" +
2219
							"    }\n" +
2220
							"}"
2221
			},
2222
			"----------\n" +
2223
			"1. WARNING in test1\\E.java (at line 4)\n" +
2224
			"	int a= 10;\n" +
2225
			"	    ^\n" +
2226
			"The value of the local variable a is not used\n" +
2227
			"----------\n",
2228
			null/*classLibraries*/,
2229
			true/*shouldFlushOutputDirectory*/,
2230
			customOptions);
2231
}
2124
}
2232
}

Return to bug 328519