capi foreign imports involving pointers to pointers to non-primitive types don't compile with recent C compilers
## Summary
Recent versions of `gcc` and `clang` treat `-Wincompatible-pointer-types` as an error by default.
The problem with this is that `capi` compiles pointers of types that aren't obvious primitives to void pointers.
Most of the time this is fine, since `-Wincompatible-pointer-types` includes an exception that allows passing void pointers to functions that accept more specific pointers, however that exception does *not* include passing `void**` to functions that accept pointers to more specific pointers, so the C compiler will still fail in that case.
## Steps to reproduce
Define a C header `example.h`
```c
typedef struct abstract abstract;
void blah(abstract** x) {}
```
And import it in a Haskell module with `capi`
```hs
{-# LANGUAGE CApiFFI #-}
module Example where
import Foreign (Ptr)
import Foreign.C (CUInt)
data Abstract
foreign import capi "example.h blah"
blah :: Ptr (Ptr Abstract) -> IO ()
```
Which produces the following error message:
```
[1 of 1] Compiling Example ( Example.hs, Example.o ) [Source file changed]
/tmp/ghc63201_tmp_5_0/ghc_tmp_5_2.c: In function ‘ghczuwrapperZC0ZCmainZCExampleZCblah’:
/tmp/ghc63201_tmp_5_0/ghc_tmp_5_2.c:8:60: error:
error: passing argument 1 of ‘blah’ from incompatible pointer type [-Wincompatible-pointer-types]
8 | void ghczuwrapperZC0ZCmainZCExampleZCblah(void** a1) {blah(a1);}
| ^~
| |
| void **
|
8 | void ghczuwrapperZC0ZCmainZCExampleZCblah(void** a1) {blah(a1);}
| ^
In file included from /tmp/ghc63201_tmp_5_0/ghc_tmp_5_2.c:7:0: error:
example.h:3:22: error:
note: expected ‘abstract **’ but argument is of type ‘void **’
3 | void blah(abstract** x) {}
| ~~~~~~~~~~~^
|
3 | void blah(abstract** x) {}
| ^
<no location info>: error:
`gcc' failed in phase `C Compiler'. (Exit code: 1)
```
## Expected behavior
I think there are two sensible solutions here:
1) Turn off `-Wincompatible-pointer-types` for `capi` wrappers. This essentially mirrors the old behavior before it was on by default. The drawback here is that there are cases where the error *does* catch genuine mistakes (such as declaring an argument of type `int*` as `Ptr Int`, which would become `HSInt*` in C) that would be a bit unfortunate to lose.
2) Compile pointers to types that would become void pointers (or pointers to ... to void pointers) to a single layer of void pointer. This way, whenever the exact C type of the pointee is not known, ghc would take the conservative option and ensure that the `void*` exception of `-Wincompatible-pointer-types` applies.
In most normal cases this shouldn't make a difference, although it might be possible to construct a macro such that a `capi` binding to it compiles with the current behavior but not with this translation.
## Environment
* GHC version used: 9.14.1
* GCC version used: 15.2.1
issue