Suppose I have a setup like so (Godbolt link):
// header.h
#pragma once
int g(int val);
// main.cpp
#include "header.h"
int main() {
return g(1);
}
// g.cpp
#include "header.h"
class C {
/*[[gnu::used]]*/ friend int g(int val) {
return val;
}
};
If I compile g.cpp
to g.o
, and main.cpp
to main.o
, and try to link them, I get the following linker error:
main.cpp:5:(.text+0xa): undefined reference to `g(int)'
Adding the [[gnu::used]]
attribute to the definition of g
in g.cpp
fixes the issue.
So what seems to be happening is that GCC (and clang exhibits the same behavior) does not realize that the definition of g
in g.cpp
is used, and so it does not include it in g.o
, unless we explicitly tell it to with [[gnu::used]]
. (But if we had simply written g
as a regular function definition in g.cpp
, and not a friend, the compiler would include it in g.o
and there would be no linker error.)
My question is essentially how does the compiler (I'm mainly interested in GCC and clang) determine which function definitions need to be included in the object file? Is there something in the standard affecting whether such a friend definition is considered accessible that causes this, or is it simply an implementation detail?
g
is implicitly inline
as inside class definition.
And you will have identical behavior without the friendship Demo
According to One Definition Rule (ODR)
For an inline function or inline variable(since C++17), a definition is required in every translation unit where it is odr-used .
And it is not the case in main
.