coptimizationinline

Will removal of all `inline` keywords from my code leave my C program semantically correct?


Note: the same question I've asked but for C++ is answered here: Will removal of all `inline` keywords for functions and methods leave my program semantically correct? . Given that C is a related but separate language that also happens to have inline, I am now looking for answers specific to C.


Inspired by the article "Why const Doesn't Make C Code Faster", I want to carry out a similar experiment in my code base, but for inline.

I have a feeling that a lot of code currently marked as inline does not help with anything. A few programmers I know still perceive the keyword as an optimization hint to the compiler.

At the same time, deciding to inline stuff often means that it has to be placed in headers, which negatively affects the program design (no isolation for unit testing, slower incremental build etc.), because everything has to know about everything, rather than being separated by interfaces inside separate independently deployable translation units.

It is not just my project that seems to be fond of using the static inline combination: there are 10k+ matches for static inline in Linux kernel source repository: https://sourcegraph.com/search?q=repo:%5Egithub%5C.com/torvalds/linux%24+%22static+inline%22&patternType=keyword&sm=0 (actually, over 85 thousand matches).

I want to produce a version of my code base that has as few inline keywords as possible left in it, then benchmark it and compare against the baseline measurements done on the unmodified code base.

Given how many occurrences of the keyword there are, I am interested in situations when removing an inline preserves semantics of a well formed program, and thus can be carried out automatically (i.e., by a find-and-replace).

Some situations and keyword combinations where inline can be encountered applied to function declaration and/or definition are listed below; most likely I have missed a few cases:

  1. inline function declaration/definition in a single .c file;
  2. inline function declaration/definition in a header included in many places (we can assume that the header guards or #pragma once are used);
  3. static inline function declaration/definition in a single .c file;
  4. static inline function declaration/definition in a header file.

I am mostly interested in standard portable C23, but if there are any cases when compiler choice or language revision specifics play any role, feel free to mention them.


Solution

  • Will removal of all inline keywords from my code leave my C program semantically correct?

    Not necessarily.

    You can safely remove inline from declarations and definitions of functions with internal linkage.

    It's more nuanced for inline functions with external linkage. If any of the declarations in a given translation unit of a given inline function with external linkage contain an explicit extern, then the definition in that translation unit (there must be one) is an external definition of the function. Otherwise, it is an inline definition, not an external definition, but if the function is called then there must be an external definition (not necessarily an inline one) provided by some other translation unit. If you remove inline from an inline definition then you get an external definition, which then duplicates at least one other external definition of that function identifier.

    So,

    1. inline function declaration/definition in a single .c file;

    ... removing inline from extern inline is safe. The program already has UB if the function is not explicitly declared extern in at least one of its declarations in the file, but that would be fixed by removing inline. If inline is removed then extern can safely be removed, too.

    1. inline function declaration/definition in a header included in many places (we can assume that the header guards or #pragma once are used);

    ... removing inline yields UB. Header guards or implementation-specific features having similar effect are not relevant to this.

    1. static inline function declaration/definition in a single .c file;

    ... removing inline is safe. If there is no external definition of the function elsewhere then removing static along with inline is safe, too.

    1. static inline function declaration/definition in a header file.

    ... removing inline is safe, provided that static is retained.