This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: GNU C extension: Function Error vs. Success
- From: Andrew Haley <aph at redhat dot com>
- To: Shahbaz Youssefi <shabbyx at gmail dot com>, Julian Brown <julian at codesourcery dot com>
- Cc: gcc at gcc dot gnu dot org
- Date: Mon, 10 Mar 2014 17:18:12 +0000
- Subject: Re: GNU C extension: Function Error vs. Success
- Authentication-results: sourceware.org; auth=none
- References: <CALeOzZ8kAOepbUsqRNWnGvHc=vAGC2M_NkHZ6+VZz3ybfs59HA at mail dot gmail dot com> <20140310145046 dot 2d5c4ca0 at octopus> <CALeOzZ8On5R7t+3_gQ+ec5Sqi4P1ysCTLUMd0ck5UK7nKiCs+A at mail dot gmail dot com>
On 03/10/2014 03:09 PM, Shahbaz Youssefi wrote:
> Regarding C++ exceptions: exceptions are not really nice. They can
> just make your function return without you even knowing it (forgetting
> a `try/catch` or not knowing it may be needed, which is C++'s fault
> and probably could have been done better). Also, they require
> complicated operations. You can read a small complaint about it here:
> http://stackoverflow.com/a/1746368/912144 and I'm sure there are many
> others on the internet.
A few quibbles here.
Firstly, C++ exceptions do not require complicated operations: an
implementation may well do complicated things, but that's not the
same at all. In GCC we use DWARF exception handling, which is
designed to be near-zero-cost for exceptions that are not thrown,
but is more expensive when they are.
There is no inherent reason why
float inverse(int x)
{
if (x == 0)
fail;
return 1.0f / x;
}
y = inverse(x) !! goto exit_inverse_failed;
should not generate the same code as
float inverse(int x)
{
if (x == 0)
throw overflow;
return 1.0f / x;
}
try {
y = inverse(x);
} catch (IntegerOverflow e) {
goto exit_inverse_failed;
}
This assumes, of course, a knowledgeable optimizing compiler.
Also, consider that C++ can already do almost what you want.
Here we have a function that returns a float wrapped with a
status:
option<float> inverse(float x) {
if (x == 0)
return option<float>(); // No value...
return 1.0f / x;
}
float poo(float x) {
option<float> res = inverse(x);
if (res.none())
return 0;
return res;
}
GCC generates, quite nicely:
poo(float):
xorps %xmm1, %xmm1
ucomiss %xmm1, %xmm0
jp .L12
jne .L12
movaps %xmm1, %xmm0
ret
.L12:
movss .LC1(%rip), %xmm1
divss %xmm0, %xmm1
movaps %xmm1, %xmm0
ret
The difference between
y = inverse(x) !! goto exit_inverse_failed;
and
option<float> y = inverse(x);
if (y.none())
goto exit_inverse_failed;
is, I suggest to you, mere syntax. The latter is more explicit.
Andrew.