-O0处的内联函数导致clang中的链接失败

时间:2015-05-28 20:24:16

标签: c optimization clang inline c99

我正在尝试使用各种优化级别的clang编译以下代码:

#include <stdio.h>

inline int foo() { return 42; }

int main() {
    printf("%d\n", foo());
}

-O1-O2-O3-Os,它成功编译,但在使用-O0时失败:

$ clang -O0 -o main main.c
Undefined symbols for architecture x86_64:
  "_foo", referenced from:
      _main in main-8b9319.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

-O0(以及解决方法)的失败可以用Clang's inline compatibility来解释,但是无论优化级别如何,我都天真地期望这会失败。似乎在-O1及以上启用的某些优化正在做一些事情以防止发生此链接错误,但我很好奇它们是哪些优化以及为什么它们似乎具有与使用{{1}不同的语义单独在inline

1 个答案:

答案 0 :(得分:5)

-O1及更高版本,它没有调用该函数,只是将代码移动到main,我们可以通过使用显示asm的godbolt来看到这一点{{3} }:

main:                                   # @main
  pushq %rax
  movl  $.L.str, %edi
  movl  $42, %esi
  xorl  %eax, %eax
  callq printf
  xorl  %eax, %eax
  popq  %rdx
  retq

see it live

是哪个
  

[...]因为如果没有内联添加(例如,在没有优化的情况下编译时),那么main将有一个未解析的对其他定义的引用[...]

草案C99标准部分6.7.4 函数说明符

  

任何具有内部链接的函数都可以是内联函数。用于外部功能   链接,以下限制适用:如果使用内联函数说明符声明函数,则它也应在同一个转换单元中定义。如果所有的   翻译单元中函数的文件范围声明包括内联函数   没有extern的说明符,那么该翻译单元中的定义是内联的   定义。内联定义不提供函数的外部定义,   并且不禁止在另一个翻译单元中使用外部定义。内联定义   提供了外部定义的替代方案,翻译人员可以使用该定义来实现   在同一翻译单元中对该功能的任何调用。没有具体说明是否打电话给   函数使用内联定义或外部定义.22)

此网站对该语言有一个很好的解释:reference says