Consider this example:
int foo(void);
extern "C" int foo(void);
int main()
{
return foo();
}
It errors out with:
$ g++ -c main.cpp
main.cpp:2:16: error: conflicting declaration of ‘int foo()’ with ‘C’ linkage
2 | extern "C" int foo(void);
| ^~~
main.cpp:1:5: note: previous declaration with ‘C++’ linkage
1 | int foo(void);
| ^~~
Which is perfectly fine.
But lets swap first 2 lines:
extern "C" int foo(void);
int foo(void);
int main()
{
return foo();
}
Now it compiles without any error, but the C linkage is chosen, even though C++ linkage is found the last.
Questions:
Background: I have a C++ program where the function name occasionally clashed with the one in a C standard library. I would expect an error in such case, but it compiled fine and the wrong linkage was chosen. I need to either find a way of making it to fail consistently (to fix all such cases), or to force the selection of a C++ linkage for all conflicting functions.
extern "C" int foo(void);
int foo(void);
Here foo is declared with extern "C". Re-declaration does not specify a different calling convention, so no problem.
But,
int foo(void);
extern "C" int foo(void);
Here first line does not explicitly specify calling convention, so default C++ is implicitly chosen. Then second line does explicitly specify a different calling convention, creating a conflict.
So question 2... It is not possible to change calling convention after it is set by first declaration.
How to solve the problem... Use a different name for your C++ function. Or put it in a namespace. Or maybe isolate conflicting C++ name in a separate .cpp file, and export a different function (or just function pointer) for calling it elsewhere (see last paragraph below).
Another solution is to be careful about #include order, so the C++ function is always declared first. There is no "nice" solution to this, other than being pedantic about include order.
The only proper, valid solution is not have any symbols, which conflict with anything in C++ standard library. That is not allowed by C++ standard. Rename your own functions, or put them in your own namespace.
An important detail is, that the linker symbol for these functions is different. C++ does symbol name mangling to enable namespaces, methods and overloading. So it is possible for both functions to exist and be callable in a linked/running program. Problem is only at source code level.
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