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

Collapse All | Expand All

(-)src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java (+267 lines)
Lines 33103-33106 Link Here
33103
		"Zork cannot be resolved to a type\n" + 
33103
		"Zork cannot be resolved to a type\n" + 
33104
		"----------\n");
33104
		"----------\n");
33105
}
33105
}
33106
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=159021 - variation
33107
public void test1038() {
33108
	Map options = getCompilerOptions();
33109
	options.put(CompilerOptions.OPTION_PreserveUnusedLocal, CompilerOptions.OPTIMIZE_OUT);
33110
	this.runConformTest(
33111
		new String[] {
33112
			"X.java",
33113
			"interface I<T> {\n" + 
33114
			"    int CONST = A.foo();\n" + 
33115
			"}\n" + 
33116
			"\n" + 
33117
			"class A<U> {\n" + 
33118
			"        static int foo() {\n" + 
33119
			"        System.out.println(\"SUCCESS\");\n" + 
33120
			"        return 0;\n" + 
33121
			"    }\n" + 
33122
			"}\n" + 
33123
			"class B<V> implements I<V> {\n" + 
33124
			"	static int LOCAL_STATIC;\n" + 
33125
			"	int local_field;\n" + 
33126
			"    B(int param) {\n" + 
33127
			"        int i = CONST; // keep for possible <clinit>\n" + 
33128
			"        int j = param; // may optimize out\n" + 
33129
			"        int k = LOCAL_STATIC; // may optimize out\n" + 
33130
			"        int l = local_field; // may optimize out\n" + 
33131
			"    }\n" + 
33132
			"}\n" + 
33133
			"public class X {\n" + 
33134
			"    public static void main(String[] args) {\n" + 
33135
			"        new B<String>(12);\n" + 
33136
			"    }\n" + 
33137
			"}", // =================
33138
		}, 
33139
		"SUCCESS",
33140
		null,
33141
		false,
33142
		null,
33143
		options,
33144
		null);
33145
	// check the reference to I.CONST still got generated (for <clinit> invocation side-effect)
33146
	String expectedOutput = 
33147
		"  // Method descriptor #10 (I)V\n" + 
33148
		"  // Stack: 1, Locals: 2\n" + 
33149
		"  B(int param);\n" + 
33150
		"    0  aload_0 [this]\n" + 
33151
		"    1  invokespecial java.lang.Object() [12]\n" + 
33152
		"    4  getstatic B.CONST : int [15]\n" + 
33153
		"    7  pop\n" + 
33154
		"    8  return\n" + 
33155
		"      Line numbers:\n" + 
33156
		"        [pc: 0, line: 14]\n" + 
33157
		"        [pc: 4, line: 15]\n" + 
33158
		"        [pc: 8, line: 19]\n" + 
33159
		"      Local variable table:\n" + 
33160
		"        [pc: 0, pc: 9] local: this index: 0 type: B\n" + 
33161
		"        [pc: 0, pc: 9] local: param index: 1 type: int\n";
33162
33163
	try {
33164
		File f = new File(OUTPUT_DIR + File.separator + "B.class");
33165
		byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(f);
33166
		ClassFileBytesDisassembler disassembler = ToolFactory.createDefaultClassFileBytesDisassembler();
33167
		String result = disassembler.disassemble(classFileBytes, "\n", ClassFileBytesDisassembler.DETAILED);
33168
		int index = result.indexOf(expectedOutput);
33169
		if (index == -1 || expectedOutput.length() == 0) {
33170
			System.out.println(Util.displayString(result, 3));
33171
		}
33172
		if (index == -1) {
33173
			assertEquals("Wrong contents", expectedOutput, result);
33174
		}
33175
	} catch (org.eclipse.jdt.core.util.ClassFormatException e) {
33176
		assertTrue(false);
33177
	} catch (IOException e) {
33178
		assertTrue(false);
33179
	}			
33180
}
33181
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=159021 - variation
33182
public void test1039() {
33183
	Map options = getCompilerOptions();
33184
	options.put(CompilerOptions.OPTION_PreserveUnusedLocal, CompilerOptions.OPTIMIZE_OUT);
33185
	this.runConformTest(
33186
		new String[] {
33187
			"X.java",
33188
			"interface I<T> {\n" + 
33189
			"	Value<String> CONST = A.foo(\"[I.CONST]\");\n" + 
33190
			"}\n" + 
33191
			"class Value<V> {\n" + 
33192
			"	static String NAME = \"\";\n" + 
33193
			"	V v;\n" + 
33194
			"	Value(V v) {\n" + 
33195
			"		this.v = v;\n" + 
33196
			"	}\n" + 
33197
			"}\n" + 
33198
			"class A {\n" + 
33199
			"	static Value<String> foo(String str) {\n" + 
33200
			"		System.out.print(str);\n" + 
33201
			"		return new Value<String>(\"str\");\n" + 
33202
			"	}\n" + 
33203
			"}\n" + 
33204
			"class B<V> implements I<V> {\n" + 
33205
			"	static Value<String> LOCAL_STATIC = A.foo(\"[B.LOCAL_STATIC]\");\n" + 
33206
			"	Value<String> local_field = A.foo(\"[B.local_field]\");\n" + 
33207
			"	B(Value<String> param) {\n" + 
33208
			"		String i = CONST.NAME; // keep for possible <clinit>\n" + 
33209
			"		String j = param.NAME; // may optimize out\n" + 
33210
			"		String k = LOCAL_STATIC.NAME; // may optimize out\n" + 
33211
			"		String l = local_field.NAME; // may optimize out\n" + 			
33212
			"	}\n" + 
33213
			"}\n" + 
33214
			"public class X {\n" + 
33215
			"	public static void main(String[] args) {\n" + 
33216
			"		new B<String>(new Value<String>(\"[PARAM]\"));\n" + 
33217
			"	}\n" + 
33218
			"}", // =================
33219
		}, 
33220
		"[B.LOCAL_STATIC][B.local_field][I.CONST]",
33221
		null,
33222
		false,
33223
		null,
33224
		options,
33225
		null);
33226
	// check the reference to I.CONST still got generated (for <clinit> invocation side-effect)
33227
	String expectedOutput = 
33228
		"  // Method descriptor #28 (LValue;)V\n" + 
33229
		"  // Signature: (LValue<Ljava/lang/String;>;)V\n" + 
33230
		"  // Stack: 2, Locals: 2\n" + 
33231
		"  B(Value param);\n" + 
33232
		"     0  aload_0 [this]\n" + 
33233
		"     1  invokespecial java.lang.Object() [30]\n" + 
33234
		"     4  aload_0 [this]\n" + 
33235
		"     5  ldc <String \"[B.local_field]\"> [32]\n" + 
33236
		"     7  invokestatic A.foo(java.lang.String) : Value [17]\n" + 
33237
		"    10  putfield B.local_field : Value [34]\n" + 
33238
		"    13  getstatic I.CONST : Value [36]\n" + 
33239
		"    16  pop\n" + 
33240
		"    17  getstatic Value.NAME : java.lang.String [39]\n" + 
33241
		"    20  pop\n" + 
33242
		"    21  getstatic Value.NAME : java.lang.String [39]\n" + 
33243
		"    24  pop\n" + 
33244
		"    25  getstatic Value.NAME : java.lang.String [39]\n" + 
33245
		"    28  pop\n" + 
33246
		"    29  getstatic Value.NAME : java.lang.String [39]\n" + 
33247
		"    32  pop\n" + 
33248
		"    33  return\n" + 
33249
		"      Line numbers:\n" + 
33250
		"        [pc: 0, line: 20]\n" + 
33251
		"        [pc: 4, line: 19]\n" + 
33252
		"        [pc: 13, line: 21]\n" + 
33253
		"        [pc: 21, line: 22]\n" + 
33254
		"        [pc: 25, line: 23]\n" + 
33255
		"        [pc: 29, line: 24]\n" + 
33256
		"        [pc: 33, line: 25]\n" + 
33257
		"      Local variable table:\n" + 
33258
		"        [pc: 0, pc: 34] local: this index: 0 type: B\n" + 
33259
		"        [pc: 0, pc: 34] local: param index: 1 type: Value\n";
33260
33261
	try {
33262
		File f = new File(OUTPUT_DIR + File.separator + "B.class");
33263
		byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(f);
33264
		ClassFileBytesDisassembler disassembler = ToolFactory.createDefaultClassFileBytesDisassembler();
33265
		String result = disassembler.disassemble(classFileBytes, "\n", ClassFileBytesDisassembler.DETAILED);
33266
		int index = result.indexOf(expectedOutput);
33267
		if (index == -1 || expectedOutput.length() == 0) {
33268
			System.out.println(Util.displayString(result, 3));
33269
		}
33270
		if (index == -1) {
33271
			assertEquals("Wrong contents", expectedOutput, result);
33272
		}
33273
	} catch (org.eclipse.jdt.core.util.ClassFormatException e) {
33274
		assertTrue(false);
33275
	} catch (IOException e) {
33276
		assertTrue(false);
33277
	}			
33278
}
33279
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=159021 - variation
33280
public void test1040() {
33281
	Map options = getCompilerOptions();
33282
	options.put(CompilerOptions.OPTION_PreserveUnusedLocal, CompilerOptions.OPTIMIZE_OUT);
33283
	this.runConformTest(
33284
		new String[] {
33285
			"X.java",
33286
			"interface I<T> {\n" + 
33287
			"	Value<String> CONST = A.foo(\"[I.CONST]\");\n" + 
33288
			"}\n" + 
33289
			"class Value<V> {\n" + 
33290
			"	static String NAME = \"\";\n" + 
33291
			"	V v;\n" + 
33292
			"	Value(V v) {\n" + 
33293
			"		this.v = v;\n" + 
33294
			"	}\n" + 
33295
			"}\n" + 
33296
			"class A {\n" + 
33297
			"	static Value<String> foo(String str) {\n" + 
33298
			"		System.out.print(str);\n" + 
33299
			"		return new Value<String>(\"str\");\n" + 
33300
			"	}\n" + 
33301
			"}\n" + 
33302
			"class B<V> implements I<V> {\n" + 
33303
			"	static Value<String> LOCAL_STATIC = A.foo(\"[B.LOCAL_STATIC]\");\n" + 
33304
			"	Value<String> local_field = A.foo(\"[B.local_field]\");\n" + 
33305
			"	B(Value<String> param) {\n" + 
33306
			"		String i = this.CONST.NAME; // keep for possible <clinit>\n" + 
33307
			"		String k = this.LOCAL_STATIC.NAME; // may optimize out\n" + 
33308
			"		String l = this.local_field.NAME; // may optimize out\n" + 			
33309
			"	}\n" + 
33310
			"}\n" + 
33311
			"public class X {\n" + 
33312
			"	public static void main(String[] args) {\n" + 
33313
			"		new B<String>(new Value<String>(\"[PARAM]\"));\n" + 
33314
			"	}\n" + 
33315
			"}", // =================
33316
		}, 
33317
		"[B.LOCAL_STATIC][B.local_field][I.CONST]",
33318
		null,
33319
		false,
33320
		null,
33321
		options,
33322
		null);
33323
	// check the reference to I.CONST still got generated (for <clinit> invocation side-effect)
33324
	String expectedOutput = 
33325
		"  // Method descriptor #28 (LValue;)V\n" + 
33326
		"  // Signature: (LValue<Ljava/lang/String;>;)V\n" + 
33327
		"  // Stack: 2, Locals: 2\n" + 
33328
		"  B(Value param);\n" + 
33329
		"     0  aload_0 [this]\n" + 
33330
		"     1  invokespecial java.lang.Object() [30]\n" + 
33331
		"     4  aload_0 [this]\n" + 
33332
		"     5  ldc <String \"[B.local_field]\"> [32]\n" + 
33333
		"     7  invokestatic A.foo(java.lang.String) : Value [17]\n" + 
33334
		"    10  putfield B.local_field : Value [34]\n" + 
33335
		"    13  getstatic B.CONST : Value [36]\n" + 
33336
		"    16  pop\n" + 
33337
		"    17  getstatic Value.NAME : java.lang.String [39]\n" + 
33338
		"    20  pop\n" + 
33339
		"    21  getstatic Value.NAME : java.lang.String [39]\n" + 
33340
		"    24  pop\n" + 
33341
		"    25  getstatic Value.NAME : java.lang.String [39]\n" + 
33342
		"    28  pop\n" + 
33343
		"    29  return\n" + 
33344
		"      Line numbers:\n" + 
33345
		"        [pc: 0, line: 20]\n" + 
33346
		"        [pc: 4, line: 19]\n" + 
33347
		"        [pc: 13, line: 21]\n" + 
33348
		"        [pc: 21, line: 22]\n" + 
33349
		"        [pc: 25, line: 23]\n" + 
33350
		"        [pc: 29, line: 24]\n" + 
33351
		"      Local variable table:\n" + 
33352
		"        [pc: 0, pc: 30] local: this index: 0 type: B\n" + 
33353
		"        [pc: 0, pc: 30] local: param index: 1 type: Value\n";
33354
33355
	try {
33356
		File f = new File(OUTPUT_DIR + File.separator + "B.class");
33357
		byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(f);
33358
		ClassFileBytesDisassembler disassembler = ToolFactory.createDefaultClassFileBytesDisassembler();
33359
		String result = disassembler.disassemble(classFileBytes, "\n", ClassFileBytesDisassembler.DETAILED);
33360
		int index = result.indexOf(expectedOutput);
33361
		if (index == -1 || expectedOutput.length() == 0) {
33362
			System.out.println(Util.displayString(result, 3));
33363
		}
33364
		if (index == -1) {
33365
			assertEquals("Wrong contents", expectedOutput, result);
33366
		}
33367
	} catch (org.eclipse.jdt.core.util.ClassFormatException e) {
33368
		assertTrue(false);
33369
	} catch (IOException e) {
33370
		assertTrue(false);
33371
	}			
33372
}
33106
}
33373
}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java (-1 / +14 lines)
Lines 653-659 Link Here
653
								codeStream.pop();
