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 (-32 / +57 lines)
Lines 28-34 Link Here
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$
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$;
31
	static final char[] SECRET_CAUGHT_THROWABLE_VARIABLE_NAME = " caughtThrowable".toCharArray(); //$NON-NLS-1$;
32
	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$
33
33
34
	private static LocalDeclaration [] NO_RESOURCES = new LocalDeclaration[0];
34
	private static LocalDeclaration [] NO_RESOURCES = new LocalDeclaration[0];
Lines 72-79 Link Here
72
	int naturalExitMergeInitStateIndex = -1;
72
	int naturalExitMergeInitStateIndex = -1;
73
	int[] catchExitInitStateIndexes;
73
	int[] catchExitInitStateIndexes;
74
	private LocalVariableBinding primaryExceptionVariable;
74
	private LocalVariableBinding primaryExceptionVariable;
75
	private LocalVariableBinding temporaryThrowableVariable;
75
	private LocalVariableBinding caughtThrowableVariable;
76
	private ExceptionLabel[] resourceBlockLabels;
76
	private ExceptionLabel[] resourceExceptionLabels;
77
77
78
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
78
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
79
79
Lines 93-100 Link Here
93
	if (this.primaryExceptionVariable != null) {
93
	if (this.primaryExceptionVariable != null) {
94
		this.primaryExceptionVariable.useFlag = LocalVariableBinding.USED;
94
		this.primaryExceptionVariable.useFlag = LocalVariableBinding.USED;
95
	}
95
	}
96
	if (this.temporaryThrowableVariable != null) {
96
	if (this.caughtThrowableVariable != null) {
97
		this.temporaryThrowableVariable.useFlag = LocalVariableBinding.USED;
97
		this.caughtThrowableVariable.useFlag = LocalVariableBinding.USED;
98
	}
98
	}
