View | Details | Raw Unified | Return to bug 255008
Collapse All | Expand All

(-)src/org/eclipse/jdt/core/tests/compiler/regression/AssertionTest.java (+68 lines)
Lines 440-443 Link Here
440
			true, // flush previous output dir content
440
			true, // flush previous output dir content
441
			new String[] {"-da"});
441
			new String[] {"-da"});
442
	}
442
	}
443
	//https://bugs.eclipse.org/bugs/show_bug.cgi?id=255008
444
	public void test017() {
445
		runNegativeTest(
446
			new String[] { /* test files */
447
				"X.java",
448
				"public class X {\n" + 
449
				"	protected void transform1(boolean srcPts) {\n" + 
450
				"		final float error1;\n" + 
451
				"		assert !(srcPts && (error1 = maxError()) > 0) : error1;\n" + 
452
				"	}\n" + 
453
				"	float foo1(boolean srcPts) {\n" + 
454
				"		final float error2;\n" + 
455
				"		if (!(srcPts && (error2 = maxError()) > 0)) {\n" + 
456
				"		} else {\n" + 
457
				"			return error2;\n" + 
458
				"		}\n" + 
459
				"		return 0;\n" + 
460
				"	}\n" + 
461
				"	float bar1(boolean srcPts) {\n" + 
462
				"		final float error3;\n" + 
463
				"		if ((srcPts && (error3 = maxError()) > 0)) {\n" + 
464
				"			return error3;\n" + 
465
				"		}\n" + 
466
				"		return 0;\n" + 
467
				"	}	\n" + 
468
				"	protected void transform2(boolean srcPts) {\n" + 
469
				"		final float error4;\n" + 
470
				"		assert (srcPts && (error4 = maxError()) > 0) : error4;\n" + 
471
				"	}\n" + 
472
				"	float foo2(boolean srcPts) {\n" + 
473
				"		final float error5;\n" + 
474
				"		if (srcPts && (error5 = maxError()) > 0) {\n" + 
475
				"		} else {\n" + 
476
				"			return error5;\n" + 
477
				"		}\n" + 
478
				"		return 0;\n" + 
479
				"	}\n" + 
480
				"	float bar2(boolean srcPts) {\n" + 
481
				"		final float error6;\n" + 
482
				"		if (!(srcPts && (error6 = maxError()) > 0)) {\n" + 
483
				"			return error6;\n" + 
484
				"		}\n" + 
485
				"		return 0;\n" + 
486
				"	}\n" + 
487
				"	private float maxError() {\n" + 
488
				"		return 0;\n" + 
489
				"	}\n" + 
490
				"\n" + 
491
				"}\n"
492
			},
493
			"----------\n" + 
494
			"1. ERROR in X.java (at line 23)\n" + 
495
			"	assert (srcPts && (error4 = maxError()) > 0) : error4;\n" + 
496
			"	                                               ^^^^^^\n" + 
497
			"The local variable error4 may not have been initialized\n" + 
498
			"----------\n" + 
499
			"2. ERROR in X.java (at line 29)\n" + 
500
			"	return error5;\n" + 
501
			"	       ^^^^^^\n" + 
502
			"The local variable error5 may not have been initialized\n" + 
503
			"----------\n" + 
504
			"3. ERROR in X.java (at line 36)\n" + 
505
			"	return error6;\n" + 
506
			"	       ^^^^^^\n" + 
507
			"The local variable error6 may not have been initialized\n" + 
508
			"----------\n");
509
	}
510
	
443
}
511
}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java (-163 / +145 lines)
Lines 25-215 Link Here
25
	int preAssertInitStateIndex = -1;
25
	int preAssertInitStateIndex = -1;
26
	private FieldBinding assertionSyntheticFieldBinding;
26
	private FieldBinding assertionSyntheticFieldBinding;
