Fix qualifiers on const array struct members
Some checks are pending
build and test / test-x86_64-linux (push) Waiting to run
build and test / test-x86_64-osx (push) Waiting to run
build and test / test-aarch64-osx (push) Waiting to run
build and test / test-x86_64-win32 (push) Waiting to run
build and test / test-i386-win32 (push) Waiting to run
build and test / test-arm64-win32 (push) Waiting to run
build and test / test-armv7-linux (push) Waiting to run
build and test / test-aarch64-linux (push) Waiting to run
build and test / test-riscv64-linux (push) Waiting to run
build and test / test-riscv64-linux-native (push) Waiting to run

Use the existing array-aware qualifier helper when propagating qualifiers from a const or volatile aggregate to a selected field. This keeps address-of array members from spuriously warning while preserving warnings for discarded qualifiers and read-only writes.

Add regression coverage for pointer-to-array returns, array decay, and writes through const array members.
This commit is contained in:
Mounir IDRASSI 2026-06-13 21:30:00 +09:00
parent fb4077f2da
commit a338258d30
3 changed files with 140 additions and 1 deletions

View File

@ -6184,7 +6184,8 @@ special_math_val:
gen_op('+'); gen_op('+');
/* change type to field type, and set to lvalue */ /* change type to field type, and set to lvalue */
vtop->type = s->type; vtop->type = s->type;
vtop->type.t |= qualifiers; if (qualifiers)
parse_btype_qualify(&vtop->type, qualifiers);
/* an array is never an lvalue */ /* an array is never an lvalue */
if (!(vtop->type.t & VT_ARRAY)) { if (!(vtop->type.t & VT_ARRAY)) {
vtop->r |= VT_LVAL; vtop->r |= VT_LVAL;

View File

@ -551,4 +551,114 @@ int main(int argc, char **argv)
} }
#elif defined test_const_array_member_addr_ok
typedef int int_array[1];
typedef struct { int_array arr; } my_struct;
int_array const *get_array(const my_struct *s)
{
return &(s->arr);
}
#elif defined test_const_array_member_decay_ok
typedef int int_array[1];
typedef struct { int_array arr; } my_struct;
const int *good_decay(const my_struct *s)
{
return s->arr;
}
#elif defined test_const_array_member_addr_bad
typedef int int_array[1];
typedef struct { int_array arr; } my_struct;
int_array *bad_array_addr(const my_struct *s)
{
return &(s->arr);
}
#elif defined test_const_array_member_decay_bad
typedef int int_array[1];
typedef struct { int_array arr; } my_struct;
int *bad_decay(const my_struct *s)
{
return s->arr;
}
#elif defined test_const_array_member_write_bad
typedef int int_array[1];
typedef struct { int_array arr; } my_struct;
void bad_write(const my_struct *s)
{
s->arr[0] = 1;
}
#elif defined test_const_struct_array_member_write_bad
typedef struct { int x; } inner;
typedef struct { inner arr[1]; } outer;
void bad_inner_write(const outer *s)
{
s->arr[0].x = 1;
}
#elif defined test_volatile_array_member_addr_ok
typedef int int_array[1];
typedef struct { int_array arr; } my_struct;
int_array volatile *get_volatile_array(volatile my_struct *s)
{
return &(s->arr);
}
#elif defined test_volatile_array_member_decay_ok
typedef int int_array[1];
typedef struct { int_array arr; } my_struct;
volatile int *good_volatile_decay(volatile my_struct *s)
{
return s->arr;
}
#elif defined test_volatile_array_member_addr_bad
typedef int int_array[1];
typedef struct { int_array arr; } my_struct;
int_array *bad_volatile_array_addr(volatile my_struct *s)
{
return &(s->arr);
}
#elif defined test_volatile_array_member_decay_bad
typedef int int_array[1];
typedef struct { int_array arr; } my_struct;
int *bad_volatile_decay(volatile my_struct *s)
{
return s->arr;
}
#elif defined test_volatile_array_member_write_ok
typedef int int_array[1];
typedef struct { int_array arr; } my_struct;
void good_volatile_write(volatile my_struct *s)
{
s->arr[0] = 1;
}
#endif #endif

View File

@ -262,3 +262,31 @@ bar 15 12 34
[test_scope_3] [test_scope_3]
60_errors_and_warnings.c:548: warning: assignment from incompatible pointer type 60_errors_and_warnings.c:548: warning: assignment from incompatible pointer type
60_errors_and_warnings.c:549: error: initialization of incomplete type 60_errors_and_warnings.c:549: error: initialization of incomplete type
[test_const_array_member_addr_ok]
[test_const_array_member_decay_ok]
[test_const_array_member_addr_bad]
60_errors_and_warnings.c:581: warning: assignment discards qualifiers from pointer target type
[test_const_array_member_decay_bad]
60_errors_and_warnings.c:591: warning: assignment discards qualifiers from pointer target type
[test_const_array_member_write_bad]
60_errors_and_warnings.c:601: warning: assignment of read-only location
[test_const_struct_array_member_write_bad]
60_errors_and_warnings.c:611: warning: assignment of read-only location
[test_volatile_array_member_addr_ok]
[test_volatile_array_member_decay_ok]
[test_volatile_array_member_addr_bad]
60_errors_and_warnings.c:641: warning: assignment discards qualifiers from pointer target type
[test_volatile_array_member_decay_bad]
60_errors_and_warnings.c:651: warning: assignment discards qualifiers from pointer target type
[test_volatile_array_member_write_ok]