calling convention for function pointers

The problem arises when compiling the PHP 5.3 code on x86. It seems
that Clang does not recognize calling conventions on function
pointers. For example,

typedef void (*__attribute__((fastcall)) foo_t)(int i);
foo_t fp = ...;
fp(42);

Clang ignores the `fastcall' attribute and produces a buggy executable.

Attached is a new patch with test code. 1) I am not sure if I used
`TargetDecl' in an appropriate way. 2) Though I tried to collect
usages in the attached test.c, some corner cases may be missing. 3)
The patch does not support member function pointers.

p.s. Currently Clang does not check incompatible pointer casts with
such attributes (e.g., from fastcall to cdecl). Should it report a
warning or something?

- xi

call.patch (3.34 KB)

test.c (549 Bytes)

Attached is a new patch with test code. 1) I am not sure if I used
`TargetDecl' in an appropriate way. 2) Though I tried to collect
usages in the attached test.c, some corner cases may be missing. 3)
The patch does not support member function pointers.

The current approach used for calling conventions isn't really
correct; we really ought to follow gcc and make the calling convention
part of the type. Otherwise, we can't handle the general case like
the following without some extremely ugly code; for example, take the
following:
__attribute((fastcall)) int a(int), b(int); void c(int x) { (cond ? a : b)(x); }

Not that this patch is necessarily unacceptable as a stopgap...

p.s. Currently Clang does not check incompatible pointer casts with
such attributes (e.g., from fastcall to cdecl). Should it report a
warning or something?

Are you talking about the assignment case, or explicit casts? The
assignment case would be covered by encoding the convention into the
type, and using it in compatibility checking. For explicit casts, I
don't think warning is a particularly good idea; the are legitimate
uses for such casts.

-Eli

The current approach used for calling conventions isn't really
correct; we really ought to follow gcc and make the calling convention
part of the type. Otherwise, we can't handle the general case like
the following without some extremely ugly code; for example, take the
following:
__attribute((fastcall)) int a(int), b(int); void c(int x) { (cond ? a : b)(x); }

I am not sure if the code could be accepted by gcc.

Not that this patch is necessarily unacceptable as a stopgap...

p.s. Currently Clang does not check incompatible pointer casts with
such attributes (e.g., from fastcall to cdecl). Should it report a
warning or something?

Are you talking about the assignment case, or explicit casts? The
assignment case would be covered by encoding the convention into the
type, and using it in compatibility checking. For explicit casts, I
don't think warning is a particularly good idea; the are legitimate
uses for such casts.

I meant something like:

void __attribute((fastcall)) foo(int x);
void (*bar)(int) = foo;

- xi

Type violations should be a hard error. Explicit casts should let the user hang themselves.