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

Collapse All | Expand All

(-)compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java (-3 / +5 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2009 IBM Corporation and others.
2
 * Copyright (c) 2000, 2010 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 30-37 Link Here
30
	public final static int Bit5 = 0x10;					// value for return (expression) | has all method bodies (unit) | supertype ref (type ref) | resolved (field decl)
30
	public final static int Bit5 = 0x10;					// value for return (expression) | has all method bodies (unit) | supertype ref (type ref) | resolved (field decl)
31
	public final static int Bit6 = 0x20;					// depth (name ref, msg) | ignore need cast check (cast expression) | error in signature (method declaration/ initializer) | is recovered (annotation reference)
31
	public final static int Bit6 = 0x20;					// depth (name ref, msg) | ignore need cast check (cast expression) | error in signature (method declaration/ initializer) | is recovered (annotation reference)
32
	public final static int Bit7 = 0x40;					// depth (name ref, msg) | operator (operator) | need runtime checkcast (cast expression) | label used (labelStatement) | needFreeReturn (AbstractMethodDeclaration)
32
	public final static int Bit7 = 0x40;					// depth (name ref, msg) | operator (operator) | need runtime checkcast (cast expression) | label used (labelStatement) | needFreeReturn (AbstractMethodDeclaration)
33
	public final static int Bit8 = 0x80;					// depth (name ref, msg) | operator (operator) | unsafe cast (cast expression) | is default constructor (constructor declaration)
33
	public final static int Bit8 = 0x80;					// depth (name ref, msg) | operator (operator) | unsafe cast (cast expression) | is default constructor (constructor declaration) | isElseStatementUnreachable (if statement)
34
	public final static int Bit9 = 0x100;				// depth (name ref, msg) | operator (operator) | is local type (type decl)
34
	public final static int Bit9 = 0x100;				// depth (name ref, msg) | operator (operator) | is local type (type decl) | isThenStatementUnreachable (if statement)
35
	public final static int Bit10= 0x200;				// depth (name ref, msg) | operator (operator) | is anonymous type (type decl)
35
	public final static int Bit10= 0x200;				// depth (name ref, msg) | operator (operator) | is anonymous type (type decl)
36
	public final static int Bit11 = 0x400;				// depth (name ref, msg) | operator (operator) | is member type (type decl)
36
	public final static int Bit11 = 0x400;				// depth (name ref, msg) | operator (operator) | is member type (type decl)
37
	public final static int Bit12 = 0x800;				// depth (name ref, msg) | operator (operator) | has abstract methods (type decl)
37
	public final static int Bit12 = 0x800;				// depth (name ref, msg) | operator (operator) | has abstract methods (type decl)
Lines 194-199 Link Here
194
	// for if statement
194
	// for if statement
195
	public static final int IsElseIfStatement = Bit30;
195
	public static final int IsElseIfStatement = Bit30;
196
	public static final int ThenExit = Bit31;
196
	public static final int ThenExit = Bit31;
197
	public static final int IsElseStatementUnreachable = Bit8;
198
	public static final int IsThenStatementUnreachable = Bit9;
197
199
198
	// for type reference
200
	// for type reference
199
	public static final int IsSuperType = Bit5;
201
	public static final int IsSuperType = Bit5;
(-)compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java (-6 lines)
Lines 59-70 Link Here
59
				}
59
				}
60
				break;
60
				break;
61
		}
61
		}
62
		// set the optimize constant to optimize code gen
63
		if ((initsWhenTrue.tagBits & FlowInfo.UNREACHABLE) != 0) {
64
			this.optimizedBooleanConstant = BooleanConstant.fromValue(false);
65
		} else if ((initsWhenFalse.tagBits & FlowInfo.UNREACHABLE) != 0) {
66
			this.optimizedBooleanConstant = BooleanConstant.fromValue(true);
67
		}
68
		// we do not impact enclosing try context because this kind of protection
62
		// we do not impact enclosing try context because this kind of protection
69
		// does not preclude the variable from being null in an enclosing scope
