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.
@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.
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)))
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"])
])
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
#include <stddef.h>
#include <stdint.h>
+#include <stdlib.h>
#include "verify.h"
# 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;
}