_______________________________________________
LLVM Developers mailing list
llvm...@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
Additional notes: I think the -fgnu89-inline & C99 inline semantics were
designed explicitly the way so that vague linkage
(https://itanium-cxx-abi.github.io/cxx-abi/abi/prop-72-comdat.html) can
be avoided. The C inline behaviors are like always explicit
instantiation in C++.
(Seems that GNU has extensions for weak symbols on the a.out binary
format. Otherwise, if a binary format has neither weak symbol nor
COMDAT, vague linkage is not representable.)
This is a user error. You may be looking for -fgnu89-inline & C99
inline documentation.
An extern inline definition is needed.
Inlining can paper over the user error. clang decides that inlining is
not good because the trip count is too large.
If you decrease the number of iterations, you may find that clang
inlines the function and the linker error goes away.
Clarification: According to the link provided earlier,
https://www.iar.com/knowledge/support/technical-notes/compiler/linker-error-undefined-external-for-inline-functions/
you need (exactly one) extern _declaration_ of the inline function, to keep it from vanishing.
inline int foo() { stuff; }
extern inline int foo(); // not a definition
int bar() { return foo(); }
--paulr
C++ `inline` means 'the definition is provided in line with the
declaration, the compiler and linker are responsible for ensuring that
exactly one definition exists in the final binary'
C `inline` means 'this definition is provided in line with a declaration
and may be used by the compiler in preference to one that a linker finds'
C `inline extern` means 'a definition of this may appear in line with
the declaration but please provide a canonical definition here for when
the compiler decides not to emit it'
C `inline static` means 'a definition exists here inline and it is not
an error if this is not used. If it is, then it is private to this
compilation unit and it is not an error for the same static function to
exist in multiple compilation units'.
*None* of these say anything about whether the compiler is required to
inline the function, but they all specify what must happen to the
original definition:
- C++ `inline`: Must exist in at least one compilation unit and the
linker must discard duplicates.
- C `inline`: Must be eliminated
- C `inline extern`: must be emitted, the linker should error if two
definitions of the same inline extern function exist in different
compilation units.
- C `inline static`: It must be emitted if references to it exist in
the object code but it may be eliminated if it is unused (including if
all uses of it are inlined).
Clang is generating IR that makes LLVM do exactly what the language
semantics require: eliminate the definition.
The `inline` keyword is probably the most confusingly named keyword in
C/C++, though `static` comes close. The general rule of thumb for C is:
- If you think you mean `inline` you probably mean `inline static`.
- If you're really sure you mean `inline`, you almost certainly mean
`__attribute__((always_inline))` or `__forceinline` (depending on
whether you're writing GNU or Microsoft-flavoured C)
- If you're not sure but think you might mean `inline`, you really
mean to be writing C++ and not C.
David
Also, note that the meaning of `extern inline` changed between C90 and
C99; it's one of the few semantic changes that are drastic changes
that I know of between C standard revisions. You can get the previous
behavior by either compiling with -std=c89/c90/gnu89, -fgnu89-inline,
or using __attribute__((gnu_inline)) on function definitions. The
behavior of the prior standard and gnu_inline was to NOT emit any
symbol; a definition was provided only for the purposes of inline
substitution.
We've actually used this in the Linux kernel to provide two
definitions of a function; one in C for inlining, one in assembler to
avoid stack protectors and other compiler instrumentation (such as
coverage and sanitizers), though now we have better constructs for
describing these intents.
> - C `inline static`: It must be emitted if references to it exist in
> the object code but it may be eliminated if it is unused (including if
> all uses of it are inlined).
>
> Clang is generating IR that makes LLVM do exactly what the language
> semantics require: eliminate the definition.
>
> The `inline` keyword is probably the most confusingly named keyword in
> C/C++, though `static` comes close. The general rule of thumb for C is:
>
> - If you think you mean `inline` you probably mean `inline static`.
> - If you're really sure you mean `inline`, you almost certainly mean
> `__attribute__((always_inline))` or `__forceinline` (depending on
> whether you're writing GNU or Microsoft-flavoured C)
It's also useful to note that always (in always_inline) doesn't mean
always. The machinery handling inline substitution can still bail. Use
-Rpass-missed=inline (or maybe -Rpass-missed=always-inline) to learn
*why*.
> - If you're not sure but think you might mean `inline`, you really
> mean to be writing C++ and not C.
>
> David
--
Thanks,
~Nick Desaulniers
No, it didn't. C90 has no inline. The change was between the language
extensions of many compilers and the new standard. That's quite a
different thing.
Joerg