Reputation: 426
I have this project, where two other projects get included, that provide headers for the same DLL. In one header the declarations are put into a namespace, in the other one not. That works well for GCC and MSVC, but I can't convince clang to compile it.. So a minimal example would be:
x.h:
#include <string>
#if defined __GNUC__
# pragma GCC system_header
#endif // __GNUC__
namespace XX {
struct Type {
std::string name;
};
extern "C" int Func(Type);
}
incl.h:
#include <string>
#if defined __GNUC__
# pragma GCC system_header
#endif // __GNUC__
struct Type {
std::string name;
};
extern "C" int Func(Type);
main.cpp
#include "incl.h"
#include "x.h"
int main()
{
return 0;
}
G++ complains with a warning, but that is turned off with # pragma GCC system_header
.
So, how can I get clang to build in an environment like this?
Upvotes: 2
Views: 152
Reputation: 238441
[dcl.link] At most one function with a particular name can have C language linkage. Two declarations for a function with C language linkage with the same function name (ignoring the namespace names that qualify it) that appear in different namespace scopes refer to the same function. ...
As such, ::Func
and XX::Func
must refer to the same function. But your two declarations have different parameter lists - one takes a parameter of ::Type
while the other takes a parameter of XX::Type
. As such, they cannot be the same function, and thus the quoted rule is violated, and the program is ill-formed.ever
A few ways to fix the program:
XX::Func
or ::Func
so that they are separate functions. Make sure that there is a definition for each.incl.h
, include x.h
and replace the definition of ::Type
with using XX::Type
. So that each Type
refers to the same type, and consequently both function names refer to the same function. Make sure that there is only one definition.x.h
, include incl.h
and replace the definition of XX::Type
with using ::Type
. To achieve the same as above.The latter is by the way how some standard library implementations implement <cstdlib>
and its friends. They include the corresponding C standard library header (<stdlib.h>
in the case of <cstdlib>
) which declares everything in global namespace (the only "namespace" in C), and then they pick all of the standard functions and types into std
namespace with using ::whatever
.
P.S. Don't use #pragma GCC system_header
(unless you're writing a system header). It will suppress all warnings (except those produced by #warning
directive).
Upvotes: 3