porgarmingduod
porgarmingduod

Reputation: 7878

Why does the following method get internal linkage?

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

Answers (1)

porgarmingduod
porgarmingduod

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

Related Questions