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 (-25 / +37 lines)
Lines 173-208 Link Here
173
			classFile.addProblemMethod(this, this.binding, problemsCopy);
173
			classFile.addProblemMethod(this, this.binding, problemsCopy);
174
			return;
174
			return;
175
		}
175
		}
176
		boolean restart = false;
177
		boolean abort = false;
176
		// regular code generation
178
		// regular code generation
177
		try {
179
		do {
178
			problemResetPC = classFile.contentsOffset;
180
			try {
179
			this.generateCode(classFile);
181
				problemResetPC = classFile.contentsOffset;
180
		} catch (AbortMethod e) {
182
				this.generateCode(classFile);
181
			// a fatal error was detected during code generation, need to restart code gen if possible
183
				restart = false;
182
			if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) {
184
			} catch (AbortMethod e) {
183
				// a branch target required a goto_w, restart code gen in wide mode.
185
				// a fatal error was detected during code generation, need to restart code gen if possible
184
				try {
186
				if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) {
187
					// a branch target required a goto_w, restart code gen in wide mode.
188
					if (!restart) {
189
						classFile.contentsOffset = problemResetPC;
190
						classFile.methodCount--;
191
						classFile.codeStream.resetInWideMode(); // request wide mode
192
						restart = true;
193
					} else {
194
						// after restarting in wide mode, code generation failed again
195
						// report a problem
196
						restart = false;
197
						abort = true;
198
					}
199
				} else if (e.compilationResult == CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE) {
185
					classFile.contentsOffset = problemResetPC;
200
					classFile.contentsOffset = problemResetPC;
186
					classFile.methodCount--;
201
					classFile.methodCount--;
187
					classFile.codeStream.resetInWideMode(); // request wide mode
202
					classFile.codeStream.resetForCodeGenUnusedLocals();
188
					this.generateCode(classFile); // restart method generation
203
					restart = true;
189
				} catch (AbortMethod e2) {
204
				} else {
190
					int problemsLength;
205
					restart = false;
191
					CategorizedProblem[] problems =
206
					abort = true; 
192
						this.scope.referenceCompilationUnit().compilationResult.getAllProblems();
193
					CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length];
194
					System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
195
					classFile.addProblemMethod(this, this.binding, problemsCopy, problemResetPC);
196
				}
207
				}
197
			} else {
198
				// produce a problem method accounting for this fatal error
199
				int problemsLength;
200
				CategorizedProblem[] problems =
201
					this.scope.referenceCompilationUnit().compilationResult.getAllProblems();
202
				CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length];
203
				System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
204
				classFile.addProblemMethod(this, this.binding, problemsCopy, problemResetPC);
205
			}
208
			}
209
		} while (restart);
210
		// produce a problem method accounting for this fatal error
211
		if (abort) {
212
			int problemsLength;
213
			CategorizedProblem[] problems =
214
				this.scope.referenceCompilationUnit().compilationResult.getAllProblems();
215
			CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length];
216
			System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
217
			classFile.addProblemMethod(this, this.binding, problemsCopy, problemResetPC);
206
		}
218
		}
207
	}
219
	}
208
220
(-)compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java (-22 / +33 lines)
Lines 100-134 Link Here
100
			// should never have to add any <clinit> problem method
100
			// should never have to add any <clinit> problem method
101
			return;
101
			return;
102
		}
102
		}
