From 4e647944bd613bb7b419779881b5f3cb053f2869 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Mon, 31 Oct 2011 22:37:30 -0700 Subject: [PATCH] stdalign: port better to MSVC and to Sun C 5.11 I think these problems were reported by Bruno Haible, in email that I've unfortunately misplaced. * doc/posix-headers/stdalign.texi (stdalign.h): Document more shortcomings of MSVC and of Sun C 5.11. * lib/stdalign.in.h (_Alignas): Omit bogus extra parenthesis around __declspec arg. * modules/stdalign-tests (Files): Add tests/macros.h. * tests/test-stdalign.c: Do not include ; no longer needed. Include macros.h, for ASSERT. (DECLARE_ALIGNED): Remove. (TEST_ALIGNMENT): Define to 16 if alignment is supported (more likely to catch bug), and to 1 if not (simplifies the rest of the code). (CHECK_STATIC): Always declare the alignment test vars; that's simpler. (CHECK_AUTO): Remove. (CHECK_ALIGNED): Check only the alignment of the static vars, since auto var alignment isn't supported by Sun C 5.11. (CHECK_TYPES): Remove. All uses replaced by inline code, so that ASSERT failures are easier to diagnose. --- ChangeLog | 22 +++++++++ doc/posix-headers/stdalign.texi | 14 ++++++ lib/stdalign.in.h | 8 +++- modules/stdalign-tests | 1 + tests/test-stdalign.c | 83 +++++++++++++++++++-------------- 5 files changed, 90 insertions(+), 38 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8347aebd0d..141f5e8a31 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2011-10-31 Paul Eggert + + stdalign: port better to MSVC and to Sun C 5.11 + I think these problems were reported by Bruno Haible, in email + that I've unfortunately misplaced. + * doc/posix-headers/stdalign.texi (stdalign.h): Document more + shortcomings of MSVC and of Sun C 5.11. + * lib/stdalign.in.h (_Alignas): Omit bogus extra parenthesis + around __declspec arg. + * modules/stdalign-tests (Files): Add tests/macros.h. + * tests/test-stdalign.c: Do not include ; no longer needed. + Include macros.h, for ASSERT. + (DECLARE_ALIGNED): Remove. + (TEST_ALIGNMENT): Define to 16 if alignment is supported (more likely + to catch bug), and to 1 if not (simplifies the rest of the code). + (CHECK_STATIC): Always declare the alignment test vars; that's simpler. + (CHECK_AUTO): Remove. + (CHECK_ALIGNED): Check only the alignment of the static vars, + since auto var alignment isn't supported by Sun C 5.11. + (CHECK_TYPES): Remove. All uses replaced by inline code, so that + ASSERT failures are easier to diagnose. + 2011-10-31 Bruno Haible doc about some IRIX 5.3 problems. diff --git a/doc/posix-headers/stdalign.texi b/doc/posix-headers/stdalign.texi index 32c582d58b..c5fbc5f284 100644 --- a/doc/posix-headers/stdalign.texi +++ b/doc/posix-headers/stdalign.texi @@ -24,6 +24,20 @@ macro @code{__alignas_is_defined} is not defined. Supported compilers include GCC, IBM C, Sun C 5.11 and later, and MSVC 7.0 and later. @item +Some compilers do not support alignment via +@code{alignas}/@code{_Alignas} of @code{auto} variables (i.e., +variables on the stack). They diagnose and ignore the alignment: Sun +C 5.11. +@item +Some compilers require the operand of @code{_Alignas}/@code{alignas} +to be a single integer constant, not an expression: MSVC 7.0 through +at least 10.0. +@item +The Sun C 5.11 compiler sometimes mishandles the alignment of multiple +external variables that are declared close together with +@code{_Alignas}/@code{alignas}. This compiler bug causes the Gnulib +module @code{stdalign-tests} to fail. +@item @code{} must be #included before @samp{_Alignas} and @samp{_Alignof} can be used. @item diff --git a/lib/stdalign.in.h b/lib/stdalign.in.h index 8e64a2a71a..37446a771d 100644 --- a/lib/stdalign.in.h +++ b/lib/stdalign.in.h @@ -62,7 +62,11 @@ 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. + 2**28 on typical GNUish hosts, and 2**13 on MSVC. To be portable + to MSVC through at least version 10.0, A should be an integer + constant, as MSVC does not support expressions such as 1 << 3. + To be portable to Sun C 5.11, do not align auto variables to + anything stricter than their default alignment. The following draft C1X requirements are not supported here: @@ -75,7 +79,7 @@ #if __GNUC__ || __IBMC__ || __IBMCPP__ || 0x5110 <= __SUNPRO_C # define _Alignas(a) __attribute__ ((__aligned__ (a))) #elif 1300 <= _MSC_VER -# define _Alignas(a) __declspec ((align (a))) +# define _Alignas(a) __declspec (align (a)) #endif #ifdef _Alignas # define alignas _Alignas diff --git a/modules/stdalign-tests b/modules/stdalign-tests index 44382bfe3e..6d97a3d2a4 100644 --- a/modules/stdalign-tests +++ b/modules/stdalign-tests @@ -1,5 +1,6 @@ Files: tests/test-stdalign.c +tests/macros.h Depends-on: verify diff --git a/tests/test-stdalign.c b/tests/test-stdalign.c index eef90632b6..c1d86775ae 100644 --- a/tests/test-stdalign.c +++ b/tests/test-stdalign.c @@ -22,10 +22,11 @@ #include #include -#include #include "verify.h" +#include "macros.h" + typedef long double longdouble; typedef struct { char a[1]; } struct1; typedef struct { char a[2]; } struct2; @@ -42,15 +43,11 @@ verify (__alignas_is_defined == 1); # ifndef alignas # error "alignas is not a macro" # endif -# 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)) +# define TEST_ALIGNMENT 16 #else -# define DECLARE_ALIGNED(type, name) -# define CHECK_ALIGNED(name) ((void) 0) +# define _Alignas(alignment) +# define alignas(alignment) +# define TEST_ALIGNMENT 1 #endif #define CHECK_STATIC(type) \ @@ -58,40 +55,54 @@ verify (__alignas_is_defined == 1); verify (alignof (type) == offsetof (type##_helper, slot2)); \ verify (_Alignof (type) == alignof (type)); \ const int type##_alignment = alignof (type); \ - DECLARE_ALIGNED(type, static_##type) + type alignas (TEST_ALIGNMENT) static_##type##_alignas; \ + type _Alignas (TEST_ALIGNMENT) static_##type##_Alignas -#define CHECK_AUTO(type) \ - { \ - DECLARE_ALIGNED(type, auto_##type) \ - CHECK_ALIGNED(static_##type); \ - CHECK_ALIGNED(auto_##type); \ - } +#define CHECK_ALIGNED(var) ASSERT ((uintptr_t) &(var) % TEST_ALIGNMENT == 0) +CHECK_STATIC (char); +CHECK_STATIC (short); +CHECK_STATIC (int); +CHECK_STATIC (long); #ifdef INT64_MAX -# define if_INT64_MAX(x) x -#else -# define if_INT64_MAX(x) +CHECK_STATIC (int64_t); #endif - -#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) +CHECK_STATIC (float); +CHECK_STATIC (double); +CHECK_STATIC (longdouble); +CHECK_STATIC (struct1); +CHECK_STATIC (struct2); +CHECK_STATIC (struct3); +CHECK_STATIC (struct4); int main () { - CHECK_TYPES (CHECK_AUTO) + CHECK_ALIGNED (static_char_alignas); + CHECK_ALIGNED (static_char_Alignas); + CHECK_ALIGNED (static_short_alignas); + CHECK_ALIGNED (static_short_Alignas); + CHECK_ALIGNED (static_int_alignas); + CHECK_ALIGNED (static_int_Alignas); + CHECK_ALIGNED (static_long_alignas); + CHECK_ALIGNED (static_long_Alignas); +#ifdef INT64_MAX + CHECK_ALIGNED (static_int64_t_alignas); + CHECK_ALIGNED (static_int64_t_Alignas); +#endif + CHECK_ALIGNED (static_float_alignas); + CHECK_ALIGNED (static_float_Alignas); + CHECK_ALIGNED (static_double_alignas); + CHECK_ALIGNED (static_double_Alignas); + CHECK_ALIGNED (static_longdouble_alignas); + CHECK_ALIGNED (static_longdouble_Alignas); + CHECK_ALIGNED (static_struct1_alignas); + CHECK_ALIGNED (static_struct1_Alignas); + CHECK_ALIGNED (static_struct2_alignas); + CHECK_ALIGNED (static_struct2_Alignas); + CHECK_ALIGNED (static_struct3_alignas); + CHECK_ALIGNED (static_struct3_Alignas); + CHECK_ALIGNED (static_struct4_alignas); + CHECK_ALIGNED (static_struct4_Alignas); return 0; } -- 2.39.5