Thanks to visit codestin.com
Credit goes to github.com

Skip to content

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

Merged
merged 1 commit into from
Jul 22, 2023
Merged

BUG: fix invalid function pointer conversion error #24212

merged 1 commit into from
Jul 22, 2023

Conversation

reckenrode
Copy link
Contributor

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.

`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.
@charris charris added the 09 - Backport-Candidate PRs tagged should be backported label Jul 19, 2023
@charris
Copy link
Member

charris commented Jul 19, 2023

@HaoZeke Thoughts?

@melissawm
Copy link
Member

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!

@reckenrode
Copy link
Contributor Author

@melissawm I can do that. I’ll report back with the results.

@seberg
Copy link
Member

seberg commented Jul 21, 2023

@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.
npy_intp is a rather "NumPy" type, so this is all on the NumPy/C wrapper (and not the fortran) side? Considering that int and npy_intp are very different beasts, was this just multiple incorrect function pointer casts cancelling out? Or the cast pointer isn't used?

@reckenrode
Copy link
Contributor Author

@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 f2py_init_func as follows:

typedef void (*f2py_init_func)(int *, npy_intp *, f2py_set_data_func, int *);

The following code in f90mod_rules.py generates a function with the following signature:

sargs.append(
'void (*%s)(int*,int*,void(*)(char*,int*),int*)' % (n))
sargsp.append('void (*)(int*,int*,void(*)(char*,int*),int*)')

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.

E                                  INFO: C compiler: clang -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -I/nix/store/cvha0krh3n4m7p3w2q532j509q6qpk7x-libxcrypt-4.4.36/include -ftrapping-math
E                                  
E                                  creating /private/tmp/nix-build-python3.10-numpy-1.24.2.drv-0/tmpgya1oeol/private
E                                  creating /private/tmp/nix-build-python3.10-numpy-1.24.2.drv-0/tmpgya1oeol/private/tmp
E                                  creating /private/tmp/nix-build-python3.10-numpy-1.24.2.drv-0/tmpgya1oeol/private/tmp/nix-build-python3.10-numpy-1.24.2.drv-0
E                                  creating /private/tmp/nix-build-python3.10-numpy-1.24.2.drv-0/tmpgya1oeol/private/tmp/nix-build-python3.10-numpy-1.24.2.drv-0/tmpgya1oeol
E                                  creating /private/tmp/nix-build-python3.10-numpy-1.24.2.drv-0/tmpgya1oeol/private/tmp/nix-build-python3.10-numpy-1.24.2.drv-0/tmpgya1oeol/src.macosx-11.0-arm64-3.10
E                                  INFO: compile options: '-DNPY_DISABLE_OPTIMIZATION=1 -I/private/tmp/nix-build-python3.10-numpy-1.24.2.drv-0/tmpgya1oeol/src.macosx-11.0-arm64-3.10 -I/nix/store/f22q2g1bcwiawawshapkzkaxsp0aar55-python3.10-numpy-1.24.2/lib/python3.10/site-packages/numpy/core/include -I/nix/store/qiz0aj04kzjq2hhc4q025vii9scbqpw1-python3-3.10.12/include/python3.10 -c'
E                                  INFO: clang: /private/tmp/nix-build-python3.10-numpy-1.24.2.drv-0/tmpgya1oeol/src.macosx-11.0-arm64-3.10/fortranobject.c
E                                  INFO: clang: /private/tmp/nix-build-python3.10-numpy-1.24.2.drv-0/tmpgya1oeol/src.macosx-11.0-arm64-3.10/_test_module_doc_TestModuleDocString_ext_modulemodule.c
E                                  /private/tmp/nix-build-python3.10-numpy-1.24.2.drv-0/tmpgya1oeol/src.macosx-11.0-arm64-3.10/_test_module_doc_TestModuleDocString_ext_modulemodule.c:192:31: error: incompatible function pointer types assigning to 'f2py_init_func' (aka 'void (*)(int *, long *, void (*)(char *, long *), int *)') from 'void (*)(int *, int *, void (*)(char *, int *), int *)' [-Wincompatible-function-pointer-types]
E                                    f2py_mod_def[i_f2py++].func = b;
E                                                                ^ ~
E                                  1 error generated.
E                                  error: Command "clang -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -I/nix/store/cvha0krh3n4m7p3w2q532j509q6qpk7x-libxcrypt-4.4.36/include -ftrapping-math -DNPY_DISABLE_OPTIMIZATION=1 -I/private/tmp/nix-build-python3.10-numpy-1.24.2.drv-0/tmpgya1oeol/src.macosx-11.0-arm64-3.10 -I/nix/store/f22q2g1bcwiawawshapkzkaxsp0aar55-python3.10-numpy-1.24.2/lib/python3.10/site-packages/numpy/core/include -I/nix/store/qiz0aj04kzjq2hhc4q025vii9scbqpw1-python3-3.10.12/include/python3.10 -c /private/tmp/nix-build-python3.10-numpy-1.24.2.drv-0/tmpgya1oeol/src.macosx-11.0-arm64-3.10/_test_module_doc_TestModuleDocString_ext_modulemodule.c -o /private/tmp/nix-build-python3.10-numpy-1.24.2.drv-0/tmpgya1oeol/private/tmp/nix-build-python3.10-numpy-1.24.2.drv-0/tmpgya1oeol/src.macosx-11.0-arm64-3.10/_test_module_doc_TestModuleDocString_ext_modulemodule.o -MMD -MF /private/tmp/nix-build-python3.10-numpy-1.24.2.drv-0/tmpgya1oeol/private/tmp/nix-build-python3.10-numpy-1.24.2.drv-0/tmpgya1oeol/src.macosx-11.0-arm64-3.10/_test_module_doc_TestModuleDocString_ext_modulemodule.o.d" failed with exit status 1

This is the generated code. You can see where b has a signature that does not match the one defined in fortranobject.h. The line f2py_mod_def[i_f2py++].func = b; is where clang 16 fails with the above error.

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);
}

npy_intp is a rather "NumPy" type, so this is all on the NumPy/C wrapper (and not the fortran) side? Considering that int and npy_intp are very different beasts, was this just multiple incorrect function pointer casts cancelling out? Or the cast pointer isn't used?

Is the question why this didn’t fail before? Clang 16 promoted -Wincompatible-function-pointer-types to an error by default. It can be downgraded back to a warning, but I’ve been trying to fix the errors instead of downgrading them to warnings and ignoring them.

'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]))
Copy link
Member

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?).

Copy link
Contributor Author

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?

@reckenrode
Copy link
Contributor Author

@melissawm I built SciPy 1.11.1 and ran the tests on the following hardware (both running macOS 13.4.1):

  • A Core i5-7600K iMac; and
  • An M1 Max MacBook Pro.

Build Notes

  • clang was clang 11 due to possible issues building SciPy with clang 16;
  • SciPy was 1.11.1 with OpenBLAS 0.3.21 using the nixpkgs derivation to automate the build; and
  • numpy was 1.24.2 built using the nixpkgs derivation including this patch.

Results

Only 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.

@seberg seberg merged commit b0ff5c5 into numpy:main Jul 22, 2023
@seberg
Copy link
Member

seberg commented Jul 22, 2023

Thanks for covering way more ground than probably necessary for this!

@reckenrode reckenrode deleted the clang16-f90mod_rules-fix branch July 23, 2023 19:55
@charris charris added this to the 1.25.2 release milestone Jul 23, 2023
@charris charris removed the 09 - Backport-Candidate PRs tagged should be backported label Jul 24, 2023
@charris charris removed this from the 1.25.2 release milestone Jul 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

Successfully merging this pull request may close these issues.

4 participants