psmedley / gcc

GNU General Public License v2.0
7 stars 1 forks source link

__cdecl implies extern "C" for functions in C++ code #18

Open dmik opened 8 years ago

dmik commented 8 years ago

It seems that gcc 4.x.x for OS/2 causes functions to be declared using extern "C" semantics when they have __attribute__((__cdecl__)) attached to them. E.g. for this declaration in C++ context

void __attribute__((__cdecl__)) foo (void **v);

the resulting assembler name (signature) will be _foo instead of __Z3fooPPv (which is the case if _cdecl gets removed). This is not the case with gcc 3.x.x for OS/2 or with gcc 4.x.x on other platforms (e.g. OS X) and looks like a regression of my change that made functions declared as _System in C++ context imply extern "C" (for compatibility with IBM VAC).

Frankly saying there are not many places where it breaks things, but one known case is VirtualBox. The RTCALL calling convention there is defined as __cdecl on OS/2 which causes all functions declared with RTCALL (and with RTDECL which implicitly uses it) to get C signatures instead of C++ ones. For some functions defined in C++ context this brings obvious problems, e.g. for overloaded operators that have the same name by definition (like operator+) but different sets of arguments. This eventually results in several functions with the same signature and the following compiler error:

In file included from D:/Coding/vbox/trunk/src/VBox/Runtime/common/string/ministring.cpp:34:0:
D:/Coding/vbox/trunk/include/iprt/cpp/ministring.h:1024:79: error: conflicting declaration of C function 'const RTCString operator+(const RTCString&, const char*)'
 RTDECL(const RTCString) operator+(const RTCString &a_rstr1, const char *a_psz2);
                                                                               ^
D:/Coding/vbox/trunk/include/iprt/cpp/ministring.h:1013:25: note: previous declaration 'const RTCString operator+(const RTCString&, const RTCString&)'
 RTDECL(const RTCString) operator+(const RTCString &a_rstr1, const RTCString &a_rstr2);
                         ^
D:/Coding/vbox/trunk/include/iprt/cpp/ministring.h:1035:79: error: conflicting declaration of C function 'const RTCString operator+(const char*, const RTCString&)'
 RTDECL(const RTCString) operator+(const char *a_psz1, const RTCString &a_rstr2);
                                                                               ^
D:/Coding/vbox/trunk/include/iprt/cpp/ministring.h:1024:25: note: previous declaration 'const RTCString operator+(const RTCString&, const char*)'
 RTDECL(const RTCString) operator+(const RTCString &a_rstr1, const char *a_psz2);
                         ^
D:/Coding/vbox/trunk/include/iprt/cpp/ministring.h:1035:79: error: conflicting declaration of C function 'const RTCString operator+(const char*, const RTCString&)'
 RTDECL(const RTCString) operator+(const char *a_psz1, const RTCString &a_rstr2);
                                                                               ^
D:/Coding/vbox/trunk/include/iprt/cpp/ministring.h:1013:25: note: previous declaration 'const RTCString operator+(const RTCString&, const RTCString&)'
 RTDECL(const RTCString) operator+(const RTCString &a_rstr1, const RTCString &a_rstr2);
dmik commented 8 years ago

I need to review my _System patch. For the time being we have to avoid using explicit _cdecl with global functions defined in C++ context.