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) != 0)) { |
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) != 0) || |
|
|
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) != 0) || |
|
|
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); |