[nasm:nasm-2.15.xx] offsetin(): use typeof() if the compiler supports it

nasm-bot for H. Peter Anvin (Intel) hpa at zytor.com
Mon Jul 6 12:42:04 PDT 2020


Commit-ID:  30844a4c628c121e26955f9e1e9eb5fa2e7f87d9
Gitweb:     http://repo.or.cz/w/nasm.git?a=commitdiff;h=30844a4c628c121e26955f9e1e9eb5fa2e7f87d9
Author:     H. Peter Anvin (Intel) <hpa at zytor.com>
AuthorDate: Mon, 6 Jul 2020 12:39:14 -0700
Committer:  H. Peter Anvin (Intel) <hpa at zytor.com>
CommitDate: Mon, 6 Jul 2020 12:39:14 -0700

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 at zytor.com>


---
 autoconf/m4/pa_c_typeof.m4 | 31 +++++++++++++++++++++++++++++++
 configure.ac               |  3 +++
 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


More information about the Nasm-commits mailing list