653
								codeStream.pop();
654
							}
654
							}
655
						} else {
655
						} else {
656
							if (this.codegenBinding != lastFieldBinding && !lastFieldBinding.isStatic()){
656
							if (this.codegenBinding == lastFieldBinding) {
657
								if (lastFieldBinding.isStatic()){
658
									// if no valueRequired, still need possible side-effects of <clinit> invocation, if field belongs to different class
659
									if (((FieldBinding)binding).original().declaringClass != this.actualReceiverType.erasure()) {
660
										MethodBinding accessor = syntheticReadAccessors == null ? null : syntheticReadAccessors[i]; 
661
										if (accessor == null) {
662
											codeStream.getstatic(lastFieldBinding);
663
										} else {
664
											codeStream.invokestatic(accessor);
665
										}
666
										codeStream.pop();
667
									}				
668
								}
669
							} else if (!lastFieldBinding.isStatic()){
657
								codeStream.invokeObjectGetClass(); // perform null check
670
								codeStream.invokeObjectGetClass(); // perform null check
658
								codeStream.pop();
671
								codeStream.pop();
659
							}						
672
							}						
(-)compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java (-34 / +48 lines)
Lines 346-388 Link Here
346
						if (valueRequired) {
346
						if (valueRequired) {
347
							codeStream.generateConstant(fieldConstant, implicitConversion);
347
							codeStream.generateConstant(fieldConstant, implicitConversion);
348
						}
348
						}
349
					} else {
349
						break;
350
						if (valueRequired) {
350
					}
351
							boolean isStatic = fieldBinding.isStatic();
351
					if (fieldBinding.isStatic()) {
352
							if (!isStatic) {
352
						if (!valueRequired) {
353
								if ((bits & DepthMASK) != 0) {
353
							// if no valueRequired, still need possible side-effects of <clinit> invocation, if field belongs to different class
354
									ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
354
							if (((FieldBinding)binding).original().declaringClass == this.actualReceiverType.erasure()) {
355
									Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
355
								break;
356
									codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
357
								} else {
358
									generateReceiver(codeStream);
359
								}
360
							}
356
							}
361
							// managing private access							
357
						}
362
							if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
358
						// managing private access							
363
								if (isStatic) {
359
						if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
364
									codeStream.getstatic(fieldBinding);
360
							codeStream.getstatic(fieldBinding);
365
								} else {
361
						} else {
366
									codeStream.getfield(fieldBinding);
362
							codeStream.invokestatic(syntheticAccessors[READ]);
367
								}
363
						}
368
							} else {
364
						if (valueRequired) {
369
								codeStream.invokestatic(syntheticAccessors[READ]);
365
							if (this.genericCast != null) codeStream.checkcast(this.genericCast);			
366
							codeStream.generateImplicitConversion(implicitConversion);
367
						} else {
368
							// could occur if !valueRequired but static field belongs to different class
369
							switch (fieldBinding.type.id) {
370
								case T_long :
371
								case T_double :
372
									codeStream.pop2();
373
									break;
374
								default :
375
									codeStream.pop();
370
							}
376
							}
371
							if (valueRequired) {
377
						}							
372
								if (this.genericCast != null) codeStream.checkcast(this.genericCast);			
378
					} else {
373
								codeStream.generateImplicitConversion(implicitConversion);
379
						if (!valueRequired) {
374
							} else {
380
							// if no valueRequired, optimize out entire gen
375
								// could occur if !valueRequired but compliance >= 1.4
381
							break;
376
								switch (fieldBinding.type.id) {
377
									case T_long :
378
									case T_double :
379
										codeStream.pop2();
380
										break;
381
									default :
382
										codeStream.pop();
383
								}
384
							}							
385
						}
