# V591. Non-void function must return value.

Анализатор обнаружил non-void функцию, для которой существует путь исполнения, не возвращающий значение. Вызов такой функции ведёт к неопределённому поведению.

Если при исполнении тела non-void функции достигнут конец её тела без 'return', то произойдёт неопределённое поведение.

Рассмотрим пример:

    int GetSign(int arg)
    {
      if (arg > 0)
      {
        return 1;
      }
      else if (arg < 0)
      {
        return -1;
      }
    }

Если в функцию 'GetSign' передать 0, то произойдёт неопределённое поведение. Исправленный вариант:

    int GetSign(int arg)
    {
      if (arg > 0)
      {
        return 1;
      }
      else if (arg < 0)
      {
        return -1;
      }

      return 0;
    }

Исключением из правила являются функции 'main' и 'wmain'. Для этих функций достижение конца тела эквивалентно выполнению конструкции 'return 0;', поэтому неопределённого поведения не будет. Рассмотрим такой пример:

    ....
    int main()
    {
      AnalyzeFile(FILE_NAME);
    }

В данном случае имеем дело с функцией 'main'. Здесь не будет неопределённого поведения. Соответственно, не будет и выдано предупреждение анализатора. Фрагмент кода эквивалентен следующему:

    ....
    int main()
    {
      AnalyzeFile(FILE_NAME);
      return 0;
    }

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

Анализатор не выдаст предупреждение на следующем фрагменте кода:

    int Calc(int arg);

    int Bar(int arg)
    {
      if (arg > 0)
      {
        return Calc(arg);
      }
      throw std::logic_error { "bad arg was passed to Bar" };
    }

Также неопределённого поведения не будет, если в ходе выполнения тела такой функции произошел вызов другой функции, которая не возвращает управление. Такие функции обычно помечают '[[noreturn]]'. Поэтому анализатор не выдаст предупреждение на следующем примере:

    [[noreturn]] void exit(int exit_code);

    int Foo()
    {
      ....
      exit(10);
    }

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

CWE-393 CERT-MSC52-CPP

Взгляните на примеры ошибок, обнаруженных с помощью диагностики V591.