I’m experiencing an extremely weird problem in a fresh OSX 10.4.11 + Xcode 2.5 installation. I’ve reduced it to a minimal test case. Here’s test.cpp:
#include "macros.h"
int main (void)
{
return 1;
}
And here’s macros.h:
#ifndef __JUST_TESTING__
#define __JUST_TESTING__
template<typename T> void swap (T& pT1, T& pT2)
{
T pTmp = pT1;
pT1 = pT2;
pT2 = pTmp;
}
#endif //__JUST_TESTING__
This compiles and works just fine if both files are in the same directory. HOWEVER, if I put macros.h in /usr/include/gfc2 (it’s part of a custom library I use) and change the #include in test.cpp, compilation fails with this error :
/usr/include/gfc2/macros.h:4: error: template with C linkage
I researched that error and most of the comments point to a “dangling extern C”, which doesn’t seem to be the case at all.
I’m at a complete loss here. Is g++ for some reason assuming everything in /usr/include/gfc2 is C even though it’s included from a .cpp file that doesn’t say extern “C” anywhere?
Any ideas?
EDIT : It does compile if I use the full path in the #include, ie #include "/usr/include/gfc2/macros.h"
EDIT2 : It’s not including the wrong header. I’ve verified this using cpp, g++ -E, and renaming macros.h to foobarmacros.h
G++ may well indeed be assuming that everything in /usr/include is C. Try compiling your code with -E and studying the line markers in the preprocessor output:
You’ll likely see things like
The
4is the preprocessor hinting to G++ that it should wrap everything inextern "C", on the supposition that your platform’s ancient header files in /usr/include predate C++. See Preprocessor Output in the CPP manual.These days G++ mostly ignores this hint, because most platforms’ C headers are no longer ancient. See the
NO_IMPLICIT_EXTERN_Ctarget macro in the GCC Internals manual. But it may be that this old version of Xcode has GCC configured withoutNO_IMPLICIT_EXTERN_Cand thus is listening to the preprocessor’s hint. (This is set when GCC itself is built — I don’t think there’s a command-line switch to override it.)You may be able to work around this by wrapping the contents of your header file in
extern "C++".