Reputation: 7878
I'm using clang-3.6
and compiling a sizeable project. After a massive re-factoring, a small number of seemingly random methods in a few classes cause warnings such as this:
warning: function 'namespace::X::do_something' has internal linkage but is not defined [-Wundefined-internal]
The same functions also show up as missing in the linker stage.
Here is the anonymized header for one such function definition in X.hpp
:
class X {
// ...
void do_something(
foo::Foo& foo,
double a
double b,
double c,
uint8_t d,
const bar::Bar& bar,
int dw, int dh);
// ...
}
The function is implemented in X.cpp
as normal. When Y.cpp
includes X.hpp
and does x->do_something
, the warning about internal linkage appears.
How can a method defined as above have internal linkage? What are all the circumstances under which a method gets internal linkage?
And seeing as this function, and others, used to compile just fine and have not even been touched during the refactoring, what kind of side effects (include order, type Foo and Bar) can cause a method to switch to internal linkage?
EDIT:
When I do a full source grep of do_something
, it gives three results:
X.hpp
: void do_something(
X.cpp
: void X::do_something(
Y.cpp
: x->do_something(
I also tried to change the name of do_something
into a long guaranteed unique name to rule out any possibility of name conflicts.
As far as I can tell, the posted method definition is unquestionably the one being flagged as having internal linkage.
Upvotes: 2
Views: 2475
Reputation: 7878
It was due to one of the types (i.e. foo:Foo
) being a template type where one of the template parameters had erroneously gotten internal linkage.
template <typename char const* Name> struct Foo{...};
const char constexpr FooBarName[] = "Bar";
using FooBar = Foo<FooBarName>;
The presence of FooBar in any argument list or as a return type would give that method internal linkage. Not even clang-3.8
with -Weverything
complained about having a template parameter with internal linkage.
The obvious fix was to properly use extern const char
for the template string parameter.
Upvotes: 3