Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What platforms have incompatible ABIs for C and C++?

Tags:

It has just come to my attention that the C++ standard says that C and C++ functions have different and incompatible types, even if their type signatures are the same (for more info see this question). That means that you technically are not allowed to pass a C++ function to a C function like pthread_create().

I am curious if there are any platforms in use where the two ABIs are actually different (aside from the obvious name mangling differences). Specifically, does anyone know of any platforms where this C++ program will fail to compile and run?

#include <assert.h>  extern "C" int run(int (*f)(int), int x) { return f(x); }  int times2(int x) { return x * 2; }  int main(int argc, char *argv[]) {   int a = times2(argc);   // This is undefined behavior according to C++ because I am passing an   // "extern C++" function pointer to an "extern C" function.   int b = run(&times2, argc);   assert(a == b);   return a; } 
like image 529
Josh Haberman Avatar asked May 17 '13 16:05

Josh Haberman


1 Answers

I don't know of any platforms where the ABI is different, but even if the C and C++ calling conventions are the same, the C++ standard requires the compiler to issue a diagnostic for the program. A pointer-to-function-with-C-language-linkage is a different type to a pointer-to-function-with-C++-language-linkage, so you should be able to overload run() like so:

extern "C" int run(int (*f)(int), int x) { return f(x); } extern "C++" int run(int (*f)(int), int x) { return f(x); } 

Now when you call run(times) it should call the second one, so it follows that the first one is not callable (there is no conversion from pointer-to-function-with-C-language-linkage to a pointer-to-function-with-C++-language-linkage) and so the original code should cause a compiler diagnostic. Most compilers get that wrong, though, e.g. http://gcc.gnu.org/bugzilla/show_bug.cgi?id=2316

N.B. The Solaris compiler does diagnose the incompatible language linkages, as a warning:

"t.c", line 11: Warning (Anachronism): Formal argument f of type extern "C" int(*)(int) in call to run(extern "C" int(*)(int), int) is being passed int(*)(int).

If you overload run with an extern "C++" function it correctly calls the extern "C++" one for run(times).

like image 107
Jonathan Wakely Avatar answered Oct 18 '22 21:10

Jonathan Wakely