Compiler error for conflicting variable declaratio

2019-07-09 06:39发布

问题:

I ran across some legacy code that's failing to build on a newer compiler. The boiled down example:

int x;
extern "C" { int x }; // conflicts with C++ linkage above
// note: without the braces it would've been equivalent to:
// extern "C" { extern int x; }
//
// for reference, see the notes section here:
//   http://en.cppreference.com/w/cpp/language/language_linkage#notes

The older compilers weren't flagging it, but both gcc (as of 4.1.2) and clang flag it.

Clang's output:

error: declaration of 'x' has different language linkage

GCC's output:

error: previous declaration of 'int x' with 'C++' linkage
error: conflicts with new declaration with 'C' linkage

This surprised me because the compiler doesn't mangle x in any special way, and as far as I can tell nothing is different about the object file other than debug information (based on my admittedly shallow test with objdump/readelf)

My question: why is this an error if there's no functional difference?

As an aside, I'm not averse to changing the code; I wanted to know whether there was something more going on than just "the standard says this is ill formed".

回答1:

I looked through the various *stack sites and mostly found questions on this topic relating to functions with conflicting linkage specifications.

I found my [first] answer in the gcc bugzilla database:

The standard says in 7.5/5: "If two declarations of the same function or object specify different linkage-specifications [...] the program is ill-formed if the declarations appear in the same translation unit [...]". That is why code like that in comment 6 is now rejected.

Whether my supposition is correct (about the functional difference between C/C++ linkage for POD variables) or not, it appears the error is intended to prevent bad style.

Then I found this article about storage class specifiers and one about language linkage. I didn't see anything in those articles conflicting with what I've learned so far; the 2nd one says:

Likewise, two variables in the same namespace cannot have two different language linkages.