Hi cfe-dev,
I am using clang to compile C programs to LLVM IR. I have the following program:
struct A {
int (*f)(int, struct A*);
int (*g)(char, struct A*);
};
int h(int a, struct A* b) {
return 0;
}
int i(char a, struct A* b) {
return 1;
}
int main() {
struct A a;
a.f = h;
a.g = 0;
a.f(0, &a);
return 0;
}
Now, if I compile this to LLVM IR, the struct A becomes:
%struct.A = type { {}, i32 (i8, %struct.A)* }
So the type of function pointer f in A is {}* and the type of g (in A) is (just as I would expect of type i32 (i8, %struct.A*)*. Now, why is the type for f abbreviated like this? If I change the order of the functions in the C program by swapping the order of the definitions of h(…) and i(…), the type of the struct A becomes:
%struct.A = type { i32 (i32, %struct.A*), {} }
Now the type of f is spelt out completely as I would expect, but g’s type is given by {}. If I slightly change the type of the function pointers whose type becomes {} (e.g. changing “int” to “long” or something like this), I get their full types back again.
From what I can see, the function pointer types within struct A become {}* if they coincide with the type of the first function following the structure definition that involves the struct itself. In other words, if I put a function
int j() {
return 0;
}
between struct A and h, then everything stays as it is (i.e. one of the types is going to be {}*), but if I make it
int j(struct A* a) {
return 0;
}
the IR for %struct.A changes (and I suddenly get the full types for both function pointers).
How is the type {}* supposed to be interpreted here? Why is it, that depending on what follows, the type is “abbreviated” as {}* and sometimes not?
I am using AppleClang on Mac OS 10.12, but I get the same behavior with pre-built clang 3.9 downloaded from the LLVM website.
Best wishes,
Chris