2
archives.c: In function ‘fd_writeback_wait’:
archives.c:121:21: warning: passing argument 1 of ‘aio_suspend’ from incompatible pointer type [-Wincompatible-pointer-types]
     r = aio_suspend(&cb, 1, NULL);
                     ^~~
In file included from ../lib/dpkg/fsys.h:28,
                 from ../lib/dpkg/triglib.h:28,
                 from archives.c:57:
/usr/include/aio.h:168:51: note: expected ‘const struct aiocb * const*’ but argument is of type ‘struct aiocb **’
 extern int aio_suspend (const struct aiocb *const __list[], int __nent,
                         ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~

Explanations:

I think there is no way to avoid this warning, without writing a dangerous type cast to change the const qualifiers, or suppressing the whole category of warnings.

Apparently C++ does better here. It also has const_cast for clearer casting, which makes sure that you are only changing const qualifiers.

In other words, POSIX defining aio_suspend() to use const like this is arguably rather dangerous.

Have I interpreted this correctly?

If I am wrong, then how can I avoid this warning, but still have the compiler check that I am only casting const qualifiers, and not casting to a completely incompatible type?


I suspect if there are methods, they would not be ones that I would want to use in practice, but I am curious.

The current code I am working on does not explicitly document a required compiler version.

I would be interested in techniques that work in standard C versions. I would be interested to hear about GCC extensions. Comments about whether it is recommended or dis-recommended to define function parameters like this are also welcome.

Readers are reminded that C and C++ are different, and not 100% compatible languages. I acknowledge that switching code bases to C++ could probably provide a solution, but I do not think that solution would be very useful to me. Thank you.

sourcejedi
  • 3,051
  • 2
  • 24
  • 42

1 Answers1

2

Here is a way to call the function with appropriate constness:

struct aiocb cb;
const struct aiocb * cblist[1] = { &cb };
aio_suspend(cblist, 1, NULL);

And alternatively:

struct aiocb cb;
const struct aiocb * cbptr = &cb;
aio_suspend(&cbptr, 1, NULL);

Note, the above answer was proposed because you used this syntax:

r = aio_suspend(&cb, 1, NULL);

Passing in the address of cb to something that expects a pointer to pointer means cb was a pointer, so this call only makes sense for a single element array.

Suppose your warning came about because you actually had this:

struct aiocb *cbv[256];
r = aio_suspend(cbv, 256, NULL);

It is easy to remove the warning. Use (void *).

r = aio_suspend((void *)cbv, 256, NULL);

However, it would be better to define the vector to be using pointers to const in the first place.

const struct aiocb *cbv[256];
r = aio_suspend(cbv, 256, NULL);

If each callback instance is indeed modifiable in reality (eg, was allocated by malloc), then just cast away const before modifying.

struct aiocb *cb = (struct aiocb *)cbv[i];
/* ... modify cb ... */
jxh
  • 69,070
  • 8
  • 110
  • 193
  • Point! And for the call site this exact warning is about, that would be fine. But I also have a call site where the array has up to 256 entries, and is modified and re-used. Even if it's possible to copy the entire array into a const local variable, and even if the optimizer knows how to elide the copy, I suspect that would not be very idiomatic C code. – sourcejedi May 30 '19 at 20:35
  • @sourcejedi: You did not actually present such a use case. I have expanded my answer nevertheless. – jxh May 30 '19 at 20:47
  • Absolutely agreed, and I apologize :-). Nitpick: both `cb` and `&cb` work if `cb` is declared as `struct aiocb *cb[1]` - arrays are weird like that. You would be right if you guessed that I did not write my code like that though :-). – sourcejedi May 30 '19 at 20:55
  • 1
    They might have the same address, but they have different types. https://tio.run/##ZYzBCsIwEETv@YoBQVqxUs8Vf0SkpNtYA3Fbks1J@uvG1ZPgMKd5j6FmIiobzxTy6HCyfj7cz8Z4FjysZ1Q1ngUamjkJksRMAtVowA40hMvx2pmPoFufclocj5Xue7Ta@p9tf@D3OTrJkdF2Zi0vugU7pdKEKG8 – jxh May 30 '19 at 20:58
  • FWIW, adding a few `const` qualifiers in the right place has now avoided both the compiler warning, and the need for any type casts to add/remove consts. It seems the POSIX `aio_suspend()` is entirely usable after all :-). Thanks. – sourcejedi May 30 '19 at 21:03