3

Sun Studio 12.1 prints the warning

Warning: The last statement should return a value.

frequently for functions like that:

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

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

It is perfectly clear that we do not need a return value at the end of the function. I hesitate to insert something like

// Silence a compiler warning
return 42;

at the end of such a function, since it is dead code anyway. For more complicated return types, it might actually be difficult to construct a 'sensible' bogus value.

What is the recommended way to silence such a warning?

lytenyn
  • 819
  • 5
  • 21

5 Answers5

4

Can you reorganize the code in the function in such a way (hopefully more logical as well) that the normal path happens at the end of the function so that a return can be used, and the exceptional path happens earlier, NOT as the last statement?

EDIT: If reorganizing the function really doesn't make sense, you can always just put a dummy return 0; with a comment. It's better to squelch the warning that way than more globally.

If you really want to quiet the warning permanently, you can use #pragma error_messages (off, wnoretvalue) but note that the warning really is useful most of the time so I absolutely don't suggest turning it off. You can use the on version of the pragma to re-enable the warning after the function, but the compiler will still emit the warning if your function is ever inlined. If you put the function in its own source file and use the pragma that should shush the warning relatively safely though, since it can't affect other translation units.

Another really wacky possibility is to switch to g++. Unless you're compiling for SPARC g++ may actually generate better code than Sun studio.

Mark B
  • 95,107
  • 10
  • 109
  • 188
  • +1 I agree with this answer, if you are throwing an exception as the last line of a function, you should be able to reorganize the method to not do that. – Andy White Apr 12 '11 at 15:24
  • you are probably right about that in general, but actually the code is pretty sensible that way and I am not sure how to handle this any better the way you suggest. – lytenyn Apr 12 '11 at 15:29
3

I find it a perfect spot for abort(). You should never end there, according to you, so something like:

UNREACHABLE("message")

which expands into:

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

Looks appropriate

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
2

Since you know the exception will be systematically called, why don't you simply return a 0?

Charles Brunet
  • 21,797
  • 24
  • 83
  • 124
  • I must admit that I do not understand that answer. I somehow just consider returning 0 or 42 to be 'ugly'. What do you mean by 'systematically called'? – lytenyn Apr 12 '11 at 15:30
  • @lytenyn I mean the exception will always be thrown and the return will never be called. – Charles Brunet Apr 12 '11 at 15:33
  • well no, typically, the function returns something. It's just that if all possible paths are exhausted, the function throws an exception. – lytenyn Apr 12 '11 at 15:36
  • That's what i'm saying. It will either return something you want, or thrown the exception, so it will never call the last return, so the value there doesn't matter. – Charles Brunet Apr 12 '11 at 15:40
  • You are right. My question was whether there is a better way than returning an arbitrary value which I consider a bit ugly. – lytenyn Apr 12 '11 at 15:42
1

Perhaps encapsulate the contents in a do { } while (false); construct:

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

The idea is for normal operation to set the result value then let the execution flow to the end or use a break to jump to the return statement.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
0

I don't know of a "recommended" way to deal with it, but to answer your question about coping with more complex types, what about:

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

This would then work with any return type. I realise it looks evil, but its there just to silence the warning. As you say, this code will never be executed, and it may even be optimised out.

Steve Folly
  • 8,327
  • 9
  • 52
  • 63