Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 338402 | Differences between
and this patch

Collapse All | Expand All

(-)compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java (-15 / +96 lines)
Lines 27-32 Link Here
27
27
28
	static final char[] SECRET_RETURN_ADDRESS_NAME = " returnAddress".toCharArray(); //$NON-NLS-1$
28
	static final char[] SECRET_RETURN_ADDRESS_NAME = " returnAddress".toCharArray(); //$NON-NLS-1$
29
	static final char[] SECRET_ANY_HANDLER_NAME = " anyExceptionHandler".toCharArray(); //$NON-NLS-1$
29
	static final char[] SECRET_ANY_HANDLER_NAME = " anyExceptionHandler".toCharArray(); //$NON-NLS-1$
30
	static final char[] SECRET_PRIMARY_EXCEPTION_VARIABLE_NAME = " primaryException".toCharArray(); //$NON-NLS-1$
31
	static final char[] SECRET_TEMPORARY_THROWABLE_VARIABLE_NAME = " temporaryThrowable".toCharArray(); //$NON-NLS-1$;
30
	static final char[] SECRET_RETURN_VALUE_NAME = " returnValue".toCharArray(); //$NON-NLS-1$
32
	static final char[] SECRET_RETURN_VALUE_NAME = " returnValue".toCharArray(); //$NON-NLS-1$
31
33
32
	private static LocalDeclaration [] NO_RESOURCES = new LocalDeclaration[0];
34
	private static LocalDeclaration [] NO_RESOURCES = new LocalDeclaration[0];
Lines 69-74 Link Here
69
	int preTryInitStateIndex = -1;
71
	int preTryInitStateIndex = -1;
70
	int naturalExitMergeInitStateIndex = -1;
72
	int naturalExitMergeInitStateIndex = -1;
71
	int[] catchExitInitStateIndexes;
73
	int[] catchExitInitStateIndexes;
74
	private LocalVariableBinding primaryExceptionVariable;
75
	private LocalVariableBinding temporaryThrowableVariable;
76
	private ExceptionLabel[] resourceBlockLabels;
72
77
73
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
78
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
74
79
Lines 85-90 Link Here
85
	if (this.anyExceptionVariable != null) {
90
	if (this.anyExceptionVariable != null) {
86
		this.anyExceptionVariable.useFlag = LocalVariableBinding.USED;
91
		this.anyExceptionVariable.useFlag = LocalVariableBinding.USED;
87
	}
92
	}
93
	if (this.primaryExceptionVariable != null) {
94
		this.primaryExceptionVariable.useFlag = LocalVariableBinding.USED;
95
	}
96
	if (this.temporaryThrowableVariable != null) {
97
		this.temporaryThrowableVariable.useFlag = LocalVariableBinding.USED;
98
	}
88
	if (this.returnAddressVariable != null) { // TODO (philippe) if subroutine is escaping, unused
99
	if (this.returnAddressVariable != null) { // TODO (philippe) if subroutine is escaping, unused
89
		this.returnAddressVariable.useFlag = LocalVariableBinding.USED;
100
		this.returnAddressVariable.useFlag = LocalVariableBinding.USED;
90
	}
101
	}
