summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--doc/posix-headers/stdalign.texi4
-rw-r--r--lib/stdalign.in.h44
-rw-r--r--m4/stdalign.m417
-rw-r--r--modules/stdalign2
-rw-r--r--tests/test-stdalign.c58
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 <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.
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{<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 092dfedae6..8e64a2a71a 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 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 <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;
}