Bug 86360 - "inline" (and neither static nor extern) function not emitted.
Summary: "inline" (and neither static nor extern) function not emitted.
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 8.1.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-06-29 09:39 UTC by David Woodhouse
Modified: 2018-06-29 10:21 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description David Woodhouse 2018-06-29 09:39:30 UTC
https://gcc.gnu.org/onlinedocs/gcc/Inline.html says:

> When an inline function is not static, then the compiler must assume
> that there may be calls from other source files; since a global symbol
> can be defined only once in any program, the function must not be defined
> in the other source files, so the calls therein cannot be integrated. 
> Therefore, a non-static inline function is always compiled on its own
> in the usual fashion. 

Either I misunderstand that, or it isn't true:

$ cat foo.c

inline int foo(int a)
{
	return a+1;
}

int main(int a)
{
	return foo(a);
}

$ gcc -O0 -o- -S foo.c
	.file	"foo.c"
	.text
	.globl	bar
	.type	bar, @function
bar:
.LFB1:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	subq	$16, %rsp
	movl	%edi, -4(%rbp)
	movl	-4(%rbp), %eax
	movl	%eax, %edi
	call	foo
	leave
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE1:
	.size	bar, .-bar
	.ident	"GCC: (GNU) 8.1.1 20180502 (Red Hat 8.1.1-1)"
	.section	.note.GNU-stack,"",@progbits


Note the 'foo' function doesn't get emitted.

cf. https://github.com/openwrt/packages/pull/6377#issuecomment-401084671
    http://lists.osmocom.org/pipermail/osmocom-sdr/2018-June/001791.html
Comment 1 Jonathan Wakely 2018-06-29 09:41:20 UTC
"The remainder of this section is specific to GNU C90 inlining." and you're compiling with the defaultoptions, which means -std=gnu99 so you get C99 inlining.
Comment 2 Jonathan Wakely 2018-06-29 09:43:30 UTC
Use -std=gnu90 to get GNU 90 semantics, and a definition emitted.

See "Different semantics for inline functions" at https://gcc.gnu.org/gcc-5/porting_to.html for more details.
Comment 3 David Woodhouse 2018-06-29 09:46:29 UTC
Thanks for the prompt response.

I'll stick with my original "compiler isn't required to emit" comment in my referenced patch submission, which everyone had questioned...
Comment 4 Jonathan Wakely 2018-06-29 09:57:41 UTC
More than that, I don't think it's allowed to. See 6.7.4 p7 in the C11 standard.

"An inline definition does not provide an external definition for the function,
and does not forbid an external definition in another translation unit."
Comment 5 David Woodhouse 2018-06-29 10:05:32 UTC
Well, it's *allowed* to emit it inline. But if it doesn't then it mustn't emit it out-of-line. At least, from your citation, it mustn't emit it out-of-line such that it can be seen from another translation unit.

I'm not sure if it would be permitted for a compiler to emit that function as a static (but out-of-line) function. Perhaps if there's no extern definition of the same function, that might be a reasonable thing for a compiler to do?

But frankly I don't care much either. I already submitted a patch to make the code that offended me use 'static inline', and although I allowed myself to be talked into filing this PR I'm more than happy just to point at the response and say "no, my initial analysis was correct".

Thanks again.
Comment 6 Jonathan Wakely 2018-06-29 10:21:49 UTC
(In reply to David Woodhouse from comment #5)
> Well, it's *allowed* to emit it inline. But if it doesn't then it mustn't
> emit it out-of-line. At least, from your citation, it mustn't emit it
> out-of-line such that it can be seen from another translation unit.
> 
> I'm not sure if it would be permitted for a compiler to emit that function
> as a static (but out-of-line) function.

It's allowed to, yes. It could produce a definition with internal linkage and make the call go to that, which would not depend on an external definition existing elsewhere.

"An inline definition provides an alternative to an external definition, which a translator may use to implement any call to the function in the same translation unit. It is unspecified whether a call to the function uses the inline definition or the external definition."

Using the inline definition doesn't actually require any code to be inlined into the caller, it could just emit a definition with internal linkage and emit a call to that instead.

> Perhaps if there's no extern
> definition of the same function, that might be a reasonable thing for a
> compiler to do?

Yes. It would avoid a linker error if there is no corresponding extern definition elsewhere in the program.

I think in practice what GCC does is either inline the code into the caller (but only when optimization is enabled) or emit a call to an extern function (which then needs to exist).

> But frankly I don't care much either. I already submitted a patch to make
> the code that offended me use 'static inline', and although I allowed myself
> to be talked into filing this PR I'm more than happy just to point at the
> response and say "no, my initial analysis was correct".

Agreed.