382
						}
383
						// managing enclosing instance access
384
						if ((bits & DepthMASK) != 0) {
385
							ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
386
							Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
387
							codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
388
						} else {
389
							generateReceiver(codeStream);
390
						}
391
						// managing private access							
392
						if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
393
							codeStream.getfield(fieldBinding);
394
						} else {
395
							codeStream.invokestatic(syntheticAccessors[READ]);
396
						}
397
						// managing generic cast
398
						if (this.genericCast != null) codeStream.checkcast(this.genericCast);			
399
						codeStream.generateImplicitConversion(implicitConversion);
386
					}
400
					}
387
					break;
401
					break;
388
				case Binding.LOCAL : // reading a local
402
				case Binding.LOCAL : // reading a local
(-)compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java (-50 / +72 lines)
Lines 168-234 Link Here
168
		if (valueRequired) {
168
		if (valueRequired) {
169
			codeStream.generateConstant(constant, implicitConversion);
169
			codeStream.generateConstant(constant, implicitConversion);
170
		}
170
		}
171
	} else {
171
		codeStream.recordPositionsFrom(pc, this.sourceStart);
172
		boolean isStatic = this.codegenBinding.isStatic();
172
		return;
173
		boolean isThisReceiver = this.receiver instanceof ThisReference;
173
	}
