Adjust to Bruno's comments.
authorPaul Eggert <eggert@cs.ucla.edu>
Thu, 27 Oct 2011 19:43:51 +0000 (12:43 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Thu, 27 Oct 2011 20:05:43 +0000 (13:05 -0700)
ChangeLog
doc/posix-headers/stdalign.texi
lib/stdalign.in.h
m4/stdalign.m4
modules/stdalign
tests/test-stdalign.c

index e862b7a..a776758 100644 (file)
--- 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.
index af37a38..32c582d 100644 (file)
@@ -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.
index 092dfed..8e64a2a 100644 (file)
    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; };
 #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)))
index d90cee3..da64dc6 100644 (file)
@@ -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"])
 ])
index 824efbb..c91e5e0 100644 (file)
@@ -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
index 136661a..eef9063 100644 (file)
@@ -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;
 }