Sat Apr 22 20:54:28 2023 UTC ()
lint: allow cast from a type to a union containing that type


(rillig)
diff -r1.13 -r1.14 src/tests/usr.bin/xlint/lint1/msg_135.c
diff -r1.518 -r1.519 src/usr.bin/xlint/lint1/tree.c

cvs diff -r1.13 -r1.14 src/tests/usr.bin/xlint/lint1/msg_135.c (expand / switch to unified diff)

--- src/tests/usr.bin/xlint/lint1/msg_135.c 2023/04/22 19:45:04 1.13
+++ src/tests/usr.bin/xlint/lint1/msg_135.c 2023/04/22 20:54:28 1.14
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: msg_135.c,v 1.13 2023/04/22 19:45:04 rillig Exp $ */ 1/* $NetBSD: msg_135.c,v 1.14 2023/04/22 20:54:28 rillig Exp $ */
2# 3 "msg_135.c" 2# 3 "msg_135.c"
3 3
4// Test for message: converting '%s' to '%s' increases alignment from %u to %u [135] 4// Test for message: converting '%s' to '%s' increases alignment from %u to %u [135]
5 5
6/* lint1-extra-flags: -h -X 351 */ 6/* lint1-extra-flags: -h -X 351 */
7 7
8void sink(const void *); 8void sink(const void *);
9 9
10unsigned 10unsigned
11read_uint(const unsigned short **pp) 11read_uint(const unsigned short **pp)
12{ 12{
13 unsigned val; 13 unsigned val;
14 14
@@ -85,19 +85,17 @@ plain_char_to_unsigned_type(char *cp) @@ -85,19 +85,17 @@ plain_char_to_unsigned_type(char *cp)
85 * member of the struct determines how the remaining members are interpreted. 85 * member of the struct determines how the remaining members are interpreted.
86 * See sbin/newfs_udf, function udf_validate_tag_and_crc_sums for an example. 86 * See sbin/newfs_udf, function udf_validate_tag_and_crc_sums for an example.
87 */ 87 */
88double 88double
89cast_to_union(void) 89cast_to_union(void)
90{ 90{
91 int align_4 = 0; 91 int align_4 = 0;
92 double align_8 = 0.0; 92 double align_8 = 0.0;
93 union both { 93 union both {
94 int p_align_4; 94 int p_align_4;
95 double p_align_8; 95 double p_align_8;
96 } *both; 96 } *both;
97 97
98 /* TODO: don't warn here. */ 
99 /* expect+1: warning: converting 'pointer to int' to 'pointer to union both' increases alignment from 4 to 8 [135] */ 
100 both = (union both *)&align_4; 98 both = (union both *)&align_4;
101 both = (union both *)&align_8; 99 both = (union both *)&align_8;
102 return both->p_align_8; 100 return both->p_align_8;
103} 101}

cvs diff -r1.518 -r1.519 src/usr.bin/xlint/lint1/tree.c (expand / switch to unified diff)

--- src/usr.bin/xlint/lint1/tree.c 2023/04/22 20:17:19 1.518
+++ src/usr.bin/xlint/lint1/tree.c 2023/04/22 20:54:28 1.519
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: tree.c,v 1.518 2023/04/22 20:17:19 rillig Exp $ */ 1/* $NetBSD: tree.c,v 1.519 2023/04/22 20:54:28 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1994, 1995 Jochen Pohl 4 * Copyright (c) 1994, 1995 Jochen Pohl
5 * All Rights Reserved. 5 * All Rights Reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -27,27 +27,27 @@ @@ -27,27 +27,27 @@
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */ 32 */
33 33
34#if HAVE_NBTOOL_CONFIG_H 34#if HAVE_NBTOOL_CONFIG_H
35#include "nbtool_config.h" 35#include "nbtool_config.h"
36#endif 36#endif
37 37
38#include <sys/cdefs.h> 38#include <sys/cdefs.h>
39#if defined(__RCSID) 39#if defined(__RCSID)
40__RCSID("$NetBSD: tree.c,v 1.518 2023/04/22 20:17:19 rillig Exp $"); 40__RCSID("$NetBSD: tree.c,v 1.519 2023/04/22 20:54:28 rillig Exp $");
41#endif 41#endif
42 42
43#include <float.h> 43#include <float.h>
44#include <limits.h> 44#include <limits.h>
45#include <math.h> 45#include <math.h>
46#include <signal.h> 46#include <signal.h>
47#include <stdlib.h> 47#include <stdlib.h>
48#include <string.h> 48#include <string.h>
49 49
50#include "lint1.h" 50#include "lint1.h"
51 51
52 52
53typedef struct integer_constraints { 53typedef struct integer_constraints {
@@ -3441,26 +3441,37 @@ struct_starts_with(const type_t *struct_ @@ -3441,26 +3441,37 @@ struct_starts_with(const type_t *struct_
3441 types_compatible(struct_tp->t_sou->sou_first_member->s_type, 3441 types_compatible(struct_tp->t_sou->sou_first_member->s_type,
3442 member_tp, true, false, NULL); 3442 member_tp, true, false, NULL);
3443} 3443}
3444 3444
3445static bool 3445static bool
3446is_byte_array(const type_t *tp) 3446is_byte_array(const type_t *tp)
3447{ 3447{
3448 3448
3449 return tp->t_tspec == ARRAY && 3449 return tp->t_tspec == ARRAY &&
3450 (tp->t_subt->t_tspec == CHAR || tp->t_subt->t_tspec == UCHAR); 3450 (tp->t_subt->t_tspec == CHAR || tp->t_subt->t_tspec == UCHAR);
3451} 3451}
3452 3452
3453static bool 3453static bool
 3454union_contains(const type_t *utp, const type_t *mtp)
 3455{
 3456 for (const sym_t *mem = utp->t_sou->sou_first_member;
 3457 mem != NULL; mem = mem->s_next) {
 3458 if (types_compatible(mem->s_type, mtp, true, false, NULL))
 3459 return true;
 3460 }
 3461 return false;
 3462}
 3463
 3464static bool
3454should_warn_about_pointer_cast(const type_t *nstp, tspec_t nst, 3465should_warn_about_pointer_cast(const type_t *nstp, tspec_t nst,
3455 const type_t *ostp, tspec_t ost) 3466 const type_t *ostp, tspec_t ost)
3456{ 3467{
3457 3468
3458 while (nst == ARRAY) 3469 while (nst == ARRAY)
3459 nstp = nstp->t_subt, nst = nstp->t_tspec; 3470 nstp = nstp->t_subt, nst = nstp->t_tspec;
3460 while (ost == ARRAY) 3471 while (ost == ARRAY)
3461 ostp = ostp->t_subt, ost = ostp->t_tspec; 3472 ostp = ostp->t_subt, ost = ostp->t_tspec;
3462 3473
3463 if (nst == STRUCT && ost == STRUCT && 3474 if (nst == STRUCT && ost == STRUCT &&
3464 (struct_starts_with(nstp, ostp) || 3475 (struct_starts_with(nstp, ostp) ||
3465 struct_starts_with(ostp, nstp))) 3476 struct_starts_with(ostp, nstp)))
3466 return false; 3477 return false;
@@ -3484,32 +3495,28 @@ should_warn_about_pointer_cast(const typ @@ -3484,32 +3495,28 @@ should_warn_about_pointer_cast(const typ
3484 true, false, NULL)) 3495 true, false, NULL))
3485 nmem = nmem->s_next, omem = omem->s_next; 3496 nmem = nmem->s_next, omem = omem->s_next;
3486 if (nmem != NULL && is_byte_array(nmem->s_type)) 3497 if (nmem != NULL && is_byte_array(nmem->s_type))
3487 return false; 3498 return false;
3488 if (omem != NULL && is_byte_array(omem->s_type)) 3499 if (omem != NULL && is_byte_array(omem->s_type))
3489 return false; 3500 return false;
3490 if (nmem == NULL && omem == NULL) 3501 if (nmem == NULL && omem == NULL)
3491 return false; 3502 return false;
3492 } 3503 }
3493 3504
3494 if (nst == UNION || ost == UNION) { 3505 if (nst == UNION || ost == UNION) {
3495 const type_t *union_tp = nst == UNION ? nstp : ostp; 3506 const type_t *union_tp = nst == UNION ? nstp : ostp;
3496 const type_t *other_tp = nst == UNION ? ostp : nstp; 3507 const type_t *other_tp = nst == UNION ? ostp : nstp;
3497 for (const sym_t *mem = union_tp->t_sou->sou_first_member; 3508 if (union_contains(union_tp, other_tp))
3498 mem != NULL; mem = mem->s_next) { 3509 return false;
3499 if (types_compatible(mem->s_type, other_tp, 
3500 true, false, NULL)) 
3501 return false; 
3502 } 
3503 } 3510 }
3504 3511
3505 if (is_struct_or_union(nst) && nstp->t_sou != ostp->t_sou) 3512 if (is_struct_or_union(nst) && nstp->t_sou != ostp->t_sou)
3506 return true; 3513 return true;
3507 3514
3508 return portable_size_in_bits(nst) != portable_size_in_bits(ost); 3515 return portable_size_in_bits(nst) != portable_size_in_bits(ost);
3509} 3516}
3510 3517
3511static void 3518static void
3512convert_pointer_from_pointer(type_t *ntp, tnode_t *tn) 3519convert_pointer_from_pointer(type_t *ntp, tnode_t *tn)
3513{ 3520{
3514 const type_t *nstp = ntp->t_subt; 3521 const type_t *nstp = ntp->t_subt;
3515 const type_t *otp = tn->tn_type; 3522 const type_t *otp = tn->tn_type;
@@ -3529,27 +3536,28 @@ convert_pointer_from_pointer(type_t *ntp @@ -3529,27 +3536,28 @@ convert_pointer_from_pointer(type_t *ntp
3529 } 3536 }
3530 return; 3537 return;
3531 } 3538 }
3532 if (nst == FUNC && ost == FUNC) 3539 if (nst == FUNC && ost == FUNC)
3533 return; 3540 return;
3534 if (nst == FUNC || ost == FUNC) { 3541 if (nst == FUNC || ost == FUNC) {
3535 /* converting '%s' to '%s' is questionable */ 3542 /* converting '%s' to '%s' is questionable */
3536 warning(229, type_name(otp), type_name(ntp)); 3543 warning(229, type_name(otp), type_name(ntp));
3537 return; 3544 return;
3538 } 3545 }
3539 3546
3540 if (hflag && alignment_in_bits(nstp) > alignment_in_bits(ostp) && 3547 if (hflag && alignment_in_bits(nstp) > alignment_in_bits(ostp) &&
3541 ost != CHAR && ost != UCHAR && 3548 ost != CHAR && ost != UCHAR &&
3542 !is_incomplete(ostp)) { 3549 !is_incomplete(ostp) &&
 3550 !(nst == UNION && union_contains(nstp, ostp))) {
3543 /* converting '%s' to '%s' increases alignment ... */ 3551 /* converting '%s' to '%s' increases alignment ... */
3544 warning(135, type_name(otp), type_name(ntp), 3552 warning(135, type_name(otp), type_name(ntp),
3545 alignment_in_bits(ostp) / CHAR_SIZE, 3553 alignment_in_bits(ostp) / CHAR_SIZE,
3546 alignment_in_bits(nstp) / CHAR_SIZE); 3554 alignment_in_bits(nstp) / CHAR_SIZE);
3547 } 3555 }
3548 3556
3549 if (cflag && should_warn_about_pointer_cast(nstp, nst, ostp, ost)) { 3557 if (cflag && should_warn_about_pointer_cast(nstp, nst, ostp, ost)) {
3550 /* pointer cast from '%s' to '%s' may be troublesome */ 3558 /* pointer cast from '%s' to '%s' may be troublesome */
3551 warning(247, type_name(otp), type_name(ntp)); 3559 warning(247, type_name(otp), type_name(ntp));
3552 } 3560 }
3553} 3561}
3554 3562
3555/* 3563/*