diff options
author | H. Peter Anvin (Intel) <hpa@zytor.com> | 2020-07-06 12:39:14 -0700 |
---|---|---|
committer | H. Peter Anvin (Intel) <hpa@zytor.com> | 2020-07-06 12:39:14 -0700 |
commit | 30844a4c628c121e26955f9e1e9eb5fa2e7f87d9 (patch) | |
tree | b0732afa43a93e7679b045319d779f824e611edb | |
parent | 70f0d04ee50a18e78c30ce6c6fc4f32427724793 (diff) | |
download | nasm-30844a4c628c121e26955f9e1e9eb5fa2e7f87d9.tar.gz |
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>
-rw-r--r-- | autoconf/m4/pa_c_typeof.m4 | 31 | ||||
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | include/compiler.h | 16 |
3 files changed, 46 insertions, 4 deletions
diff --git a/autoconf/m4/pa_c_typeof.m4 b/autoconf/m4/pa_c_typeof.m4 new file mode 100644 index 00000000..036d02f2 --- /dev/null +++ b/autoconf/m4/pa_c_typeof.m4 @@ -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.])])])]) diff --git a/configure.ac b/configure.ac index b101f46c..8dc47322 100644 --- a/configure.ac +++ b/configure.ac @@ -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) diff --git a/include/compiler.h b/include/compiler.h index a1c1b0db..e289aece 100644 --- a/include/compiler.h +++ b/include/compiler.h @@ -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 |