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

Collapse All | Expand All

(-)compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java (-28 / +3 lines)
Lines 53-86 Link Here
53
		.analyseAssignment(currentScope, flowContext, flowInfo, this, false)
53
		.analyseAssignment(currentScope, flowContext, flowInfo, this, false)
54
		.unconditionalInits();
54
		.unconditionalInits();
55
	if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
55
	if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
56
		switch(nullStatus) {
56
		flowInfo.markNullStatus(local, nullStatus);
57
			case FlowInfo.NULL :
57
		if (flowContext.initsOnFinally != null)
58
				flowInfo.markAsDefinitelyNull(local);
58
			flowContext.initsOnFinally.markNullStatus(local, nullStatus);
59
				break;
60
			case FlowInfo.NON_NULL :
61
				flowInfo.markAsDefinitelyNonNull(local);
62
				break;
63
			case FlowInfo.POTENTIALLY_NULL :
64
				flowInfo.markAsPotentiallyNull(local);
65
				break;
66
			default:
67
				flowInfo.markAsDefinitelyUnknown(local);
68
		}
69
		if (flowContext.initsOnFinally != null) {
70
			switch(nullStatus) {
71
				case FlowInfo.NULL :
72
					flowContext.initsOnFinally.markAsDefinitelyNull(local);
73
					break;
74
				case FlowInfo.NON_NULL :
75
					flowContext.initsOnFinally.markAsDefinitelyNonNull(local);
76
					break;
77
				case FlowInfo.POTENTIALLY_NULL :
78
					flowContext.initsOnFinally.markAsPotentiallyNull(local);
79
					break;
80
				default:
81
					flowContext.initsOnFinally.markAsDefinitelyUnknown(local);
82
			}
83
		}
84
	}
59
	}
85
	return flowInfo;
60
	return flowInfo;
86
}
61
}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java (-13 / +12 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephen Herrmann <stephan@cs.tu-berlin.de> -  Contribution for bug 133125
10
 *     Stephen Herrmann <stephan@cs.tu-berlin.de> -  Contributions for bugs 133125, 292478
11
 *******************************************************************************/
11
 *******************************************************************************/
12
package org.eclipse.jdt.internal.compiler.ast;
12
package org.eclipse.jdt.internal.compiler.ast;
13
13
Lines 319-338 Link Here
319
	if (ifTrueNullStatus == ifFalseNullStatus) {
319
	if (ifTrueNullStatus == ifFalseNullStatus) {
320
		return ifTrueNullStatus;
320
		return ifTrueNullStatus;
321
	}
321
	}
322
	// is there a chance of null? -> potentially null
322
	// is there a chance of null (or non-null)? -> potentially null etc.
323
	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=133125
323
	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=133125
324
	switch (ifTrueNullStatus) {
324
	int status = 0;
325
		case FlowInfo.NULL:
325
	int combinedStatus = ifTrueNullStatus|ifFalseNullStatus;
326
		case FlowInfo.POTENTIALLY_NULL:
326
	if ((combinedStatus & (FlowInfo.NULL|FlowInfo.POTENTIALLY_NULL)) != 0)
327
			return FlowInfo.POTENTIALLY_NULL;
327
		status |= FlowInfo.POTENTIALLY_NULL;
328
	}
328
	if ((combinedStatus & (FlowInfo.NON_NULL|FlowInfo.POTENTIALLY_NON_NULL)) != 0)
329
	switch (ifFalseNullStatus) {
329
		status |= FlowInfo.POTENTIALLY_NON_NULL;
330
		case FlowInfo.NULL:
330
	if ((combinedStatus & (FlowInfo.UNKNOWN|FlowInfo.POTENTIALLY_UNKNOWN)) != 0)
331
		case FlowInfo.POTENTIALLY_NULL:
331
		status |= FlowInfo.POTENTIALLY_UNKNOWN;
332
			return FlowInfo.POTENTIALLY_NULL;
332
	if (status > 0)
333
	}
333
		return status;
334
	return FlowInfo.UNKNOWN;
334
	return FlowInfo.UNKNOWN;
335
	// cannot decide which branch to take, and they disagree
336
}
335
}
337
336
338
	public Constant optimizedBooleanConstant() {
337
	public Constant optimizedBooleanConstant() {
(-)compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java (-9 / +2 lines)
Lines 837-851 Link Here
837
	return FlowInfo.NON_NULL; // constant expression cannot be null
837
	return FlowInfo.NON_NULL; // constant expression cannot be null
838
838
839
	LocalVariableBinding local = localVariableBinding();
839
	LocalVariableBinding local = localVariableBinding();
840
	if (local != null) {
840
	if (local != null)
841
		if (flowInfo.isDefinitelyNull(local))
841
		return flowInfo.nullStatus(local);
842
			return FlowInfo.NULL;
843
		if (flowInfo.isDefinitelyNonNull(local))
844
			return FlowInfo.NON_NULL;
845
		if (flowInfo.isPotentiallyNull(local))
846
			return FlowInfo.POTENTIALLY_NULL;
847
		return FlowInfo.UNKNOWN;
848
	}
849
	return FlowInfo.NON_NULL;
842
	return FlowInfo.NON_NULL;
850
}
843
}
851
844
(-)compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java (-13 / +1 lines)
Lines 57-75 Link Here
57
	}