174
		Constant fieldConstant = this.codegenBinding.constant();
174
	boolean isStatic = this.codegenBinding.isStatic();
175
		if (fieldConstant != Constant.NotAConstant) {
175
	boolean isThisReceiver = this.receiver instanceof ThisReference;
176
			if (!isThisReceiver) {
176
	Constant fieldConstant = this.codegenBinding.constant();
177
				receiver.generateCode(currentScope, codeStream, !isStatic);
177
	if (fieldConstant != Constant.NotAConstant) {
178
				if (!isStatic){
178
		if (!isThisReceiver) {
179
					codeStream.invokeObjectGetClass();
179
			receiver.generateCode(currentScope, codeStream, !isStatic);
180
					codeStream.pop();
180
			if (!isStatic){
181
				}
181
				codeStream.invokeObjectGetClass();
182
				codeStream.pop();
182
			}
183
			}
184
		}
185
		if (valueRequired) {
186
			codeStream.generateConstant(fieldConstant, implicitConversion);
187
		}
188
		codeStream.recordPositionsFrom(pc, this.sourceStart);
189
		return;
190
	}
191
	if (valueRequired || (!isThisReceiver && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4)) {
192
		receiver.generateCode(currentScope, codeStream, !isStatic);
193
		if (this.codegenBinding.declaringClass == null) { // array length
194
			codeStream.arraylength();
183
			if (valueRequired) {
195
			if (valueRequired) {
184
				codeStream.generateConstant(fieldConstant, implicitConversion);
196
				codeStream.generateImplicitConversion(implicitConversion);
197
			} else {
198
				// could occur if !valueRequired but compliance >= 1.4
199
				codeStream.pop();
185
			}
200
			}
186
		} else {
201
		} else {
187
			if (valueRequired || (!isThisReceiver && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4)) {
202
			if (syntheticAccessors == null || syntheticAccessors[READ] == null) {
188
				receiver.generateCode(currentScope, codeStream, !isStatic);
203
				if (isStatic) {
189
				if (this.codegenBinding.declaringClass == null) { // array length
204
					codeStream.getstatic(this.codegenBinding);
190
					codeStream.arraylength();
191
					if (valueRequired) {
192
						codeStream.generateImplicitConversion(implicitConversion);
193
					} else {
194
						// could occur if !valueRequired but compliance >= 1.4
195
						codeStream.pop();
196
					}
197
				} else {
205
				} else {
198
					if (syntheticAccessors == null || syntheticAccessors[READ] == null) {
206
					codeStream.getfield(this.codegenBinding);
199
						if (isStatic) {
200
							codeStream.getstatic(this.codegenBinding);
201
						} else {
202
							codeStream.getfield(this.codegenBinding);
203
						}
204
					} else {
205
						codeStream.invokestatic(syntheticAccessors[READ]);
206
					}
207
					if (valueRequired) {
208
						if (this.genericCast != null) codeStream.checkcast(this.genericCast);			
209
						codeStream.generateImplicitConversion(implicitConversion);
210
					} else {
211
						// could occur if !valueRequired but compliance >= 1.4
212
						switch (this.codegenBinding.type.id) {
213
							case T_long :
214
							case T_double :
215
								codeStream.pop2();
216
								break;
217
							default :
218
								codeStream.pop();
219
						}
220
					}
221
				}
207
				}
222
			} else {
208
			} else {
223
				if (!isThisReceiver) {
209
				codeStream.invokestatic(syntheticAccessors[READ]);
224
					receiver.generateCode(currentScope, codeStream, !isStatic);				
210
			}
225
					if (!isStatic){
211
			if (valueRequired) {
226
						codeStream.invokeObjectGetClass(); // perform null check
212
				if (this.genericCast != null) codeStream.checkcast(this.genericCast);			
213
				codeStream.generateImplicitConversion(implicitConversion);
214
			} else {
215
				// could occur if !valueRequired but compliance >= 1.4
216
				switch (this.codegenBinding.type.id) {
217
					case T_long :
218
					case T_double :
219
						codeStream.pop2();
220
						break;
221
					default :
227
						codeStream.pop();
222
						codeStream.pop();
228
					}
229
				}
223
				}
230
			}
224
			}
231
		}
225
		}
226
	} else {
227
		if (isThisReceiver) {
228
			if (isStatic){
229
				// if no valueRequired, still need possible side-effects of <clinit> invocation, if field belongs to different class
230
				if (this.binding.original().declaringClass != this.receiverType.erasure()) {
231
					MethodBinding accessor = syntheticAccessors == null ? null : syntheticAccessors[READ]; 
232
					if (accessor == null) {
233
						codeStream.getstatic(this.codegenBinding);
234
					} else {
235
						codeStream.invokestatic(accessor);
236
					}
237
					switch (this.codegenBinding.type.id) {
238
						case T_long :
239
						case T_double :
240
							codeStream.pop2();
241
							break;
242
						default :
243
							codeStream.pop();
244
					}
245
				}
246
			}
247
		} else {
248
			receiver.generateCode(currentScope, codeStream, !isStatic);				
249
			if (!isStatic){
250
				codeStream.invokeObjectGetClass(); // perform null check
251
				codeStream.pop();
252
			}
253
		}						
232
	}
