# V1087. Upper bound of case range is less than its lower bound. This case may be unreachable.

Анализатор обнаружил ситуацию, когда верхняя граница диапазона в метке 'case' меньше, чем его нижняя граница. Возможно, это опечатка, из-за которой часть кода может быть недостижима.

В компиляторах GCC и Clang существует расширение Case Ranges, которое позволяет вместо единственного значения метки 'case' указать диапазон константных значений. Такой диапазон будет аналогичен последовательности меток 'case', включая граничные значения:

    switch (....)
    {
    case 1 ... 3:
      // Do something
      break;
    }

    // Similar to the previous 'switch' statement
    switch (....)
    {
    case 1:
    case 2:
    case 3:
      // Do something
      break;
    }

Однако если верхняя граница указанного диапазона будет меньше, чем его нижняя граница, то диапазон будет считаться пустым. Если указать такой диапазон, то при проверке условия управление никогда не сможет быть передано метке. Следовательно, ветка кода может быть недостижимой.

Рассмотрим синтетический пример:

    void foo(int i)
    {
      switch (i)
      {
      case 1 ... 3:
        // First case
        break;
      case 6 ... 4:    // <=
        // Second case
        break;
      case 7 ... 9:
        // Third case
        break;
      }
    }

Здесь во второй метке были перепутаны местами константы '4' и '6', из-за чего управление никогда не будет передано метке. Исправленный пример:

    void foo(int i)
    {
      switch (i)
      {
      case 1 ... 3:
        // First case
        break;
      case 4 ... 6:    // <=
        // Second case
        break;
      case 7 ... 9:
        // Third case
        break;
      }
    }

Ошибка такого рода может возникнуть при неверном использовании именованных констант или значений, возвращаемых 'constexpr'-функциями. Рассмотрим синтетический пример:

    constexpr int for_yourself_min() noexcept { return 1; }
    constexpr int for_yourself_max() noexcept { return 3; }
    constexpr int for_neighbors_min() noexcept { return 4; }
    constexpr int for_neighbors_max() noexcept { return 6; }

    void distributeCats(int count)
    {
      switch (count)
      {
      case for_yourself_min() ... for_yourself_max():
        // Keep for yourself
        break;
      case for_neighbors_max() ... for_neighbors_min():      // <=
        // Give cats to neighbors
        break;
      default:
        // Give cats to a cattery
        break;
      }
    }

Во второй метке из-за опечатки вызовы функций были перепутаны местами, и управление никогда не будет передано метке. Исправленный пример:

    constexpr int for_yourself_min() noexcept { return 1; }
    constexpr int for_yourself_max() noexcept { return 3; }
    constexpr int for_neighbors_min() noexcept { return 4; }
    constexpr int for_neighbors_max() noexcept { return 6; }

    void distributeCats(int count)
    {
      switch (count)
      {
      case for_yourself_min() ... for_yourself_max():
        // Keep for yourself
        break;
      case for_neighbors_min() ... for_neighbors_max():      // <=
        // Give cats to neighbors
        break;
      default:
        // Give cats to a cattery
        break;
      }
    }

Однако неправильный диапазон не всегда ведет к недостижимому коду. Если в метке 'case' выше отсутствует 'break', то после выполнения его ветки управление будет передано в 'case' с пустым диапазоном. Синтетический пример:

    void foo(int i)
    {
      switch (i)
      {
      case 0: // no break
      case 3 ... 1:
        // First and second case
        break;
      case 4:
        // Third case
      default:
        // Do something
      }
    }

Несмотря на достижимость кода, пустой диапазон выглядит странно и бессмысленно. Это может быть опечатка или неправильное раскрытие макросов. Поэтому отсутствие 'break' в метке выше не является исключением для диагностики, а предупреждение будет выдано.

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

CWE-670