57
	}
58
	flowInfo.markAsDefinitelyAssigned(this.binding);
58
	flowInfo.markAsDefinitelyAssigned(this.binding);
59
	if ((this.binding.type.tagBits & TagBits.IsBaseType) == 0) {
59
	if ((this.binding.type.tagBits & TagBits.IsBaseType) == 0) {
60
		switch(nullStatus) {
60
		flowInfo.markNullStatus(this.binding, nullStatus);
61
			case FlowInfo.NULL :
62
				flowInfo.markAsDefinitelyNull(this.binding);
63
				break;
64
			case FlowInfo.NON_NULL :
65
				flowInfo.markAsDefinitelyNonNull(this.binding);
66
				break;
67
			case FlowInfo.POTENTIALLY_NULL :
68
				flowInfo.markAsPotentiallyNull(this.binding);
69
				break;
70
			default:
71
				flowInfo.markAsDefinitelyUnknown(this.binding);
72
		}
73
		// no need to inform enclosing try block since its locals won't get
61
		// no need to inform enclosing try block since its locals won't get
74
		// known by the finally block
62
		// known by the finally block
75
	}
63
	}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java (-9 / +2 lines)
Lines 770-784 Link Here
770
			return FlowInfo.UNKNOWN;
770
			return FlowInfo.UNKNOWN;
771
		case Binding.LOCAL : // reading a local variable
771
		case Binding.LOCAL : // reading a local variable
772
			LocalVariableBinding local = (LocalVariableBinding) this.binding;
772
			LocalVariableBinding local = (LocalVariableBinding) this.binding;
773
			if (local != null) {
773
			if (local != null)
774
				if (flowInfo.isDefinitelyNull(local))
774
				return flowInfo.nullStatus(local);
775
					return FlowInfo.NULL;
776
				if (flowInfo.isDefinitelyNonNull(local))
777
					return FlowInfo.NON_NULL;
778
				if (flowInfo.isPotentiallyNull(local))
779
					return FlowInfo.POTENTIALLY_NULL;
780
				return FlowInfo.UNKNOWN;
781
			}
782
	}
775
	}
783
	return FlowInfo.NON_NULL; // never get there
776
	return FlowInfo.NON_NULL; // never get there
784
}
777
}
(-)compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java (-3 / +18 lines)
Lines 157-165 Link Here
157
	this.initsWhenFalse.markAsDefinitelyNull(local);
157
	this.initsWhenFalse.markAsDefinitelyNull(local);
