1*b2baa501Srillig /* $NetBSD: msg_115.c,v 1.11 2023/03/28 14:44:34 rillig Exp $ */
2a0a15c14Srillig # 3 "msg_115.c"
3a0a15c14Srillig
4a0a15c14Srillig // Test for message: %soperand of '%s' must be modifiable lvalue [115]
5a0a15c14Srillig
6*b2baa501Srillig /* lint1-extra-flags: -X 351 */
7*b2baa501Srillig
8af03d2a0Srillig void
example(const int * const_ptr)9af03d2a0Srillig example(const int *const_ptr)
10af03d2a0Srillig {
11af03d2a0Srillig
1265e5c21bSrillig /* expect+1: warning: left operand of '=' must be modifiable lvalue [115] */
1365e5c21bSrillig *const_ptr = 3;
1465e5c21bSrillig /* expect+1: warning: left operand of '+=' must be modifiable lvalue [115] */
1565e5c21bSrillig *const_ptr += 1;
1665e5c21bSrillig /* expect+1: warning: left operand of '-=' must be modifiable lvalue [115] */
1765e5c21bSrillig *const_ptr -= 4;
1865e5c21bSrillig /* expect+1: warning: left operand of '*=' must be modifiable lvalue [115] */
1965e5c21bSrillig *const_ptr *= 1;
2065e5c21bSrillig /* expect+1: warning: left operand of '/=' must be modifiable lvalue [115] */
2165e5c21bSrillig *const_ptr /= 5;
2265e5c21bSrillig /* expect+1: warning: left operand of '%=' must be modifiable lvalue [115] */
2365e5c21bSrillig *const_ptr %= 9;
2465e5c21bSrillig /* expect+1: warning: operand of 'x++' must be modifiable lvalue [115] */
2565e5c21bSrillig (*const_ptr)++;
261890122fSrillig
271890122fSrillig /* In the next example, the left operand is not an lvalue at all. */
281890122fSrillig /* expect+1: error: left operand of '=' must be lvalue [114] */
291890122fSrillig (const_ptr + 3) = const_ptr;
30af03d2a0Srillig }
31fe7cbecdSrillig
3236db97e5Srillig typedef struct {
3336db97e5Srillig int const member;
3436db97e5Srillig } const_member;
3536db97e5Srillig
3636db97e5Srillig void take_const_member(const_member);
3736db97e5Srillig
381890122fSrillig /*
391890122fSrillig * Before init.c 1.208 from 2021-08-14 and decl.c 1.221 from 2021-08-10,
401890122fSrillig * lint issued a wrong "warning: left operand of '%s' must be modifiable
411890122fSrillig * lvalue", even in cases where the left operand was being initialized
421890122fSrillig * instead of overwritten.
431890122fSrillig *
441890122fSrillig * See initialization_expr_using_op, typeok_assign, has_constant_member.
451890122fSrillig * See C99 6.2.5p25.
461890122fSrillig */
4736db97e5Srillig const_member
initialize_const_struct_member(void)48fe7cbecdSrillig initialize_const_struct_member(void)
49fe7cbecdSrillig {
50c8a8302dSrillig /* In a simple initialization, const members can be assigned. */
5136db97e5Srillig const_member cm1 = (const_member) { 12345 };
52c8a8302dSrillig
5336db97e5Srillig if (cm1.member != 0)
5436ba9804Srillig /* In a function call, const members can be assigned. */
5536db97e5Srillig take_const_member(cm1);
56fe7cbecdSrillig
5736db97e5Srillig struct {
5836db97e5Srillig const_member member;
5936db97e5Srillig } cm2 = {
60c8a8302dSrillig /* In a nested initialization, const members can be assigned. */
6136db97e5Srillig cm1,
6236db97e5Srillig };
6336db97e5Srillig if (cm2.member.member != 0) {
6436db97e5Srillig }
6536db97e5Srillig
6636ba9804Srillig /* In a return statement, const members can be assigned. */
6736db97e5Srillig return cm1;
68fe7cbecdSrillig }
69