# V2659. MISRA. Switch statements should be well-formed.

This diagnostic rule is based on the MISRA (Motor Industry Software Reliability Association) software development guidelines.

This diagnostic rule is relevant only for C.

The `switch` construct in C has fairly flexible syntax. A lack of strict rules can result in the creation of complex, unstructured code. To minimize errors and simplify code maintenance, MISRA introduces the concept of a "well-formed" `switch`.

To explain what "well-formed" means, we will introduce two more definitions:

1. `case-group` is a sequence of one or more consecutive `case label`s (which may include `default`), for example:

    case 42:
    // or
    case 1: case 2: case 300:
    // or
    case 12:
    default:

2. `switch-clause` is one of the following:

- statements* `break;`
- C90: `{` declarations* statements* `break; }`
- C99 and later: `{` (declarations | statements)* `break; }`

Where `*` means repeat 0 or more times.

The example:

    x = 5; y = 19; printf("%d", x); break;
    // or
    { int x; int y; x = 5; y = x + 1; printf("%d", x); break; }
    // or (except C90)
    { int x; x = 5; int y = x + 1; printf("%d", x); break; }

Considering the introduced definitions, a "well-formed" `switch` can look as follows:

    switch (expression)
    {
      case-group_1: switch-clause;
      case-group_2: switch-clause;
      ....
      case-group_n: switch-clause;
    }

There are two additional requirements:

- The `default` label must appear either at the beginning of the first `case-group` or at the end of the last one.
- There must be at least two `case-group`s.

The examples of erroneous `switch` statements:

      switch (n)
      {
        case 1:
        default:                               // <= (1)
        case 2: n++; int x = 0; x++; break;    // <= (2)
        case 3: { n++; break; }
      }

This example contains the following issues:

- the `default` label's position is incorrect: it must either be the first or the last label in the list;
- there is an incorrect `switch-clause` after `case 2`: it contains a declaration that is outside the block.

    switch (n)
    {
      case 10:
      case 20: break;
    }

This example contains the following issues:

- the `default` label is missing;
- since the second `case` label is included in the first one, the number of `case-groups` is less than two. In this case, `switch-case` does not make any sense.

    switch (count % 4)
    {
      case 0: do { *to = *from++;
      case 3:      *to = *from++;
      case 2:      *to = *from++;
      case 1:      *to = *from++;
                 } while (--n > 0);
    }

This example (the well-known Duff's device) contains the following issues:

- the incorrect `switch-clause`: `break` is missing;
- the incorrect `case-group`: the `case 3`, `case 2`, and `case 1` labels are inside the `switch-clause` and form a `case-group` sequence that is not directly inside the `switch-case`;
- the `default` label is missing.

The example of a "well-formed" `switch`:

    switch (n)
    {
      case 1: case 2: { n = 5; } break;
      case 10:
      case 20: break;
      case 30: { int x; x = 4; printf("%d", x); break; }
      default: if (n > 6) { n++; } break;
    }

This diagnostic is classified as:

MISRA-C-2012-16.1 MISRA-C-2023-16.1