net: socket: Workaround issue with recent GCC and fcntl macro

If we have CONFIG_NET_SOCKETS_POSIX_NAMES enabled (which is now
default), and also have CONFIG_NEWLIB_LIBC enabled, latest versions
of GCC throw a strange error like:

error: conflicting types for 'zsock_fcntl'
  692 | #define fcntl zsock_fcntl

After enough consideration, it seems that when Newlib is used, its
fcntl.h header is used, which declares fcntl() with POSIX prototype:
"int fcntl(int fd, int cmd, ...)". It seems that recent GCC, when
seeing the #define like above, checks that its right-hand side
(zsock_fcntl(int, int, int) above) is compatible with an existing
LHS prototype. That doesn't make sense from the point of view of
the C preprocessor semantics, and yet that's what apparently happens.

Make GCC happy by defining an inline wrapper function with
signature compatible with POSIX fcntl prototype, and use it in
the define, instead of zsock_fcntl directly.

Signed-off-by: Paul Sokolovsky <paul.sokolovsky@linaro.org>
This commit is contained in:
Paul Sokolovsky 2021-04-14 15:28:46 +03:00 committed by Kumar Gala
commit 958e826b69

View file

@ -688,8 +688,22 @@ static inline ssize_t recv(int sock, void *buf, size_t max_len, int flags)
return zsock_recv(sock, buf, max_len, flags);
}
/* This conflicts with fcntl.h, so code must include fcntl.h before socket.h: */
#define fcntl zsock_fcntl
/*
* Need this wrapper because newer GCC versions got too smart and "typecheck"
* even macros, so '#define fcntl zsock_fcntl' leads to error.
*/
static inline int zsock_fcntl_wrapper(int sock, int cmd, ...)
{
va_list args;
int flags;
va_start(args, cmd);
flags = va_arg(args, int);
va_end(args);
return zsock_fcntl(sock, cmd, flags);
}
#define fcntl zsock_fcntl_wrapper
static inline ssize_t sendto(int sock, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr,