summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin (Intel) <hpa@zytor.com>2020-07-06 12:39:14 -0700
committerH. Peter Anvin (Intel) <hpa@zytor.com>2020-07-06 12:39:14 -0700
commit30844a4c628c121e26955f9e1e9eb5fa2e7f87d9 (patch)
treeb0732afa43a93e7679b045319d779f824e611edb
parent70f0d04ee50a18e78c30ce6c6fc4f32427724793 (diff)
downloadnasm-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.m431
-rw-r--r--configure.ac3
-rw-r--r--include/compiler.h16
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