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