Thanks for all those comments. I incorporated them and pushed the stdalign code, with the following extra patch, which I hope addresses all the comments. I'm using this in my test version of Emacs; see <http://debbugs.gnu.org/cgi/bugreport.cgi?bug=9772>.
One other thing: none of this stuff affects the existing alignof module. Perhaps the documentation for each should refer to the other? Maybe alignof should use stdalign? (Obviously none of this is high priority.) >From 610ca128a2e9199fcb4ae780dac2f7b34a65a4a6 Mon Sep 17 00:00:00 2001 From: Paul Eggert <egg...@cs.ucla.edu> Date: Thu, 27 Oct 2011 12:43:51 -0700 Subject: [PATCH] Adjust to Bruno's comments. --- ChangeLog | 4 +++ doc/posix-headers/stdalign.texi | 4 +- lib/stdalign.in.h | 44 +++++++++++++++++++++++------- m4/stdalign.m4 | 17 +----------- modules/stdalign | 2 +- tests/test-stdalign.c | 58 ++++++++++++++++++++++++++------------- 6 files changed, 81 insertions(+), 48 deletions(-) diff --git a/ChangeLog b/ChangeLog index e862b7a..a776758 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2011-10-27 Paul Eggert <egg...@cs.ucla.edu> + Add stdalign module and use it in other modules. + This is based on a previous proposal by Bruno Haible + <https://lists.gnu.org/archive/html/bug-gnulib/2011-07/msg00226.html>. + stdalign: new module * doc/posix-headers/stdalign.texi, lib/stdalign.in.h, m4/stdalign.m4: * modules/stdalign: New files. diff --git a/doc/posix-headers/stdalign.texi b/doc/posix-headers/stdalign.texi index af37a38..32c582d 100644 --- a/doc/posix-headers/stdalign.texi +++ b/doc/posix-headers/stdalign.texi @@ -21,8 +21,8 @@ Portability problems not fixed by Gnulib: @code{_Alignas} and @code{alignas} are not always supported; on platforms lacking support, the macro @code{__alignas_is_defined} is not defined. -Supported platforms includes GCC 2 and later, Sun C 5.11 and later, -and MSVC 7.0 or later. +Supported compilers include GCC, IBM C, Sun C 5.11 and later, +and MSVC 7.0 and later. @item @code{<stdalign.h>} must be #included before @samp{_Alignas} and @samp{_Alignof} can be used. diff --git a/lib/stdalign.in.h b/lib/stdalign.in.h index 092dfed..8e64a2a 100644 --- a/lib/stdalign.in.h +++ b/lib/stdalign.in.h @@ -29,14 +29,18 @@ C++0X <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf> section 18.10. */ -/* Return the alignment of a structure slot (field) of TYPE, - as an integer constant expression. The result cannot be used as a - value for an 'enum' constant, if you want to be portable to HP-UX - 10.20 cc and AIX 3.2.5 xlc. - - This is not the same as GCC's __alignof__ operator; for example, on - x86 with GCC, _Alignof (long long) is typically 4 whereas - __alignof__ (long long) is 8. */ +/* alignof (TYPE), also known as _Alignof (TYPE), yields the alignment + requirement of a structure member (i.e., slot or field) that is of + type TYPE, as an integer constant expression. + + This differs from GCC's __alignof__ operator, which can yield a + better-performing alignment for an object of that type. For + example, on x86 with GCC, __alignof__ (double) and __alignof__ + (long long) are 8, whereas alignof (double) and alignof (long long) + are 4 unless the option '-malign-double' is used. + + The result cannot be used as a value for an 'enum' constant, if you + want to be portable to HP-UX 10.20 cc and AIX 3.2.5 xlc. */ #include <stddef.h> #if defined __cplusplus template <class __t> struct __alignof_helper { char __a; __t __b; }; @@ -47,8 +51,28 @@ #define alignof _Alignof #define __alignof_is_defined 1 -/* Align a type or variable to the alignment A. */ -#if @HAVE_ATTRIBUTE_ALIGNED@ && !defined __cplusplus +/* alignas (A), also known as _Alignas (A), aligns a variable or type + to the alignment A, where A is an integer constant expression. For + example: + + int alignas (8) foo; + struct s { int a; int alignas (8) bar; }; + + aligns the address of FOO and the offset of BAR to be multiples of 8. + + A should be a power of two that is at least the type's alignment + and at most the implementation's alignment limit. This limit is + 2**28 on typical GNUish hosts, and 2**13 on MSVC. + + The following draft C1X requirements are not supported here: + + - If A is zero, alignas has no effect. + - alignas can be used multiple times; the strictest one wins. + - alignas (TYPE) is equivalent to alignas (alignof (TYPE)). + + */ + +#if __GNUC__ || __IBMC__ || __IBMCPP__ || 0x5110 <= __SUNPRO_C # define _Alignas(a) __attribute__ ((__aligned__ (a))) #elif 1300 <= _MSC_VER # define _Alignas(a) __declspec ((align (a))) diff --git a/m4/stdalign.m4 b/m4/stdalign.m4 index d90cee3..da64dc6 100644 --- a/m4/stdalign.m4 +++ b/m4/stdalign.m4 @@ -10,28 +10,13 @@ dnl with or without modifications, as long as this notice is preserved. AC_DEFUN([gl_STDALIGN_H], [ AC_CHECK_HEADERS_ONCE([stdalign.h]) - HAVE_ATTRIBUTE_ALIGNED='?' - if test "$ac_cv_header_stdalign_h" = yes; then + if test $ac_cv_header_stdalign_h = yes; then STDALIGN_H='' else STDALIGN_H='stdalign.h' - AC_CACHE_CHECK([for __attribute__ ((__aligned__ (expr)))], - [gl_cv_attribute_aligned], - [AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM( - [[char __attribute__ ((__aligned__ (1 << 3))) c;]], - [[]])], - [gl_cv_attribute_aligned=yes], - [gl_cv_attribute_aligned=no])]) - if test $gl_cv_attribute_aligned = yes; then - HAVE_ATTRIBUTE_ALIGNED=1 - else - HAVE_ATTRIBUTE_ALIGNED=0 - fi fi - AC_SUBST([HAVE_ATTRIBUTE_ALIGNED]) AC_SUBST([STDALIGN_H]) AM_CONDITIONAL([GL_GENERATE_STDALIGN_H], [test -n "$STDALIGN_H"]) ]) diff --git a/modules/stdalign b/modules/stdalign index 824efbb..c91e5e0 100644 --- a/modules/stdalign +++ b/modules/stdalign @@ -19,7 +19,7 @@ if GL_GENERATE_STDALIGN_H stdalign.h: stdalign.in.h $(top_builddir)/config.status $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - sed -e 's/@''HAVE_ATTRIBUTE_ALIGNED''@/$(HAVE_ATTRIBUTE_ALIGNED)/g' < $(srcdir)/stdalign.in.h; \ + cat $(srcdir)/stdalign.in.h; \ } > $@-t && \ mv $@-t $@ else diff --git a/tests/test-stdalign.c b/tests/test-stdalign.c index 136661a..eef9063 100644 --- a/tests/test-stdalign.c +++ b/tests/test-stdalign.c @@ -22,6 +22,7 @@ #include <stddef.h> #include <stdint.h> +#include <stdlib.h> #include "verify.h" @@ -41,37 +42,56 @@ verify (__alignas_is_defined == 1); # ifndef alignas # error "alignas is not a macro" # endif -# define CHECK_ALIGNAS(type) \ - type alignas (1 << 3) type##_alignas; \ - type _Alignas (1 << 3) type##_Alignas; +# define DECLARE_ALIGNED(type, name) \ + type alignas (1 << 3) name##_alignas; \ + type _Alignas (1 << 3) name##_Alignas; +# define CHECK_ALIGNED(name) \ + (((uintptr_t) &name##_alignas % (1 << 3) ? abort () : (void) 0), \ + ((uintptr_t) &name##_Alignas % (1 << 3) ? abort () : (void) 0)) #else -# define CHECK_ALIGNAS(type) +# define DECLARE_ALIGNED(type, name) +# define CHECK_ALIGNED(name) ((void) 0) #endif -#define CHECK(type) \ +#define CHECK_STATIC(type) \ typedef struct { char slot1; type slot2; } type##_helper; \ verify (alignof (type) == offsetof (type##_helper, slot2)); \ verify (_Alignof (type) == alignof (type)); \ const int type##_alignment = alignof (type); \ - CHECK_ALIGNAS(type) - -CHECK (char) -CHECK (short) -CHECK (int) -CHECK (long) -CHECK (float) -CHECK (double) -CHECK (longdouble) + DECLARE_ALIGNED(type, static_##type) + +#define CHECK_AUTO(type) \ + { \ + DECLARE_ALIGNED(type, auto_##type) \ + CHECK_ALIGNED(static_##type); \ + CHECK_ALIGNED(auto_##type); \ + } + #ifdef INT64_MAX -CHECK (int64_t) +# define if_INT64_MAX(x) x +#else +# define if_INT64_MAX(x) #endif -CHECK (struct1) -CHECK (struct2) -CHECK (struct3) -CHECK (struct4) + +#define CHECK_TYPES(check) \ + check (char) \ + check (short) \ + check (int) \ + check (long) \ + if_INT64_MAX (check (int64_t)) \ + check (float) \ + check (double) \ + check (longdouble) \ + check (struct1) \ + check (struct2) \ + check (struct3) \ + check (struct4) + +CHECK_TYPES (CHECK_STATIC) int main () { + CHECK_TYPES (CHECK_AUTO) return 0; } -- 1.7.6.4