27
27
28
	public AssertStatement(
28
public AssertStatement(	Expression exceptionArgument, Expression assertExpression, int startPosition) {
29
		Expression exceptionArgument,
29
	this.assertExpression = assertExpression;
30
		Expression assertExpression,
30
	this.exceptionArgument = exceptionArgument;
31
		int startPosition) {
31
	this.sourceStart = startPosition;
32
32
	this.sourceEnd = exceptionArgument.sourceEnd;
33
		this.assertExpression = assertExpression;
33
}
34
		this.exceptionArgument = exceptionArgument;
35
		this.sourceStart = startPosition;
36
		this.sourceEnd = exceptionArgument.sourceEnd;
37
	}
38
39
	public AssertStatement(Expression assertExpression, int startPosition) {
40
41
		this.assertExpression = assertExpression;
42
		this.sourceStart = startPosition;
43
		this.sourceEnd = assertExpression.sourceEnd;
44
	}
45
46
	public FlowInfo analyseCode(
47
		BlockScope currentScope,
48
		FlowContext flowContext,
49
		FlowInfo flowInfo) {
50
51
		this.preAssertInitStateIndex = currentScope.methodScope().recordInitializationStates(flowInfo);
52
53
		Constant cst = this.assertExpression.optimizedBooleanConstant();
54
		boolean isOptimizedTrueAssertion = cst != Constant.NotAConstant && cst.booleanValue() == true;
55
		boolean isOptimizedFalseAssertion = cst != Constant.NotAConstant && cst.booleanValue() == false;
56
57
		FlowInfo assertRawInfo = this.assertExpression.
58
			analyseCode(currentScope, flowContext, flowInfo.copy());
59
		UnconditionalFlowInfo assertWhenTrueInfo = assertRawInfo.initsWhenTrue().
60
			unconditionalInits();
61
		UnconditionalFlowInfo assertInfo = assertRawInfo.unconditionalCopy();
62
		if (isOptimizedTrueAssertion) {
63
			assertInfo.setReachMode(FlowInfo.UNREACHABLE);
64
		}
65
34
66
		if (this.exceptionArgument != null) {
35
public AssertStatement(Expression assertExpression, int startPosition) {
67
			// only gets evaluated when escaping - results are not taken into account
36
	this.assertExpression = assertExpression;
68
			FlowInfo exceptionInfo = this.exceptionArgument.analyseCode(currentScope, flowContext, assertInfo.copy());
37
	this.sourceStart = startPosition;
38
	this.sourceEnd = assertExpression.sourceEnd;
39
}
69
40
70
			if (isOptimizedTrueAssertion){
41
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
71
				currentScope.problemReporter().fakeReachable(this.exceptionArgument);
42
	this.preAssertInitStateIndex = currentScope.methodScope().recordInitializationStates(flowInfo);
72
			} else {
43
73
				flowContext.checkExceptionHandlers(
44
	Constant cst = this.assertExpression.optimizedBooleanConstant();
74
					currentScope.getJavaLangAssertionError(),
45
	boolean isOptimizedTrueAssertion = cst != Constant.NotAConstant && cst.booleanValue() == true;
75
					this,
46
	boolean isOptimizedFalseAssertion = cst != Constant.NotAConstant && cst.booleanValue() == false;
76
					exceptionInfo,
47
77
					currentScope);
48
	FlowInfo conditionFlowInfo = this.assertExpression.analyseCode(currentScope, flowContext, flowInfo.copy());
78
			}
49
	UnconditionalFlowInfo assertWhenTrueInfo = conditionFlowInfo.initsWhenTrue().unconditionalInits();
79
		}
50
	FlowInfo assertInfo = conditionFlowInfo.initsWhenFalse();
51
	if (isOptimizedTrueAssertion) {
52
		assertInfo.setReachMode(FlowInfo.UNREACHABLE);
53
	}
54
55
	if (this.exceptionArgument != null) {
56
		// only gets evaluated when escaping - results are not taken into account
57
		FlowInfo exceptionInfo = this.exceptionArgument.analyseCode(currentScope, flowContext, assertInfo.copy());
80
58
81
		if (!isOptimizedTrueAssertion){
59
		if (isOptimizedTrueAssertion){
82
			// add the assert support in the clinit
60
			currentScope.problemReporter().fakeReachable(this.exceptionArgument);
83
			manageSyntheticAccessIfNecessary(currentScope, flowInfo);
84
		}
85
		if (isOptimizedFalseAssertion) {
86
			return flowInfo; // if assertions are enabled, the following code will be unreachable
87
			// change this if we need to carry null analysis results of the assert
88
			// expression downstream
89
		} else {
61
		} else {
90
			return flowInfo.mergedWith(assertInfo.nullInfoLessUnconditionalCopy()).
62
			flowContext.checkExceptionHandlers(
91
				addInitializationsFrom(assertWhenTrueInfo.discardInitializationInfo());
63
				currentScope.getJavaLangAssertionError(),
92
			// keep the merge from the initial code for the definite assignment
64
				this,
93
			// analysis, tweak the null part to influence nulls downstream
65
				exceptionInfo,
66
				currentScope);
94
		}
67
		}
95
	}
68
	}