63
		// does not preclude the variable from being null in an enclosing scope
70
	}
64
	}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java (-13 / +35 lines)
Lines 30-36 Link Here
30
	int elseInitStateIndex = -1;
30
	int elseInitStateIndex = -1;
31
	int mergedInitStateIndex = -1;
31
	int mergedInitStateIndex = -1;
32
32
33
public IfStatement(Expression condition, Statement thenStatement, 	int sourceStart, int sourceEnd) {
33
public IfStatement(Expression condition, Statement thenStatement, int sourceStart, int sourceEnd) {
34
	this.condition = condition;
34
	this.condition = condition;
35
	this.thenStatement = thenStatement;
35
	this.thenStatement = thenStatement;
36
	// remember useful empty statement
36
	// remember useful empty statement
Lines 69-80 Link Here
69
	if (isConditionOptimizedTrue) {
69
	if (isConditionOptimizedTrue) {
70
		elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
70
		elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
71
	}
71
	}
72
	if (((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) && 
73
			((thenFlowInfo.tagBits & FlowInfo.UNREACHABLE) != 0)) {
74
		// Mark then block as unreachable
75
		// No need if the whole if-else construct itself lies in unreachable code
76
		this.bits |= ASTNode.IsThenStatementUnreachable;
77
	} else if (((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) &&
78
			((elseFlowInfo.tagBits & FlowInfo.UNREACHABLE) != 0)) {
79
		// Mark else block as unreachable
80
		// No need if the whole if-else construct itself lies in unreachable code
81
		this.bits |= ASTNode.IsElseStatementUnreachable;
82
	}
72
	if (this.thenStatement != null) {
83
	if (this.thenStatement != null) {
73
		// Save info for code gen
84
		// Save info for code gen
74
		this.thenInitStateIndex = currentScope.methodScope().recordInitializationStates(thenFlowInfo);
85
		this.thenInitStateIndex = currentScope.methodScope().recordInitializationStates(thenFlowInfo);
75
		if (isConditionOptimizedFalse) {
86
		if (isConditionOptimizedFalse || ((this.bits & ASTNode.IsThenStatementUnreachable) == ASTNode.IsThenStatementUnreachable)) {
76
			if (!isKnowDeadCodePattern(this.condition) || currentScope.compilerOptions().reportDeadCodeInTrivialIfStatement) {
87
			if (!isKnowDeadCodePattern(this.condition) || currentScope.compilerOptions().reportDeadCodeInTrivialIfStatement) {
77
				this.thenStatement.complainIfUnreachable(thenFlowInfo, currentScope, initialComplaintLevel);
88
				this.thenStatement.complainIfUnreachable(thenFlowInfo, currentScope, initialComplaintLevel);
89
			} else {
90
				// its a known coding pattern which should be tolerated by dead code analysis
91
				// according to isKnowDeadCodePattern()
92
				this.bits &= ~ASTNode.IsThenStatementUnreachable;
78
			}
93
			}
79
		}
94
		}
80
		thenFlowInfo = this.thenStatement.analyseCode(currentScope, flowContext, thenFlowInfo);
95
		thenFlowInfo = this.thenStatement.analyseCode(currentScope, flowContext, thenFlowInfo);
Lines 86-113 Link Here
86
101
87
	// process the ELSE part
102
	// process the ELSE part
88
	if (this.elseStatement != null) {
103
	if (this.elseStatement != null) {
89
	    // signal else clause unnecessarily nested, tolerate else-if code pattern
104
		// signal else clause unnecessarily nested, tolerate else-if code pattern
90
	    if (thenFlowInfo == FlowInfo.DEAD_END
105
		if (thenFlowInfo == FlowInfo.DEAD_END
91
	            && (this.bits & IsElseIfStatement) == 0 	// else of an else-if
106
				&& (this.bits & IsElseIfStatement) == 0 	// else of an else-if
92
	            && !(this.elseStatement instanceof IfStatement)) {
107
				&& !(this.elseStatement instanceof IfStatement)) {
93
	        currentScope.problemReporter().unnecessaryElse(this.elseStatement);
108
			currentScope.problemReporter().unnecessaryElse(this.elseStatement);
94
	    }
109
		}
95
		// Save info for code gen
110
		// Save info for code gen
96
		this.elseInitStateIndex = currentScope.methodScope().recordInitializationStates(elseFlowInfo);
111
		this.elseInitStateIndex = currentScope.methodScope().recordInitializationStates(elseFlowInfo);
97
		if (isConditionOptimizedTrue) {
112
		if (isConditionOptimizedTrue || ((this.bits & ASTNode.IsElseStatementUnreachable) != 0)) {
98
			if (!isKnowDeadCodePattern(this.condition) || currentScope.compilerOptions().reportDeadCodeInTrivialIfStatement) {
113
			if (!isKnowDeadCodePattern(this.condition) || currentScope.compilerOptions().reportDeadCodeInTrivialIfStatement) {
99
				this.elseStatement.complainIfUnreachable(elseFlowInfo, currentScope, initialComplaintLevel);
114
				this.elseStatement.complainIfUnreachable(elseFlowInfo, currentScope, initialComplaintLevel);
115
			} else {
116
				// its a known coding pattern which should be tolerated by dead code analysis
117
				// according to isKnowDeadCodePattern()
118
				this.bits &= ~ASTNode.IsElseStatementUnreachable;
100
			}
119
			}
101
		}
120
		}
102
		elseFlowInfo = this.elseStatement.analyseCode(currentScope, flowContext, elseFlowInfo);
121
		elseFlowInfo = this.elseStatement.analyseCode(currentScope, flowContext, elseFlowInfo);
103
	}
122
	}
104
	// merge THEN & ELSE initializations
123
	// merge THEN & ELSE initializations
105
	FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches(
124
	FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranchesIfElse(
106
		thenFlowInfo,
125
		thenFlowInfo,
107
		isConditionOptimizedTrue,
126
		isConditionOptimizedTrue,
108
		elseFlowInfo,
127
		elseFlowInfo,
109
		isConditionOptimizedFalse,
128
		isConditionOptimizedFalse,
110
		true /*if(true){ return; }  fake-reachable(); */);
129
		true /*if(true){ return; }  fake-reachable(); */,
130
		flowInfo);
111
	this.mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
131
	this.mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
112
	return mergedInfo;
132
	return mergedInfo;
113
}
133
}
Lines 139-145 Link Here
139
	if (hasThenPart) {
159
	if (hasThenPart) {
140
		BranchLabel falseLabel = null;
160
		BranchLabel falseLabel = null;
141
		// generate boolean condition only if needed
161
		// generate boolean condition only if needed
142
		if (cst != Constant.NotAConstant && cst.booleanValue() == true) {
162
		if (((this.bits & ASTNode.IsElseStatementUnreachable) == ASTNode.IsElseStatementUnreachable) ||
163
				(cst != Constant.NotAConstant && cst.booleanValue() == true)) {
143
			// No need to generate if condition statement when we know that only the then action
164
			// No need to generate if condition statement when we know that only the then action
144
			// will be executed
165
			// will be executed
145
			this.condition.generateCode(currentScope, codeStream, false);
166
			this.condition.generateCode(currentScope, codeStream, false);
Lines 180-186 Link Here
180
		}
201
		}
181
	} else if (hasElsePart) {
202
	} else if (hasElsePart) {
182
		// generate boolean condition only if needed
203
		// generate boolean condition only if needed
183
		if (cst != Constant.NotAConstant && cst.booleanValue() == false) {
204
		if ((this.bits & ASTNode.IsThenStatementUnreachable) == ASTNode.IsThenStatementUnreachable ||
205
				(cst != Constant.NotAConstant && cst.booleanValue() == false)) {
184
			// No need to generate if condition statement when we know that only the else action
206
			// No need to generate if condition statement when we know that only the else action
185
			// will be executed
207
			// will be executed
186
			this.condition.generateCode(currentScope, codeStream, false);
208
			this.condition.generateCode(currentScope, codeStream, false);
(-)compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java (-1 / +72 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2009 IBM Corporation and others.
2
 * Copyright (c) 2000, 2010 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 295-300 Link Here
295
}
295
}
296
296
297
/**
297
/**
298
 * Merge if-else branches using optimized boolean conditions
299
 */
300
public static UnconditionalFlowInfo mergedOptimizedBranchesIfElse(
301
		FlowInfo initsWhenTrue, boolean isOptimizedTrue,
302
		FlowInfo initsWhenFalse, boolean isOptimizedFalse,
303
		boolean allowFakeDeadBranch, FlowInfo flowInfo) {
304
	UnconditionalFlowInfo mergedInfo;
305
	if (isOptimizedTrue){
306
		if (initsWhenTrue == FlowInfo.DEAD_END && allowFakeDeadBranch) {
307
			mergedInfo = initsWhenFalse.setReachMode(FlowInfo.UNREACHABLE).
308
				unconditionalInits();
309
		}
310
		else {
311
			mergedInfo =
312
				initsWhenTrue.addPotentialInitializationsFrom(initsWhenFalse.
313
					nullInfoLessUnconditionalCopy()).
314
				unconditionalInits();
315
		}
316
	}
317
	else if (isOptimizedFalse) {
318
		if (initsWhenFalse == FlowInfo.DEAD_END && allowFakeDeadBranch) {
319
			mergedInfo = initsWhenTrue.setReachMode(FlowInfo.UNREACHABLE).
320
				unconditionalInits();
321
		}
322
		else {
323
			mergedInfo =
324
				initsWhenFalse.addPotentialInitializationsFrom(initsWhenTrue.
325
					nullInfoLessUnconditionalCopy()).
326
				unconditionalInits();
327
		}
328
	}
329
	else if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0 &&
330
				(initsWhenFalse.tagBits & FlowInfo.UNREACHABLE) != 0 &&
331
				initsWhenTrue != FlowInfo.DEAD_END &&
332
				initsWhenFalse != FlowInfo.DEAD_END) {
333
		// Done when the then branch will always be executed but the condition doesnt have a boolean
334
		// true or false (i.e if(true), etc) for sure
335
		// We don't do this if both if and else branches themselves are in an unreachable code
336
		// or if any of them is a DEAD_END (eg. contains 'return' or 'throws')
337
		mergedInfo =
338
			initsWhenTrue.addPotentialInitializationsFrom(initsWhenFalse.
339
				nullInfoLessUnconditionalCopy()).
340
			unconditionalInits();
341
		// if a variable is only initialized in one branch and not initialized in the other,
342
		// then we need to cast a doubt on its initialization in the merged info
343
		mergedInfo.definiteInits &= initsWhenFalse.unconditionalCopy().definiteInits;
344
		
345
	}
346
	else if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0 &&
347
			(initsWhenTrue.tagBits & FlowInfo.UNREACHABLE) != 0 && initsWhenTrue != FlowInfo.DEAD_END
348
			&& initsWhenFalse != FlowInfo.DEAD_END) {
349
		// Done when the else branch will always be executed but the condition doesnt have a boolean
350
		// true or false (i.e if(true), etc) for sure
351
		// We don't do this if both if and else branches themselves are in an unreachable code
352
		// or if any of them is a DEAD_END (eg. contains 'return' or 'throws')
353
		mergedInfo = 
354
			initsWhenFalse.addPotentialInitializationsFrom(initsWhenTrue.
355
				nullInfoLessUnconditionalCopy()).
356
			unconditionalInits();
357
		// if a variable is only initialized in one branch and not initialized in the other,
358
		// then we need to cast a doubt on its initialization in the merged info
359
		mergedInfo.definiteInits &= initsWhenTrue.unconditionalCopy().definiteInits;
360
	}
361
	else {
362
		mergedInfo = initsWhenTrue.
363
			mergedWith(initsWhenFalse.unconditionalInits());
364
	}
365
	return mergedInfo;
366
}
367
368
/**
298
 * Return REACHABLE if this flow info is reachable, UNREACHABLE
369
 * Return REACHABLE if this flow info is reachable, UNREACHABLE
299
 * else.
370
 * else.
300
 * @return REACHABLE if this flow info is reachable, UNREACHABLE
371
 * @return REACHABLE if this flow info is reachable, UNREACHABLE
(-)src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java (-16 / +166 lines)
Lines 26-43 Link Here
26
}
26
}
27
27
28
	// Static initializer to specify tests subset using TESTS_* static variables
28
	// Static initializer to specify tests subset using TESTS_* static variables
29
  	// All specified tests which does not belong to the class are skipped...
29
// All specified tests which does not belong to the class are skipped...
30
  	// Only the highest compliance level is run; add the VM argument
30
// Only the highest compliance level is run; add the VM argument
31
  	// -Dcompliance=1.4 (for example) to lower it if needed
31
// -Dcompliance=1.4 (for example) to lower it if needed
32
  	static {
32
static {
33
//    	TESTS_NAMES = new String[] { "test011" };
33
//	TESTS_NAMES = new String[] { "test0572_if_statement" };
34
//    	TESTS_NUMBERS = new int[] { 561 };
34
//    	TESTS_NUMBERS = new int[] { 561 };
35
//    	TESTS_NUMBERS = new int[] { 2999 };
35
//    	TESTS_NUMBERS = new int[] { 2999 };
36
//    	TESTS_RANGE = new int[] { 2050, -1 };
36
//    	TESTS_RANGE = new int[] { 2050, -1 };
37
//  	TESTS_RANGE = new int[] { 1, 2049 };
37
//  	TESTS_RANGE = new int[] { 1, 2049 };
38
//  	TESTS_RANGE = new int[] { 449, 451 };
38
//  	TESTS_RANGE = new int[] { 449, 451 };
39
//    	TESTS_RANGE = new int[] { 900, 999 };
39
//    	TESTS_RANGE = new int[] { 900, 999 };
40
  	}
40
}
41
41
42
public static Test suite() {
42
public static Test suite() {
43
    return buildAllCompliancesTestSuite(testClass());
43
    return buildAllCompliancesTestSuite(testClass());
Lines 4133-4140 Link Here
4133
			"  }\n" +
4133
			"  }\n" +
4134
			"}\n"},
4134
			"}\n"},
4135
		"----------\n" +
4135
		"----------\n" +
4136
		"1. ERROR in X.java (at line 11)\r\n" +
4136
		"1. ERROR in X.java (at line 11)\n" +
4137
		"	while (o == null) {\r\n" +
4137
		"	while (o == null) {\n" +
4138
		"	       ^\n" +
4138
		"	       ^\n" +
4139
		"Null comparison always yields false: The variable o cannot be null at this location\n" +
4139
		"Null comparison always yields false: The variable o cannot be null at this location\n" +
4140
		"----------\n",
4140
		"----------\n",
Lines 5177-5184 Link Here
5177
			"  }\n" +
5177
			"  }\n" +
5178
			"}"},
5178
			"}"},
5179
		"----------\n" +
5179
		"----------\n" +
5180
		"1. ERROR in X.java (at line 13)\r\n" +
5180
		"1. ERROR in X.java (at line 13)\n" +
5181
		"	o.toString();\r\n" +
5181
		"	o.toString();\n" +
5182
		"	^\n" +
5182
		"	^\n" +
5183
		"Potential null pointer access: The variable o may be null at this location\n" +
5183
		"Potential null pointer access: The variable o may be null at this location\n" +
5184
		"----------\n",
5184
		"----------\n",
Lines 6054-6060 Link Here
6054
			},
6054
			},
6055
			"");
6055
			"");
6056
}
6056
}
6057
6057
// null analysis -- try/catch
6058
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=302446
6059
public void test0569_try_catch() {
6060
	this.runNegativeTest(
6061
		new String[] {
6062
			"X.java",
6063
			"public class X {\n" +
6064
			"  void foo() {\n" +
6065
			"    Object o = null;\n" +
6066
			"	 int i;\n" +
6067
			"	 if (o == null)\n" +	// redundant check
6068
			"	 	i = 0;\n" +
6069
			"    try {\n" +
6070
			"      System.out.println(i);\n" +  // might throw a runtime exception
6071
			"      o = new Object();\n" +
6072
			"	   throw new Exception(\"Exception thrown from try block\");\n" +
6073
			"    }\n" +
6074
			"    catch (Throwable t) {\n" + // catches everything
6075
			"      return;\n" +             // gets out
6076
			"    }\n" +
6077
			"  }\n" +
6078
			"}\n"},
6079
		"----------\n" + 
6080
		"1. ERROR in X.java (at line 5)\n" + 
6081
		"	if (o == null)\n" + 
6082
		"	    ^\n" + 
6083
		"Redundant null check: The variable o can only be null at this location\n" + 
6084
		"----------\n" + 
6085
		"2. ERROR in X.java (at line 8)\n" + 
6086
		"	System.out.println(i);\n" + 
6087
		"	                   ^\n" + 
6088
		"The local variable i may not have been initialized\n" + 
6089
		"----------\n");
6090
}
6091
// null analysis -- try/catch
6092
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=302446
6093
public void test0570_try_catch() {
6094
	this.runNegativeTest(
6095
		new String[] {
6096
			"X.java",
6097
			"public class X {\n" +
6098
			"  void foo() {\n" +
6099
			"    Object o = null;\n" +
6100
			"	 int i;\n" +
6101
			"	 if (o == null)\n" +	// redundant check
6102
			"	 	i = 0;\n" +
6103
			"    try {\n" +
6104
			"      System.out.println();\n" +  // might throw a runtime exception
6105
			"      o = new Object();\n" +
6106
			"	   if (o != null)\n" +		// redundant check
6107
			"			i = 1\n;" +
6108
			"		throw new Exception(\"Exception thrown from try block\");\n" +
6109
			"    }\n" +
6110
			"    catch (Exception e) {\n" +
6111
			"      if(i == 0)\n" +
6112
			"			System.out.println(\"o was initialised\");\n" +
6113
			"    }\n" +
6114
			"  }\n" +
6115
			"}\n"},
6116
		"----------\n" + 
6117
		"1. ERROR in X.java (at line 5)\n" + 
6118
		"	if (o == null)\n" + 
6119
		"	    ^\n" + 
6120
		"Redundant null check: The variable o can only be null at this location\n" + 
6121
		"----------\n" + 
6122
		"2. ERROR in X.java (at line 10)\n" + 
6123
		"	if (o != null)\n" + 
6124
		"	    ^\n" + 
6125
		"Redundant null check: The variable o cannot be null at this location\n" + 
6126
		"----------\n" + 
6127
		"3. ERROR in X.java (at line 15)\n" + 
6128
		"	if(i == 0)\n" + 
6129
		"	   ^\n" + 
6130
		"The local variable i may not have been initialized\n" + 
6131
		"----------\n");
6132
}
6133
//null analysis -- try/catch
6134
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=302446
6135
public void test0571_try_catch_finally() {
6136
	this.runNegativeTest(
6137
		new String[] {
6138
			"X.java",
6139
			"public class X {\n" +
6140
			"  void foo() {\n" +
6141
			"    Object o = null;\n" +
6142
			"	 int i;\n" +
6143
			"	 if (o == null)\n" +	// redundant check
6144
			"	 	i = 0;\n" +
6145
			"    try {\n" +
6146
			"      o = new Object();\n" +
6147
			"	   i = 1\n;" +
6148
			"	   throw new Exception(\"Exception thrown from try block\");\n" +
6149
			"    }\n" +
6150
			"    catch (Exception e) {\n" +
6151
			"      if(o == null)\n" +
6152
			"			o = new Object();\n" +
6153
			"	   i = 1;\n" +
6154
			"    }\n" +
6155
			"	 finally {\n" +
6156
			"		if (i==1) {\n" +
6157
			"	 		System.out.println(\"Method ended with o being initialised\");\n" +
6158
			"		System.out.println(o.toString());\n" +	// may be null
6159
			"		} \n" +
6160
			"	 }\n" +
6161
			"  }\n" +
6162
			"}\n"},
6163
		"----------\n" + 
6164
		"1. ERROR in X.java (at line 5)\n" + 
6165
		"	if (o == null)\n" + 
6166
		"	    ^\n" + 
6167
		"Redundant null check: The variable o can only be null at this location\n" + 
6168
		"----------\n" + 
6169
		"2. ERROR in X.java (at line 18)\n" + 
6170
		"	if (i==1) {\n" + 
6171
		"	    ^\n" + 
6172
		"The local variable i may not have been initialized\n" + 
6173
		"----------\n" + 
6174
		"3. ERROR in X.java (at line 20)\n" + 
6175
		"	System.out.println(o.toString());\n" + 
6176
		"	                   ^\n" + 
6177
		"Potential null pointer access: The variable o may be null at this location\n" + 
6178
		"----------\n");
6179
}
6180
//null analysis -- if statement
6181
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=302446
6182
public void test0572_if_statement() {
6183
	this.runNegativeTest(
6184
		new String[] {
6185
			"X.java",
6186
			"public class X {\n" + 
6187
			"	void foo() {\n" + 
6188
			"		Object o = null;\n" + 
6189
			"		int i;\n" + 
6190
			"		if (o == null) // redundant check\n" + 
6191
			"			i = 0;\n" + 
6192
			"		System.out.println(i);\n" + 
6193
			"	}\n" + 
6194
			"}\n" + 
6195
			""},
6196
		"----------\n" + 
6197
		"1. ERROR in X.java (at line 5)\n" + 
6198
		"	if (o == null) // redundant check\n" + 
6199
		"	    ^\n" + 
6200
		"Redundant null check: The variable o can only be null at this location\n" + 
6201
		"----------\n" + 
6202
		"2. ERROR in X.java (at line 7)\n" + 
6203
		"	System.out.println(i);\n" + 
6204
		"	                   ^\n" + 
6205
		"The local variable i may not have been initialized\n" + 
6206
		"----------\n");
6207
}
6058
// null analysis - throw
6208
// null analysis - throw
6059
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=201182
6209
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=201182
6060
public void test0595_throw() {
6210
public void test0595_throw() {
Lines 8975-8991 Link Here
8975
			"  }\n" +
9125
			"  }\n" +
8976
			"}"},
9126
			"}"},
8977
		"----------\n" +
9127
		"----------\n" +
8978
		"1. ERROR in X.java (at line 6)\r\n" +
9128
		"1. ERROR in X.java (at line 6)\n" +
8979
		"	if (o != null) return;\r\n" +
9129
		"	if (o != null) return;\n" +
8980
		"	    ^\n" +
9130
		"	    ^\n" +
8981
		"Null comparison always yields false: The variable o can only be null at this location\n" +
9131
		"Null comparison always yields false: The variable o can only be null at this location\n" +
8982
		"----------\n" +
9132
		"----------\n" +
8983
		"2. ERROR in X.java (at line 7)\r\n" +
9133
		"2. ERROR in X.java (at line 7)\n" +
8984
		"	o = null;\r\n" +
9134
		"	o = null;\n" +
8985
		"	^\n" +
9135
		"	^\n" +
8986
		"Redundant assignment: The variable o can only be null at this location\n" +
9136
		"Redundant assignment: The variable o can only be null at this location\n" +
8987
		"----------\n",
9137
		"----------\n",
8988
	    JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
9138
		JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
8989
}
9139
}
8990
9140
8991
public void test1019() {
9141
public void test1019() {

Return to bug 302446