254
	}
233
	codeStream.recordPositionsFrom(pc, this.sourceStart);
255
	codeStream.recordPositionsFrom(pc, this.sourceStart);
234
}
256
}
(-)Eclipse Java Tests Compiler/org/eclipse/jdt/tests/compiler/regression/InitializationTest.java (+327 lines)
Lines 10-18 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.jdt.tests.compiler.regression;
11
package org.eclipse.jdt.tests.compiler.regression;
12
12
13
import java.io.File;
14
import java.io.IOException;
13
import java.util.Hashtable;
15
import java.util.Hashtable;
16
import java.util.Map;
14
17
18
import org.eclipse.jdt.core.ToolFactory;
15
import org.eclipse.jdt.core.tests.compiler.regression.*;
19
import org.eclipse.jdt.core.tests.compiler.regression.*;
20
import org.eclipse.jdt.core.tests.util.Util;
21
import org.eclipse.jdt.core.util.ClassFileBytesDisassembler;
22
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
16
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
23
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
17
24
18
import junit.framework.Test;
25
import junit.framework.Test;
Lines 5101-5106 Link Here
5101
		"	^^^^\n" + 
5108
		"	^^^^\n" + 
5102
		"Zork cannot be resolved to a type\n" + 
5109
		"Zork cannot be resolved to a type\n" + 
5103
		"----------\n");
5110
		"----------\n");
