From 3800c0e96839a4f2209f4047428e88abeb21658e Mon Sep 17 00:00:00 2001 From: Alex Dowad Date: Wed, 17 Jun 2020 23:02:38 +0200 Subject: [PATCH] In FFI, assume that identifier is a typedef if followed by '*' in parameter list Bug #79576 (https://bugs.php.net/bug.php?id=79576) reports that the error message shown by FFI when parsing a C function declaration which uses typedef's it doesn't know about can be confusing. For example, given this definition: int func(oid *); Since FFI has not seen a typedef for 'oid', it treats 'oid' as being the name of a parameter. But since it is followed by '*', it fails with this message: unsupported type specifier combination Interestingly, GCC is able to detect that 'oid' is a type name and reports: unknown type name 'oid' Implement a simple workaround: If the identifier in the above case is directly followed by '*', take it as being a typedef. This does not actually allow the parse to succeed, but does make it fail with a more informative message: undefined C type 'oid' Since this fix is quite simplistic, there are probably more complicated cases where it will still not display the most informative error message. --- ext/ffi/ffi.g | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/ext/ffi/ffi.g b/ext/ffi/ffi.g index 4d7c00390611d..e26ee60e7ca35 100644 --- a/ext/ffi/ffi.g +++ b/ext/ffi/ffi.g @@ -65,6 +65,21 @@ php llk.php ffi.g static void yy_error(const char *msg); static void yy_error_sym(const char *msg, int sym); +static int get_sym(void); +static int peek_sym(void) { + unsigned const char *saved_text = yy_text; + unsigned const char *saved_pos = yy_pos; + int saved_line = yy_line; + + int sym = get_sym(); + + yy_text = saved_text; + yy_pos = saved_pos; + yy_line = saved_line; + + return sym; +} + %} declarations: @@ -143,7 +158,7 @@ declaration_specifiers(zend_ffi_dcl *dcl): specifier_qualifier_list(zend_ffi_dcl *dcl): "__extension__"? - ( ?{sym != YY_ID || zend_ffi_is_typedef_name((const char*)yy_text, yy_pos - yy_text)} + ( ?{sym != YY_ID || zend_ffi_is_typedef_name((const char*)yy_text, yy_pos - yy_text) || peek_sym() == YY__STAR} ( type_specifier(dcl) | type_qualifier(dcl) | attributes(dcl)