From the C++11 draft, 7.5 (para. 1):
Two function types with different language linkages are distinct types even if they are otherwise identical.
So I can do overload based on language linkages:
extern "C" typedef void (*c_function)();
typedef void (*cpp_function)();
void call_fun(c_function f)
{
}
void call_fun(cpp_function f)
{
}
extern "C" void my_c()
{
}
void my_cpp()
{
}
int main()
{
call_fun(my_c);
call_fun(my_cpp);
}
But, with GCC 4.7.1 this sample code gives the error messages:
test.cpp: In function 'void call_fun(cpp_function)':
test.cpp:7:6: error: redefinition of 'void call_fun(cpp_function)'
test.cpp:4:6: error: 'void call_fun(c_function)' previously defined here
And with CLang++ :
test.cpp:7:6: error: redefinition of 'call_fun'
void call_fun(cpp_function f)
^
test.cpp:4:6: note: previous definition is here
void call_fun(c_function f)
^
Now the questions:
Is my understanding of the standard correct? Is this code valid?
Does anybody know if these are bugs in the compilers or if they are intentionally doing it that way for compatibility purposes?
extern "C" specifies that the function is defined elsewhere and uses the C-language calling convention. The extern "C" modifier may also be applied to multiple function declarations in a block. In a template declaration, extern specifies that the template has already been instantiated elsewhere.
By declaring a function with extern "C" , it changes the linkage requirements so that the C++ compiler does not add the extra mangling information to the symbol. This pattern relies on the presence of the __cplusplus definition when using the C++ compiler. If you are using the C compiler, extern "C" is not used.
the extern keyword is used to extend the visibility of variables/functions. Since functions are visible throughout the program by default, the use of extern is not needed in function declarations or definitions. Its use is implicit. When extern is used with a variable, it's only declared, not defined.
Using extern "C" lets the compiler know that we want to use C naming and calling conventions. This causes the compiler to sort of entering C mode inside our C++ code. This is needed because C++ compilers mangle the names in their symbol table differently than C compilers and hence behave differently than C compilers.
The code is clearly valid. G++ (and a number of other compilers) are a bit lax (to put it mildly) about integrating the linkage into the type.
It's a known bug in gcc, and they record that it's non-conforming since this bug blocks the uber-bug, "C++98 conformance issues".
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=2316
Check the creation date.
There's some discussion towards the end, about the practicalities of introducing a fix. So the answer to your last question is "both": it's a bug and the bug has intentionally been left in for compatibility.
Other compilers with the same issue might have made the error independently, but I think more likely they also know that it's wrong but want to be bug-compatible with gcc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With