From 610ca128a2e9199fcb4ae780dac2f7b34a65a4a6 Mon Sep 17 00:00:00 2001 From: Paul Eggert 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 e862b7a415..a776758ad6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2011-10-27 Paul Eggert + Add stdalign module and use it in other modules. + This is based on a previous proposal by Bruno Haible + . + 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 af37a381a2..32c582d58b 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{} 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 092dfedae6..8e64a2a71a 100644 --- a/lib/stdalign.in.h +++ b/lib/stdalign.in.h @@ -29,14 +29,18 @@ C++0X 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 #if defined __cplusplus template 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 d90cee3756..da64dc6332 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 824efbbb76..c91e5e0dd2 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 136661a2e2..eef90632b6 100644 --- a/tests/test-stdalign.c +++ b/tests/test-stdalign.c @@ -22,6 +22,7 @@ #include #include +#include #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; } -- 2.39.5