views:

178

answers:

4

When calling functions that always throw from a function returning a value, the compiler often warns that not all control paths return a value. Legitimately so.

void AlwaysThrows() { throw "something"; }

bool foo()
{
    if (cond)
        AlwaysThrows();
    else
        return true; // Warning C4715 here
}

Is there a way to tell the compiler that AlwaysThrows does what it says?

I'm aware that I can add another throw after the function call:

{ AlwaysThrows(); throw "dummy"; }

And I'm aware that I can disable the warning explicitly. But I was wondering if there is a more elegant solution.

+2  A: 

With Visual C++, you can use __declspec(noreturn).

Michael
Is there a portable solution to that?
LiraNuna
Porable: no, there's nothing like this in the language specification. GCC understands __attribute__((noreturn)), if that helps...
ephemient
+6  A: 

You could add a dummy return statement after the call to AlwaysThrows(), with a comment explaining why it's there. This is also useful when the function you're calling always exit()s or abort()s.

Jesse Hall
That is what we do at our shop. It is the easiest way to avoid the compiler complaints. You must be sure, though that the function does always throw.
David Rodríguez - dribeas
+4  A: 

Of course, one question is why would you write code like that in the first place.? The obvious answer to that is that AlwaysTrows() is actually an error reporting function of some kind. In my own code, I actually use a macro to do error reporting, because it lets me perform string formatting & get at the standatd __LINE__ and __FILE__ macros. The macro looks roughly like this:

#define ATHROW( msg )              \
{                   \
    std::ostringstream os_;           \
    os_ << msg;              \
    throw ALib::Exception( os_.str(), __LINE__, __FILE__ );   \
}

where the exception constructor does any extra formatting, extra logging etc. A side effect of this is of course thatv the compiler can see that an exception is being thrown, so that when I say something like:

int f() int val ) {
   if ( val >= BADVALUE ) {
       ATHROW( "Invalid value " << val << " for val" );
   }
   else {
       return val / 3;
   }
}

then I won't get a warning about f() not returning a value.

anon
I generally deplore the use of macros, however they are just so damn handy for throwing exceptions!!
0xC0DEFACE
+1  A: 

i've run into this annoying little problem as well. Usually the scenario involves:

  1. There are a few common lines of code in several catch blocks that i'd like to refactor
  2. All of the aforementioned catch blocks ultimately rethrow the exception.

While you can put a dummy return after the always-throwing method, that will probably offend your Programmer's OCD.

The compromise I use is to instead of having the called method throw it's exception, return it instead. Then, when you call the method just throw the return value:

Exception HandleException() 
{ 
    // Do stuff, like some logging maybe
    return SomeException("something"); 
}

bool foo()
{    
   if (cond)        
       throw HandleException();    
   else        
       return true; // no more warning

}

This way, you don't have to add any extra lines of code.

As written, this appears to slice SomeException into Exception. Is that what you expect to happen?
TokenMacGuy