Salim
Salim

Reputation: 373

MISRA C 2012 Rule 16.1 All switch statements should be well formed

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

Answers (4)

Andrew
Andrew

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

Lundin
Lundin

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

Jonathan Leffler
Jonathan Leffler

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

AJD
AJD

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

Related Questions