The type within the cast (int (__attribute__((foo)) *)(void)) was misparsed because of the presence of the attribute (parse_btype prematurely concluded that (__attribute__() *) is a type. Also see testcase. This construct is used in sqlite it seems.
Unified · Split
| @@ -4180,7 +4180,7 @@ static int parse_btype(CType *type, AttributeDef *ad) · 4179 unmodified lines | ||
| 4180 | 4180 | u = ad->attr_mode -1; |
| 4181 | 4181 | t = (t & ~(VT_BTYPE|VT_LONG)) | u; |
| 4182 | 4182 | } |
| 4183 | − break; | |
| 4183 | + continue; | |
| 4184 | 4184 | /* GNUC typeof */ |
| 4185 | 4185 | case TOK_TYPEOF1: |
| 4186 | 4186 | case TOK_TYPEOF2: |
| @@ -16,4 +16,25 @@ void __attribute__((stdcall)) foo (void) · 15 unmodified lines | ||
| 16 | 16 | { |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | −int main () { return 0; } | |
| 19 | +/* The actual attribute isn't important, must just be | |
| 20 | + parsable. */ | |
| 21 | +#define ATTR __attribute__((__noinline__)) | |
| 22 | +int ATTR actual_function() { | |
| 23 | + return 42; | |
| 24 | +} | |
| 25 | + | |
| 26 | +extern int printf (const char *, ...); | |
| 27 | +int main() | |
| 28 | +{ | |
| 29 | + void *function_pointer = &actual_function; | |
| 30 | + | |
| 31 | + int a = ((ATTR int(*) (void)) function_pointer)(); | |
| 32 | + printf("%i\n", a); | |
| 33 | + | |
| 34 | + /* In the following we once misparsed 'ATTR *' is a btype | |
| 35 | + and hence the whole type was garbled. */ | |
| 36 | + int b = ( (int(ATTR *)(void)) function_pointer)(); | |
| 37 | + printf("%i\n", b); | |
| 38 | + | |
| 39 | + return 0; | |
| 40 | +} | |
| @@ -0,0 +1,2 @@ | ||
| 1 | +42 | |
| 2 | +42 | |