Consider the following example (in the same translation unit):
inline void f();
void f() {}
What happens at the redeclaration of f
? Is f
still considered inline
?
I looked in the standard for this situation but I only found the reverse of it in 10.1.6/6 [dcl.inline]:
[...] If the definition of a function or variable appears in a translation unit before its first declaration as inline, the program is ill-formed. [...]
I would like some references in the standard which specify what happens in this situation.
I saw this post, but it doesn't show an explicit reference in the standard. I'm inclined to believe there is no such reference.
What happens at the redeclaration of
f
? Isf
still consideredinline
?
Yes, f
is still considered inline
.
The relevant sections of the standard pertaining to the semantics of the inline
function specifier can be found in [dcl.fct.spec]:
A function declaration ... with an
inline
specifier declares an inline function. Theinline
specifier indicates to the implementation that inline substitution of the function body at the point of call is to be preferred to the usual function call mechanism.An inline function shall be defined in every translation unit in which it is odr-used and shall have exactly the same definition in every case ([basic.def.odr]). [ Note: A call to the inline function may be encountered before its definition appears in the translation unit. — end note ] If the definition of a function appears in a translation unit before its first declaration as inline, the program is ill-formed. If a function with external linkage is declared inline in one translation unit, it shall be declared inline in all translation units in which it appears; no diagnostic is required. An
inline
function with external linkage shall have the same address in all translation units.
And in [basic.def.odr]:
Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program
Also see an example in [dcl.stc]/8:
void h(); inline void h(); // external linkage inline void l(); void l(); // external linkage
The interpretation of all that is:
inline
as a function specifier acts as a flag, expressing your wish to have the call to the given function inlined. Once it is encountered on a certain function declaration, it remains "set" for that specific function overload, and there is no way to "unset" it.
It doesn't matter if you specify inline
on a declaration or a definition of a function, because a definition is also a declaration and because multiple declarations are allowed.
However, the inline
specifier must be encountered before or with the definition of the function and before it is odr-used (odr-use means the compiler needs to actually emit code that invokes the function, or needs its address for whatever reason).
The inline
specifier has no effect on the linkage of the function, which remains external for non-static global functions. If an address of an inline
function (that has external linkage) is taken, the compiler will emit an out-of-line definition for it, making sure the linker can fold multiple definitions if necessary (e.g. using a weak symbol). That way the address of the inline
function in different TUs will be the same.
Once a function is declared inline
and has external linkage, it must be declared inline
in all other translation units that odr-use it.
You must provide the definition of the inline
function in every translation unit that odr-uses it, and it must be exactly the same.