question about function with linkage type AvailableExternallyLinkage

I am getting linkage errors when I try to compile foo1.c:

$: clang foo1.c -o foo1 -O3
/tmp/cc-VXVfGf.o:(.data+0x0): undefined reference to f1' /tmp/cc-VXVfGf.o:(.data+0x4): undefined reference to f2’
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I inspected the bitcode foo1.ll, and it seems that definitions of f1 and f2 are not emitted because their linkage types are “available_externally”.

Is this a bug?

// foo1.c
#include <stdlib.h>

typedef int (*ftype)(int);

inline int f1(int x) {
return x * 3;
}

inline int f2(int x) {
return x * 4;
}

ftype farray[] = {f1, f2};

int main(int argc, char** argv) {
int sum = 0, i;

for (i = 0; i < 2; ++i)
sum += (*farray[i])(atoi(argv[1]));

return sum;
}

// foo1.ll
; ModuleID = ‘foo1.c’
target datalayout = “e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32”
target triple = “i386-pc-linux-gnu”

@farray = global [2 x i32 (i32)*] [i32 (i32)* @f1, i32 (i32)* @f2], align 4

define available_externally i32 @f1(i32 %x) nounwind readnone inlinehint {
entry:
%mul = mul i32 %x, 3
ret i32 %mul
}

define available_externally i32 @f2(i32 %x) nounwind readnone inlinehint {
entry:
%mul = shl i32 %x, 2
ret i32 %mul
}

define i32 @main(i32 %argc, i8** nocapture %argv) nounwind {
entry:
%arrayidx4 = getelementptr inbounds i8** %argv, i32 1
%tmp2 = load i32 (i32)** getelementptr inbounds ([2 x i32 (i32)] @farray, i32 0, i32 0), align 4, !tbaa !0
%tmp5 = load i8** %arrayidx4, align 4, !tbaa !0
%call.i = tail call i32 @strtol(i8* nocapture %tmp5, i8** null, i32 10) nounwind
%call6 = tail call i32 %tmp2(i32 %call.i) nounwind
%tmp2.1 = load i32 (i32)** getelementptr inbounds ([2 x i32 (i32)] @farray, i32 0, i32 1), align 4, !tbaa !0
%tmp5.1 = load i8** %arrayidx4, align 4, !tbaa !0
%call.i.1 = tail call i32 @strtol(i8* nocapture %tmp5.1, i8** null, i32 10) nounwind
%call6.1 = tail call i32 %tmp2.1(i32 %call.i.1) nounwind
%add.1 = add i32 %call6.1, %call6
ret i32 %add.1
}

declare i32 @strtol(i8*, i8** nocapture, i32) nounwind

!0 = metadata !{metadata !“any pointer”, metadata !1}
!1 = metadata !{metadata !“omnipotent char”, metadata !2}
!2 = metadata !{metadata !“Simple C/C++ TBAA”, null}

Clang compiles C files in C99 mode by default. In C99, 'inline' is a promise that a non-inline declaration exists somewhere else in your program. Therefore, if the compiler doesn't actually inline the functions, it's supposed to emit an external reference instead of emitting them in this file.

You have five options, which I've listed in descending order of recommendation.
  - Make the functions 'static inline'. This will cause them to be emitted in this translation unit if they're used but not inlined. This is the best option if you don't need to call these functions from a different file.
  - Remove 'inline'. It isn't required in order to get the compiler to inline a function, and while we do honor it as an optimization hint, functions this small will always get inlined anyway. (Here it's impossible to inline because we can't statically prove what farray[i] will call, in part because farray is mutable.)
  - Make sure there's a different file in your program which provides non-inline definitions of these functions.
  - Compile the file with -std=gnu89, which will cause the functions to be emitted with strong linkage despite the 'inline'. gcc uses gnu89 by default.
  - Write this in C++ instead of C. In C++, you can provide definitions of inline functions in multiple translation units and they'll get automatically merged together by the linker.

John.

Okay, that explains the difference of linkage type assignment between clang and llvm-gcc.

Thank you for the clarification.