bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] stdlib: support non-GCC __attribute__


From: Paul Eggert
Subject: [PATCH] stdlib: support non-GCC __attribute__
Date: Sat, 12 Feb 2011 15:35:09 -0800
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.13) Gecko/20101208 Thunderbird/3.1.7

Fix a serious and tricky problem encountered when attempting to
add the getloadavg module to Emacs.  Emacs worked fine on RHEL
5.5, but it crashed due to memory corruption on Solaris 10 with
Sun C 5.11.  Emacs normally ORs 3-bit tags into their low-order
bits that are otherwise zero.  This tagging is optional inside
Emacs but is preferred and is used when __attribute__ ((__aligned
(8))) works, as it does with both recent-enough GCC and with Sun C
5.11.  However, Sun C 5.11 is not GCC and does not #define
__GNUC__ and __GNUC_MINOR__.

When I added the getloadavg module to Emacs, it brought in
stdlib.in.h, which contained this fragment:

   #ifndef __attribute__
   # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)
   #  define __attribute__(Spec)   /* empty */
   # endif
   #endif

When files that include <stdlib.h> were compiled with Sun C 5.11,
the above code disabled __attribute__ ((__aligned (8))), which
caused variables to not be properly aligned, which eventually led
to the pointer corruption mentioned above.  (This was a bit hard
to diagnose, unfortunately.)

Several "#define __attribute__(X) /* empty */" code snippets need
to be eradicated from Gnulib to work with non-GCC compilers that
support __attribute__.  The Autoconf way to do this is to test for
each kind of attribute that we want support for, and selectively
enable that in source code.

Fix this problem just for stdlib.h, by adding a test for the
__noreturn__ attribute, and change stdlib.in.h to use that test
when needed.  This technique can be easily generalized to the
other *.in.h files and attributes, and a similar technique can be
used for *.h and *.c files.  This patch is enough to solve the
problem for Emacs + getloadavg, and I thought I'd publish it for
feedback before undertaking further, similar fixes in other
modules.

This patch does not arrange to #define HAVE_ATTRIBUTE_NORETURN
because it's not needed for stdlib.h.  It merely substitutes the
value directly into stdlib.h.  We may well need to #define it, or
similar symbols, for other modules, but it's nice to also have an
option to not #define it for applications like Emacs that do not
need it.

* lib/stdlib.in.h (__attribute__): Do not #define.
(_GL_ATTRIBUTE_NORETURN): New macro, which in stdlib.h needs to
be defined only if the _Exit module is also used.
* m4/_Exit.m4 (gl_FUNC__EXIT): Require gl_ATTRIBUTE_NORETURN.
* m4/stdlib_h.m4 (gl_STDLIB_H_DEFAULTS): Subst
HAVE_ATTRIBUTE_NORETURN and default it to 1, its value on GNU
platforms.
* modules/_Exit (Files): Add m4/attribute.m4.
* modules/stdlib (Makefile.am): Substitute HAVE_ATTRIBUTE_NORETURN.
* m4/attribute.m4: New file.
---
 ChangeLog       |   62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/stdlib.in.h |   13 +++++------
 m4/_Exit.m4     |    4 ++-
 m4/attribute.m4 |   29 +++++++++++++++++++++++++
 m4/stdlib_h.m4  |    3 +-
 modules/_Exit   |    1 +
 modules/stdlib  |    1 +
 7 files changed, 104 insertions(+), 9 deletions(-)
 create mode 100644 m4/attribute.m4

diff --git a/ChangeLog b/ChangeLog
index c6ab4cc..23cc805 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,65 @@
+2011-02-12  Paul Eggert  <address@hidden>
+
+       stdlib: support non-GCC __attribute__
+
+       Fix a serious and tricky problem encountered when attempting to
+       add the getloadavg module to Emacs.  Emacs worked fine on RHEL
+       5.5, but it crashed due to memory corruption on Solaris 10 with
+       Sun C 5.11.  Emacs normally ORs 3-bit tags into their low-order
+       bits that are otherwise zero.  This tagging is optional inside
+       Emacs but is preferred and is used when __attribute__ ((__aligned
+       (8))) works, as it does with both recent-enough GCC and with Sun C
+       5.11.  However, Sun C 5.11 is not GCC and does not #define
+       __GNUC__ and __GNUC_MINOR__.
+
+       When I added the getloadavg module to Emacs, it brought in
+       stdlib.in.h, which contained this fragment:
+
+          #ifndef __attribute__
+          # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)
+          #  define __attribute__(Spec)   /* empty */
+          # endif
+          #endif
+
+       When files that include <stdlib.h> were compiled with Sun C 5.11,
+       the above code disabled __attribute__ ((__aligned (8))), which
+       caused variables to not be properly aligned, which eventually led
+       to the pointer corruption mentioned above.  (This was a bit hard
+       to diagnose, unfortunately.)
+
+       Several "#define __attribute__(X) /* empty */" code snippets need
+       to be eradicated from Gnulib to work with non-GCC compilers that
+       support __attribute__.  The Autoconf way to do this is to test for
+       each kind of attribute that we want support for, and selectively
+       enable that in source code.
+
+       Fix this problem just for stdlib.h, by adding a test for the
+       __noreturn__ attribute, and change stdlib.in.h to use that test
+       when needed.  This technique can be easily generalized to the
+       other *.in.h files and attributes, and a similar technique can be
+       used for *.h and *.c files.  This patch is enough to solve the
+       problem for Emacs + getloadavg, and I thought I'd publish it for
+       feedback before undertaking further, similar fixes in other
+       modules.
+
+       This patch does not arrange to #define HAVE_ATTRIBUTE_NORETURN
+       because it's not needed for stdlib.h.  It merely substitutes the
+       value directly into stdlib.h.  We may well need to #define it, or
+       similar symbols, for other modules, but it's nice to also have an
+       option to not #define it for applications like Emacs that do not
+       need it.
+
+       * lib/stdlib.in.h (__attribute__): Do not #define.
+       (_GL_ATTRIBUTE_NORETURN): New macro, which in stdlib.h needs to
+       be defined only if the _Exit module is also used.
+       * m4/_Exit.m4 (gl_FUNC__EXIT): Require gl_ATTRIBUTE_NORETURN.
+       * m4/stdlib_h.m4 (gl_STDLIB_H_DEFAULTS): Subst
+       HAVE_ATTRIBUTE_NORETURN and default it to 1, its value on GNU
+       platforms.
+       * modules/_Exit (Files): Add m4/attribute.m4.
+       * modules/stdlib (Makefile.am): Substitute HAVE_ATTRIBUTE_NORETURN.
+       * m4/attribute.m4: New file.
+
 2011-02-12  Bruno Haible  <address@hidden>
 
        wcsrtombs: Work around bug on native Windows.
diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h
index 6e69a27..029d15d 100644
--- a/lib/stdlib.in.h
+++ b/lib/stdlib.in.h
@@ -88,12 +88,6 @@ struct random_data
 # include <unistd.h>
 #endif
 
-#ifndef __attribute__
-# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)
-#  define __attribute__(Spec)   /* empty */
-# endif
-#endif
-
 /* The definitions of _GL_FUNCDECL_RPL etc. are copied here.  */
 
 /* The definition of _GL_ARG_NONNULL is copied here.  */
@@ -119,7 +113,12 @@ struct random_data
 /* Terminate the current process with the given return code, without running
    the 'atexit' handlers.  */
 # if address@hidden@
-_GL_FUNCDECL_SYS (_Exit, void, (int status) __attribute__ ((__noreturn__)));
+#  if @HAVE_ATTRIBUTE_NORETURN@
+#   define _GL_ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
+#  else
+#   define _GL_ATTRIBUTE_NORETURN
+#  endif
+_GL_FUNCDECL_SYS (_Exit, void, (int status)) _GL_ATTRIBUTE_NORETURN;
 # endif
 _GL_CXXALIAS_SYS (_Exit, void, (int status));
 _GL_CXXALIASWARN (_Exit);
diff --git a/m4/_Exit.m4 b/m4/_Exit.m4
index 329b8cd..3d01f1a 100644
--- a/m4/_Exit.m4
+++ b/m4/_Exit.m4
@@ -1,4 +1,4 @@
-# _Exit.m4 serial 1
+# _Exit.m4 serial 2
 dnl Copyright (C) 2010-2011 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -7,6 +7,8 @@ dnl with or without modifications, as long as this notice is 
preserved.
 AC_DEFUN([gl_FUNC__EXIT],
 [
   AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
+  AC_REQUIRE([gl_ATTRIBUTE_NORETURN])
+
   AC_CHECK_FUNCS([_Exit])
   if test $ac_cv_func__Exit = no; then
     HAVE__EXIT=0
diff --git a/m4/attribute.m4 b/m4/attribute.m4
new file mode 100644
index 0000000..04758fd
--- /dev/null
+++ b/m4/attribute.m4
@@ -0,0 +1,29 @@
+# Test for GCC-style __attribute__ support.
+
+dnl Copyright (C) 2011 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl from Paul Eggert
+
+# Currently only __attribute__ ((__noreturn__)) is done,
+# but other macros can be added to this file as needed.
+
+# Test whether __attribute__ ((__noreturn__)) works.
+AC_DEFUN([gl_ATTRIBUTE_NORETURN], [
+  AC_CACHE_CHECK([for  __attribute__ ((__noreturn__))],
+    [gl_cv_attribute_noreturn],
+    [gl_save_werror_flag=$ac_[]_AC_LANG_ABBREV[]_werror_flag
+     ac_[]_AC_LANG_ABBREV[]_werror_flag=yes
+     AC_COMPILE_IFELSE(
+       [AC_LANG_PROGRAM(
+          [[void never_come_back (int) __attribute__ ((__noreturn__));]])],
+       [gl_cv_attribute_noreturn=yes],
+       [gl_cv_attribute_noreturn=no])
+     ac_[]_AC_LANG_ABBREV[]_werror_flag=$gl_save_werror_flag])
+  if test $gl_cv_attribute_noreturn = no; then
+    HAVE_ATTRIBUTE_NORETURN=0
+  fi
+  AC_SUBST([HAVE_ATTRIBUTE_NORETURN])
+])
diff --git a/m4/stdlib_h.m4 b/m4/stdlib_h.m4
index d28b552..56713dd 100644
--- a/m4/stdlib_h.m4
+++ b/m4/stdlib_h.m4
@@ -1,4 +1,4 @@
-# stdlib_h.m4 serial 36
+# stdlib_h.m4 serial 37
 dnl Copyright (C) 2007-2011 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -65,6 +65,7 @@ AC_DEFUN([gl_STDLIB_H_DEFAULTS],
   dnl Assume proper GNU behavior unless another module says otherwise.
   HAVE__EXIT=1;              AC_SUBST([HAVE__EXIT])
   HAVE_ATOLL=1;              AC_SUBST([HAVE_ATOLL])
+  HAVE_ATTRIBUTE_NORETURN=1; AC_SUBST([HAVE_ATTRIBUTE_NORETURN])
   HAVE_CANONICALIZE_FILE_NAME=1;  AC_SUBST([HAVE_CANONICALIZE_FILE_NAME])
   HAVE_DECL_GETLOADAVG=1;    AC_SUBST([HAVE_DECL_GETLOADAVG])
   HAVE_GETSUBOPT=1;          AC_SUBST([HAVE_GETSUBOPT])
diff --git a/modules/_Exit b/modules/_Exit
index 2b5cc08..d9a590c 100644
--- a/modules/_Exit
+++ b/modules/_Exit
@@ -4,6 +4,7 @@ _Exit() function: terminate current process.
 Files:
 lib/_Exit.c
 m4/_Exit.m4
+m4/attribute.m4
 
 Depends-on:
 stdlib
diff --git a/modules/stdlib b/modules/stdlib
index 7d7e769..6ba95ba 100644
--- a/modules/stdlib
+++ b/modules/stdlib
@@ -57,6 +57,7 @@ stdlib.h: stdlib.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) 
$(WARN_ON_USE_H)
              < $(srcdir)/stdlib.in.h | \
          sed -e 's|@''HAVE__EXIT''@|$(HAVE__EXIT)|g' \
              -e 's|@''HAVE_ATOLL''@|$(HAVE_ATOLL)|g' \
+             -e 's|@''HAVE_ATTRIBUTE_NORETURN''@|$(HAVE_ATTRIBUTE_NORETURN)|g' 
\
              -e 
's|@''HAVE_CANONICALIZE_FILE_NAME''@|$(HAVE_CANONICALIZE_FILE_NAME)|g' \
              -e 's|@''HAVE_DECL_GETLOADAVG''@|$(HAVE_DECL_GETLOADAVG)|g' \
              -e 's|@''HAVE_GETSUBOPT''@|$(HAVE_GETSUBOPT)|g' \
-- 
1.7.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]