From a338258d309c888bde96b2d1f206299231a54ddf Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Sat, 13 Jun 2026 21:30:00 +0900 Subject: [PATCH] Fix qualifiers on const array struct members 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. --- tccgen.c | 3 +- tests/tests2/60_errors_and_warnings.c | 110 +++++++++++++++++++++ tests/tests2/60_errors_and_warnings.expect | 28 ++++++ 3 files changed, 140 insertions(+), 1 deletion(-) diff --git a/tccgen.c b/tccgen.c index a5df8876..8806f0ed 100644 --- a/tccgen.c +++ b/tccgen.c @@ -6184,7 +6184,8 @@ special_math_val: gen_op('+'); /* change type to field type, and set to lvalue */ vtop->type = s->type; - vtop->type.t |= qualifiers; + if (qualifiers) + parse_btype_qualify(&vtop->type, qualifiers); /* an array is never an lvalue */ if (!(vtop->type.t & VT_ARRAY)) { vtop->r |= VT_LVAL; diff --git a/tests/tests2/60_errors_and_warnings.c b/tests/tests2/60_errors_and_warnings.c index 2b8489d6..c3eda13f 100644 --- a/tests/tests2/60_errors_and_warnings.c +++ b/tests/tests2/60_errors_and_warnings.c @@ -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 diff --git a/tests/tests2/60_errors_and_warnings.expect b/tests/tests2/60_errors_and_warnings.expect index a90f4153..5f7be4ba 100644 --- a/tests/tests2/60_errors_and_warnings.expect +++ b/tests/tests2/60_errors_and_warnings.expect @@ -262,3 +262,31 @@ bar 15 12 34 [test_scope_3] 60_errors_and_warnings.c:548: warning: assignment from incompatible pointer 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]