Convert "pointer to const" to "pointer to const VLA"


Diapier

In this code snippet, the large lookup table is easier to access using a pointer to the VLA :

#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 works fine when compiled with Clang 4.0.0 (trunk) , both -Wcast-qualenabled.

In function 'lookup':
warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual]
   DATA_PTR data = (DATA_PTR)raw;
                   ^

The code will work as expected.

My guess is that GCC is confusing "pointer to VLA of const element" and "pointer to const VLA", but I'm getting to...

Is there a way to turn off GCC without fiddling with warnings? Is this a GCC bug?

Edit 1:

Details of 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];
}

Edit 2:

So... the C11 draft standard says in 6.7.3/9:

If the specification of the array type includes any type qualifiers, the element type is qualified, not the array type.

See @hvd answer.

A trick of silence -Wcast-qual:

    DATA_PTR data = (DATA_PTR)(intptr_t)raw;
username

This is a long-standing problem in the C language. This is why

int array[2];
const int (*ptr)[2] = &array;

is invalid in C (but will be valid in C++): this declares an array of pointer const-qualified integers, which is not an constinteger-qualified array, so the normal rules of pointer types can be implicitly converted to pointers to constthat type- The qualified version of the pointer is not applicable.

In your case, you are converting from const char *( should warn ) from (pointer to -qualified consttype ) to ( char const (*)[a][b][c]pointer to non const-qualified type ) -Wcast-qual.

clang never thought to implement this special feature of C, it treats C code using C++ semantics which say that arrays of constelements themselves are also consteligible.

Usually you can work around this by wrapping the array in struct:

typedef struct { char d[a][b][c]; } const *DATA_PTR;

But that's not an option for VLAs. I don't think there is a proper workaround here other than not using multidimensional arrays at all or not -Wcast-qual.

Related


Convert "pointer to const" to "pointer to const VLA"

Diapier In this code snippet, the large lookup table is easier to access using a pointer to the VLA : #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

Convert "pointer to const" to "pointer to const VLA"

Diapier In this code snippet, the large lookup table is easier to access using a pointer to the VLA : #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

Convert "pointer to const" to "pointer to const VLA"

Diapier In this code snippet, the large lookup table is easier to access using a pointer to the VLA : #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

Convert "pointer to const" to "pointer to const VLA"

Diapier In this code snippet, the large lookup table is easier to access using a pointer to the VLA : #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

Convert "pointer to const" to "pointer to const VLA"

Diapier In this code snippet, the large lookup table is easier to access using a pointer to the VLA : #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

Convert pointer to const in container type

emkey08 C++ provides implicit conversions from T *to const T *. If now used T *in container classes like in vector<T *>, then of course there is no implicit conversion anymore vector<const T *>. Using a reinterpret_castseems to cast the entire container, but i

Convert pointer to const in container type

emkey08 C++ provides implicit conversions from T *to const T *. If now used T *in container classes like in vector<T *>, then of course there is no implicit conversion anymore vector<const T *>. Using a reinterpret_castseems to cast the entire container, but i

pointer to const (or pointer to const)

Wengers I have the following code: #include <iostream> int main(){ int v1 = 20; int *p1 = &v1; int **p2 = &p1; return 0; } What I'm trying to do here is point one pointer to another and it works fine in this case. I make p1 point to a cons

use double pointer with const

MathMan Suppose we have int *p1; const int **pp2= &p1; const int n=13; // This means we cannot use PP2 to modify // the value of the variable whose address is stored in *PP2. *pp2 stores the address of some variable (n in this case) The book I'm reading - Int

pointer to const in function call

Acetate I have an array of integers int foo[3]and I want to pass it to another function. I want to accomplish two things: pass by reference Set it to constant as it should not be modified. The function I define is: void print_foo(const int(*const foo)[3]) {

pointer to const as function parameter

Cerno I have the following basic code: base code int main() { int i = 1; const int* p = &i; int* q = &i; test_ptr(p); test_ptr(q); } Can anyone explain why the first and third examples work with the above basic code, but not the second? Example im

pointer to const as function parameter

Cerno I have the following basic code: base code int main() { int i = 1; const int* p = &i; int* q = &i; test_ptr(p); test_ptr(q); } Can anyone explain why the first and third examples work with the above basic code, but not the second? Example im

pointer to const as function parameter

Cerno I have the following basic code: base code int main() { int i = 1; const int* p = &i; int* q = &i; test_ptr(p); test_ptr(q); } Can anyone explain why the first and third examples work with the above basic code, but not the second? Example im

use double pointer with const

MathMan Suppose we have int *p1; const int **pp2= &p1; const int n=13; // This means we cannot use PP2 to modify // the value of the variable whose address is stored in *PP2. *pp2 stores the address of some variable (n in this case) The book I'm reading - Int

pointer to const in function call

Acetate I have an array of integers int foo[3]and I want to pass it to another function. I want to accomplish two things: pass by reference Set it to constant as it should not be modified. The function I define is: void print_foo(const int(*const foo)[3]) {

use double pointer with const

MathMan Suppose we have int *p1; const int **pp2= &p1; const int n=13; // This means we cannot use PP2 to modify // the value of the variable whose address is stored in *PP2. *pp2 stores the address of some variable (n in this case) The book I'm reading - Int

pointer to const as function parameter

Cerno I have the following basic code: base code int main() { int i = 1; const int* p = &i; int* q = &i; test_ptr(p); test_ptr(q); } Can anyone explain why the first and third examples work with the above basic code, but not the second? Example im

Pass pointer by const reference

csguy Isn't passing pointers by const reference for optimization? predecessor. bool testHelper(const TreeNode*& p, const TreeNode*& q) { return false; } TreeNode* test(TreeNode* root, TreeNode* p, TreeNode* q) { recursiveHelper(p, q); } mistake: Line

pointer to const array of int

mr_Alex_Nok_ I have created a menu structure in an embedded system as follows: struct DisplayMenu { short int MenuTitle; // Menu title text offset - the title used in the calling menu char NoOfSubmenuItems;

pointer to const as function parameter

Cerno I have the following basic code: base code int main() { int i = 1; const int* p = &i; int* q = &i; test_ptr(p); test_ptr(q); } Can anyone explain why the first and third examples work with the above basic code, but not the second? Example im

pointer to const as function parameter

Cerno I have the following basic code: base code int main() { int i = 1; const int* p = &i; int* q = &i; test_ptr(p); test_ptr(q); } Can anyone explain why the first and third examples work with the above basic code, but not the second? Example im

use double pointer with const

MathMan Suppose we have int *p1; const int **pp2= &p1; const int n=13; // This means we cannot use PP2 to modify // the value of the variable whose address is stored in *PP2. *pp2 stores the address of some variable (n in this case) The book I'm reading - Int

use double pointer with const

MathMan Suppose we have int *p1; const int **pp2= &p1; const int n=13; // This means we cannot use PP2 to modify // the value of the variable whose address is stored in *PP2. *pp2 stores the address of some variable (n in this case) The book I'm reading - Int