96
69
97
	public void generateCode(BlockScope currentScope, CodeStream codeStream) {
70
	if (!isOptimizedTrueAssertion){
98
71
		// add the assert support in the clinit
99
		if ((this.bits & IsReachable) == 0) {
72
		manageSyntheticAccessIfNecessary(currentScope, flowInfo);
100
			return;
73
	}
101
		}
74
	if (isOptimizedFalseAssertion) {
102
		int pc = codeStream.position;
75
		return flowInfo; // if assertions are enabled, the following code will be unreachable
103
76
		// change this if we need to carry null analysis results of the assert
104
		if (this.assertionSyntheticFieldBinding != null) {
77
		// expression downstream
105
			BranchLabel assertionActivationLabel = new BranchLabel(codeStream);
78
	} else {
106
			codeStream.fieldAccess(Opcodes.OPC_getstatic, this.assertionSyntheticFieldBinding, null /* default declaringClass */);
79
		return flowInfo.mergedWith(assertInfo.nullInfoLessUnconditionalCopy()).
107
			codeStream.ifne(assertionActivationLabel);
80
			addInitializationsFrom(assertWhenTrueInfo.discardInitializationInfo());
108
81
		// keep the merge from the initial code for the definite assignment
109
			BranchLabel falseLabel;
82
		// analysis, tweak the null part to influence nulls downstream
110
			this.assertExpression.generateOptimizedBoolean(currentScope, codeStream, (falseLabel = new BranchLabel(codeStream)), null , true);
83
	}
111
			codeStream.newJavaLangAssertionError();
84
}
112
			codeStream.dup();
113
			if (this.exceptionArgument != null) {
114
				this.exceptionArgument.generateCode(currentScope, codeStream, true);
115
				codeStream.invokeJavaLangAssertionErrorConstructor(this.exceptionArgument.implicitConversion & 0xF);
116
			} else {
117
				codeStream.invokeJavaLangAssertionErrorDefaultConstructor();
118
			}
119
			codeStream.athrow();
120
85
121
			// May loose some local variable initializations : affecting the local variable attributes
86
public void generateCode(BlockScope currentScope, CodeStream codeStream) {
122
			if (this.preAssertInitStateIndex != -1) {
87
	if ((this.bits & IsReachable) == 0) {
123
				codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preAssertInitStateIndex);
88
		return;
124
			}
89
	}
125
			falseLabel.place();
90
	int pc = codeStream.position;
126
			assertionActivationLabel.place();
91
92
	if (this.assertionSyntheticFieldBinding != null) {
93
		BranchLabel assertionActivationLabel = new BranchLabel(codeStream);
94
		codeStream.fieldAccess(Opcodes.OPC_getstatic, this.assertionSyntheticFieldBinding, null /* default declaringClass */);
95
		codeStream.ifne(assertionActivationLabel);
96
97
		BranchLabel falseLabel;
98
		this.assertExpression.generateOptimizedBoolean(currentScope, codeStream, (falseLabel = new BranchLabel(codeStream)), null , true);
99
		codeStream.newJavaLangAssertionError();
100
		codeStream.dup();
101
		if (this.exceptionArgument != null) {
102
			this.exceptionArgument.generateCode(currentScope, codeStream, true);
103
			codeStream.invokeJavaLangAssertionErrorConstructor(this.exceptionArgument.implicitConversion & 0xF);
127
		} else {
104
		} else {
128
			// May loose some local variable initializations : affecting the local variable attributes
105
			codeStream.invokeJavaLangAssertionErrorDefaultConstructor();
129
			if (this.preAssertInitStateIndex != -1) {
130
				codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preAssertInitStateIndex);
131
			}
132
		}
106
		}
