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

This diagnostic rule is based on the [MISRA](https://misra.org.uk/) \(Motor Industry Software Reliability Association\) software development guidelines\.

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:

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

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

* `statement*` `break;`\.
* C90: `{` `declaration*` `statement*` `break;` `}`\.
* C99 and later: `{ ` `(declaration | statement)*` `break;` `}`\. 
* C\+\+: `(declaration | statement)*` `termination-statement`\.

Where `*` means repeat 0 or more times\.

**Note**\. MISRA C\+\+ threats declarations to be executable statements, so declarations following a `case` label do not need to be enclosed in a `{...}` block\. Each branch must terminate with a termination statement: `break`, `return`, `throw`, `continue`, `goto`, or the `[[fallthrough]]` attribute\.

The example:

```cpp
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:

```cpp
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 example N1\. Erroneous `switch` statement:

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

The example N1 contains the following issues:

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

The example N2\. Erroneous `switch` statement:

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

The example N2 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` is redundant\.

The example N3\. Erroneous `switch` statement\.

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

The example N3 \([Duff's device](https://en.wikipedia.org/wiki/Duff%27s_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\.

Example N4\. Well\-formed `switch` statement:

```cpp
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; 
}
```