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

(-)compiler/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java (-6 / +13 lines)
Lines 35-46 Link Here
35
		BlockScope currentScope,
35
		BlockScope currentScope,
36
		FlowContext flowContext,
36
		FlowContext flowContext,
37
		FlowInfo flowInfo) {
37
		FlowInfo flowInfo) {
38
	left.checkNPE(currentScope, flowContext, flowInfo, false /* skip String */);
38
	if (this.resolvedType.id == T_JavaLangString) {
39
	flowInfo = left.analyseCode(currentScope, flowContext, flowInfo).
39
		return right.analyseCode(currentScope, flowContext, 
40
		unconditionalInits();
40
				left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits()).
41
	right.checkNPE(currentScope, flowContext, flowInfo, false /* skip String */);
41
			unconditionalInits();
42
	return right.analyseCode(currentScope, flowContext, flowInfo).
42
	}
43
		unconditionalInits();
43
	else {
44
		left.checkNPE(currentScope, flowContext, flowInfo);
45
		flowInfo = left.analyseCode(currentScope, flowContext, flowInfo).
46
			unconditionalInits();
47
		right.checkNPE(currentScope, flowContext, flowInfo);
48
		return right.analyseCode(currentScope, flowContext, flowInfo).
49
			unconditionalInits();
50
	}
44
}
51
}
45
52
46
	public void computeConstant(BlockScope scope, int leftId, int rightId) {
53
	public void computeConstant(BlockScope scope, int leftId, int rightId) {
(-)compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java (-5 / +2 lines)
Lines 480-494 Link Here
480
 * @param scope the scope of the analysis
480
 * @param scope the scope of the analysis
481
 * @param flowContext the current flow context
481
 * @param flowContext the current flow context
482
 * @param flowInfo the upstream flow info; caveat: may get modified
482
 * @param flowInfo the upstream flow info; caveat: may get modified
483
 * @param checkString if true, a local variable of type String is checked; else
484
 *        it is skipped
485
 */
483
 */
486
public void checkNPE(BlockScope scope, FlowContext flowContext, 
484
public void checkNPE(BlockScope scope, FlowContext flowContext, 
487
		FlowInfo flowInfo, boolean checkString) {
485
		FlowInfo flowInfo) {
488
	LocalVariableBinding local = this.localVariableBinding();
486
	LocalVariableBinding local = this.localVariableBinding();
489
	if (local != null && 
487
	if (local != null && 
490
			(local.type.tagBits & TagBits.IsBaseType) == 0 &&
488
			(local.type.tagBits & TagBits.IsBaseType) == 0) {
491
			(checkString || local.type.id != T_JavaLangString)) {
492
		if ((this.bits & IsNonNull) == 0) {
489
		if ((this.bits & IsNonNull) == 0) {
493
			flowContext.recordUsingNullReference(scope, local, this, 
490
			flowContext.recordUsingNullReference(scope, local, this, 
494
					FlowContext.MAY_NULL, flowInfo);
491
					FlowContext.MAY_NULL, flowInfo);
(-)compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java (-1 / +1 lines)
Lines 49-55 Link Here
49
		BlockScope currentScope,
49
		BlockScope currentScope,
50
		FlowContext flowContext,
50
		FlowContext flowContext,
51
		FlowInfo flowInfo) {
51
		FlowInfo flowInfo) {
52
	receiver.checkNPE(currentScope, flowContext, flowInfo, true);
52
	receiver.checkNPE(currentScope, flowContext, flowInfo);
53
	flowInfo = receiver.analyseCode(currentScope, flowContext, flowInfo);
53
	flowInfo = receiver.analyseCode(currentScope, flowContext, flowInfo);
54
	return position.analyseCode(currentScope, flowContext, flowInfo);
54
	return position.analyseCode(currentScope, flowContext, flowInfo);
55
}
55
}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java (-1 / +1 lines)
Lines 43-49 Link Here
43
	boolean nonStatic = !binding.isStatic();
43
	boolean nonStatic = !binding.isStatic();
44
	flowInfo = receiver.analyseCode(currentScope, flowContext, flowInfo, nonStatic).unconditionalInits();
44
	flowInfo = receiver.analyseCode(currentScope, flowContext, flowInfo, nonStatic).unconditionalInits();
45
	if (nonStatic) {
45
	if (nonStatic) {
46
		receiver.checkNPE(currentScope, flowContext, flowInfo, true);
46
		receiver.checkNPE(currentScope, flowContext, flowInfo);
47
	}
47
	}
48
48
49
	if (arguments != null) {
49
	if (arguments != null) {
(-)compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java (-1 / +1 lines)
Lines 31-37 Link Here
31
		BlockScope currentScope,
31
		BlockScope currentScope,
32
		FlowContext flowContext,
32
		FlowContext flowContext,
33
		FlowInfo flowInfo) {
33
		FlowInfo flowInfo) {
34
	this.expression.checkNPE(currentScope, flowContext, flowInfo, true);	
34
	this.expression.checkNPE(currentScope, flowContext, flowInfo);	
35
	if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
35
	if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
36
		return this.expression.
36
		return this.expression.
37
			analyseCode(currentScope, flowContext, flowInfo).
37
			analyseCode(currentScope, flowContext, flowInfo).
(-)compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java (-1 / +1 lines)
Lines 99-105 Link Here
99
	boolean nonStatic = !binding.isStatic();
99
	boolean nonStatic = !binding.isStatic();
100
	receiver.analyseCode(currentScope, flowContext, flowInfo, nonStatic);
100
	receiver.analyseCode(currentScope, flowContext, flowInfo, nonStatic);
101
	if (nonStatic) {
101
	if (nonStatic) {
102
		receiver.checkNPE(currentScope, flowContext, flowInfo, true);
102
		receiver.checkNPE(currentScope, flowContext, flowInfo);
103
	}
103
	}
104
	
104
	
105
	if (valueRequired || currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) {
105
	if (valueRequired || currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) {
(-)compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java (-1 / +1 lines)
Lines 81-87 Link Here
81
		continueLabel = new BranchLabel();
81
		continueLabel = new BranchLabel();
82
82
83
		// process the element variable and collection
83
		// process the element variable and collection
84
		this.collection.checkNPE(currentScope, flowContext, flowInfo, true);
84
		this.collection.checkNPE(currentScope, flowContext, flowInfo);
85
		flowInfo = this.elementVariable.analyseCode(scope, flowContext, flowInfo);
85
		flowInfo = this.elementVariable.analyseCode(scope, flowContext, flowInfo);
86
		FlowInfo condInfo = this.collection.analyseCode(scope, flowContext, flowInfo.copy());
86
		FlowInfo condInfo = this.collection.analyseCode(scope, flowContext, flowInfo.copy());
87
87
(-)compiler/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java (-1 / +3 lines)
Lines 39-45 Link Here
39
	// record setting a variable: various scenarii are possible, setting an array reference, 
39
	// record setting a variable: various scenarii are possible, setting an array reference, 
40
	// a field reference, a blank final field reference, a field of an enclosing instance or 
40
	// a field reference, a blank final field reference, a field of an enclosing instance or 
41
	// just a local variable.
41
	// just a local variable.
42
	lhs.checkNPE(currentScope, flowContext, flowInfo, false /* skip String */);
42
	if (this.resolvedType.id != T_JavaLangString) {
43
		lhs.checkNPE(currentScope, flowContext, flowInfo);
44
	}
43
	return  ((Reference) lhs).analyseAssignment(currentScope, flowContext, flowInfo, this, true).unconditionalInits();
45
	return  ((Reference) lhs).analyseAssignment(currentScope, flowContext, flowInfo, this, true).unconditionalInits();
44
}
46
}
45
	
47
	
(-)src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java (-54 / +111 lines)
Lines 33-43 Link Here
33
  	// -Dcompliance=1.4 (for example) to lower it if needed
33
  	// -Dcompliance=1.4 (for example) to lower it if needed
34
  	static {
34
  	static {
35
//    	TESTS_NAMES = new String[] { "test011" };
35
//    	TESTS_NAMES = new String[] { "test011" };
36
//    	TESTS_NUMBERS = new int[] { 729 };   
36
//    	TESTS_NUMBERS = new int[] { 48 };
37
//    	TESTS_NUMBERS = new int[] { 2999 };   
37
//    	TESTS_NUMBERS = new int[] { 2999 };   
38
//    	TESTS_RANGE = new int[] { 2050, -1 }; 
38
//    	TESTS_RANGE = new int[] { 2050, -1 }; 
39
//  	TESTS_RANGE = new int[] { 1, 2049 }; 
39
//  	TESTS_RANGE = new int[] { 1, 2049 }; 
40
//  	TESTS_RANGE = new int[] { 449, 451 }; 
40
  	TESTS_RANGE = new int[] { 120, 130 }; 
41
//    	TESTS_RANGE = new int[] { 900, 999 }; 
41
//    	TESTS_RANGE = new int[] { 900, 999 }; 
42
  	}
42
  	}
43
43
Lines 853-910 Link Here
853
		"");
853
		"");
854
}
854
}
855
855
856
// null analysis -- strings concatenation
857
// JLS 15.18.1: if one of the operands is null, it is replaced by "null"
858
// Note: having the diagnostic could come handing when the initialization path
859
//       is non trivial; to get the diagnostic, simply put in place an
860
//       extraneous call to toString() -- and remove it before releasing.
861
public void test0045_strings_concatenation() {
862
	this.runConformTest(
863
		new String[] {
864
			"X.java",
865
			"public class X {\n" + 
866
			"  String foo(String s1, String s2) {\n" + 
867
			"    if (s1 == null) { /* */ };\n" +
868
			"    return s1 + s2;\n" + 
869
			"  }\n" + 
870
			"}\n"},
871
		"");
872
}
873
874
// null analysis -- strings concatenation
875
public void test0046_strings_concatenation() {
876
	this.runConformTest(
877
		new String[] {
878
			"X.java",
879
			"public class X {\n" + 
880
			"  String foo(String s1, String s2) {\n" + 
881
			"    if (s1 == null) { /* */ };\n" +
882
			"    s1 += s2;\n" + 
883
			"    return s1;\n" + 
884
			"  }\n" + 
885
			"}\n"},
886
		"");
887
}
888
889
// null analysis -- strings concatenation
890
public void test0047_strings_concatenation() {
891
	this.runNegativeTest(
892
		new String[] {
893
			"X.java",
894
			"public class X {\n" + 
895
			"  String foo(String s1) {\n" + 
896
			"    if (s1 == null) { /* */ };\n" +
897
			"    return s1.toString();\n" + 
898
			"  }\n" + 
899
			"}\n"},
900
		"----------\n" + 
901
		"1. ERROR in X.java (at line 4)\n" + 
902
		"	return s1.toString();\n" + 
903
		"	       ^^\n" + 
904
		"The variable s1 may be null\n" + 
905
		"----------\n");
906
}
907
908
// null analysis -- array
856
// null analysis -- array
909
public void test0050_array() {
857
public void test0050_array() {
910
	this.runConformTest(
858
	this.runConformTest(
Lines 1321-1326 Link Here
1321
		"");
1269
		"");
1322
}
1270
}
1323
1271
1272
// null analysis -- strings concatenation
1273
// JLS 15.18.1: if one of the operands is null, it is replaced by "null"
1274
// Note: having the diagnostic could come handing when the initialization path
1275
//       is non trivial; to get the diagnostic, simply put in place an
1276
//       extraneous call to toString() -- and remove it before releasing.
1277
public void test0120_strings_concatenation() {
1278
	this.runConformTest(
1279
		new String[] {
1280
			"X.java",
1281
			"public class X {\n" + 
1282
			"  String foo(String s1, String s2) {\n" + 
1283
			"    if (s1 == null) { /* */ };\n" +
1284
			"    return s1 + s2;\n" + 
1285
			"  }\n" + 
1286
			"}\n"},
1287
		"");
1288
}
1289
1290
// null analysis -- strings concatenation
1291
public void test0121_strings_concatenation() {
1292
	this.runConformTest(
1293
		new String[] {
1294
			"X.java",
1295
			"public class X {\n" + 
1296
			"  String foo(String s1, String s2) {\n" + 
1297
			"    if (s1 == null) { /* */ };\n" +
1298
			"    s1 += s2;\n" + 
1299
			"    return s1;\n" + 
1300
			"  }\n" + 
1301
			"}\n"},
1302
		"");
1303
}
1304
1305
// null analysis -- strings concatenation
1306
public void test0122_strings_concatenation() {
1307
	this.runNegativeTest(
1308
		new String[] {
1309
			"X.java",
1310
			"public class X {\n" + 
1311
			"  String foo(String s1) {\n" + 
1312
			"    if (s1 == null) { /* */ };\n" +
1313
			"    return s1.toString();\n" + 
1314
			"  }\n" + 
1315
			"}\n"},
1316
		"----------\n" + 
1317
		"1. ERROR in X.java (at line 4)\n" + 
1318
		"	return s1.toString();\n" + 
1319
		"	       ^^\n" + 
1320
		"The variable s1 may be null\n" + 
1321
		"----------\n");
1322
}
1323
1324
// null analysis -- strings concatenation
1325
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=127919
1326
// it should suffice that the return type is String to avoid
1327
// errors
1328
public void test0123_strings_concatenation() {
1329
	this.runConformTest(
1330
		new String[] {
1331
			"X.java",
1332
			"public class X {\n" + 
1333
			"  String foo(String s, Object o, Integer i) {\n" + 
1334
			"    if (s == null || o == null || i == null) { /* */ };\n" +
1335
			"    if (bar()) {\n" +
1336
			"      return s + i;\n" + // quiet: i replaced by "null" if null
1337
			"    }\n" +
1338
			"    return o + s;\n" + // quiet: o replaced by "null" if null
1339
			"  }\n" + 
1340
			"  boolean bar() {\n" +
1341
			"    return false;\n" +
1342
			"  }\n" + 
1343
			"}\n"},
1344
		"");
1345
}
1346
1347
// null analysis -- strings concatenation
1348
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=127919
1349
// variant
1350
public void test0124_strings_concatenation() {
1351
	this.runConformTest(
1352
		new String[] {
1353
			"X.java",
1354
			"public class X {\n" + 
1355
			"  String foo(String s, Object o, Integer i) {\n" + 
1356
			"    if (s == null || o == null || i == null) { /* */ };\n" +
1357
			"    s += o;\n" + // quiet: o replaced by "null" if null
1358
			"    s += i;\n" + // quiet: i replaced by "null" if null
1359
			"    return s;\n" + 
1360
			"  }\n" + 
1361
			"}\n"},
1362
		"");
1363
}
1364
1365
// null analysis -- strings concatenation
1366
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=127919
1367
// variant
1368
public void test0125_strings_concatenation() {
1369
	this.runConformTest(
1370
		new String[] {
1371
			"X.java",
1372
			"public class X {\n" + 
1373
			"  void foo(Object o, Integer i) {\n" + 
1374
			"    System.out.println(o + (o == null ? \"\" : o.toString()));\n" + // quiet: o replaced by "null" if null
1375
			"    System.out.println(i + (i == null ? \"\" : i.toString()));\n" + // quiet: o replaced by "null" if null
1376
			"  }\n" + 
1377
			"}\n"},
1378
		"");
1379
}
1380
1324
// null analysis -- if/else
1381
// null analysis -- if/else
1325
// check that obviously unreachable code does not modify the null
1382
// check that obviously unreachable code does not modify the null
1326
// status of a local
1383
// status of a local

Return to bug 127919