offsetin(): use typeof() if the compiler supports it

If the C compiler has typeof(), we can use a safer implementation of
the offsetin() macro by using typeof(). Since typeof() isn't standard
(yet?) autoconf has to test for it.

Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin (Intel) 2020-07-06 12:39:14 -07:00
parent 70f0d04ee5
commit 30844a4c62
3 changed files with 46 additions and 4 deletions

View File

@ -0,0 +1,31 @@
dnl --------------------------------------------------------------------------
dnl PA_C_TYPEOF
dnl
dnl Find if typeof() exists, or an equvalent (__typeof__, decltype,
dnl __decltype__)
dnl --------------------------------------------------------------------------
AC_DEFUN([PA_C_TYPEOF],
[AC_CACHE_CHECK([if $CC supports typeof], [pa_cv_typeof],
[pa_cv_typeof=no
for pa_typeof_try in typeof __typeof__ decltype __decltype__; do
AS_IF([test $pa_cv_typeof = no],
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([
AC_INCLUDES_DEFAULT
int testme(int x);
int testme(int x)
{
$pa_typeof_try(x) y = x*x;
return y;
}
])],
[pa_cv_typeof=$pa_typeof_try])])
done
])
AS_IF([test $pa_cv_typeof = no],
[],
[AC_DEFINE([HAVE_TYPEOF], 1,
[Define to 1 if you have some version of the typeof operator.])
AS_IF([test $pa_cv_typeof = typeof],
[],
[AC_DEFINE_UNQUOTED([typeof], [$pa_cv_typeof],
[Define if your typeof operator is not named typeof.])])])])

View File

@ -103,6 +103,9 @@ dnl assume all compilers support common, and this will help find those
dnl problems. This also works around an OSX linker problem.
PA_ADD_CFLAGS([-fno-common])
dnl Other C features
PA_C_TYPEOF
dnl Look for programs...
AC_CHECK_PROGS(NROFF, nroff, false)
AC_CHECK_PROGS(ASCIIDOC, asciidoc, false)

View File

@ -189,11 +189,19 @@ typedef enum bool { false, true } bool;
# define offsetof(t,m) ((size_t)&(((t *)0)->m))
#endif
/* This is like offsetof(), but takes an object rather than a type.
Ironically enough this is actually guaranteed to be portable,
as far as I know... */
/* If typeof is defined as a macro, assume we have typeof even if
HAVE_TYPEOF is not declared (e.g. due to not using autoconf.) */
#ifdef typeof
# define HAVE_TYPEOF 1
#endif
/* This is like offsetof(), but takes an object rather than a type. */
#ifndef offsetin
# define offsetin(p,m) ((const char *)&((p).m) - (const char *)&(p))
# ifdef HAVE_TYPEOF
# define offsetin(p,m) offsetof(typeof(p),m)
# else
/* Fallback, technically non-portable if p is uninitialized. */
# define offsetin(p,m) ((const char *)&((p).m) - (const char *)&(p))
#endif
/* The container_of construct: if p is a pointer to member m of