133
		codeStream.recordPositionsFrom(pc, this.sourceStart);
107
		codeStream.athrow();
134
	}
135
108
136
	public void resolve(BlockScope scope) {
109
		// May loose some local variable initializations : affecting the local variable attributes
137
		this.assertExpression.resolveTypeExpecting(scope, TypeBinding.BOOLEAN);
110
		if (this.preAssertInitStateIndex != -1) {
138
		if (this.exceptionArgument != null) {
111
			codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preAssertInitStateIndex);
139
			TypeBinding exceptionArgumentType = this.exceptionArgument.resolveType(scope);
112
		}
140
			if (exceptionArgumentType != null){
113
		falseLabel.place();
141
			    int id = exceptionArgumentType.id;
114
		assertionActivationLabel.place();
142
			    switch(id) {
115
	} else {
143
					case T_void :
116
		// May loose some local variable initializations : affecting the local variable attributes
144
						scope.problemReporter().illegalVoidExpression(this.exceptionArgument);
117
		if (this.preAssertInitStateIndex != -1) {
145
						//$FALL-THROUGH$
118
			codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preAssertInitStateIndex);
146
					default:
147
					    id = T_JavaLangObject;
148
					//$FALL-THROUGH$
149
					case T_boolean :
150
					case T_byte :
151
					case T_char :
152
					case T_short :
153
					case T_double :
154
					case T_float :
155
					case T_int :
156
					case T_long :
157
					case T_JavaLangString :
158
						this.exceptionArgument.implicitConversion = (id << 4) + id;
159
				}
160
			}
161
		}
119
		}
162
	}
120
	}
121
	codeStream.recordPositionsFrom(pc, this.sourceStart);
122
}
163
123
164
	public void traverse(ASTVisitor visitor, BlockScope scope) {
124
public void resolve(BlockScope scope) {
165
125
	this.assertExpression.resolveTypeExpecting(scope, TypeBinding.BOOLEAN);
166
		if (visitor.visit(this, scope)) {
126
	if (this.exceptionArgument != null) {
167
			this.assertExpression.traverse(visitor, scope);
127
		TypeBinding exceptionArgumentType = this.exceptionArgument.resolveType(scope);
168
			if (this.exceptionArgument != null) {
128
		if (exceptionArgumentType != null){
169
				this.exceptionArgument.traverse(visitor, scope);
129
		    int id = exceptionArgumentType.id;
130
		    switch(id) {
131
				case T_void :
132
					scope.problemReporter().illegalVoidExpression(this.exceptionArgument);
133
					//$FALL-THROUGH$
134
				default:
135
				    id = T_JavaLangObject;
136
				//$FALL-THROUGH$
137
				case T_boolean :
138
				case T_byte :
139
				case T_char :
140
				case T_short :
141
				case T_double :
142
				case T_float :
143
				case T_int :
144
				case T_long :
145
				case T_JavaLangString :
146
					this.exceptionArgument.implicitConversion = (id << 4) + id;
170
			}
147
			}
171
		}
148
		}
172
		visitor.endVisit(this, scope);
173
	}
149
	}
150
}
174
151
175
	public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
