-
-
Notifications
You must be signed in to change notification settings - Fork 10.9k
BUG: fix invalid function pointer conversion error #24212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
`f2py_init_func` is defined in `fortranobject.h` as: typedef void (*f2py_init_func)(int *, npy_intp *, f2py_set_data_func, int *); `f90mod_rules.py` attempts to assign functions with the following prototype to `func` of `struct FortranDataDef`: void(*)(int*, int*, void(*)(char*, int*), int*) This causes the `test_module_doc.py` test to fail when `npy_intp` is `long` and clang 16 is used as the compiler because the assignment is identified as an invalid function pointer conversion, which clang 16 treats as an error by default. Using `npy_intp` instead of `int` fixes the error.
@HaoZeke Thoughts? |
Hi @reckenrode - thanks for this, since you are already running tests can I ask you to also build SciPy from source and verify that the SciPy test suite runs successfully with this change? Just to be safe, as f2py is used extensively there. Thanks! |
@melissawm I can do that. I’ll report back with the results. |
@reckenrode sorry to ask, but this code is hard to track down (and I am not deep in f2py): Can you say where this ends up being used? Maybe that is which function gets cast incorrectly. |
The signature of numpy/numpy/f2py/src/fortranobject.h Line 54 in 8f15f5e
The following code in numpy/numpy/f2py/f90mod_rules.py Lines 163 to 165 in 8f15f5e
The combination of these two things results in an error when using f2py then building the resulting C code with clang 16. For example, test_module_doc.py, generates C code that fails to compile with the following error.
This is the generated code. You can see where static void f2py_setup_mod(char *i,char *x,char *a,void (*b)(int*,int*,void(*)(char*,int*),int*),char *foo) {
int i_f2py=0;
f2py_mod_def[i_f2py++].data = i;
f2py_mod_def[i_f2py++].data = x;
f2py_mod_def[i_f2py++].data = a;
f2py_mod_def[i_f2py++].func = b;
f2py_mod_def[i_f2py++].data = foo;
}
extern void F_FUNC(f2pyinitmod,F2PYINITMOD)(void (*)(char*,char*,char*,void (*)(int*,int*,void(*)(char*,int*),int*),char *));
static void f2py_init_mod(void) {
F_FUNC(f2pyinitmod,F2PYINITMOD)(f2py_setup_mod);
}
Is the question why this didn’t fail before? Clang 16 promoted |
'void (*%s)(int*,int*,void(*)(char*,int*),int*)' % (n)) | ||
sargsp.append('void (*)(int*,int*,void(*)(char*,int*),int*)') | ||
'void (*%s)(int*,npy_intp*,void(*)(char*,npy_intp*),int*)' % (n)) | ||
sargsp.append('void (*)(int*,npy_intp*,void(*)(char*,npy_intp*),int*)') | ||
iadd('\tf2py_%s_def[i_f2py++].func = %s;' % (m['name'], n)) | ||
fadd('subroutine %s(r,s,f2pysetdata,flag)' % (fargs[-1])) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, yeah. So the values passed are clearly intp
, so the change is correct from the C-side and we could probably also just use f2py_init_func
but maybe someone likes to be able to audit that it maches.
So the change is correct, and we can put it in. I am still confused, the f2pysetdata
takes care of intp
's size not being the default integer. I would have guessed that s
should be specified as that also, but I don't understand the following (or maybe it gets taken from f2pysetdata
even?).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added the generated Fortran to the gist. I don’t know if that helps.
I’m not very familiar with Fortran, but I’ve been trying to dig into the generated code to understand the issue. s
is defined in f90mod_rules.py
as np.intp().itemsize
. In the generated Fortran, it’s integer(8) s(*)
. That should be the same size as npy_intp
, right?
@melissawm I built SciPy 1.11.1 and ran the tests on the following hardware (both running macOS 13.4.1):
Build Notes
ResultsOnly one unexpected failure on on x86_64-darwin, which appears to be scipy/scipy#17125. All tests passed that should pass on aarch64-darwin. The logs are available in this gist. |
Thanks for covering way more ground than probably necessary for this! |
I am working on updating the Darwin stdenv in nixpkgs to clang 16. I ran into an issue building numpy with clang 16 due to an invalid function pointer conversion. This fix updates
f90mod_rules.py
to provide compatible prototypes.Test were run successfully on macOS 13.4.1(c) using clang 16 from nixpkgs on both aarch64-darwin and x86_64-darwin. The fix is covered by
f2py/tests/test_module_doc.py::TestModuleDocString::test_module_docstring
, which otherwise fails with clang 16.