Given the following code:
$ cat test.cpp
char __attribute__((aligned(4))) c[sizeof(int)];
int *i = reinterpret_cast<int *>(&f.c);
*i = 0;
When compiled for ARM produces the warning:
$ arm-none-linux-gnueabi-g++ -Wcast-align -O3 -fsyntax-only /tmp/test.cpp
test.cpp:11: warning: cast from 'char (*)' to 'int*' increases required alignment of target type
Note that we requested that Foo::c be aligned to 4 bytes, which is the required alignment for int. The assembly dump of the build confirms that the alignment was honoured:
.type f, %object
.size f, 4
According to Dirk Müller, the following code is at fault (I have no idea where it's from):
/* Warn about possible alignment problems. */
if (STRICT_ALIGNMENT && warn_cast_align
&& (complain & tf_warning)
· && !VOID_TYPE_P (type)
· && TREE_CODE (TREE_TYPE (intype)) != FUNCTION_TYPE
· && COMPLETE_TYPE_P (TREE_TYPE (type))
· && COMPLETE_TYPE_P (TREE_TYPE (intype))
· && TYPE_ALIGN (TREE_TYPE (type)) > TYPE_ALIGN (TREE_TYPE (intype)))
· warning (OPT_Wcast_align, "cast from %qT to %qT "
"increases required alignment of target type", intype, type);
As it only verifies the aligment of the type in question (char*), not of the variable in question (&f.c).
I think the warning is correct as the resulting type of &f.c is a pointer to an array and that array is of type char which has an alignment of 1. Yes f.c has an alignment of 4 but the array type has an alignment of 1.
Well, technically f.c has a type of 'char (__attribute__((aligned(4)))) '.
Anyway, the point is that the variable is properly aligned, so the warning is superfluous.
Or, in other words, we need a way to tell GCC "I know this is properly aligned, so don't tell me there's a problem". The -Wcast-align warning is very useful to catch real mistakes, but there's no way to weed out the false positives.
The struct Foo looks like an odd way to try and express
char c[sizeof (int)];
but that doesn't work either, for my 4.3.1 arm-linux build.
Neither does moving the attribute just before the ";" (either ones) or before "char" (the original or the above). Neither in C (changing reinterpret_cast to a C cast).
(In reply to comment #3)
> The struct Foo looks like an odd way to try and express
> union Foo
> int i;
> char c[sizeof (int)];
Well, that is the objective, but you can't replace int with a non-POD type in C++98. C++0x relaxes the unions and that's exactly what is intended: delayed construction.
I used int as an example, but the objective is to have:
template <typename T>
char __attribute__((aligned(__alignof__(T)))) buf[sizeof(T)];
[the WebKit WTF::Vector code is a bit more complex than that to get around the fact that gcc 4.2 can't do aligned(__alignof__(T)), so it partially specialises alignments of 1, 2, 4, 8, 16, and 64]
Confirmed on latest 4.4, 4.5 and 4.6 (trunk).
Related GCC documentation on alignment of structure fields is here:
In the short-term, one workaround is to write the code as follows:
int *i = reinterpret_cast<int *>(&f);
*i = 0x44434241;
printf("%c %c %c %c", f.c, f.c, f.c, f.c);
By aligning the structure Foo to 4 bytes, you can successfully cast a Foo* to an int* and then initialise all four chars in one go. (Without the type attribute for the struct Foo, you still get the warning.) My example prints "A B C D".
FYI: I have tracked down the alleged offending code mentioned in an earlier comment to build_c_cast() in c-typeck.c.