In this snippet, a pointer to VLA is used for easier access to a big lookup table :
#pragma GCC diagnostic warning "-Wcast-qual"
char
lookup(int a, int b, int c, char const *raw, int x, int y, int z)
{
typedef char const (*DATA_PTR)[a][b][c];
DATA_PTR data = (DATA_PTR)raw;
return (*data)[x][y][z];
}
GCC 6.2.0 chokes on it while Clang 4.0.0(trunk) compiles just fine, both with -Wcast-qual
enabled.
In function 'lookup':
warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual]
DATA_PTR data = (DATA_PTR)raw;
^
The code runs as expected either way.
My guess is GCC confuses a "pointer to VLA of const elements" and "pointer to const VLA" but I'm reaching ...
Is there a way to shut up GCC without fiddling with warnings ? Is this a GCC bug ?
EDIT1:
Details on the actual code :
struct table {
int a;
int b;
int c;
char *raw;
};
char
lookup2(struct table const *table, int x, int y, int z)
{
typedef char const(*DATA_PTR)[table->a][table->b][table->c];
DATA_PTR data;
data = (DATA_PTR)table->raw; // GCC ok
data = (DATA_PTR)(char const *)table->raw; // GCC raises -Wcast-qual
return (*data)[x][y][z];
}
EDIT2:
So there it is ... the C11 standard draft says in 6.7.3/9 :
If the specification of an array type includes any type qualifiers, the element type is so-qualified, not the array type.
See @hvd answer.
One hack to silence -Wcast-qual
:
DATA_PTR data = (DATA_PTR)(intptr_t)raw;
This is a long-standing issue in C. It's the same reason why
is invalid in C (but would be valid in C++): this declares a pointer to an array of
const
-qualified integers, which is not aconst
-qualified array of integers, so the normal rule that a pointer to an type can be implicitly converted to a pointer to theconst
-qualified version of that type does not apply.In your case, you're converting from
const char *
(a pointer to aconst
-qualified type) tochar const (*)[a][b][c]
(a pointer to a non-const
-qualified type), which-Wcast-qual
is supposed to warn about.clang just never bothered to implement this particular oddity of C, it treats C code with the C++ semantics, which say that an array of
const
elements is itselfconst
-qualified as well.You'd normally be able to work around it by wrapping the array in a
struct
:but this is not an option for VLAs. I do not believe there is a suitable workaround other than not using multi-dimensional arrays at all here, or not using
-Wcast-qual
.