Issue
I compiled this C++ code with g++
(7.3.0).
struct C {
__attribute__((noinline)) int foo() { return 0; };
};
int bar(C &c) { return c.foo(); }
And using nm
I found that foo
is weak. Is that due to the C++ specification or a decision of GCC?
The experiment flow:
$ g++ test.cpp -c -Og
$ nm test.o
0000000000000000 T _Z3barR1C
0000000000000000 W _ZN1C3fooEv
Solution
Is that C++ specification or decision of GCC?
A bit of both. Not that the C++ specification deals with strong or weak symbols (it doesn't). But it does affect GCC's behavior, since usually extensions try to build upon standard mandated behavior.
When you define a member function in the class body, it's automatically an inline function. In the C++ language, an inline function is a function that can have multiple definitions, so long as they appear in different translation units. It's not a problem, because in C++, an inline function must have the exact same definition in every translation unit (down to the token sequence). So even though they are "different" definitions, they are identical, and so can be reduced to a single one at some point.
The function doesn't have to actually be inlined at the call site. As far as C++ is concerend, inline
is about the one-definition rule and linkage. So you have that, there can be multiple definitions of C::foo
according to the spec.
And then you specify __attribute__((noinline))
, so the function cannot be physically inlined, and so every TU must contain a symbol for the function.
This leaves only one choice. The symbol must be weak, otherwise the different symbols in different translation units will interfere with eachother. By making the symbol weak, you can have your mandatory definition and avoid physically inlining the function, while the C++ specification is upheld. Those different symbols stand for the exact same function, and so any one of them can "win" when linking.
Answered By - StoryTeller - Unslander Monica Answer Checked By - Terry (WPSolving Volunteer)