158
}
158
}
159
159
160
public void markAsPotentiallyNull(LocalVariableBinding local) {
160
public void resetNullInfo(LocalVariableBinding local) {
161
	this.initsWhenTrue.markAsPotentiallyNull(local);
161
	this.initsWhenTrue.resetNullInfo(local);
162
	this.initsWhenFalse.markAsPotentiallyNull(local);
162
	this.initsWhenFalse.resetNullInfo(local);
163
}
164
165
public void markPotentiallyNullBit(LocalVariableBinding local) {
166
	this.initsWhenTrue.markPotentiallyNullBit(local);
167
	this.initsWhenFalse.markPotentiallyNullBit(local);
168
}
169
170
public void markPotentiallyNonNullBit(LocalVariableBinding local) {
171
	this.initsWhenTrue.markPotentiallyNonNullBit(local);
172
	this.initsWhenFalse.markPotentiallyNonNullBit(local);
163
}
173
}
164
174
165
public void markAsDefinitelyUnknown(LocalVariableBinding local) {
175
public void markAsDefinitelyUnknown(LocalVariableBinding local) {
Lines 167-172 Link Here
167
	this.initsWhenFalse.markAsDefinitelyUnknown(local);
177
	this.initsWhenFalse.markAsDefinitelyUnknown(local);
168
}
178
}
169
179
180
public void markPotentiallyUnknownBit(LocalVariableBinding local) {
181
	this.initsWhenTrue.markPotentiallyUnknownBit(local);
182
	this.initsWhenFalse.markPotentiallyUnknownBit(local);
183
}
184
170
public FlowInfo setReachMode(int reachMode) {
185
public FlowInfo setReachMode(int reachMode) {
171
	if (reachMode == REACHABLE) {
186
	if (reachMode == REACHABLE) {
172
		this.tagBits &= ~UNREACHABLE;
187
		this.tagBits &= ~UNREACHABLE;
(-)compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java (-7 / +79 lines)
Lines 23-32 Link Here
23
	public final static int UNREACHABLE = 1;
23
	public final static int UNREACHABLE = 1;
24
	public final static int NULL_FLAG_MASK = 2;
24
	public final static int NULL_FLAG_MASK = 2;
25
25
26
	public final static int UNKNOWN = 0;
26
	public final static int UNKNOWN = 1;
27
	public final static int NULL = 1;
27
	public final static int NULL = 2;
28
	public final static int NON_NULL = -1;
28
	public final static int NON_NULL = 4;
29
	public final static int POTENTIALLY_NULL = 2;
29
	public final static int POTENTIALLY_UNKNOWN = 8;
30
	public final static int POTENTIALLY_NULL = 16;
31
	public final static int POTENTIALLY_NON_NULL = 32;
30
32
31
	public static final UnconditionalFlowInfo DEAD_END; // Represents a dead branch status of initialization
33
	public static final UnconditionalFlowInfo DEAD_END; // Represents a dead branch status of initialization
32
	static {
34
	static {
Lines 248-258 Link Here
248
	 * Record a local got definitely assigned to null.
250
	 * Record a local got definitely assigned to null.
249
	 */
251
	 */
250
	abstract public void markAsDefinitelyNull(LocalVariableBinding local);
252
	abstract public void markAsDefinitelyNull(LocalVariableBinding local);
251
	
253
252
	/**
254
	/**
253
	 * Record a local may have got assigned to null.
255
	 * Reset all null-information about a given local.
254
	 */
256
	 */
255
	abstract public void markAsPotentiallyNull(LocalVariableBinding local);
257
	abstract public void resetNullInfo(LocalVariableBinding local);
258
259
	/**
260
	 * Record a local may have got assigned to unknown (set the bit on existing info).
261
	 */
262
	abstract public void markPotentiallyUnknownBit(LocalVariableBinding local);
263
264
	/**
265
	 * Record a local may have got assigned to null (set the bit on existing info).
266
	 */
267
	abstract public void markPotentiallyNullBit(LocalVariableBinding local);
268
269
	/**
270
	 * Record a local may have got assigned to non-null (set the bit on existing info).
271
	 */
272
	abstract public void markPotentiallyNonNullBit(LocalVariableBinding local);
256
273
257
	/**
274
	/**
258
	 * Record a local got definitely assigned.
275
	 * Record a local got definitely assigned.
Lines 265-270 Link Here
265
abstract public void markAsDefinitelyUnknown(LocalVariableBinding local);
282
abstract public void markAsDefinitelyUnknown(LocalVariableBinding local);
266
283
267
/**
284
/**
285
 * Mark the null status of the given local according to the given status
286
 * @param local
287
 * @param nullStatus bitset of FLowInfo.UNKNOWN ... FlowInfo.POTENTIALLY_NON_NULL
288
 */
289
public void markNullStatus(LocalVariableBinding local, int nullStatus) {
290
	switch(nullStatus) {
291
		// definite status?
292
		case FlowInfo.UNKNOWN :
293
			markAsDefinitelyUnknown(local);
294
			break;
295
		case FlowInfo.NULL :
296
			markAsDefinitelyNull(local);
297
			break;
298
		case FlowInfo.NON_NULL :
299
			markAsDefinitelyNonNull(local);
300
			break;
301
		default:
302
			// collect potential status:
303
			resetNullInfo(local);
304
			if ((nullStatus & FlowInfo.POTENTIALLY_UNKNOWN) != 0)
305
				markPotentiallyUnknownBit(local);
306
			if ((nullStatus & FlowInfo.POTENTIALLY_NULL) != 0)
307
				markPotentiallyNullBit(local);
308
			if ((nullStatus & FlowInfo.POTENTIALLY_NON_NULL) != 0)
309
				markPotentiallyNonNullBit(local);
310
			if ((nullStatus & (FlowInfo.POTENTIALLY_NULL|FlowInfo.POTENTIALLY_NON_NULL|FlowInfo.POTENTIALLY_UNKNOWN)) == 0)
311
				markAsDefinitelyUnknown(local);
312
	}
313
}
314
315
/**
316
 * Answer the null status of the given local
317
 * @param local
318
 * @return bitset of FlowInfo.UNKNOWN ... FlowInfo.POTENTIALLY_NON_NULL
319
 */
320
public int nullStatus(LocalVariableBinding local) {
321
	if (isDefinitelyUnknown(local))
322
		return FlowInfo.UNKNOWN;
323
	if (isDefinitelyNull(local))
324
		return FlowInfo.NULL;
325
	if (isDefinitelyNonNull(local))
326
		return FlowInfo.NON_NULL;
327
	int status = 0;
328
	if (isPotentiallyUnknown(local))
329
		status |= FlowInfo.POTENTIALLY_UNKNOWN;
330
	if (isPotentiallyNull(local))
331
		status |= FlowInfo.POTENTIALLY_NULL;
332
	if (isPotentiallyNonNull(local))
333
		status |= FlowInfo.POTENTIALLY_NON_NULL;
334
	if (status > 0)
335
		return status;
336
	return FlowInfo.UNKNOWN;
337
}
338
339
/**
268
 * Merge branches using optimized boolean conditions
340
 * Merge branches using optimized boolean conditions
269
 */
341
 */
270
public static UnconditionalFlowInfo mergedOptimizedBranches(
342
public static UnconditionalFlowInfo mergedOptimizedBranches(
(-)compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java (-13 / +109 lines)
Lines 24-33 Link Here
24
 * No caching of pre-allocated instances.
24
 * No caching of pre-allocated instances.
25
 */
25
 */
26
public class UnconditionalFlowInfo extends FlowInfo {
26
public class UnconditionalFlowInfo extends FlowInfo {
27
	// Coverage tests
28
	/**
27
	/**
29
	 * Exception raised when unexpected behavior is detected during coverage
28
	 * Exception raised when unexpected behavior is detected.
30
	 * tests.
31
	 */
29
	 */
32
	public static class AssertionFailedException extends RuntimeException {
30
	public static class AssertionFailedException extends RuntimeException {
33
		private static final long serialVersionUID = 1827352841030089703L;
31
		private static final long serialVersionUID = 1827352841030089703L;
Lines 976-982 Link Here
976
	        & (this.extra[4][vectorIndex] ^ this.extra[5][vectorIndex])
974
	        & (this.extra[4][vectorIndex] ^ this.extra[5][vectorIndex])
977
		    & (1L << (position % BitCacheSize))) != 0;
975
		    & (1L << (position % BitCacheSize))) != 0;
978
}
976
}
979
977
/** Asserts that the given boolean is <code>true</code>. If this
978
 * is not the case, some kind of unchecked exception is thrown.
979
 * The given message is included in that exception, to aid debugging.
980
 *
981
 * @param expression the outcome of the check
982
 * @param message the message to include in the exception
983
 * @return <code>true</code> if the check passes (does not return
984
 *    if the check fails)
985
 */
986
private static boolean isTrue(boolean expression, String message) {
987
	if (!expression)
988
		throw new AssertionFailedException("assertion failed: " + message); //$NON-NLS-1$
989
	return expression;
990
}
980
public void markAsComparedEqualToNonNull(LocalVariableBinding local) {
991
public void markAsComparedEqualToNonNull(LocalVariableBinding local) {
981
	// protected from non-object locals in calling methods
992
	// protected from non-object locals in calling methods
982
	if (this != DEAD_END) {
993
	if (this != DEAD_END) {
Lines 1330-1346 Link Here
1330
	}
1341
	}
1331
}
1342
}
1332
1343
1333
public void markAsPotentiallyNull(LocalVariableBinding local) {
1344
public void resetNullInfo(LocalVariableBinding local) {
1345
	if (this != DEAD_END) {
1346
		this.tagBits |= NULL_FLAG_MASK;
1347
        int position;
1348
        long mask;
1349
        if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
1350
            // use bits
1351
            this.nullBit1 &= (mask = ~(1L << position));
1352
            this.nullBit2 &= mask;
1353
            this.nullBit3 &= mask;
1354
            this.nullBit4 &= mask;
1355
        } else {
1356
    		// use extra vector
1357
    		int vectorIndex ;
1358
    		this.extra[2][vectorIndex = (position / BitCacheSize) - 1]
1359
    		    &= (mask = ~(1L << (position % BitCacheSize)));
1360
    		this.extra[3][vectorIndex] &= mask;
1361
    		this.extra[4][vectorIndex] &= mask;
1362
    		this.extra[5][vectorIndex] &= mask;
1363
    	}
1364
	}
1365
}
1366
1367
/**
1368
 * Mark a local as potentially having been assigned to an unknown value.
1369
 * @param local the local to mark
1370
 */
1371
public void markPotentiallyUnknownBit(LocalVariableBinding local) {
1372
	// protected from non-object locals in calling methods
1334
	if (this != DEAD_END) {
1373
	if (this != DEAD_END) {
1335
		this.tagBits |= NULL_FLAG_MASK;
1374
		this.tagBits |= NULL_FLAG_MASK;
1336
        int position;
1375
        int position;
1337
        long mask;
1376
        long mask;
1338
        if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
1377
        if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
1339
            // use bits
1378
            // use bits
1340
            this.nullBit1 &= ~(mask = 1L << position);
1379
        	mask = 1L << position;
1380
        	isTrue((this.nullBit1 & mask) == 0, "Adding 'unknown' mark in unexpected state"); //$NON-NLS-1$
1381
            this.nullBit4 |= mask;
1382
            if (COVERAGE_TEST_FLAG) {
1383
				if(CoverageTestId == 46) {
1384
				  	this.nullBit4 = ~0;
1385
				}
1386
			}
1387
        } else {
1388
    		// use extra vector
1389
    		int vectorIndex = (position / BitCacheSize) - 1;
1390
    		mask = 1L << (position % BitCacheSize);
1391
    		isTrue((this.extra[2][vectorIndex] & mask) == 0, "Adding 'unknown' mark in unexpected state"); //$NON-NLS-1$
1392
    		this.extra[5][vectorIndex] |= mask;
1393
    		if (COVERAGE_TEST_FLAG) {
1394
				if(CoverageTestId == 47) {
1395
					this.extra[5][vectorIndex] = ~0;
1396
				}
1397
			}
1398
    	}
1399
	}
1400
}
1401
1402
public void markPotentiallyNullBit(LocalVariableBinding local) {
1403
	if (this != DEAD_END) {
1404
		this.tagBits |= NULL_FLAG_MASK;
1405
        int position;
1406
        long mask;
1407
        if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
1408
            // use bits
1409
        	mask = 1L << position;
1410
        	isTrue((this.nullBit1 & mask) == 0, "Adding 'potentially null' mark in unexpected state"); //$NON-NLS-1$
1341
            this.nullBit2 |= mask;
1411
            this.nullBit2 |= mask;
1342
            this.nullBit3 &= ~mask;
1343
            this.nullBit4 &= ~mask;
1344
            if (COVERAGE_TEST_FLAG) {
1412
            if (COVERAGE_TEST_FLAG) {
1345
				if(CoverageTestId == 40) {
1413
				if(CoverageTestId == 40) {
1346
				  	this.nullBit4 = ~0;
1414
				  	this.nullBit4 = ~0;
Lines 1348-1359 Link Here
1348
			}
1416
			}
1349
        } else {
1417
        } else {
1350
    		// use extra vector
1418
    		// use extra vector
1351
    		int vectorIndex ;
1419
    		int vectorIndex = (position / BitCacheSize) - 1;
1352
    		this.extra[2][vectorIndex = (position / BitCacheSize) - 1]
1420
    		mask = 1L << (position % BitCacheSize);
1353
    		    &= ~(mask = 1L << (position % BitCacheSize));
1354
    		this.extra[3][vectorIndex] |= mask;
1421
    		this.extra[3][vectorIndex] |= mask;
1355
    		this.extra[4][vectorIndex] &= (mask = ~mask);
1422
    		isTrue((this.extra[2][vectorIndex] & mask) == 0, "Adding 'potentially null' mark in unexpected state"); //$NON-NLS-1$
1356
    		this.extra[5][vectorIndex] &= mask;
1357
    		if (COVERAGE_TEST_FLAG) {
1423
    		if (COVERAGE_TEST_FLAG) {
1358
				if(CoverageTestId == 41) {
1424
				if(CoverageTestId == 41) {
1359
					this.extra[5][vectorIndex] = ~0;
1425
					this.extra[5][vectorIndex] = ~0;
Lines 1363-1368 Link Here
1363
	}
1429
	}
1364
}
1430
}
1365
1431
1432
public void markPotentiallyNonNullBit(LocalVariableBinding local) {
1433
	if (this != DEAD_END) {
1434
		this.tagBits |= NULL_FLAG_MASK;
1435
        int position;
1436
        long mask;
1437
        if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
1438
            // use bits
1439
        	mask = 1L << position;
1440
        	isTrue((this.nullBit1 & mask) == 0, "Adding 'potentially non-null' mark in unexpected state"); //$NON-NLS-1$
1441
            this.nullBit3 |= mask;
1442
            if (COVERAGE_TEST_FLAG) {
1443
				if(CoverageTestId == 42) {
1444
				  	this.nullBit4 = ~0;
1445
				}
1446
			}
1447
        } else {
1448
    		// use extra vector
1449
    		int vectorIndex  = (position / BitCacheSize) - 1;
1450
    		mask = 1L << (position % BitCacheSize);
1451
    		isTrue((this.extra[2][vectorIndex] & mask) == 0, "Adding 'potentially non-null' mark in unexpected state"); //$NON-NLS-1$
1452
    		this.extra[4][vectorIndex] |= mask;
1453
    		if (COVERAGE_TEST_FLAG) {
1454
				if(CoverageTestId == 43) {
1455
					this.extra[5][vectorIndex] = ~0;
1456
				}
1457
			}
1458
    	}
1459
	}
1460
}
1461
1366
public UnconditionalFlowInfo mergedWith(UnconditionalFlowInfo otherInits) {
1462
public UnconditionalFlowInfo mergedWith(UnconditionalFlowInfo otherInits) {
1367
	if ((otherInits.tagBits & UNREACHABLE) != 0 && this != DEAD_END) {
1463
	if ((otherInits.tagBits & UNREACHABLE) != 0 && this != DEAD_END) {
1368
		if (COVERAGE_TEST_FLAG) {
1464
		if (COVERAGE_TEST_FLAG) {
(-)src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTests.java (-12 lines)
Lines 559-569 Link Here
559
	assertTrue("nb of failures: " + failures, failures == 0);
559
	assertTrue("nb of failures: " + failures, failures == 0);
560
}
560
}
561
561
562
public void test2058_markAsPotentiallyNull() {
563
	int failures = NullReferenceImplTransformations.markAsPotentiallyNull.test();
564
	assertTrue("nb of failures: " + failures, failures == 0);
565
}
566
567
public void test2060_addInitializationsFrom() {
562
public void test2060_addInitializationsFrom() {
568
	int failures = NullReferenceImplTransformations.addInitializationsFrom.test();
563
	int failures = NullReferenceImplTransformations.addInitializationsFrom.test();
569
	assertTrue("nb of failures: " + failures, failures == 0);
564
	assertTrue("nb of failures: " + failures, failures == 0);
Lines 875-881 Link Here
875
		test2055_markAsDefinitelyNonNull();
870
		test2055_markAsDefinitelyNonNull();
876
		test2056_markAsDefinitelyNull();
871
		test2056_markAsDefinitelyNull();
877
		test2057_markAsDefinitelyUnknown();
872
		test2057_markAsDefinitelyUnknown();
878
		test2058_markAsPotentiallyNull();
879
		test2060_addInitializationsFrom();
873
		test2060_addInitializationsFrom();
880
		test2061_addPotentialInitializationsFrom();
874
		test2061_addPotentialInitializationsFrom();
881
		test2062_mergedWith();
875
		test2062_mergedWith();
Lines 897-903 Link Here
897
				test2055_markAsDefinitelyNonNull();
891
				test2055_markAsDefinitelyNonNull();
898
				test2056_markAsDefinitelyNull();
892
				test2056_markAsDefinitelyNull();
899
				test2057_markAsDefinitelyUnknown();
893
				test2057_markAsDefinitelyUnknown();
900
				test2058_markAsPotentiallyNull();
901
				test2060_addInitializationsFrom();
894
				test2060_addInitializationsFrom();
902
				test2061_addPotentialInitializationsFrom();
895
				test2061_addPotentialInitializationsFrom();
903
				test2062_mergedWith();
896
				test2062_mergedWith();
Lines 1105-1115 Link Here
1105
	super.markAsDefinitelyUnknown(local);
1098
	super.markAsDefinitelyUnknown(local);
1106
}
1099
}
1107
1100
1108
public void markAsPotentiallyNull(LocalVariableBinding local) {
1109
	grow(local.id + this.maxFieldCount);
1110
	super.markAsPotentiallyNull(local);
1111
}
1112
1113
/**
1101
/**
1114
 * Return a fake unconditional flow info which bit fields represent the given
1102
 * Return a fake unconditional flow info which bit fields represent the given
1115
 * null bits for a local variable of id 0 within a class that would have no
1103
 * null bits for a local variable of id 0 within a class that would have no
(-)src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTransformations.java (-44 lines)
Lines 242-291 Link Here
242
				return result;
242
				return result;
243
			}
243
			}
244
		},
244
		},
245
		markAsPotentiallyNull =
246
			// markAsDefinitelyNull DEFINITION START
247
			// start => pot. null
248
			// prot. non null => pot. null
249
			// prot. null => pot. null
250
			// pot. unknown => pot. null
251
			// pot. non null => pot. null
252
			// pot. nn & prot. nn => pot. null
253
			// pot. nn & pot. un => pot. null
254
			// pot. null => pot. null
255
			// pot. n & prot. n => pot. null
256
			// pot. n & pot. un => pot. null
257
			// pot. n & pot. nn => pot. null
258
			// def. unknown => pot. null
259
			// def. non null => pot. null
260
			// def. null => pot. null
261
			// markAsPotentiallyNull DEFINITION END
262
				// PREMATURE add 'catch rules'
263
				new TwoDimensionalTransformation("markAsPotentiallyNull",
264
					new byte[][] {
265
					// markAsPotentiallyNull INITIALIZER START
266
					{0x00,0x08},
267
					{0x04,0x08},
268
					{0x08,0x08},
269
					{0x0C,0x08},
270
					{0x10,0x08},
271
					{0x14,0x08},
272
					{0x18,0x08},
273
					{0x24,0x08},
274
					{0x28,0x08},
275
					{0x2C,0x08},
276
					{0x30,0x08},
277
					{0x34,0x08},
278
					{0x38,0x08},
279
					{0x3C,0x08},
280
					// markAsPotentiallyNull INITIALIZER END
281
					}) {
282
				UnconditionalFlowInfo output(UnconditionalFlowInfo input,
283
						TestLocalVariableBinding local) {
284
					UnconditionalFlowInfo result = (UnconditionalFlowInfo)input.copy();
285
					result.markAsPotentiallyNull(local);
286
					return result;
287
				}
288
			},
289
		addInitializationsFrom =
245
		addInitializationsFrom =
290
		// addInitializationsFrom DEFINITION START
246
		// addInitializationsFrom DEFINITION START
291
		// def. non null + def. non null => def. non null
247
		// def. non null + def. non null => def. non null
(-)src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java (-1 / +129 lines)
Lines 35-41 Link Here
35
// Only the highest compliance level is run; add the VM argument
35
// Only the highest compliance level is run; add the VM argument
36
// -Dcompliance=1.4 (for example) to lower it if needed
36
// -Dcompliance=1.4 (for example) to lower it if needed
37
static {
37
static {
38
//		TESTS_NAMES = new String[] { "testBug320414" };
38
//		TESTS_NAMES = new String[] { "testBug292478g" };
39
//		TESTS_NUMBERS = new int[] { 561 };
39
//		TESTS_NUMBERS = new int[] { 561 };
40
//		TESTS_RANGE = new int[] { 1, 2049 };
40
//		TESTS_RANGE = new int[] { 1, 2049 };
41
}
41
}
Lines 13222-13225 Link Here
13222
		"Potential null pointer access: The variable y may be null at this location\n" + 
13222
		"Potential null pointer access: The variable y may be null at this location\n" + 
13223
		"----------\n");
13223
		"----------\n");
13224
}
13224
}
13225
13226
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=292478 -  Report potentially null across variable assignment
13227
// test regression reported in comment 8
13228
public void testBug292478e() {
13229
	this.runConformTest(
13230
		new String[] {
13231
			"Test.java",
13232
			"public class Test {\n" +
13233
			"	Object foo(int i, boolean b1, boolean b2) {\n" +
13234
			"		Object o1 = null;\n" +
13235
			"		done : while (true) { \n" +
13236
			"			switch (i) {\n" +
13237
			"				case 1 :\n" +
13238
			"					Object o2 = null;\n" +
13239
			"					if (b2)\n" +
13240
			"						o2 = new Object();\n" +
13241
			"					o1 = o2;\n" +
13242
			"					break;\n" +
13243
			"				case 2 :\n" +
13244
			"					break done;\n" +
13245
			"			}\n" +
13246
			"		}		\n" +
13247
			"		if (o1 != null)\n" +
13248
			"			return o1;\n" +
13249
			"		return null;\n" +
13250
			"	}\n" +
13251
			"}\n"
13252
		});
13253
}
13254
13255
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=292478 -  Report potentially null across variable assignment
13256
// variant where regression occurred inside the while-switch structure
13257
public void testBug292478f() {
13258
	this.runConformTest(
13259
		new String[] {
13260
			"Test.java",
13261
			"public class Test {\n" +
13262
			"	Object foo(int i, boolean b1, boolean b2) {\n" +
13263
			"		Object o1 = null;\n" +
13264
			"		done : while (true) { \n" +
13265
			"			switch (i) {\n" +
13266
			"				case 1 :\n" +
13267
			"					Object o2 = null;\n" +
13268
			"					if (b2)\n" +
13269
			"						o2 = new Object();\n" +
13270
			"					o1 = o2;\n" +
13271
			"					if (o1 != null)\n" +
13272
			"						return o1;\n" +
13273
			"					break;\n" +
13274
			"				case 2 :\n" +
13275
			"					break done;\n" +
13276
			"			}\n" +
13277
			"		}		\n" +
13278
			"		return null;\n" +
13279
			"	}\n" +
13280
			"}\n"
13281
		});
13282
}
13283
13284
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=292478 -  Report potentially null across variable assignment
13285
// variant for transfering state potentially unknown
13286
public void testBug292478g() {
13287
	this.runConformTest(
13288
		new String[] {
13289
			"Test.java",
13290
			"public class Test {\n" +
13291
			"	Object foo(int i, boolean b1, boolean b2, Object o2) {\n" +
13292
			"		Object o1 = null;\n" +
13293
			"		done : while (true) { \n" +
13294
			"			switch (i) {\n" +
13295
			"				case 1 :\n" +
13296
			"					if (b2)\n" +
13297
			"						o2 = bar();\n" +
13298
			"					o1 = o2;\n" +
13299
			"					if (o1 != null)\n" +
13300
			"						return o1;\n" +
13301
			"					break;\n" +
13302
			"				case 2 :\n" +
13303
			"					break done;\n" +
13304
			"			}\n" +
13305
			"		}		\n" +
13306
			"		return null;\n" +
13307
			"	}\n" +
13308
			"   Object bar() { return null; }\n" +
13309
			"}\n"
13310
		});
13311
}
13312
13313
// Bug 324762 -  Compiler thinks there is deadcode and removes it!
13314
// regression caused by the fix for bug 133125
13315
// ternary is non-null or null
13316
public void testBug324762() {
13317
	this.runConformTest(
13318
		new String[] {
13319
			"Test.java",
13320
			"public class Test {\n" +
13321
			"	void zork(boolean b1) {\n" +
13322
			"		Object satisfied = null;\n" +
13323
			"		if (b1) {\n" +
13324
			"			String[] s = new String[] { \"a\", \"b\" };\n" +
13325
			"			for (int k = 0; k < s.length && satisfied == null; k++)\n" +
13326
			"				satisfied = s.length > 1 ? new Object() : null;\n" +
13327
			"		}\n" +
13328
			"	}\n" +
13329
			"}\n"
13330
		});
13331
}
13332
13333
// Bug 324762 -  Compiler thinks there is deadcode and removes it!
13334
// regression caused by the fix for bug 133125
13335
// ternary is unknown or null
13336
public void testBug324762a() {
13337
	this.runConformTest(
13338
		new String[] {
13339
			"Test.java",
13340
			"public class Test {\n" +
13341
			"	void zork(boolean b1) {\n" +
13342
			"		Object satisfied = null;\n" +
13343
			"		if (b1) {\n" +
13344
			"			String[] s = new String[] { \"a\", \"b\" };\n" +
13345
			"			for (int k = 0; k < s.length && satisfied == null; k++)\n" +
13346
			"				satisfied = s.length > 1 ? bar() : null;\n" +
13347
			"		}\n" +
13348
			"	}\n" +
13349
			"	Object bar() { return null; }\n" +
13350
			"}\n"
13351
		});
13352
}
13225
}
13353
}

Return to bug 292478