152
public void traverse(ASTVisitor visitor, BlockScope scope) {
176
153
	if (visitor.visit(this, scope)) {
177
		if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) {
154
		this.assertExpression.traverse(visitor, scope);
178
155
		if (this.exceptionArgument != null) {
179
    		// need assertion flag: $assertionsDisabled on outer most source clas
156
			this.exceptionArgument.traverse(visitor, scope);
180
    		// (in case of static member of interface, will use the outermost static member - bug 22334)
181
    		SourceTypeBinding outerMostClass = currentScope.enclosingSourceType();
182
			while (outerMostClass.isLocalType()) {
183
    			ReferenceBinding enclosing = outerMostClass.enclosingType();
184
    			if (enclosing == null || enclosing.isInterface()) break;
185
    			outerMostClass = (SourceTypeBinding) enclosing;
186
    		}
187
188
    		this.assertionSyntheticFieldBinding = outerMostClass.addSyntheticFieldForAssert(currentScope);
189
190
    		// find <clinit> and enable assertion support
191
    		TypeDeclaration typeDeclaration = outerMostClass.scope.referenceType();
192
    		AbstractMethodDeclaration[] methods = typeDeclaration.methods;
193
    		for (int i = 0, max = methods.length; i < max; i++) {
194
    			AbstractMethodDeclaration method = methods[i];
195
    			if (method.isClinit()) {
196
    				((Clinit) method).setAssertionSupport(this.assertionSyntheticFieldBinding, currentScope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_5);
197
    				break;
198
    			}
199
    		}
200
		}
157
		}
201
	}
158
	}
159
	visitor.endVisit(this, scope);
160
}
202
161
203
	public StringBuffer printStatement(int tab, StringBuffer output) {
162
public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
204
163
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) {
205
		printIndent(tab, output);
164
		// need assertion flag: $assertionsDisabled on outer most source clas
206
		output.append("assert "); //$NON-NLS-1$
165
		// (in case of static member of interface, will use the outermost static member - bug 22334)
207
		this.assertExpression.printExpression(0, output);
166
		SourceTypeBinding outerMostClass = currentScope.enclosingSourceType();
208
		if (this.exceptionArgument != null) {
167
		while (outerMostClass.isLocalType()) {
209
			output.append(": "); //$NON-NLS-1$
168
			ReferenceBinding enclosing = outerMostClass.enclosingType();
210
			this.exceptionArgument.printExpression(0, output);
169
			if (enclosing == null || enclosing.isInterface()) break;
170
			outerMostClass = (SourceTypeBinding) enclosing;
171
		}
172
		this.assertionSyntheticFieldBinding = outerMostClass.addSyntheticFieldForAssert(currentScope);
173
174
		// find <clinit> and enable assertion support
175
		TypeDeclaration typeDeclaration = outerMostClass.scope.referenceType();
176
		AbstractMethodDeclaration[] methods = typeDeclaration.methods;
177
		for (int i = 0, max = methods.length; i < max; i++) {
178
			AbstractMethodDeclaration method = methods[i];
179
			if (method.isClinit()) {
180
				((Clinit) method).setAssertionSupport(this.assertionSyntheticFieldBinding, currentScope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_5);
181
				break;
182
			}
211
		}
183
		}
212
		return output.append(';');
213
	}
184
	}
185
}
214
186
187
public StringBuffer printStatement(int tab, StringBuffer output) {
188
	printIndent(tab, output);
189
	output.append("assert "); //$NON-NLS-1$
190
	this.assertExpression.printExpression(0, output);
191
	if (this.exceptionArgument != null) {
192
		output.append(": "); //$NON-NLS-1$
193
		this.exceptionArgument.printExpression(0, output);
194
	}
195
	return output.append(';');
196
}
215
}
197
}

Return to bug 255008