不能内联函数定义之前的调用?

Calls that precede a function's definition cannot be inlined?

gcc documentation 包含以下内容:

When a function is both inline and static, if all calls to the function are integrated into the caller, and the function's address is never used, then the function's own assembler code is never referenced. In this case, GCC does not actually output assembler code for the function, unless you specify the option -fkeep-inline-functions. Some calls cannot be integrated for various reasons (in particular, calls that precede the function's definition cannot be integrated, and neither can recursive calls within the definition).

这对我来说总是听起来很荒谬——为什么现代编译器会那么愚蠢?经过快速测试后,它似乎不真实。

测试代码:

static inline int foo();

int bar() {
    return foo();
}

int foo() {
    return 42;
}

gcc-4.9.2 在 Linux 上的结果包含 bar() 的代码,但 none 包含 foo() 的代码。可以看到已经集成了foo()

bar:
.LFB0:
    .cfi_startproc
    movl    , %eax
    ret
    .cfi_endproc

如果我编译为 C++,结果是相同的,除了名称修改。

与文档相反,尽管 foo() 是在 bar() 中的调用之后定义的,但 foo() 已完全集成到 bar().

是我误解了文档还是不正确?也许对于一些更复杂的情况是正确的?

我不知道 "integrate" 和 "inline" 之间是否有技术上的区别,但我怀疑 "integrate" 被用来与关键字 inline 区分开来,它只是指的是函数内联(因此得名)。

这个问题被标记为 C 和 C++,因为这部分 gcc 文档属于 "C language family",我希望这两种语言的答案相同。

Gcc 曾经一次编译和优化一个函数,一旦它们被解析,就在解析下一个函数之前。 IIRC,他们只是在 4.X 时间范围内引入了 -funit-at-a-time 选项,该选项将优化推迟到阅读了整个编译单元之后,然后他们等待一些版本以默认启用它。

在调用之后定义内联函数的可能性可能已经作为 -funit-at-a-time 工作的一部分引入,并且内联的文档(关于定义之前的调用的提及至少可以追溯到 2.95)已经到时候没更新。