99
	if (this.returnAddressVariable != null) { // TODO (philippe) if subroutine is escaping, unused
99
	if (this.returnAddressVariable != null) { // TODO (philippe) if subroutine is escaping, unused
100
		this.returnAddressVariable.useFlag = LocalVariableBinding.USED;
100
		this.returnAddressVariable.useFlag = LocalVariableBinding.USED;
Lines 440-455 Link Here
440
		this.declaredExceptionLabels = exceptionLabels;
440
		this.declaredExceptionLabels = exceptionLabels;
441
		int resourceCount = this.resources.length;
441
		int resourceCount = this.resources.length;
442
		if (resourceCount > 0) {
442
		if (resourceCount > 0) {
443
			this.resourceBlockLabels = new ExceptionLabel[resourceCount + 1];
443
			this.resourceExceptionLabels = new ExceptionLabel[resourceCount + 1];
444
			codeStream.aconst_null();
444
			codeStream.aconst_null();
445
			codeStream.store(this.primaryExceptionVariable, false /* value not required */);
445
			codeStream.store(this.primaryExceptionVariable, false /* value not required */);
446
			codeStream.addVariable(this.primaryExceptionVariable);
446
			codeStream.addVariable(this.primaryExceptionVariable);
447
			codeStream.aconst_null();
447
			codeStream.aconst_null();
448
			codeStream.store(this.temporaryThrowableVariable, false /* value not required */);
448
			codeStream.store(this.caughtThrowableVariable, false /* value not required */);
449
			codeStream.addVariable(this.temporaryThrowableVariable);
449
			codeStream.addVariable(this.caughtThrowableVariable);
450
			for (int i = 0; i <= resourceCount; i++) {
450
			for (int i = 0; i <= resourceCount; i++) {
451
				this.resourceBlockLabels[i] = new ExceptionLabel(codeStream, this.scope.getJavaLangThrowable());
451
				this.resourceExceptionLabels[i] = new ExceptionLabel(codeStream, this.scope.getJavaLangThrowable());
452
				this.resourceBlockLabels[i].placeStart();
452
				this.resourceExceptionLabels[i].placeStart();
453
				if (i < resourceCount) {
453
				if (i < resourceCount) {
454
					this.resources[i].generateCode(this.scope, codeStream);
454
					this.resources[i].generateCode(this.scope, codeStream);
455
				}
455
				}
Lines 459-465 Link Here
459
		if (resourceCount > 0) {
459
		if (resourceCount > 0) {
460
			for (int i = resourceCount; i >= 0; i--) {
460
			for (int i = resourceCount; i >= 0; i--) {
461
				BranchLabel exitLabel = new BranchLabel(codeStream);
461
				BranchLabel exitLabel = new BranchLabel(codeStream);
462
				this.resourceBlockLabels[i].placeEnd();
462
				this.resourceExceptionLabels[i].placeEnd();
463
				
463
				
464
				LocalVariableBinding localVariable = i > 0 ? this.resources[i-1].binding : null;
464
				LocalVariableBinding localVariable = i > 0 ? this.resources[i-1].binding : null;
465
				if ((this.bits & ASTNode.IsTryBlockExiting) == 0) {
465
				if ((this.bits & ASTNode.IsTryBlockExiting) == 0) {
Lines 472-493 Link Here
472
					codeStream.goto_(exitLabel);
472
					codeStream.goto_(exitLabel);
473
				}
473
				}
474
				codeStream.pushExceptionOnStack(this.scope.getJavaLangThrowable());
474
				codeStream.pushExceptionOnStack(this.scope.getJavaLangThrowable());
475
				this.resourceBlockLabels[i].place();
475
				this.resourceExceptionLabels[i].place();
476
				BranchLabel elseLabel = new BranchLabel(codeStream), postElseLabel = new BranchLabel(codeStream);
476
				if (i == resourceCount) { 
477
				codeStream.store(this.temporaryThrowableVariable, false);
477
					// inner most try's catch/finally can be a lot simpler. 
478
				codeStream.load(this.primaryExceptionVariable);
478
					codeStream.store(this.primaryExceptionVariable, false);
479
				codeStream.ifnonnull(elseLabel);
479
					// fall through, invoke close() and re-throw.
480
				codeStream.load(this.temporaryThrowableVariable);
480
				} else {
481
				codeStream.store(this.primaryExceptionVariable, false);
481
					BranchLabel elseLabel = new BranchLabel(codeStream), postElseLabel = new BranchLabel(codeStream);
482
				codeStream.goto_(postElseLabel);
482
					codeStream.store(this.caughtThrowableVariable, false);
483
				elseLabel.place();
483
					codeStream.load(this.primaryExceptionVariable);
484
				codeStream.load(this.primaryExceptionVariable);
484
					codeStream.ifnonnull(elseLabel);
485
				codeStream.load(this.temporaryThrowableVariable);
485
					codeStream.load(this.caughtThrowableVariable);
486
				codeStream.if_acmpeq(postElseLabel);
486
					codeStream.store(this.primaryExceptionVariable, false);
487
				codeStream.load(this.primaryExceptionVariable);
487
					codeStream.goto_(postElseLabel);
488
				codeStream.load(this.temporaryThrowableVariable);
488
					elseLabel.place();
489
				codeStream.invokeThrowableAddSuppressed();
489
					codeStream.load(this.primaryExceptionVariable);
490
				postElseLabel.place();
490
					codeStream.load(this.caughtThrowableVariable);
491
					codeStream.if_acmpeq(postElseLabel);
492
					codeStream.load(this.primaryExceptionVariable);
493
					codeStream.load(this.caughtThrowableVariable);
494
					codeStream.invokeThrowableAddSuppressed();
495
					postElseLabel.place();
496
				}
491
				if (i > 0) {
497
				if (i > 0) {
492
					// inline resource close here rather than bracketing the current catch block with a try region.
498
					// inline resource close here rather than bracketing the current catch block with a try region.
493
					BranchLabel postCloseLabel = new BranchLabel(codeStream);
499
					BranchLabel postCloseLabel = new BranchLabel(codeStream);
Lines 503-509 Link Here
503
				exitLabel.place();
509
				exitLabel.place();
504
			}
510
			}
505
			codeStream.removeVariable(this.primaryExceptionVariable);
511
			codeStream.removeVariable(this.primaryExceptionVariable);
506
			codeStream.removeVariable(this.temporaryThrowableVariable);
512
			codeStream.removeVariable(this.caughtThrowableVariable);
507
		}
513
		}
508
	} finally {
514
	} finally {
509
		this.declaredExceptionLabels = null;
515
		this.declaredExceptionLabels = null;
Lines 755-760 Link Here
755
 */
761
 */
756
public boolean generateSubRoutineInvocation(BlockScope currentScope, CodeStream codeStream, Object targetLocation, int stateIndex, LocalVariableBinding secretLocal) {
762
public boolean generateSubRoutineInvocation(BlockScope currentScope, CodeStream codeStream, Object targetLocation, int stateIndex, LocalVariableBinding secretLocal) {
757
763
764
	int resourceCount = this.resources.length;
765
	if (resourceCount > 0) {
766
		for (int i = resourceCount; i > 0; --i) {
767
			// disarm the handlers and take care of resource closure.
768
			this.resourceExceptionLabels[i].placeEnd();
769
			LocalVariableBinding localVariable = this.resources[i-1].binding;
770
			BranchLabel exitLabel = new BranchLabel(codeStream);
771
			codeStream.load(localVariable);
772
			codeStream.ifnull(exitLabel);
773
			codeStream.load(localVariable);
774
			codeStream.invokeAutoCloseableClose(localVariable.type);
775
			exitLabel.place();
776
		}
777
		// restore handlers
778
		for (int i = resourceCount; i > 0; --i) {
779
			this.resourceExceptionLabels[i].placeStart();
780
		}
781
	}
782
758
	boolean isStackMapFrameCodeStream = codeStream instanceof StackMapFrameCodeStream;
783
	boolean isStackMapFrameCodeStream = codeStream instanceof StackMapFrameCodeStream;
759
	int finallyMode = finallyMode();
784
	int finallyMode = finallyMode();
760
	switch(finallyMode) {
785
	switch(finallyMode) {
Lines 893-902 Link Here
893
			new LocalVariableBinding(TryStatement.SECRET_PRIMARY_EXCEPTION_VARIABLE_NAME, this.scope.getJavaLangThrowable(), ClassFileConstants.AccDefault, false);
918
			new LocalVariableBinding(TryStatement.SECRET_PRIMARY_EXCEPTION_VARIABLE_NAME, this.scope.getJavaLangThrowable(), ClassFileConstants.AccDefault, false);
894
		resourceManagementScope.addLocalVariable(this.primaryExceptionVariable);
919
		resourceManagementScope.addLocalVariable(this.primaryExceptionVariable);
895
		this.primaryExceptionVariable.setConstant(Constant.NotAConstant); // not inlinable
920
		this.primaryExceptionVariable.setConstant(Constant.NotAConstant); // not inlinable
896
		this.temporaryThrowableVariable =
921
		this.caughtThrowableVariable =
897
			new LocalVariableBinding(TryStatement.SECRET_TEMPORARY_THROWABLE_VARIABLE_NAME, this.scope.getJavaLangThrowable(), ClassFileConstants.AccDefault, false);
922
			new LocalVariableBinding(TryStatement.SECRET_CAUGHT_THROWABLE_VARIABLE_NAME, this.scope.getJavaLangThrowable(), ClassFileConstants.AccDefault, false);
898
		resourceManagementScope.addLocalVariable(this.temporaryThrowableVariable);
923
		resourceManagementScope.addLocalVariable(this.caughtThrowableVariable);
899
		this.temporaryThrowableVariable.setConstant(Constant.NotAConstant); // not inlinable
924
		this.caughtThrowableVariable.setConstant(Constant.NotAConstant); // not inlinable
900
	}
925
	}
901
	for (int i = 0; i < resourceCount; i++) {
926
	for (int i = 0; i < resourceCount; i++) {
902
		this.resources[i].resolve(resourceManagementScope);
927
		this.resources[i].resolve(resourceManagementScope);
(-)src/org/eclipse/jdt/core/tests/compiler/regression/TryWithResourcesStatementTest.java (+208 lines)
Lines 1079-1084 Link Here
1079
		},
1079
		},
1080
		"Got IO exception");
1080
		"Got IO exception");
1081
}
1081
}
1082
public void test030() {  // test return + resources
1083
	this.runConformTest(
1084
		new String[] {
1085
			"X.java",
1086
			"public class X implements AutoCloseable {\n" +
1087
			"    public static void main(String [] args) throws Exception { \n" +
1088
			"    	final boolean getOut = true;\n" +
1089
			"    	System.out.println(\"Main\");\n" +
1090
			"    	try (X x1 = new X(); X x2 = new X()) {\n" +
1091
			"            System.out.println(\"Outer Try\");\n" +
1092
			"            while (true) {\n" +
1093
			"            	try (Y y1 = new Y(); Y y2 = new Y()) {\n" +
1094
			"            		System.out.println(\"Middle Try\");\n" +
1095
			"            		try (Z z1 = new Z(); Z z2 = new Z()) {\n" +
1096
			"            			System.out.println(\"Inner Try\");\n" +
1097
			"            			if (getOut) \n" +
1098
			"            				return;\n" +
1099
			"            			else\n" +
1100
			"            				break;\n" +
1101
			"            		}\n" +
1102
			"            	}\n" +
1103
			"            }\n" +
1104
			"            System.out.println(\"Out of while\");\n" +
1105
			"        }\n" +
1106
			"    }\n" +
1107
			"    public X() {\n" +
1108
			"        System.out.println(\"X::X\");\n" +
1109
			"    }\n" +
1110
			"    public void close() throws Exception {\n" +
1111
			"        System.out.println(\"X::~X\");\n" +
1112
			"    }\n" +
1113
			"}\n" +
1114
			"class Y implements AutoCloseable {\n" +
1115
			"    public Y() {\n" +
1116
			"        System.out.println(\"Y::Y\");\n" +
1117
			"    }\n" +
1118
			"    public void close() throws Exception {\n" +
1119
			"        System.out.println(\"Y::~Y\");\n" +
1120
			"    }\n" +
1121
			"}\n" +
1122
			"class Z implements AutoCloseable {\n" +
1123
			"    public Z() {\n" +
1124
			"        System.out.println(\"Z::Z\");\n" +
1125
			"    }\n" +
1126
			"    public void close() throws Exception {\n" +
1127
			"        System.out.println(\"Z::~Z\");\n" +
1128
			"    }\n" +
1129
			"}\n"
1130
		},
1131
		"Main\n" + 
1132
		"X::X\n" + 
1133
		"X::X\n" + 
1134
		"Outer Try\n" + 
1135
		"Y::Y\n" + 
1136
		"Y::Y\n" + 
1137
		"Middle Try\n" + 
1138
		"Z::Z\n" + 
1139
		"Z::Z\n" + 
1140
		"Inner Try\n" + 
1141
		"Z::~Z\n" + 
1142
		"Z::~Z\n" + 
1143
		"Y::~Y\n" + 
1144
		"Y::~Y\n" + 
1145
		"X::~X\n" + 
1146
		"X::~X");
1147
}
1148
public void test031() { // test break + resources
1149
	this.runConformTest(
1150
		new String[] {
1151
			"X.java",
1152
			"public class X implements AutoCloseable {\n" +
1153
			"    public static void main(String [] args) throws Exception { \n" +
1154
			"    	final boolean getOut = false;\n" +
1155
			"    	System.out.println(\"Main\");\n" +
1156
			"    	try (X x1 = new X(); X x2 = new X()) {\n" +
1157
			"            System.out.println(\"Outer Try\");\n" +
1158
			"            while (true) {\n" +
1159
			"            	try (Y y1 = new Y(); Y y2 = new Y()) {\n" +
1160
			"            		System.out.println(\"Middle Try\");\n" +
1161
			"            		try (Z z1 = new Z(); Z z2 = new Z()) {\n" +
1162
			"            			System.out.println(\"Inner Try\");\n" +
1163
			"            			if (getOut) \n" +
1164
			"            				return;\n" +
1165
			"            			else\n" +
1166
			"            				break;\n" +
1167
			"            		}\n" +
1168
			"            	}\n" +
1169
			"            }\n" +
1170
			"            System.out.println(\"Out of while\");\n" +
1171
			"        }\n" +
1172
			"    }\n" +
1173
			"    public X() {\n" +
1174
			"        System.out.println(\"X::X\");\n" +
1175
			"    }\n" +
1176
			"    public void close() throws Exception {\n" +
1177
			"        System.out.println(\"X::~X\");\n" +
1178
			"    }\n" +
1179
			"}\n" +
1180
			"class Y implements AutoCloseable {\n" +
1181
			"    public Y() {\n" +
1182
			"        System.out.println(\"Y::Y\");\n" +
1183
			"    }\n" +
1184
			"    public void close() throws Exception {\n" +
1185
			"        System.out.println(\"Y::~Y\");\n" +
1186
			"    }\n" +
1187
			"}\n" +
1188
			"class Z implements AutoCloseable {\n" +
1189
			"    public Z() {\n" +
1190
			"        System.out.println(\"Z::Z\");\n" +
1191
			"    }\n" +
1192
			"    public void close() throws Exception {\n" +
1193
			"        System.out.println(\"Z::~Z\");\n" +
1194
			"    }\n" +
1195
			"}\n"
1196
		},
1197
		"Main\n" + 
1198
		"X::X\n" + 
1199
		"X::X\n" + 
1200
		"Outer Try\n" + 
1201
		"Y::Y\n" + 
1202
		"Y::Y\n" + 
1203
		"Middle Try\n" + 
1204
		"Z::Z\n" + 
1205
		"Z::Z\n" + 
1206
		"Inner Try\n" + 
1207
		"Z::~Z\n" + 
1208
		"Z::~Z\n" + 
1209
		"Y::~Y\n" + 
1210
		"Y::~Y\n" + 
1211
		"Out of while\n" + 
1212
		"X::~X\n" + 
1213
		"X::~X");
1214
}
1215
public void test032() { // test continue + resources
1216
	this.runConformTest(
1217
		new String[] {
1218
			"X.java",
1219
			"public class X implements AutoCloseable {\n" +
1220
			"    public static void main(String [] args) throws Exception { \n" +
1221
			"    	final boolean getOut = false;\n" +
1222
			"    	System.out.println(\"Main\");\n" +
1223
			"    	try (X x1 = new X(); X x2 = new X()) {\n" +
1224
			"            System.out.println(\"Outer Try\");\n" +
1225
			"            boolean more = true;\n" +
1226
			"            while (more) {\n" +
1227
			"            	try (Y y1 = new Y(); Y y2 = new Y()) {\n" +
1228
			"            		System.out.println(\"Middle Try\");\n" +
1229
			"            		try (Z z1 = new Z(); Z z2 = new Z()) {\n" +
1230
			"            			System.out.println(\"Inner Try\");\n" +
1231
			"                       more = false;\n" +
1232
			"                       continue;\n" +
1233
			"            		} finally { \n" +
1234
			"                       System.out.println(\"Inner Finally\");\n" +
1235
			"                   }\n" +
1236
			"            	} finally {\n" +
1237
			"                   System.out.println(\"Middle Finally\");\n" +
1238
			"               }\n" +
1239
			"            }\n" +
1240
			"            System.out.println(\"Out of while\");\n" +
1241
			"        } finally {\n" +
1242
			"            System.out.println(\"Outer Finally\");\n" +
1243
			"        }\n" +
1244
			"    }\n" +
1245
			"    public X() {\n" +
1246
			"        System.out.println(\"X::X\");\n" +
1247
			"    }\n" +
1248
			"    public void close() throws Exception {\n" +
1249
			"        System.out.println(\"X::~X\");\n" +
1250
			"    }\n" +
1251
			"}\n" +
1252
			"class Y implements AutoCloseable {\n" +
1253
			"    public Y() {\n" +
1254
			"        System.out.println(\"Y::Y\");\n" +
1255
			"    }\n" +
1256
			"    public void close() throws Exception {\n" +
1257
			"        System.out.println(\"Y::~Y\");\n" +
1258
			"    }\n" +
1259
			"}\n" +
1260
			"class Z implements AutoCloseable {\n" +
1261
			"    public Z() {\n" +
1262
			"        System.out.println(\"Z::Z\");\n" +
1263
			"    }\n" +
1264
			"    public void close() throws Exception {\n" +
1265
			"        System.out.println(\"Z::~Z\");\n" +
1266
			"    }\n" +
1267
			"}\n"
1268
		},
1269
		"Main\n" + 
1270
		"X::X\n" + 
1271
		"X::X\n" + 
1272
		"Outer Try\n" + 
1273
		"Y::Y\n" + 
1274
		"Y::Y\n" + 
1275
		"Middle Try\n" + 
1276
		"Z::Z\n" + 
1277
		"Z::Z\n" + 
1278
		"Inner Try\n" + 
1279
		"Z::~Z\n" + 
1280
		"Z::~Z\n" + 
1281
		"Inner Finally\n" + 
1282
		"Y::~Y\n" + 
1283
		"Y::~Y\n" + 
1284
		"Middle Finally\n" + 
1285
		"Out of while\n" + 
1286
		"X::~X\n" + 
1287
		"X::~X\n" + 
1288
		"Outer Finally");
1289
}
1082
public static Class testClass() {
1290
public static Class testClass() {
1083
	return TryWithResourcesStatementTest.class;
1291
	return TryWithResourcesStatementTest.class;
1084
}
1292
}

Return to bug 338402