changeset 15999:bf4984d2b939

Adjust to Bruno's comments.
author Paul Eggert <eggert@cs.ucla.edu>
date Thu, 27 Oct 2011 12:43:51 -0700
parents 9b28a5d31bb5
children 79bbea2afc18
files ChangeLog doc/posix-headers/stdalign.texi lib/stdalign.in.h m4/stdalign.m4 modules/stdalign tests/test-stdalign.c
diffstat 6 files changed, 81 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2011-10-27  Paul Eggert  <eggert@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.
--- a/doc/posix-headers/stdalign.texi
+++ b/doc/posix-headers/stdalign.texi
@@ -21,8 +21,8 @@
 @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.
--- 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.
+/* 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 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.  */
+   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)))
--- a/m4/stdalign.m4
+++ b/m4/stdalign.m4
@@ -10,28 +10,13 @@
 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"])
 ])
--- a/modules/stdalign
+++ b/modules/stdalign
@@ -19,7 +19,7 @@
 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
--- 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 @@
 # 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)
+  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
+# define if_INT64_MAX(x) x
+#else
+# define if_INT64_MAX(x)
+#endif
 
-CHECK (char)
-CHECK (short)
-CHECK (int)
-CHECK (long)
-CHECK (float)
-CHECK (double)
-CHECK (longdouble)
-#ifdef INT64_MAX
-CHECK (int64_t)
-#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;
 }