| @@ -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 | |
53 | typedef struct integer_constraints { | | 53 | typedef 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 | |
3445 | static bool | | 3445 | static bool |
3446 | is_byte_array(const type_t *tp) | | 3446 | is_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 | |
3453 | static bool | | 3453 | static bool |
| | | 3454 | union_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 | |
| | | 3464 | static bool |
3454 | should_warn_about_pointer_cast(const type_t *nstp, tspec_t nst, | | 3465 | should_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 | |
3511 | static void | | 3518 | static void |
3512 | convert_pointer_from_pointer(type_t *ntp, tnode_t *tn) | | 3519 | convert_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 | /* |