103
		try {
103
		boolean restart = false;
104
			clinitOffset = classFile.contentsOffset;
104
		do {
105
			this.generateCode(classScope, classFile, clinitOffset);
105
			try {
106
		} catch (AbortMethod e) {
106
				clinitOffset = classFile.contentsOffset;
107
			// should never occur
107
				this.generateCode(classScope, classFile, clinitOffset);
108
			// the clinit referenceContext is the type declaration
108
				restart = false;
109
			// All clinit problems will be reported against the type: AbortType instead of AbortMethod
109
			} catch (AbortMethod e) {
110
			// reset the contentsOffset to the value before generating the clinit code
110
				// should never occur
111
			// decrement the number of method info as well.
111
				// the clinit referenceContext is the type declaration
112
			// This is done in the addProblemMethod and addProblemConstructor for other
112
				// All clinit problems will be reported against the type: AbortType instead of AbortMethod
113
			// cases.
113
				// reset the contentsOffset to the value before generating the clinit code
114
			if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) {
114
				// decrement the number of method info as well.
115
				// a branch target required a goto_w, restart code gen in wide mode.
115
				// This is done in the addProblemMethod and addProblemConstructor for other
116
				try {
116
				// cases.
117
				if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) {
118
					// a branch target required a goto_w, restart code gen in wide mode.
119
					if (!restart) {
120
						classFile.contentsOffset = clinitOffset;
121
						classFile.methodCount--;
122
						classFile.codeStream.resetInWideMode(); // request wide mode
123
						// restart method generation
124
						restart = true;
125
					} else {
126
						classFile.contentsOffset = clinitOffset;
127
						classFile.methodCount--;
128
					}
129
				} else if (e.compilationResult == CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE) {
117
					classFile.contentsOffset = clinitOffset;
130
					classFile.contentsOffset = clinitOffset;
118
					classFile.methodCount--;
131
					classFile.methodCount--;
119
					classFile.codeStream.resetInWideMode(); // request wide mode
132
					classFile.codeStream.resetForCodeGenUnusedLocals();
120
					this.generateCode(classScope, classFile, clinitOffset);
121
					// restart method generation
133
					// restart method generation
122
				} catch (AbortMethod e2) {
134
					restart = true;
135
				} else {
136
					// produce a problem method accounting for this fatal error
123
					classFile.contentsOffset = clinitOffset;
137
					classFile.contentsOffset = clinitOffset;
124
					classFile.methodCount--;
138
					classFile.methodCount--;
139
					restart = false;
125
				}
140
				}
126
			} else {
127
				// produce a problem method accounting for this fatal error
128
				classFile.contentsOffset = clinitOffset;
129
				classFile.methodCount--;
130
			}
141
			}
131
		}
142
		} while (restart);
132
	}
143
	}
