mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 455828 - Proper handling of 'switch' without explicit default
(including empty switch) Change-Id: I3e20400f86c5e4273d8b0c62ed9ac3f429a84879 Signed-off-by: Nathan Ridge <zeratul976@hotmail.com>
This commit is contained in:
parent
3586267e6b
commit
43097ce04e
3 changed files with 58 additions and 4 deletions
|
@ -338,6 +338,7 @@ public class ControlFlowGraphBuilder {
|
||||||
IBasicBlock prev = switchNode;
|
IBasicBlock prev = switchNode;
|
||||||
IConnectorNode savedBreak = outerBreak;
|
IConnectorNode savedBreak = outerBreak;
|
||||||
outerBreak = mergeNode;
|
outerBreak = mergeNode;
|
||||||
|
boolean encounteredDefault = false;
|
||||||
try {
|
try {
|
||||||
for (IASTStatement statement : comp.getStatements()) {
|
for (IASTStatement statement : comp.getStatements()) {
|
||||||
if (statement instanceof IASTCaseStatement || statement instanceof IASTDefaultStatement) {
|
if (statement instanceof IASTCaseStatement || statement instanceof IASTDefaultStatement) {
|
||||||
|
@ -346,6 +347,7 @@ public class ControlFlowGraphBuilder {
|
||||||
lbl = factory.createBranchNode(statement);
|
lbl = factory.createBranchNode(statement);
|
||||||
} else if (statement instanceof IASTDefaultStatement) {
|
} else if (statement instanceof IASTDefaultStatement) {
|
||||||
lbl = factory.createBranchNode(IBranchNode.DEFAULT);
|
lbl = factory.createBranchNode(IBranchNode.DEFAULT);
|
||||||
|
encounteredDefault = true;
|
||||||
}
|
}
|
||||||
if (!(prev instanceof IExitNode) && prev != switchNode) {
|
if (!(prev instanceof IExitNode) && prev != switchNode) {
|
||||||
IConnectorNode here = factory.createConnectorNode();
|
IConnectorNode here = factory.createConnectorNode();
|
||||||
|
@ -363,6 +365,16 @@ public class ControlFlowGraphBuilder {
|
||||||
} finally {
|
} finally {
|
||||||
outerBreak = savedBreak;
|
outerBreak = savedBreak;
|
||||||
}
|
}
|
||||||
|
// If the switch didn't have an explicit 'default' case, we still have to
|
||||||
|
// add an edge for the situation where no case was matched.
|
||||||
|
if (!encounteredDefault) {
|
||||||
|
if (!(prev instanceof IExitNode) && prev != switchNode) {
|
||||||
|
addJump(prev, mergeNode);
|
||||||
|
}
|
||||||
|
IBranchNode defaultBranch = factory.createBranchNode(IBranchNode.DEFAULT);
|
||||||
|
addOutgoing(switchNode, defaultBranch);
|
||||||
|
prev = defaultBranch;
|
||||||
|
}
|
||||||
addJump(prev, mergeNode);
|
addJump(prev, mergeNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -638,4 +638,27 @@ public class ControlFlowGraphTest extends CodanFastCxxAstTestCase {
|
||||||
IJumpNode case1Jump = (IJumpNode) case1Branch.getOutgoing();
|
IJumpNode case1Jump = (IJumpNode) case1Branch.getOutgoing();
|
||||||
assertEquals(swittch.getMergeNode(), case1Jump.getJumpNode());
|
assertEquals(swittch.getMergeNode(), case1Jump.getJumpNode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// int main(int a) {
|
||||||
|
// switch (a) {
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
public void test_empty_switch() {
|
||||||
|
buildAndCheck(getAboveComment());
|
||||||
|
// Decision node should be optimized away entirely
|
||||||
|
assertFalse(graph.getStartNode() instanceof IDecisionNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// int main(int a) {
|
||||||
|
// switch (a) {
|
||||||
|
// case 1: {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
public void test_switch_no_explicit_default() {
|
||||||
|
buildAndCheck(getAboveComment());
|
||||||
|
IDecisionNode swittch = (IDecisionNode) graph.getStartNode().getOutgoing();
|
||||||
|
assertTrue(swittch.getOutgoingSize() == 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,10 +241,20 @@ public class ReturnCheckerTest extends CheckerTestCase {
|
||||||
// {
|
// {
|
||||||
// switch (g()) {
|
// switch (g()) {
|
||||||
// case 1: return 1;
|
// case 1: return 1;
|
||||||
// case 2:
|
// case 2: return 0;
|
||||||
// return 0;
|
|
||||||
// }
|
// }
|
||||||
public void testBranchesSwitch_Bug343767() {
|
public void testBranchesSwitch_Bug343767a() {
|
||||||
|
loadCodeAndRunCpp(getAboveComment());
|
||||||
|
checkErrorLine(1);
|
||||||
|
}
|
||||||
|
// int f()
|
||||||
|
// {
|
||||||
|
// switch (g()) {
|
||||||
|
// case 1: return 1;
|
||||||
|
// case 2: return 0;
|
||||||
|
// default: return -1;
|
||||||
|
// }
|
||||||
|
public void testBranchesSwitch_Bug343767b() {
|
||||||
loadCodeAndRunCpp(getAboveComment());
|
loadCodeAndRunCpp(getAboveComment());
|
||||||
checkNoErrors();
|
checkNoErrors();
|
||||||
}
|
}
|
||||||
|
@ -429,4 +439,13 @@ public class ReturnCheckerTest extends CheckerTestCase {
|
||||||
// Just check that codan runs without any exceptions being thrown.
|
// Just check that codan runs without any exceptions being thrown.
|
||||||
loadCodeAndRunCpp(getAboveComment());
|
loadCodeAndRunCpp(getAboveComment());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// int foo(int x) { // no warning
|
||||||
|
// switch (x) {
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
public void testEmptySwitch_455828() throws Exception {
|
||||||
|
loadCodeAndRunCpp(getAboveComment());
|
||||||
|
checkErrorLine(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue