+2011-02-12 Paul Eggert <eggert@cs.ucla.edu>
+
+ 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 <bruno@clisp.org>
wcsrtombs: Work around bug on native Windows.
# 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. */
/* Terminate the current process with the given return code, without running
the 'atexit' handlers. */
# if !@HAVE__EXIT@
-_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);
-# _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,
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
--- /dev/null
+# 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])
+])
-# 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,
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])
Files:
lib/_Exit.c
m4/_Exit.m4
+m4/attribute.m4
Depends-on:
stdlib
< $(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' \