5111
}
5112
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=159021
5113
public void test189() {
5114
	Map options = getCompilerOptions();
5115
	options.put(CompilerOptions.OPTION_PreserveUnusedLocal, CompilerOptions.OPTIMIZE_OUT);
5116
	this.runConformTest(
5117
		new String[] {
5118
			"X.java",
5119
			"interface I {\n" + 
5120
			"    int CONST = A.foo();\n" + 
5121
			"}\n" + 
5122
			"\n" + 
5123
			"class A {\n" + 
5124
			"        static int foo() {\n" + 
5125
			"        System.out.println(\"SUCCESS\");\n" + 
5126
			"        return 0;\n" + 
5127
			"    }\n" + 
5128
			"}\n" + 
5129
			"class B implements I {\n" + 
5130
			"	static int LOCAL_STATIC;\n" + 
5131
			"	int local_field;\n" +
5132
			"    B(int param) {\n" + 
5133
			"        int i = CONST; // keep for possible <clinit>\n" + 
5134
			"        int j = param; // may optimize out\n" + 
5135
			"        int k = LOCAL_STATIC; // may optimize out\n" + 
5136
			"        int l = local_field; // may optimize out\n" + 
5137
			"    }\n" + 
5138
			"}\n" + 
5139
			"public class X {\n" + 
5140
			"    public static void main(String[] args) {\n" + 
5141
			"        new B(12);\n" + 
5142
			"    }\n" + 
5143
			"}", // =================
5144
		}, 
5145
		"SUCCESS",
5146
		null,
5147
		false,
5148
		null,
5149
		options,
5150
		null);
5151
	// check the reference to I.CONST still got generated (for <clinit> invocation side-effect)
5152
	String expectedOutput = new CompilerOptions(options).complianceLevel < ClassFileConstants.JDK1_4
5153
			? 	"  // Method descriptor #10 (I)V\n" + 
5154
				"  // Stack: 1, Locals: 2\n" + 
5155
				"  B(int param);\n" + 
5156
				"    0  aload_0 [this]\n" + 
5157
				"    1  invokespecial java.lang.Object() [12]\n" + 
5158
				"    4  getstatic I.CONST : int [15]\n" + 
5159
				"    7  pop\n" + 
5160
				"    8  return\n" + 
5161
				"      Line numbers:\n" + 
5162
				"        [pc: 0, line: 14]\n" + 
5163
				"        [pc: 4, line: 15]\n" + 
5164
				"        [pc: 8, line: 19]\n" + 
5165
				"      Local variable table:\n" + 
5166
				"        [pc: 0, pc: 9] local: this index: 0 type: B\n" + 
5167
				"        [pc: 0, pc: 9] local: param index: 1 type: int\n"
5168
			: 	"  // Method descriptor #10 (I)V\n" + 
5169
				"  // Stack: 1, Locals: 2\n" + 
5170
				"  B(int param);\n" + 
5171
				"    0  aload_0 [this]\n" + 
5172
				"    1  invokespecial java.lang.Object() [12]\n" + 
5173
				"    4  getstatic B.CONST : int [15]\n" + 
5174
				"    7  pop\n" + 
5175
				"    8  return\n" + 
5176
				"      Line numbers:\n" + 
5177
				"        [pc: 0, line: 14]\n" + 
5178
				"        [pc: 4, line: 15]\n" + 
5179
				"        [pc: 8, line: 19]\n" + 
5180
				"      Local variable table:\n" + 
5181
				"        [pc: 0, pc: 9] local: this index: 0 type: B\n" + 
5182
				"        [pc: 0, pc: 9] local: param index: 1 type: int\n";
5183
5184
	try {
5185
		File f = new File(OUTPUT_DIR + File.separator + "B.class");
5186
		byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(f);
5187
		ClassFileBytesDisassembler disassembler = ToolFactory.createDefaultClassFileBytesDisassembler();
5188
		String result = disassembler.disassemble(classFileBytes, "\n", ClassFileBytesDisassembler.DETAILED);
5189
		int index = result.indexOf(expectedOutput);
5190
		if (index == -1 || expectedOutput.length() == 0) {
5191
			System.out.println(Util.displayString(result, 3));
5192
		}
5193
		if (index == -1) {
5194
			assertEquals("Wrong contents", expectedOutput, result);
5195
		}
5196
	} catch (org.eclipse.jdt.core.util.ClassFormatException e) {
5197
		assertTrue(false);
5198
	} catch (IOException e) {
5199
		assertTrue(false);
5200
	}			
5201
}
5202
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=159021 - variation
5203
public void test190() {
5204
	Map options = getCompilerOptions();
5205
	options.put(CompilerOptions.OPTION_PreserveUnusedLocal, CompilerOptions.OPTIMIZE_OUT);
5206
	this.runConformTest(
5207
		new String[] {
5208
			"X.java",
5209
			"interface I {\n" + 
5210
			"	Value CONST = A.foo(\"[I.CONST]\");\n" + 
5211
			"}\n" + 
5212
			"class Value {\n" + 
5213
			"	static String NAME = \"\";\n" + 
5214
			"	String v;\n" + 
5215
			"	Value(String v) {\n" + 
5216
			"		this.v = v;\n" + 
5217
			"	}\n" + 
5218
			"}\n" + 
5219
			"class A {\n" + 
5220
			"	static Value foo(String str) {\n" + 
5221
			"		System.out.print(str);\n" + 
5222
			"		return new Value(\"str\");\n" + 
5223
			"	}\n" + 
5224
			"}\n" + 
5225
			"class B implements I {\n" + 
5226
			"	static Value LOCAL_STATIC = A.foo(\"[B.LOCAL_STATIC]\");\n" + 
5227
			"	Value local_field = A.foo(\"[B.local_field]\");\n" + 
5228
			"	B(Value param) {\n" + 
5229
			"		String i = CONST.NAME; // keep for possible <clinit>\n" + 
5230
			"		String j = param.NAME; // may optimize out\n" + 
5231
			"		String k = LOCAL_STATIC.NAME; // may optimize out\n" + 
5232
			"		String l = local_field.NAME; // may optimize out\n" + 
5233
			"	}\n" + 
5234
			"}\n" + 
5235
			"public class X {\n" + 
5236
			"	public static void main(String[] args) {\n" + 
5237
			"		new B(new Value(\"[PARAM]\"));\n" + 
5238
			"	}\n" + 
5239
			"}", // =================
5240
		}, 
5241
		"[B.LOCAL_STATIC][B.local_field][I.CONST]",
5242
		null,
5243
		false,
5244
		null,
5245
		options,
5246
		null);
5247
	// check the reference to I.CONST still got generated (for <clinit> invocation side-effect)
5248
	String expectedOutput = new CompilerOptions(options).complianceLevel < ClassFileConstants.JDK1_4
5249
			? 	"  // Method descriptor #26 (LValue;)V\n" + 
5250
				"  // Stack: 2, Locals: 2\n" + 
5251
				"  B(Value param);\n" + 
5252
				"     0  aload_0 [this]\n" + 
5253
				"     1  invokespecial java.lang.Object() [27]\n" + 
5254
				"     4  aload_0 [this]\n" + 
5255
				"     5  ldc <String \"[B.local_field]\"> [29]\n" + 
5256
				"     7  invokestatic A.foo(java.lang.String) : Value [15]\n" + 
5257
				"    10  putfield B.local_field : Value [31]\n" + 
5258
				"    13  getstatic I.CONST : Value [33]\n" + 
5259
				"    16  pop\n" + 
5260
				"    17  return\n" + 
5261
				"      Line numbers:\n" + 
5262
				"        [pc: 0, line: 20]\n" + 
5263
				"        [pc: 4, line: 19]\n" + 
5264
				"        [pc: 13, line: 21]\n" + 
5265
				"        [pc: 17, line: 25]\n" + 
5266
				"      Local variable table:\n" + 
5267
				"        [pc: 0, pc: 18] local: this index: 0 type: B\n" + 
5268
				"        [pc: 0, pc: 18] local: param index: 1 type: Value\n"
5269
			: 	"  // Method descriptor #26 (LValue;)V\n" + 
5270
				"  // Stack: 2, Locals: 2\n" + 
5271
				"  B(Value param);\n" + 
5272
				"     0  aload_0 [this]\n" + 
5273
				"     1  invokespecial java.lang.Object() [27]\n" + 
5274
				"     4  aload_0 [this]\n" + 
5275
				"     5  ldc <String \"[B.local_field]\"> [29]\n" + 
5276
				"     7  invokestatic A.foo(java.lang.String) : Value [15]\n" + 
5277
				"    10  putfield B.local_field : Value [31]\n" + 
5278
				"    13  getstatic I.CONST : Value [33]\n" + 
5279
				"    16  pop\n" + 
5280
				"    17  getstatic Value.NAME : java.lang.String [36]\n" + 
5281
				"    20  pop\n" + 
5282
				"    21  getstatic Value.NAME : java.lang.String [36]\n" + 
5283
				"    24  pop\n" + 
5284
				"    25  getstatic Value.NAME : java.lang.String [36]\n" + 
5285
				"    28  pop\n" + 
5286
				"    29  getstatic Value.NAME : java.lang.String [36]\n" + 
5287
				"    32  pop\n" + 
5288
				"    33  return\n" + 
5289
				"      Line numbers:\n" + 
5290
				"        [pc: 0, line: 20]\n" + 
5291
				"        [pc: 4, line: 19]\n" + 
5292
				"        [pc: 13, line: 21]\n" + 
5293
				"        [pc: 21, line: 22]\n" + 
5294
				"        [pc: 25, line: 23]\n" + 
5295
				"        [pc: 29, line: 24]\n" + 
5296
				"        [pc: 33, line: 25]\n" + 
5297
				"      Local variable table:\n" + 
5298
				"        [pc: 0, pc: 34] local: this index: 0 type: B\n" + 
5299
				"        [pc: 0, pc: 34] local: param index: 1 type: Value\n";
5300
5301
	try {
5302
		File f = new File(OUTPUT_DIR + File.separator + "B.class");
5303
		byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(f);
5304
		ClassFileBytesDisassembler disassembler = ToolFactory.createDefaultClassFileBytesDisassembler();
5305
		String result = disassembler.disassemble(classFileBytes, "\n", ClassFileBytesDisassembler.DETAILED);
5306
		int index = result.indexOf(expectedOutput);
5307
		if (index == -1 || expectedOutput.length() == 0) {
5308
			System.out.println(Util.displayString(result, 3));
5309
		}
5310
		if (index == -1) {
5311
			assertEquals("Wrong contents", expectedOutput, result);
5312
		}
5313
	} catch (org.eclipse.jdt.core.util.ClassFormatException e) {
5314
		assertTrue(false);
5315
	} catch (IOException e) {
5316
		assertTrue(false);
5317
	}			
5318
}
5319
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=159021 - variation
5320
public void test191() {
5321
	Map options = getCompilerOptions();
5322
	options.put(CompilerOptions.OPTION_PreserveUnusedLocal, CompilerOptions.OPTIMIZE_OUT);
5323
	this.runConformTest(
5324
		new String[] {
5325
			"X.java",
5326
			"interface I {\n" + 
5327
			"	Value CONST = A.foo(\"[I.CONST]\");\n" + 
5328
			"}\n" + 
5329
			"class Value {\n" + 
5330
			"	static String NAME = \"\";\n" + 
5331
			"	String v;\n" + 
5332
			"	Value(String v) {\n" + 
5333
			"		this.v = v;\n" + 
5334
			"	}\n" + 
5335
			"}\n" + 
5336
			"class A {\n" + 
5337
			"	static Value foo(String str) {\n" + 
5338
			"		System.out.print(str);\n" + 
5339
			"		return new Value(\"str\");\n" + 
5340
			"	}\n" + 
5341
			"}\n" + 
5342
			"class B implements I {\n" + 
5343
			"	static Value LOCAL_STATIC = A.foo(\"[B.LOCAL_STATIC]\");\n" + 
5344
			"	Value local_field = A.foo(\"[B.local_field]\");\n" + 
5345
			"	B(Value param) {\n" + 
5346
			"		String i = this.CONST.NAME; // keep for possible <clinit>\n" + 
5347
			"		String k = this.LOCAL_STATIC.NAME; // may optimize out\n" + 
5348
			"		String l = this.local_field.NAME; // may optimize out\n" + 
5349
			"	}\n" + 
5350
			"}\n" + 
5351
			"public class X {\n" + 
5352
			"	public static void main(String[] args) {\n" + 
5353
			"		new B(new Value(\"[PARAM]\"));\n" + 
5354
			"	}\n" + 
5355
			"}", // =================
5356
		}, 
5357
		"[B.LOCAL_STATIC][B.local_field][I.CONST]",
5358
		null,
5359
		false,
5360
		null,
5361
		options,
5362
		null);
5363
	// check the reference to I.CONST still got generated (for <clinit> invocation side-effect)
5364
	String expectedOutput = new CompilerOptions(options).complianceLevel < ClassFileConstants.JDK1_4
5365
			? 	"  // Method descriptor #26 (LValue;)V\n" + 
5366
				"  // Stack: 2, Locals: 2\n" + 
5367
				"  B(Value param);\n" + 
5368
				"     0  aload_0 [this]\n" + 
5369
				"     1  invokespecial java.lang.Object() [27]\n" + 
5370
				"     4  aload_0 [this]\n" + 
5371
				"     5  ldc <String \"[B.local_field]\"> [29]\n" + 
5372
				"     7  invokestatic A.foo(java.lang.String) : Value [15]\n" + 
5373
				"    10  putfield B.local_field : Value [31]\n" + 
5374
				"    13  getstatic I.CONST : Value [33]\n" + 
5375
				"    16  pop\n" + 
5376
				"    17  return\n" + 
5377
				"      Line numbers:\n" + 
5378
				"        [pc: 0, line: 20]\n" + 
5379
				"        [pc: 4, line: 19]\n" + 
5380
				"        [pc: 13, line: 21]\n" + 
5381
				"        [pc: 17, line: 24]\n" + 
5382
				"      Local variable table:\n" + 
5383
				"        [pc: 0, pc: 18] local: this index: 0 type: B\n" + 
5384
				"        [pc: 0, pc: 18] local: param index: 1 type: Value\n"
5385
			: 	"  // Method descriptor #26 (LValue;)V\n" + 
5386
				"  // Stack: 2, Locals: 2\n" + 
5387
				"  B(Value param);\n" + 
5388
				"     0  aload_0 [this]\n" + 
5389
				"     1  invokespecial java.lang.Object() [27]\n" + 
5390
				"     4  aload_0 [this]\n" + 
5391
				"     5  ldc <String \"[B.local_field]\"> [29]\n" + 
5392
				"     7  invokestatic A.foo(java.lang.String) : Value [15]\n" + 
5393
				"    10  putfield B.local_field : Value [31]\n" + 
5394
				"    13  getstatic B.CONST : Value [33]\n" + 
5395
				"    16  pop\n" + 
5396
				"    17  getstatic Value.NAME : java.lang.String [36]\n" + 
5397
				"    20  pop\n" + 
5398
				"    21  getstatic Value.NAME : java.lang.String [36]\n" + 
5399
				"    24  pop\n" + 
5400
				"    25  getstatic Value.NAME : java.lang.String [36]\n" + 
5401
				"    28  pop\n" + 
5402
				"    29  return\n" + 
5403
				"      Line numbers:\n" + 
5404
				"        [pc: 0, line: 20]\n" + 
5405
				"        [pc: 4, line: 19]\n" + 
5406
				"        [pc: 13, line: 21]\n" + 
5407
				"        [pc: 21, line: 22]\n" + 
5408
				"        [pc: 25, line: 23]\n" + 
5409
				"        [pc: 29, line: 24]\n" + 
5410
				"      Local variable table:\n" + 
5411
				"        [pc: 0, pc: 30] local: this index: 0 type: B\n" + 
5412
				"        [pc: 0, pc: 30] local: param index: 1 type: Value\n";
5413
5414
	try {
5415
		File f = new File(OUTPUT_DIR + File.separator + "B.class");
5416
		byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(f);
5417
		ClassFileBytesDisassembler disassembler = ToolFactory.createDefaultClassFileBytesDisassembler();
5418
		String result = disassembler.disassemble(classFileBytes, "\n", ClassFileBytesDisassembler.DETAILED);
5419
		int index = result.indexOf(expectedOutput);
5420
		if (index == -1 || expectedOutput.length() == 0) {
5421
			System.out.println(Util.displayString(result, 3));
5422
		}
5423
		if (index == -1) {
5424
			assertEquals("Wrong contents", expectedOutput, result);
5425
		}
5426
	} catch (org.eclipse.jdt.core.util.ClassFormatException e) {
5427
		assertTrue(false);
5428
	} catch (IOException e) {
5429
		assertTrue(false);
5430
	}			
5104
}
5431
}
5105
public static Class testClass() {
5432
public static Class testClass() {
5106
	return InitializationTest.class;
5433
	return InitializationTest.class;

Return to bug 159021