Анализатор обнаружил ситуацию, когда верхняя граница диапазона в метке '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' в метке выше не является исключением для диагностики, а предупреждение будет выдано.
Данная диагностика классифицируется как: