Как заставить замолчать предупреждение «Последнее утверждение должно возвращать значение»? - PullRequest
3 голосов
/ 12 апреля 2011

Sun Studio 12.1 печатает предупреждение

Warning: The last statement should return a value.

часто для таких функций:

int f()
{
  /* some code that may return */

  // if we end up here, something is broken
  throw std::runtime_error("Error ...");
}

Совершенно очевидно, что нам не нужно возвращаемое значение в конце функции. Стесняюсь вставить что-то вроде

// Silence a compiler warning
return 42;

в конце такой функции, так как в любом случае это мертвый код. Для более сложных типов возвращаемых значений может быть трудно создать «разумное» поддельное значение.

Каков рекомендуемый способ заставить замолчать такое предупреждение?

Ответы [ 5 ]

4 голосов
/ 12 апреля 2011

Можете ли вы реорганизовать код в функции таким образом (возможно, более логичным), чтобы нормальный путь происходил в конце функции, чтобы можно было использовать возврат, а исключительный путь - раньше, а НЕ какпоследнее утверждение?

РЕДАКТИРОВАТЬ: Если реорганизация функции действительно не имеет смысла, вы всегда можете просто поставить фиктивный return 0; с комментарием.Лучше подавить предупреждение таким образом, чем глобально.

Если вы действительно хотите навсегда отключить предупреждение, вы можете использовать #pragma error_messages (off, wnoretvalue), но учтите, что предупреждение действительно полезно большую часть времени, поэтому я абсолютно не согласенне предлагаю отключить его.Вы можете использовать версию прагмы on для повторного включения предупреждения после функции, но компилятор все равно выдаст предупреждение, если ваша функция когда-либо встроена.Если вы поместите функцию в ее собственный исходный файл и используете прагму, которая должна относительно безопасно скрывать предупреждение, поскольку она не может повлиять на другие единицы перевода.

Другая действительно дурацкая возможность - перейти на g ++.Если вы не компилируете для SPARC, g ++ может генерировать лучший код, чем Sun studio.

3 голосов
/ 12 апреля 2011

Я считаю это идеальным местом для abort().Вы никогда не должны заканчиваться там, согласно вам, так что-то вроде:

UNREACHABLE("message")

, которое расширяется до:

#ifdef NDEBUG
  #define UNREACHABLE(Message_) abort();
#else
  #define UNREACHABLE(Message_) assert(0 && Message_);
#endif

Выглядит уместно

2 голосов
/ 12 апреля 2011

Поскольку вы знаете, что исключение будет вызываться систематически, почему бы вам просто не вернуть 0?

1 голос
/ 12 апреля 2011

Возможно инкапсулировать содержимое в конструкции do { } while (false);:

int my_function()
{
  int result = DEFAULT_VALUE;
  do
  {
     result = /*...*/
     // Whatever
     if (error)
     {
       throw std::runtime_error("Error ...");
     }
   } while (false);
   return result;
}

Идея состоит в том, чтобы при нормальной работе установить значение результата, а затем позволить потоку выполнения завершиться или использовать break для переходана return заявление.

0 голосов
/ 12 апреля 2011

Я не знаю "рекомендуемого" способа справиться с этим, но чтобы ответить на ваш вопрос о том, как справиться с более сложными типами, как насчет:

ComplexType foo()
{
    ...
    throw std::runtime( "Error..." );
    return *(ComplexType*)(0);
}

Это будет работать с любым возвратомтип.Я понимаю, что это выглядит злым, но его там просто, чтобы заставить замолчать предупреждение.Как вы говорите, этот код никогда не будет выполнен, и его даже можно оптимизировать.

...