In C, if I call a static function from an inline function, I typically get a compiler warning like
warning: static function <name> is used in an inline function with external linkage [-Wstatic-in-inline]
According to the C23 standard 6.7.5.3:
An inline definition of a function with external linkage shall not contain, anywhere in the tokens making up the function definition, a definition of a modifiable object with static or thread storage duration, and shall not contain, anywhere in the tokens making up the function definition, a reference to an identifier with internal linkage
Is it not allowed to call a static function from an inline function? If so, why? Is it because a static function can use a non-const static variable, and if the definitions are included into several translation units, the different inline definitions will access different copies of the static variable via the static function which may be undesirable as demonstrated below?
inlinedef.h
static double a = 0;
static double f(void) {
a += 1;
return a;
}
inline double g(void) {
return f();
}
TU0.c
#include "inlinedef.h"
// External definition of inline function
double g(void);
TU1.c
#include "inlinedef.h"
#include <stdio.h>
void h1(void) {
printf("%f\n",g());
}
TU2.c
#include "inlinedef.h"
#include <stdio.h>
void h2(void) {
printf("%f\n",g());
}
Here, it is unspecified whether h1() and h2() are incrementing the same static variable or not because the compiler is free to choose whether to inline or use the external definition in TU0.c.
Let's say the static function does not use any static variables neither directly nor indirectly. Is there a way to call the static function from the inline function while adhearing to the C standard?
Motivation of question
There are some functions I need to inline into GPU kernels to make it compile and work, but I am not necessarily interested in inlining them when compiling for CPU. I don't think I want to make them static inline since it will force inlining or copying into each TU which results in unnecessary bloat if the functions are large.
static inline double g(void) ...staticis normally enough by itself for the compiler to inline the function, unless it's very large and called from a lot of places. And even theinlinekeyword is officially just a suggestion.static inlineinstead ofinline, then the static variable will be duplicated into the different translation units, and the behaviour is uniquely specified as opposed to when the compiler can choose to use an external definition.