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

Диагностическое правило основано на руководстве MISRA (Motor Industry Software Reliability Association) по разработке программного обеспечения.

Правило актуально только для языка C.

В языке C конструкция `switch` обладает достаточно свободным синтаксисом. Отсутствие строгих правил может привести к написанию сложного неструктурированного кода. Для уменьшения вероятности допущения ошибки, а также для упрощения поддержки кода стандартом MISRA вводится понятие "well-formed" `switch`.

Чтобы пояснить, что такое "well-formed", введём ещё два определения:

1. `case-group` — последовательность из одного и более идущих подряд `case label` (которые могут включать `default`), например:

    case 42:
    //или
    case 1: case 2: case 300:
    //или
    case 12:
    default:

2. `switch-clause` — одно из следующего:

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

Где `*` означает повторение 0 или более раз.

Например:

    x = 5; y = 19; printf("%d", x); break;
    //или
    { int x; int y; x = 5; y = x + 1; printf("%d", x); break; }
    //или(кроме C90)
    { int x; x = 5; int y = x + 1; printf("%d", x); break; }

С учётом введённых определений "well-formed" `switch` можно представить в виде:

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

Также есть два дополнительных требования:

- метка `default` обязана присутствовать и либо стоять в начале первой `case-group`, либо в конце последней;
- Количество `case-group` должно быть не меньше двух.

Примеры некорректных `switch`-statement:

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

В данном примере присутствуют следующие нарушения:

- неправильно расположена метка `default`: она должна быть либо первой в списке меток, либо последней;
- некорректный `switch-clause` после `case 2`: он содержит декларацию, которая не находится внутри блока.

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

В данном примере присутствуют следующие нарушения:

- отсутствует метка `default`;
- так как вторая метка `case` входит в первую, то количество `case-group` меньше двух. В таком случае `switch-case` не имеет смысла.

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

В данном примере (знаменитый метод Даффа) присутствуют следующие нарушения:

- некорректный `switch-clause`: отсутствует `break`;
- некорректный `case-group`: метки `case 3`, `case 2`и `case 1` находятся внутри `switch-clause` и образуют последовательность `case-group`, которая не находится непосредственно внутри `switch-case`;
- отсутствует метка `default`.

Пример "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;
    }

Данная диагностика классифицируется как:

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