Reputation: 373
I am trying to get rid of violation og rule 16.1 from my code.
Sample code:
switch (cmd) {
case ADD:
result = add(op1, op2);
break;
case SUB:
if (!flag) { // Problem here!
break;
}
//Fallthrough
case ALU_CMD_SUB:
result = sub(op1, op2);
.
.
.
.
.
.
break;
case ALU_CMD_DIV:
result = divide(op1, op2);
break;
case ALU_CMD_EXP:
result = (int32_t)expo((uint32_t)op1, (uint32_t)op2);
break;
default:
incr_default(&default_cond);
//fix for the violation: insert a break statement
break;
}
Here the switch case with SUB is not well formed.
Is there any way to fix this issue without having much noise in the code.
This is also violating rule 16.3 where switch case doesn't have a break statement.
Upvotes: 1
Views: 13039
Reputation: 2312
The simplest answer to the question, if indeed the fallthrough is deliberate, is to raise a Deviation.
Attempts to circumvent the Rule, by trying to write clever code, makes things less clear, and less maintainable - a Deviation makes it clear what you are wanting to do, and means future maintainers do not make mistakes.
As an aside, it is proposed, for the next edition of the C standard, to add an annotation [[fallthrough]]
to convey that this is the expected behaviour! I am pretty sure MISRA C will recognize this attribute promptly after publication, and Rule 16.3 updated...
Upvotes: 0
Reputation: 213892
It is fairly trivial to fix:
case SUB:
SUB_stuff();
ALU_CMD_SUB_stuff();
break;
case ALU_CMD_SUB:
ALU_CMD_SUB_stuff();
break;
Let the compiler worry about how to translate the above to machine code with a minimum amount of branches.
These are very sound MISRA rules, as the presence of a "case fall-through" is very dangerous and almost always the result either from forgetting break
by accident or from a poor underlying design. I used to be a fan of "case fall-through" once, but eventually realised that the need for using such fall-throughs originates from muddy thinking elsewhere in the program.
Similarly, using it for code optimization purposes (such as "Duff's Device") is a thing of the 1980s and nowadays nothing but pre-mature optimization.
Upvotes: 2
Reputation: 753990
In context, meeting the letter of the MISRA law (Rule 16.3), you could consider:
switch (cmd) {
case ADD:
result = add(op1, op2);
break;
case SUB:
case ALU_CMD_SUB:
if (cmd == SUB && !flag) {
break;
}
result = sub(op1, op2);
.
.
.
break;
…
}
or perhaps:
switch (cmd) {
case ADD:
result = add(op1, op2);
break;
case SUB:
case ALU_CMD_SUB:
if (cmd == ALU_CMD_SUB || flag) {
result = sub(op1, op2);
.
.
.
}
break;
…
}
Upvotes: 1
Reputation: 2438
Fall through is a valid construct in C - it can improve code efficiency. One of the joys of having a lot of experience is knowing when it is alright to break 'rules'. In this case, where good engineering and code safety is important (*), document why this rule has been broken at this point.
I am assuming in this case that the if !flag
element should not be checked under ALU_CMD_SUB
, and that the SUB
element is a valid precursor to doing the ALU_CMD_SUB
element.
(*) The adoption of MISRA implies a heightened requirement for code safety.
Upvotes: -2