133
144
134
	/**
145
	/**
(-)compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java (-23 / +33 lines)
Lines 209-241 Link Here
209
		classFile.addProblemConstructor(this, this.binding, problemsCopy);
209
		classFile.addProblemConstructor(this, this.binding, problemsCopy);
210
		return;
210
		return;
211
	}
211
	}
212
	try {
212
	boolean restart = false;
213
		problemResetPC = classFile.contentsOffset;
213
	boolean abort = false;
214
		internalGenerateCode(classScope, classFile);
214
	do {
215
	} catch (AbortMethod e) {
215
		try {
216
		if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) {
216
			problemResetPC = classFile.contentsOffset;
217
			// a branch target required a goto_w, restart code gen in wide mode.
217
			internalGenerateCode(classScope, classFile);
218
			try {
218
			restart = false;
219
		} catch (AbortMethod e) {
220
			if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) {
221
				// a branch target required a goto_w, restart code gen in wide mode.
222
				if (!restart) {
223
					classFile.contentsOffset = problemResetPC;
224
					classFile.methodCount--;
225
					classFile.codeStream.resetInWideMode(); // request wide mode
226
					restart = true;
227
				} else {
228
					restart = false;
229
					abort = true;
230
				}
231
			} else if (e.compilationResult == CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE) {
219
				classFile.contentsOffset = problemResetPC;
232
				classFile.contentsOffset = problemResetPC;
220
				classFile.methodCount--;
233
				classFile.methodCount--;
221
				classFile.codeStream.resetInWideMode(); // request wide mode
234
				classFile.codeStream.resetForCodeGenUnusedLocals();
222
				internalGenerateCode(classScope, classFile); // restart method generation
235
				restart = true;
223
			} catch (AbortMethod e2) {
236
			} else {
224
				int problemsLength;
237
				restart = false;
225
				CategorizedProblem[] problems =
238
				abort = true;
226
					this.scope.referenceCompilationUnit().compilationResult.getAllProblems();
227
				CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length];
228
				System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
229
				classFile.addProblemConstructor(this, this.binding, problemsCopy, problemResetPC);
230
			}
239
			}
231
		} else {
232
			int problemsLength;
233
			CategorizedProblem[] problems =
234
				this.scope.referenceCompilationUnit().compilationResult.getAllProblems();
235
			CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length];
236
			System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
237
			classFile.addProblemConstructor(this, this.binding, problemsCopy, problemResetPC);
238
		}
240
		}
241
	} while (restart);
242
	if (abort) {
243
		int problemsLength;
244
		CategorizedProblem[] problems =
245
				this.scope.referenceCompilationUnit().compilationResult.getAllProblems();
246
		CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length];
247
		System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
248
		classFile.addProblemConstructor(this, this.binding, problemsCopy, problemResetPC);
239
	}
249
	}
240
}
250
}
241
251
(-)compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java (-3 / +53 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
			Constant assignConstant;
528
			switch (localBinding.type.id) {
539
			switch (localBinding.type.id) {
529
				case T_JavaLangString :
540
				case T_JavaLangString :
530
					codeStream.generateStringConcatenationAppend(currentScope, this, expression);
541
					codeStream.generateStringConcatenationAppend(currentScope, this, expression);
Lines 534-543 Link Here
534
					codeStream.store(localBinding, false);
545
					codeStream.store(localBinding, false);
535
					return;
546
					return;
536
				case T_int :
547
				case T_int :
537
					Constant assignConstant;
548
					assignConstant = expression.constant;
538
					if (((assignConstant = expression.constant) != Constant.NotAConstant)
549
					if (localBinding.resolvedPosition == -1) {
550
						if (valueRequired) {
551
							/*
552
							 * restart code gen because we either:
553
							 * - need the value
554
							 * - the constant can have potential side-effect
555
							 */
556
							localBinding.useFlag = LocalVariableBinding.USED;
557
							throw new AbortMethod(CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE, null);
558
						} else if (assignConstant == Constant.NotAConstant) {
559
							// we only need to generate the value of the expression's constant if it is not a constant expression
560
							expression.generateCode(currentScope, codeStream, false);
561
						}
562
						return;
563
					}
564
					if ((assignConstant != Constant.NotAConstant)
539
							&& (assignConstant.typeID() != TypeIds.T_float) // only for integral types
565
							&& (assignConstant.typeID() != TypeIds.T_float) // only for integral types
540
							&& (assignConstant.typeID() != TypeIds.T_double)) {// TODO (philippe) is this test needed ?
566
							&& (assignConstant.typeID() != TypeIds.T_double)) { // TODO (philippe) is this test needed ?
541
						switch (operator) {
567
						switch (operator) {
542
							case PLUS :
568
							case PLUS :
543
								int increment  = assignConstant.intValue();
569
								int increment  = assignConstant.intValue();
Lines 559-564 Link Here
559
					}
585
					}
560
					//$FALL-THROUGH$
586
					//$FALL-THROUGH$
561
				default :
587
				default :
588
					if (localBinding.resolvedPosition == -1) {
589
						assignConstant = expression.constant;
590
						if (valueRequired) {
591
							/*
592
							 * restart code gen because we either:
593
							 * - need the value
594
							 * - the constant can have potential side-effect
595
							 */
596
							localBinding.useFlag = LocalVariableBinding.USED;
597
							throw new AbortMethod(CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE, null);
598
						} else if (assignConstant == Constant.NotAConstant) {
599
							// we only need to generate the value of the expression's constant if it is not a constant expression
600
							expression.generateCode(currentScope, codeStream, false);
601
						}
602
						return;
603
					}
562
					codeStream.load(localBinding);
604
					codeStream.load(localBinding);
563
			}
605
			}
564
	}
606
	}
Lines 687-692 Link Here
687
			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=185682
729
			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=185682
688
			// check if postIncrement is the only usage of this local
730
			// check if postIncrement is the only usage of this local
689
			Reference.reportOnlyUselesslyReadLocal(currentScope, localBinding, valueRequired);
731
			Reference.reportOnlyUselesslyReadLocal(currentScope, localBinding, valueRequired);
732
			if (localBinding.resolvedPosition == -1) {
733
				if (valueRequired) {
734
					// restart code gen
735
					localBinding.useFlag = LocalVariableBinding.USED;
736
					throw new AbortMethod(CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE, null);
737
				}
738
				return;
739
			}
690
740
691
			// using incr bytecode if possible
741
			// using incr bytecode if possible
692
			if (localBinding.type == TypeBinding.INT) {
742
			if (localBinding.type == TypeBinding.INT) {
(-)compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java (-2 / +5 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.
Lines 6197-6203 Link Here
6197
public void resetInWideMode() {
6198
public void resetInWideMode() {
6198
	this.wideMode = true;
6199
	this.wideMode = true;
6199
}
6200
}
6200
6201
public void resetForCodeGenUnusedLocals() {
6202
	// nothing to do in standard code stream
6203
}
6201
private final void resizeByteArray() {
6204
private final void resizeByteArray() {
6202
	int length = this.bCodeStream.length;
6205
	int length = this.bCodeStream.length;
6203
	int requiredSize = length + length;
6206
	int requiredSize = length + length;
(-)compiler/org/eclipse/jdt/internal/compiler/codegen/StackMapFrameCodeStream.java (-1 / +5 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2006, 2009 IBM Corporation and others.
2
 * Copyright (c) 2006, 2010 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 539-544 Link Here
539
	this.resetSecretLocals();
539
	this.resetSecretLocals();
540
	super.resetInWideMode();
540
	super.resetInWideMode();
541
}
541
}
542
public void resetForCodeGenUnusedLocals() {
543
	this.resetSecretLocals();
544
	super.resetForCodeGenUnusedLocals();
545
}
542
public void resetSecretLocals() {
546
public void resetSecretLocals() {
543
	for (int i = 0, max = this.locals.length; i < max; i++) {
547
	for (int i = 0, max = this.locals.length; i < max; i++) {
544
		LocalVariableBinding localVariableBinding = this.locals[i];
548
		LocalVariableBinding localVariableBinding = this.locals[i];
(-)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 (-2 / +44 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 341-346 Link Here
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;
343
			// using incr bytecode if possible
353
			// using incr bytecode if possible
354
			Constant assignConstant;
344
			switch (localBinding.type.id) {
355
			switch (localBinding.type.id) {
345
				case T_JavaLangString :
356
				case T_JavaLangString :
346
					codeStream.generateStringConcatenationAppend(currentScope, this, expression);
357
					codeStream.generateStringConcatenationAppend(currentScope, this, expression);
Lines 350-357 Link Here
350
					codeStream.store(localBinding, false);
361
					codeStream.store(localBinding, false);
351
					return;
362
					return;
352
				case T_int :
363
				case T_int :
353
					Constant assignConstant;
364
					assignConstant = expression.constant;
354
					if (((assignConstant = expression.constant) != Constant.NotAConstant)
365
					if (localBinding.resolvedPosition == -1) {
366
						if (valueRequired) {
367
							/*
368
							 * restart code gen because we either:
369
							 * - need the value
370
							 * - the constant can have potential side-effect
371
							 */
372
							localBinding.useFlag = LocalVariableBinding.USED;
373
							throw new AbortMethod(CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE, null);
374
						} else if (assignConstant == Constant.NotAConstant) {
375
							// we only need to generate the value of the expression's constant if it is not a constant expression
376
							expression.generateCode(currentScope, codeStream, false);
377
						}
378
						return;
379
					}
380
					if ((assignConstant != Constant.NotAConstant)
355
							&& (assignConstant.typeID() != TypeIds.T_float) // only for integral types
381
							&& (assignConstant.typeID() != TypeIds.T_float) // only for integral types
356
							&& (assignConstant.typeID() != TypeIds.T_double)) { // TODO (philippe) is this test needed ?
382
							&& (assignConstant.typeID() != TypeIds.T_double)) { // TODO (philippe) is this test needed ?
357
						switch (operator) {
383
						switch (operator) {
Lines 375-380 Link Here
375
					}
401
					}
376
					//$FALL-THROUGH$
402
					//$FALL-THROUGH$
377
				default :
403
				default :
404
					if (localBinding.resolvedPosition == -1) {
405
						assignConstant = expression.constant;
406
						if (valueRequired) {
407
							/*
408
							 * restart code gen because we either:
409
							 * - need the value
410
							 * - the constant can have potential side-effect
411
							 */
412
							localBinding.useFlag = LocalVariableBinding.USED;
413
							throw new AbortMethod(CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE, null);
414
						} else if (assignConstant == Constant.NotAConstant) {
415
							// we only need to generate the value of the expression's constant if it is not a constant expression
416
							expression.generateCode(currentScope, codeStream, false);
417
						}
418
						return;
419
					}
378
					codeStream.load(localBinding);
420
					codeStream.load(localBinding);
379
			}
421
			}
380
	}
422
	}
(-)src/org/eclipse/jdt/core/tests/compiler/regression/EnumTest.java (-1 / +123 lines)
Lines 33-39 Link Here
33
	// All specified tests which does not belong to the class are skipped...
33
	// All specified tests which does not belong to the class are skipped...
34
	static {
34
	static {
35
//		TESTS_NAMES = new String[] { "test000" };
35
//		TESTS_NAMES = new String[] { "test000" };
36
//		TESTS_NUMBERS = new int[] { 181 };
36
//		TESTS_NUMBERS = new int[] { 182 };
37
//		TESTS_RANGE = new int[] { 21, 50 };
37
//		TESTS_RANGE = new int[] { 21, 50 };
38
	}
38
	}
39
	public static Test suite() {
39
	public static Test suite() {
Lines 6542-6545 Link Here
6542
		},
6542
		},
6543
		"SUCCESS");
6543
		"SUCCESS");
6544
}
6544
}
6545
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=328519
6546
public void test182() throws Exception {
6547
	Map customOptions = getCompilerOptions();
6548
	customOptions.put(CompilerOptions.OPTION_ReportUnusedLocal, CompilerOptions.ERROR);
6549
	customOptions.put(CompilerOptions.OPTION_PreserveUnusedLocal, CompilerOptions.OPTIMIZE_OUT);
6550
	this.runConformTest(
6551
		new String[] {
6552
			"X.java",
6553
			"public class X {\n" + 
6554
			"	public static void main(String argv[])   {\n" + 
6555
			"		foo();\n" + 
6556
			"	}\n" + 
6557
			"	public static void foo() {\n" + 
6558
			"		int n = 0;\n" + 
6559
			"		for (E e : E.values()) {\n" + 
6560
			"			if (e.val() == E.VALUES[n++] ) {\n" + 
6561
			"				System.out.print(e.val());\n" + 
6562
			"			}\n" + 
6563
			"		}\n" + 
6564
			"	}\n" + 
6565
			"}",
6566
			"E.java",
6567
			"enum E {\n" + 
6568
			"	a1(1), a2(2);\n" + 
6569
			"	static int[] VALUES = { 1, 2 };\n" + 
6570
			"	private int value;\n" + 
6571
			"	E(int v) {\n" + 
6572
			"		this.value = v;\n" + 
6573
			"	}\n" + 
6574
			"	public int val() {\n" + 
6575
			"		return this.value;\n" + 
6576
			"	}\n" + 
6577
			"}"
6578
		},
6579
		"12",
6580
		null/*classLibraries*/,
6581
		true/*shouldFlushOutputDirectory*/,
6582
		null,
6583
		customOptions,
6584
		null);
6585
}
6586
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=328519
6587
public void test183() throws Exception {
6588
	Map customOptions = getCompilerOptions();
6589
	customOptions.put(CompilerOptions.OPTION_ReportUnusedLocal, CompilerOptions.ERROR);
6590
	customOptions.put(CompilerOptions.OPTION_PreserveUnusedLocal, CompilerOptions.OPTIMIZE_OUT);
6591
	this.runConformTest(
6592
		new String[] {
6593
			"X.java",
6594
			"public class X {\n" + 
6595
			"	public static void main(String argv[]) {\n" + 
6596
			"	}\n" + 
6597
			"	static {\n" + 
6598
			"		int n = 0;\n" + 
6599
			"		for (E e : E.values()) {\n" + 
6600
			"			if (e.val() == E.VALUES[n++] ) {\n" + 
6601
			"				System.out.print(e.val());\n" + 
6602
			"			}\n" + 
6603
			"		}\n" + 
6604
			"	}\n" + 
6605
			"}",
6606
			"E.java",
6607
			"enum E {\n" + 
6608
			"	a1(1), a2(2);\n" + 
6609
			"	static int[] VALUES = { 1, 2 };\n" + 
6610
			"	private int value;\n" + 
6611
			"	E(int v) {\n" + 
6612
			"		this.value = v;\n" + 
6613
			"	}\n" + 
6614
			"	public int val() {\n" + 
6615
			"		return this.value;\n" + 
6616
			"	}\n" + 
6617
			"}"
6618
		},
6619
		"12",
6620
		null/*classLibraries*/,
6621
		true/*shouldFlushOutputDirectory*/,
6622
		null,
6623
		customOptions,
6624
		null);
6625
}
6626
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=328519
6627
public void test184() throws Exception {
6628
	Map customOptions = getCompilerOptions();
6629
	customOptions.put(CompilerOptions.OPTION_ReportUnusedLocal, CompilerOptions.ERROR);
6630
	customOptions.put(CompilerOptions.OPTION_PreserveUnusedLocal, CompilerOptions.OPTIMIZE_OUT);
6631
	this.runConformTest(
6632
		new String[] {
6633
			"X.java",
6634
			"public class X {\n" + 
6635
			"	public static void main(String argv[]) {\n" +
6636
			"		new X();\n" +
6637
			"	}\n" + 
6638
			"	X() {\n" + 
6639
			"		int n = 0;\n" + 
6640
			"		for (E e : E.values()) {\n" + 
6641
			"			if (e.val() == E.VALUES[n++] ) {\n" + 
6642
			"				System.out.print(e.val());\n" + 
6643
			"			}\n" + 
6644
			"		}\n" + 
6645
			"	}\n" + 
6646
			"}",
6647
			"E.java",
6648
			"enum E {\n" + 
6649
			"	a1(1), a2(2);\n" + 
6650
			"	static int[] VALUES = { 1, 2 };\n" + 
6651
			"	private int value;\n" + 
6652
			"	E(int v) {\n" + 
6653
			"		this.value = v;\n" + 
6654
			"	}\n" + 
6655
			"	public int val() {\n" + 
6656
			"		return this.value;\n" + 
6657
			"	}\n" + 
6658
			"}"
6659
		},
6660
		"12",
6661
		null/*classLibraries*/,
6662
		true/*shouldFlushOutputDirectory*/,
6663
		null,
6664
		customOptions,
6665
		null);
6666
}
6545
}
6667
}
(-)src/org/eclipse/jdt/core/tests/compiler/regression/ProgrammingProblemsTest.java (-8 / +166 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-42 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[] { 56 };
40
//  	TESTS_RANGE = new int[] { 1, -1 };
41
//  	TESTS_RANGE = new int[] { 1, -1 };
41
  	}
42
  	}
42
43
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 141-148 Link Here
141
		null /* ignoreOptions */,
146
		null /* ignoreOptions */,
142
		false /* expectingCompilerErrors */,
147
		false /* expectingCompilerErrors */,
143
		"----------\n" +
148
		"----------\n" +
144
		"1. WARNING in X.java (at line 2)\r\n" +
149
		"1. WARNING in X.java (at line 2)\n" +
145
		"	public void foo(boolean b) {\r\n" +
150
		"	public void foo(boolean b) {\n" +
146
		"	                        ^\n" +
151
		"	                        ^\n" +
147
		"The value of the parameter b is not used\n" +
152
		"The value of the parameter b is not used\n" +
148
		"----------\n" /* expectedCompilerLog */,
153
		"----------\n" /* expectedCompilerLog */,
Lines 277-284 Link Here
277
		null /* ignoreOptions */,
282
		null /* ignoreOptions */,
278
		true /* expectingCompilerErrors */,
283
		true /* expectingCompilerErrors */,
279
		"----------\n" +
284
		"----------\n" +
280
		"1. ERROR in X.java (at line 2)\r\n" +
285
		"1. ERROR in X.java (at line 2)\n" +
281
		"	public void foo(boolean b) {\r\n" +
286
		"	public void foo(boolean b) {\n" +
282
		"	                        ^\n" +
287
		"	                        ^\n" +
283
		"The value of the parameter b is not used\n" +
288
		"The value of the parameter b is not used\n" +
284
		"----------\n" /* expectedCompilerLog */,
289
		"----------\n" /* expectedCompilerLog */,
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
}
2232
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=328519
2233
public void test0056() throws Exception {
2234
	Map customOptions = getCompilerOptions();
2235
	customOptions.put(CompilerOptions.OPTION_ReportUnusedLocal, CompilerOptions.ERROR);
2236
	this.runConformTest(
2237
		new String[] {
2238
			"X.java",
2239
			"public class X {\n" + 
2240
			"    static int foo() {\n" + 
2241
			"        int i = 2;\n" + 
2242
			"        int j = 3;\n" + 
2243
			"        return (i += j *= 3);\n" + 	// value is used as it is returned
2244
			"    }\n" + 
2245
			"    public static void main(String[] args) {\n" + 
2246
			"        System.out.println(foo());\n" + 
2247
			"    }\n" + 
2248
			"}"
2249
		},
2250
		"11",
2251
		null/*classLibraries*/,
2252
		true/*shouldFlushOutputDirectory*/,
2253
		null,
2254
		customOptions,
2255
		null);
2256
}
2257
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=328519
2258
public void test0057() throws Exception {
2259
	Map customOptions = getCompilerOptions();
2260
	customOptions.put(CompilerOptions.OPTION_ReportUnusedLocal, CompilerOptions.IGNORE);
2261
	this.runConformTest(
2262
		new String[] {
2263
			"X.java",
2264
			"public class X {\n" + 
2265
			"    public static void main (String args[]) {\n" + 
2266
			"        int i = 0;\n" + 
2267
			"        i += 4 + foo();\n" + 
2268
			"    }\n" + 
2269
			"    public static int foo() {\n" + 
2270
			"    	System.out.println(\"OK\");\n" + 
2271
			"    	return 0;\n" + 
2272
			"    }\n" + 
2273
			"}"
2274
		},
2275
		"OK",
2276
		null/*classLibraries*/,
2277
		true/*shouldFlushOutputDirectory*/,
2278
		null,
2279
		customOptions,
2280
		null);
2281
}
2124
}
2282
}

Return to bug 328519