
GCC: the impressive and the disappointing - mbrubeck
http://blog.reverberate.org/2011/03/03/gcc-the-impressive-and-the-disappointing/
======
kragen
For those who are wondering what the issue could possibly be, if you use the
Pascal calling convention in which you push the parameters on the stack and
the callee pops them off, then you'll crash when you try to return from a
function that was passed the wrong number of parameters. It's perfectly valid
for a C compiler to use that calling convention, at least for some functions.
It's not traditional, and you need another calling convention for variadic
functions, and ANSI C prototypes are a really good idea in that case, but it's
certainly valid.

I'm so sure it's valid not because I've actually read the C standard, but
because the whole Win16 API was called this way, and Win32 uses a slight
variation that passes more things in registers.

Further reading:

[http://blogs.msdn.com/b/oldnewthing/archive/2004/01/02/47184...](http://blogs.msdn.com/b/oldnewthing/archive/2004/01/02/47184.aspx)
<http://en.wikipedia.org/wiki/X86_calling_conventions>
<http://unixwiz.net/techtips/win32-callconv.html>
<http://webster.cs.ucr.edu/Page_win32/IczelionTuts/tut1.html>

~~~
jckarter
This is incorrect. It's not possible to implicitly use an incompatible ABI for
prototyped and vararg functions, since a foo f(bar, bas) function needs to be
callable via an unprototyped foo (* )() pointer. Thus, even prototyped C
functions need to use a caller-cleanup convention. To use the callee-cleanup
convention, the entire Win16 and Win32 apis are annotated with explicit
__stdcall attributes and are addressed by distinctly-typed (__stdcall * )
function pointers, of which no vararg variation is allowed.

~~~
haberman
I really wish this were true since it would solve my original problem, but
after reading the standard I don't think this is true. From c99, 6.5.2.2 p6:

"If the expression that denotes the called function has a type that does not
include a prototype, the integer promotions are performed on each argument,
and arguments that have type float are promoted to double. These are called
the default argument promotions. If the number of arguments does not equal the
number of parameters, the behavior is undefined."

I take the last sentence to mean that an unprototyped function pointer may
only be used to call a function that takes zero parameters.

~~~
ajross
That's not what it says. The last statement is talking about what happens at
runtime (i.e. the number of values on the stack vs. the number expected, _not_
the number of values passed vs. declared).

Obviously if you don't pass the right number of parameters, the function
behavior is undefined (i.e. a pascal function will of course muck up the
stack)

------
ajg1977
unions are well known for scaring compilers away from many types of
optimizations when encountered. For example, if you're writing a SIMD vector
class then pretty much the worst thing you can do is put the SIMD data type in
a union with a float array.

~~~
haberman
The union is irrelevant, even with a union the compiler eliminated the branch
in another test I ran where both functions had the same prototype. I'm on an
iPad at the moment so can't verify, but I'd be willing to bet that exactly the
same code would be generated if the two function pointers were passed as
separate parameters (ie not in a union)

