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 atypedef
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 atypedef
declaration.From [dcl.align] (7.6.2)p1:
These are the only places where the standard says an alignment-specifier (
alignas(...)
) may be applied. Note that this does not includetypedef
declarations nor alias-declarations.Per [dcl.attr.grammar] (7.6.1)p4:
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).I think you just placed the
alignas
in the wrong position. If you move it directly after the identifier, both GCC and Clang are happy and apply the alignment:this is also true if you use
using
, where the difference also becomes more apparent. Here are two versions that are not accepted by GCC (warning, alignment ignored):and here's the accepted one:
I think that GCC applies
(emphasis mine)
The above is quite clear for
using
, the rules fortypedef
are spread through several paragraphs, including at the end of §8.3/1, where you find:(again, emphasis mine)
Update: The above answer concentrated on where the
alignas
has to be placed, not on its exact meaning. After thinking about it some more, I still think that the above should be valid. Consider:It lists cases where it can be clearly applied and it lists cases where it clearly can not be applied. The above question's example is neither.
One could also argue that the type alias created by
typedef
orusing
is carrying the alignment specification as part of the aliased type. This alias can than be used to create a variable, etc. as allowed by 7.6.2p1 but not to create a variable withregister
, etc.In that sense I think that the attribute specifier is applied (in the sense of 7.6.2) in a deferred way and thus OPs example should still be valid when the alignment specification is put in the syntactically correct place.
Try:
Draft C++11 standard http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf says about it (Alignment-specifier is of the form
alignas
( assignment-expression )):I found this original proposal http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1877.pdf , it says:
with this example:
Looks like it's illegal to use it with
typedef
.