In an effort to standardize my code and make it more portable, I replaced
#ifdef __GNUC__
typedef __attribute__((aligned(16))) float aligned_block[4];
#else
typedef __declspec(align(16)) float aligned_block[4];
#endif
with
typedef float alignas(16) aligned_block[4];
in C++11. However, gnu (4.8) doesn't like that but complains
test.cc:3:9: warning: attribute ignored [-Wattributes]
typedef float alignas(16) aligned_block[4];
^
test.cc:3:9: note: an attribute that appertains to a type-specifier is ignored
whereas clang 3.2 creates no warning (even with -Weverything -Wno-c++98-compat -pedantic
).
So I wonder whether my code above is correct and, more generally, where alignas()
can and cannot be placed.
EDIT (Apr 2013):
The relevant article from the standard is 7.6.2, in particular 7.6.2.1
An alignment-specifier may be applied to a variable or to a class data member, but it shall not be applied to a bit-field, a function parameter, the formal parameter of a catch clause (15.3), or a variable declared with the register storage class specifier. An alignment-specifier may also be applied to the declaration of a class or enumeration type. An alignment-specifier with an ellipsis is a pack expansion (14.5.3).
as already dug out by Red XIII. However, I'm not expert enough to know what this means for my test above.
If the fact that clang accepts my attribute means anything, it's perhaps worth mentioning that when trying to use a using
directive instead of a typedef
, clang also complains. Also, contrary to a statement in an earlier version of this question, gcc does not only warn, but indeed ignores my wish for alignment.
You cannot apply an alignment to a typedef
. In the C++ model of alignment specifiers, the alignment is an inseparable part of the type itself, and a typedef
does not create a new type (it only provides a new name for an existing type) so it is not meaningful to apply an alignment specifier in a typedef
declaration.
From [dcl.align] (7.6.2)p1:
An alignment-specifier may be applied to a variable or to a class data member [...]. An alignment-specifier may also be applied to the declaration or definition of a class (in an elaborated-type-specifier (7.1.6.3) or class-head (Clause 9), respectively) and to the declaration or definition of an enumeration (in an opaque-enum-declaration or enum-head, respectively (7.2)).
These are the only places where the standard says an alignment-specifier (alignas(...)
) may be applied. Note that this does not include typedef
declarations nor alias-declarations.
Per [dcl.attr.grammar] (7.6.1)p4:
If an attribute-specifier-seq that appertains to some entity or statement contains an attribute that is not allowed to apply to that entity or statement, the program is ill-formed.
This wording was intended to apply to alignas
as well as the other forms of attribute that may appear within an attribute-specifier-seq, but was not correctly updated when alignment switched from being a "real" attribute to being a different kind of attribute-specifier-seq.
So: your example code using alignas
is supposed to be ill-formed. The C++ standard does not currently explicitly say this, but it also does not permit the usage, so instead it currently would result in undefined behavior (because the standard does not define any behavior for it).