Lines 106-111 Link Here
106
117
107
		for (int i = 0, max = this.resources.length; i < max; i++) {
118
		for (int i = 0, max = this.resources.length; i < max; i++) {
108
			flowInfo = this.resources[i].analyseCode(currentScope, handlingContext, flowInfo.copy());
119
			flowInfo = this.resources[i].analyseCode(currentScope, handlingContext, flowInfo.copy());
120
			this.resources[i].binding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways.
109
			TypeBinding type = this.resources[i].binding.type;
121
			TypeBinding type = this.resources[i].binding.type;
110
			if (type != null && type.isValidBinding()) {
122
			if (type != null && type.isValidBinding()) {
111
				ReferenceBinding binding = (ReferenceBinding) type;
123
				ReferenceBinding binding = (ReferenceBinding) type;
Lines 229-234 Link Here
229
241
230
		for (int i = 0, max = this.resources.length; i < max; i++) {
242
		for (int i = 0, max = this.resources.length; i < max; i++) {
231
			flowInfo = this.resources[i].analyseCode(currentScope, handlingContext, flowInfo.copy());
243
			flowInfo = this.resources[i].analyseCode(currentScope, handlingContext, flowInfo.copy());
244
			this.resources[i].binding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways.
232
			TypeBinding type = this.resources[i].binding.type;
245
			TypeBinding type = this.resources[i].binding.type;
233
			if (type != null && type.isValidBinding()) {
246
			if (type != null && type.isValidBinding()) {
234
				ReferenceBinding binding = (ReferenceBinding) type;
247
				ReferenceBinding binding = (ReferenceBinding) type;
Lines 425-431 Link Here
425
	// generate the try block
438
	// generate the try block
426
	try {
439
	try {
427
		this.declaredExceptionLabels = exceptionLabels;
440
		this.declaredExceptionLabels = exceptionLabels;
441
		int resourceCount = this.resources.length;
442
		if (resourceCount > 0) {
443
			this.resourceBlockLabels = new ExceptionLabel[resourceCount + 1];
444
			codeStream.aconst_null();
445
			codeStream.store(this.primaryExceptionVariable, false /* value not required */);
446
			codeStream.addVariable(this.primaryExceptionVariable);
447
			codeStream.aconst_null();
448
			codeStream.store(this.temporaryThrowableVariable, false /* value not required */);
449
			codeStream.addVariable(this.temporaryThrowableVariable);
450
			for (int i = 0; i <= resourceCount; i++) {
451
				this.resourceBlockLabels[i] = new ExceptionLabel(codeStream, this.scope.getJavaLangThrowable());
452
				this.resourceBlockLabels[i].placeStart();
453
				if (i < resourceCount) {
454
					this.resources[i].generateCode(this.scope, codeStream);
455
				}
456
			}
457
		}
428
		this.tryBlock.generateCode(this.scope, codeStream);
458
		this.tryBlock.generateCode(this.scope, codeStream);
459
		if (resourceCount > 0) {
460
			for (int i = resourceCount; i >= 0; i--) {
461
				BranchLabel exitLabel = new BranchLabel(codeStream);
462
				this.resourceBlockLabels[i].placeEnd();
463
				
464
				LocalVariableBinding localVariable = i > 0 ? this.resources[i-1].binding : null;
465
				if ((this.bits & ASTNode.IsTryBlockExiting) == 0) {
466
					if (i > 0) {
467
						codeStream.load(localVariable);
468
				    	codeStream.ifnull(exitLabel);
469
				    	codeStream.load(localVariable);
470
				    	codeStream.invokeAutoCloseableClose(localVariable.type);
471
				    }
472
					codeStream.goto_(exitLabel);
473
				}
474
				codeStream.pushExceptionOnStack(this.scope.getJavaLangThrowable());
475
				this.resourceBlockLabels[i].place();
476
				BranchLabel elseLabel = new BranchLabel(codeStream), postElseLabel = new BranchLabel(codeStream);
477
				codeStream.store(this.temporaryThrowableVariable, false);
478
				codeStream.load(this.primaryExceptionVariable);
479
				codeStream.ifnonnull(elseLabel);
480
				codeStream.load(this.temporaryThrowableVariable);
481
				codeStream.store(this.primaryExceptionVariable, false);
482
				codeStream.goto_(postElseLabel);
483
				elseLabel.place();
484
				codeStream.load(this.primaryExceptionVariable);
485
				codeStream.load(this.temporaryThrowableVariable);
486
				codeStream.if_acmpeq(postElseLabel);
487
				codeStream.load(this.primaryExceptionVariable);
488
				codeStream.load(this.temporaryThrowableVariable);
489
				codeStream.invokeThrowableAddSuppressed();
490
				postElseLabel.place();
491
				if (i > 0) {
492
					// inline resource close here rather than bracketing the current catch block with a try region.
493
					BranchLabel postCloseLabel = new BranchLabel(codeStream);
494
					codeStream.load(localVariable);
495
					codeStream.ifnull(postCloseLabel);
496
					codeStream.load(localVariable);
497
					codeStream.invokeAutoCloseableClose(localVariable.type);
498
					codeStream.removeVariable(localVariable);
499
					postCloseLabel.place();
500
				}
501
				codeStream.load(this.primaryExceptionVariable);
502
				codeStream.athrow();
503
				exitLabel.place();
504
			}
505
			codeStream.removeVariable(this.primaryExceptionVariable);
506
			codeStream.removeVariable(this.temporaryThrowableVariable);
507
		}
429
	} finally {
508
	} finally {
430
		this.declaredExceptionLabels = null;
509
		this.declaredExceptionLabels = null;
431
	}
510
	}
Lines 806-816 Link Here
806
	this.scope = new BlockScope(upperScope);
885
	this.scope = new BlockScope(upperScope);
807
886
808
	BlockScope finallyScope = null;
887
	BlockScope finallyScope = null;
809
888
    BlockScope resourceManagementScope = null;
810
	// resolve all resources and inject them into separate scopes
889
	int resourceCount = this.resources.length;
811
	BlockScope localScope = new BlockScope(this.scope);
890
	if (resourceCount > 0) {
812
	for (int i = 0, max = this.resources.length; i < max; i++) {
891
		resourceManagementScope = new BlockScope(this.scope);
813
		this.resources[i].resolve(localScope);
892
		this.primaryExceptionVariable =
893
			new LocalVariableBinding(TryStatement.SECRET_PRIMARY_EXCEPTION_VARIABLE_NAME, this.scope.getJavaLangThrowable(), ClassFileConstants.AccDefault, false);
894
		resourceManagementScope.addLocalVariable(this.primaryExceptionVariable);
895
		this.primaryExceptionVariable.setConstant(Constant.NotAConstant); // not inlinable
896
		this.temporaryThrowableVariable =
897
			new LocalVariableBinding(TryStatement.SECRET_TEMPORARY_THROWABLE_VARIABLE_NAME, this.scope.getJavaLangThrowable(), ClassFileConstants.AccDefault, false);
898
		resourceManagementScope.addLocalVariable(this.temporaryThrowableVariable);
899
		this.temporaryThrowableVariable.setConstant(Constant.NotAConstant); // not inlinable
900
	}
901
	for (int i = 0; i < resourceCount; i++) {
902
		this.resources[i].resolve(resourceManagementScope);
814
		LocalVariableBinding localVariableBinding = this.resources[i].binding;
903
		LocalVariableBinding localVariableBinding = this.resources[i].binding;
815
		if (localVariableBinding != null && localVariableBinding.isValidBinding()) {
904
		if (localVariableBinding != null && localVariableBinding.isValidBinding()) {
816
			localVariableBinding.modifiers |= ClassFileConstants.AccFinal;
905
			localVariableBinding.modifiers |= ClassFileConstants.AccFinal;
Lines 826-834 Link Here
826
				localVariableBinding.type = new ProblemReferenceBinding(CharOperation.splitOn('.', resourceType.shortReadableName()), null, ProblemReasons.InvalidTypeForAutoManagedResource);
915
				localVariableBinding.type = new ProblemReferenceBinding(CharOperation.splitOn('.', resourceType.shortReadableName()), null, ProblemReasons.InvalidTypeForAutoManagedResource);
827
			}
916
			}
828
		}
917
		}
829
		localScope = new BlockScope(localScope, 1);
830
	}
918
	}
831
	BlockScope tryScope = localScope;
919
	BlockScope tryScope = new BlockScope(resourceManagementScope != null ? resourceManagementScope : this.scope);
832
920
833
	if (this.finallyBlock != null) {
921
	if (this.finallyBlock != null) {
834
		if (this.finallyBlock.isEmptyBlock()) {
922
		if (this.finallyBlock.isEmptyBlock()) {
Lines 875-889 Link Here
875
			this.finallyBlock.resolveUsing(finallyScope);
963
			this.finallyBlock.resolveUsing(finallyScope);
876
			// force the finally scope to have variable positions shifted after its try scope and catch ones
964
			// force the finally scope to have variable positions shifted after its try scope and catch ones
877
			int shiftScopesLength = this.catchArguments == null ? 1 : this.catchArguments.length + 1;
965
			int shiftScopesLength = this.catchArguments == null ? 1 : this.catchArguments.length + 1;
878
			shiftScopesLength += this.resources.length;
879
			finallyScope.shiftScopes = new BlockScope[shiftScopesLength];
966
			finallyScope.shiftScopes = new BlockScope[shiftScopesLength];
880
			for (int i = 0, max = this.resources.length; i < max; i++) {
967
			finallyScope.shiftScopes[0] = tryScope;
881
				LocalVariableBinding localVariableBinding = this.resources[i].binding;
882
				if (localVariableBinding != null && localVariableBinding.isValidBinding()) {
883
					finallyScope.shiftScopes[i] = localVariableBinding.declaringScope;
884
				}
885
			}
886
			finallyScope.shiftScopes[this.resources.length] = tryScope;
887
		}
968
		}
888
	}
969
	}
889
	this.tryBlock.resolveUsing(tryScope);
970
	this.tryBlock.resolveUsing(tryScope);
(-)compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java (+20 lines)
Lines 4030-4035 Link Here
4030
			ConstantPool.ITERATOR_SIGNATURE);
4030
			ConstantPool.ITERATOR_SIGNATURE);
4031
}
4031
}
4032
4032
4033
public void invokeAutoCloseableClose(TypeBinding resourceType) {
4034
	// invokevirtual/interface: <resourceType>.close()
4035
	invoke(
4036
			resourceType.isInterface() ? Opcodes.OPC_invokeinterface : Opcodes.OPC_invokevirtual,
4037
			1, // receiverAndArgsSize
4038
			0, // returnTypeSize
4039
			resourceType.constantPoolName(), 
4040
			ConstantPool.Close, 
4041
			ConstantPool.CloseSignature);
4042
}
4043
4044
public void invokeThrowableAddSuppressed() {
4045
	invoke(Opcodes.OPC_invokevirtual,
4046
			2, // receiverAndArgsSize
4047
			0, // returnTypeSize
4048
			ConstantPool.JavaLangThrowableConstantPoolName,
4049
			ConstantPool.AddSuppressed, 
4050
			ConstantPool.AddSuppressedSignature);
4051
}
4052
4033
public void invokeJavaLangAssertionErrorConstructor(int typeBindingID) {
4053
public void invokeJavaLangAssertionErrorConstructor(int typeBindingID) {
4034
	// invokespecial: java.lang.AssertionError.<init>(typeBindingID)V
4054
	// invokespecial: java.lang.AssertionError.<init>(typeBindingID)V
4035
	int receiverAndArgsSize;
4055
	int receiverAndArgsSize;
(-)compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java (+3 lines)
Lines 76-81 Link Here
76
	public static final char[] DefaultConstructorSignature = "()V".toCharArray(); //$NON-NLS-1$
76
	public static final char[] DefaultConstructorSignature = "()V".toCharArray(); //$NON-NLS-1$
77
	public static final char[] ClinitSignature = DefaultConstructorSignature;
77
	public static final char[] ClinitSignature = DefaultConstructorSignature;
78
	public static final char[] Close = "close".toCharArray(); //$NON-NLS-1$
78
	public static final char[] Close = "close".toCharArray(); //$NON-NLS-1$
79
	public static final char[] CloseSignature = "()V".toCharArray(); //$NON-NLS-1$
79
	public static final char[] DesiredAssertionStatus = "desiredAssertionStatus".toCharArray(); //$NON-NLS-1$
80
	public static final char[] DesiredAssertionStatus = "desiredAssertionStatus".toCharArray(); //$NON-NLS-1$
80
	public static final char[] DesiredAssertionStatusSignature = "()Z".toCharArray(); //$NON-NLS-1$
81
	public static final char[] DesiredAssertionStatusSignature = "()Z".toCharArray(); //$NON-NLS-1$
81
	public static final char[] DoubleConstrSignature = "(D)V".toCharArray(); //$NON-NLS-1$
82
	public static final char[] DoubleConstrSignature = "(D)V".toCharArray(); //$NON-NLS-1$
Lines 256-261 Link Here
256
	public static final char[] HashCodeSignature = "()I".toCharArray(); //$NON-NLS-1$; 
257
	public static final char[] HashCodeSignature = "()I".toCharArray(); //$NON-NLS-1$; 
257
	public static final char[] Equals = "equals".toCharArray(); //$NON-NLS-1$
258
	public static final char[] Equals = "equals".toCharArray(); //$NON-NLS-1$
258
	public static final char[] EqualsSignature = "(Ljava/lang/Object;)Z".toCharArray(); //$NON-NLS-1$; 
259
	public static final char[] EqualsSignature = "(Ljava/lang/Object;)Z".toCharArray(); //$NON-NLS-1$; 
260
	public static final char[] AddSuppressed = "addSuppressed".toCharArray(); //$NON-NLS-1$;
261
	public static final char[] AddSuppressedSignature = "(Ljava/lang/Throwable;)V".toCharArray(); //$NON-NLS-1$
259
	/**
262
	/**
260
	 * ConstantPool constructor comment.
263
	 * ConstantPool constructor comment.
261
	 */
264
	 */
(-)src/org/eclipse/jdt/core/tests/compiler/regression/TryWithResourcesStatementTest.java (-3 / +81 lines)
Lines 147-164 Link Here
147
}
147
}
148
//check that try statement can be empty
148
//check that try statement can be empty
149
public void test006() {
149
public void test006() {
150
	this.runConformTest(
150
	this.runNegativeTest( // cannot be a conform test as this triggers an AIOOB.
151
		new String[] {
151
		new String[] {
152
			"X.java",
152
			"X.java",
153
			"import java.io.*;\n" + 
153
			"import java.io.*;\n" + 
154
			"public class X {\n" + 
154
			"public class X {\n" + 
155
			"	public static void main(String[] args) throws IOException {\n" + 
155
			"	public static void main(String[] args) throws IOException {\n" + 
156
			"		try (Reader r = new LineNumberReader(new BufferedReader(new FileReader(args[0])))) {\n" + 
156
			"		try (Reader r = new LineNumberReader(new BufferedReader(new FileReader(args[0])))) {\n" + 
157
			"		}\n" + 
157
			"		} catch(Zork z) {" +
158
			"       }\n" + 
158
			"	}\n" + 
159
			"	}\n" + 
159
			"}",
160
			"}",
160
		},
161
		},
161
		"");
162
		"----------\n" + 
163
		"1. ERROR in X.java (at line 5)\n" + 
164
		"	} catch(Zork z) {       }\n" + 
165
		"	        ^^^^\n" + 
166
		"Zork cannot be resolved to a type\n" + 
167
		"----------\n");
162
}
168
}
163
//check that resources are implicitly final but they can be explicitly final 
169
//check that resources are implicitly final but they can be explicitly final 
164
public void test007() {
170
public void test007() {
Lines 966-971 Link Here
966
		"The serializable class ZZException does not declare a static final serialVersionUID field of type long\n" + 
972
		"The serializable class ZZException does not declare a static final serialVersionUID field of type long\n" + 
967
		"----------\n");
973
		"----------\n");
968
}
974
}
975
public void _test027() {
976
	this.runConformTest(
977
		new String[] {
978
			"X.java",
979
			"public class X implements AutoCloseable {\n" +
980
			"	public static void main(String [] args) throws Exception {\n" +
981
			"		try (X x = new X(); Y y = new Y()) {\n" +
982
			"			System.out.println(\"Body\");\n" +
983
			"			throw new Exception(\"Body\");\n" +
984
			"		} catch (Exception e) {\n" +
985
			"			e.printStackTrace(System.out);\n" +
986
			"			Throwable [] suppressed = e.getSuppressed();\n" +
987
			"           if (suppressed.length == 0) System.out.println(\"Nothing suppressed\");\n" +
988
			"			for (int i = 0; i < suppressed.length; i++) {\n" +
989
			"				System.out.println(\"Suppressed:\" + suppressed[i]);\n" +
990
			"			}\n" +
991
			"		} finally {\n" +
992
			"			int finallyVar = 10;\n" +
993
			"			System.out.println(finallyVar);\n" +
994
			"		}\n" +
995
			"	}\n" +
996
			"	public X() {\n" +
997
			"	    System.out.println(\"X CTOR\");\n" +
998
			"	}\n" +
999
			"	public void close() throws Exception {\n" +
1000
			"	    System.out.println(\"X Close\");\n" +
1001
			"	    throw new Exception(\"X Close\");\n" +
1002
			"	}\n" +
1003
			"}\n" +
1004
			"\n" +
1005
			"class Y implements AutoCloseable {\n" +
1006
			"	public Y() {\n" +
1007
			"	    System.out.println(\"Y CTOR\");\n" +
1008
			"	}\n" +
1009
			"	public void close() throws Exception {\n" +
1010
			"	    System.out.println(\"Y Close\");\n" +
1011
			"	    throw new Exception(\"Y Close\");\n" +
1012
			"	}\n" +
1013
			"}\n"
1014
		},
1015
		"----------\n" + 
1016
		"1. WARNING in X.java (at line 37)\n" + 
1017
		"	class XException extends Exception {}\n" + 
1018
		"	      ^^^^^^^^^^\n" + 
1019
		"The serializable class XException does not declare a static final serialVersionUID field of type long\n" + 
1020
		"----------\n" + 
1021
		"2. WARNING in X.java (at line 38)\n" + 
1022
		"	class XXException extends Exception {}\n" + 
1023
		"	      ^^^^^^^^^^^\n" + 
1024
		"The serializable class XXException does not declare a static final serialVersionUID field of type long\n" + 
1025
		"----------\n" + 
1026
		"3. WARNING in X.java (at line 39)\n" + 
1027
		"	class YException extends Exception {}\n" + 
1028
		"	      ^^^^^^^^^^\n" + 
1029
		"The serializable class YException does not declare a static final serialVersionUID field of type long\n" + 
1030
		"----------\n" + 
1031
		"4. WARNING in X.java (at line 40)\n" + 
1032
		"	class YYException extends Exception {}\n" + 
1033
		"	      ^^^^^^^^^^^\n" + 
1034
		"The serializable class YYException does not declare a static final serialVersionUID field of type long\n" + 
1035
		"----------\n" + 
1036
		"5. WARNING in X.java (at line 41)\n" + 
1037
		"	class ZException extends Exception {}\n" + 
1038
		"	      ^^^^^^^^^^\n" + 
1039
		"The serializable class ZException does not declare a static final serialVersionUID field of type long\n" + 
1040
		"----------\n" + 
1041
		"6. WARNING in X.java (at line 42)\n" + 
1042
		"	class ZZException extends Exception {}\n" + 
1043
		"	      ^^^^^^^^^^^\n" + 
1044
		"The serializable class ZZException does not declare a static final serialVersionUID field of type long\n" + 
1045
		"----------\n");
1046
}
969
public static Class testClass() {
1047
public static Class testClass() {
970
	return TryWithResourcesStatementTest.class;
1048
	return TryWithResourcesStatementTest.class;
971
}
1049
}

Return to bug 338402