diff options
| author | rillig <rillig@NetBSD.org> | 2023-07-08 16:13:00 +0000 |
|---|---|---|
| committer | rillig <rillig@NetBSD.org> | 2023-07-08 16:13:00 +0000 |
| commit | 9299a7c5194512b0d5ea06c7b286d4bae6640791 (patch) | |
| tree | c91e393a4af29d255b4af29197c80f1202c0f6f2 /usr.bin | |
| parent | 96e65dba728fddd2104244f530812358469a0896 (diff) | |
lint: warn about pointer casts between different kinds of types
Pointer casts from an integer type to a floating-point type and vice
versa get a 'maybe troublesome' warning now. The previous assumption
that all types of the same bit-size are convertible may have been valid
from a technical point of view, but still such code should get more
attention.
The rules for struct and union types could be made more fine-grained
later, if the need arises. To suppress this warning, it's always
possible to cast to an intermediate 'void *'.
Diffstat (limited to 'usr.bin')
| -rw-r--r-- | usr.bin/xlint/common/inittyp.c | 60 | ||||
| -rw-r--r-- | usr.bin/xlint/common/lint.h | 13 | ||||
| -rw-r--r-- | usr.bin/xlint/lint1/decl.c | 13 | ||||
| -rw-r--r-- | usr.bin/xlint/lint1/tree.c | 21 |
4 files changed, 65 insertions, 42 deletions
diff --git a/usr.bin/xlint/common/inittyp.c b/usr.bin/xlint/common/inittyp.c index ee9263554b5..1fcb9bb10c3 100644 --- a/usr.bin/xlint/common/inittyp.c +++ b/usr.bin/xlint/common/inittyp.c @@ -1,4 +1,4 @@ -/* $NetBSD: inittyp.c,v 1.38 2023/07/08 09:35:35 rillig Exp $ */ +/* $NetBSD: inittyp.c,v 1.39 2023/07/08 16:13:00 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -37,7 +37,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: inittyp.c,v 1.38 2023/07/08 09:35:35 rillig Exp $"); +__RCSID("$NetBSD: inittyp.c,v 1.39 2023/07/08 16:13:00 rillig Exp $"); #endif #if defined(IS_LINT1) @@ -46,12 +46,17 @@ __RCSID("$NetBSD: inittyp.c,v 1.38 2023/07/08 09:35:35 rillig Exp $"); #include "lint2.h" #endif -#define INT_RSIZE (/*CONSTCOND*/INTPTR_TSPEC == LONG ? 3 : 4) +#define INT_RANK (/*CONSTCOND*/INTPTR_TSPEC == LONG ? 4 : 5) #ifdef IS_LINT1 -#define typeinfo(name, signed_type, unsigned_type, size_in_bits, rank, c) \ +#define typeinfo(name, signed_type, unsigned_type, size_in_bits, rv, c) \ { /*CONSTCOND*/ \ - size_in_bits, rank, \ + size_in_bits, \ + (c) == 'u' || (c) == 's' || (c) == 'p' ? RK_INTEGER : \ + (c) == 'f' ? RK_FLOATING : \ + (c) == 'c' ? RK_COMPLEX : \ + RK_NONE, \ + rv, \ signed_type, unsigned_type, \ (c) == 's' || (c) == 'u', \ (c) == 'u' || (c) == 'p', \ @@ -78,41 +83,44 @@ ttab_t ttab[NTSPEC] = { typeinfo("signed", SIGNED, UNSIGN, 0, 0, ' '), typeinfo("unsigned", SIGNED, UNSIGN, 0, 0, ' '), typeinfo("_Bool", BOOL, BOOL, CHAR_SIZE, 1, 'u'), - typeinfo("char", SCHAR, UCHAR, CHAR_SIZE, 8, + typeinfo("char", SCHAR, UCHAR, CHAR_SIZE, 2, TARG_CHAR_MIN == 0 ? 'u' : 's'), - typeinfo("signed char", SCHAR, UCHAR, CHAR_SIZE, 8, 's'), - typeinfo("unsigned char", SCHAR, UCHAR, CHAR_SIZE, 8, 'u'), - typeinfo("short", SHORT, USHORT, SHORT_SIZE, 16, 's'), - typeinfo("unsigned short", SHORT, USHORT, SHORT_SIZE, 16, 'u'), - typeinfo("int", INT, UINT, INT_SIZE, INT_RSIZE * 8, 's'), - typeinfo("unsigned int", INT, UINT, INT_SIZE, INT_RSIZE * 8, 'u'), - typeinfo("long", LONG, ULONG, LONG_SIZE, 32, 's'), - typeinfo("unsigned long", LONG, ULONG, LONG_SIZE, 32, 'u'), - typeinfo("long long", LLONG, ULLONG, LLONG_SIZE, 64, 's'), - typeinfo("unsigned long long", LLONG, ULLONG, LLONG_SIZE, 64, 'u'), + typeinfo("signed char", SCHAR, UCHAR, CHAR_SIZE, 2, 's'), + typeinfo("unsigned char", SCHAR, UCHAR, CHAR_SIZE, 2, 'u'), + typeinfo("short", SHORT, USHORT, SHORT_SIZE, 3, 's'), + typeinfo("unsigned short", SHORT, USHORT, SHORT_SIZE, 3, 'u'), + typeinfo("int", INT, UINT, INT_SIZE, INT_RANK, 's'), + typeinfo("unsigned int", INT, UINT, INT_SIZE, INT_RANK, 'u'), + typeinfo("long", LONG, ULONG, LONG_SIZE, 5, 's'), + typeinfo("unsigned long", LONG, ULONG, LONG_SIZE, 5, 'u'), + typeinfo("long long", LLONG, ULLONG, LLONG_SIZE, 6, 's'), + typeinfo("unsigned long long", LLONG, ULLONG, LLONG_SIZE, 6, 'u'), #ifdef INT128_SIZE - typeinfo("__int128_t", INT128, UINT128, INT128_SIZE, 128, 's'), - typeinfo("__uint128_t", INT128, UINT128, INT128_SIZE, 128, 'u'), + typeinfo("__int128_t", INT128, UINT128, INT128_SIZE, 7, 's'), + typeinfo("__uint128_t", INT128, UINT128, INT128_SIZE, 7, 'u'), #endif - typeinfo("float", FLOAT, FLOAT, FLOAT_SIZE, 32, 'f'), - typeinfo("double", DOUBLE, DOUBLE, DOUBLE_SIZE, 64, 'f'), - typeinfo("long double", LDOUBLE, LDOUBLE, LDOUBLE_SIZE, 80, 'f'), + typeinfo("float", FLOAT, FLOAT, FLOAT_SIZE, 1, 'f'), + typeinfo("double", DOUBLE, DOUBLE, DOUBLE_SIZE, 2, 'f'), + typeinfo("long double", LDOUBLE, LDOUBLE, LDOUBLE_SIZE, 3, 'f'), #ifdef DEBUG typeinfo("_Complex", NO_TSPEC, NO_TSPEC, 0, 0, ' '), #else typeinfo(NULL, NO_TSPEC, NO_TSPEC, 0, 0, ' '), #endif typeinfo("float _Complex", FCOMPLEX, FCOMPLEX, - FLOAT_SIZE * 2, 32 * 2, 'c'), + FLOAT_SIZE * 2, 1, 'c'), typeinfo("double _Complex", DCOMPLEX, DCOMPLEX, - DOUBLE_SIZE * 2, 64 * 2, 'c'), + DOUBLE_SIZE * 2, 2, 'c'), typeinfo("long double _Complex", LCOMPLEX, LCOMPLEX, - LDOUBLE_SIZE * 2, 80 * 2, 'c'), + LDOUBLE_SIZE * 2, 3, 'c'), typeinfo("void", VOID, VOID, 0, 0, ' '), typeinfo("struct", STRUCT, STRUCT, 0, 0, ' '), typeinfo("union", UNION, UNION, 0, 0, ' '), - typeinfo("enum", ENUM, ENUM, ENUM_SIZE, 24, 's'), - typeinfo("pointer", PTR, PTR, PTR_SIZE, 32, 'p'), + // Will become more complicated in C23, which allows to choose the + // underlying type. + typeinfo("enum", ENUM, ENUM, ENUM_SIZE, INT_RANK, 's'), + // Same as 'unsigned long', which matches all supported platforms. + typeinfo("pointer", PTR, PTR, PTR_SIZE, 5, 'p'), typeinfo("array", ARRAY, ARRAY, 0, 0, ' '), typeinfo("function", FUNC, FUNC, 0, 0, ' '), }; diff --git a/usr.bin/xlint/common/lint.h b/usr.bin/xlint/common/lint.h index 6dd9431395f..77c8a518206 100644 --- a/usr.bin/xlint/common/lint.h +++ b/usr.bin/xlint/common/lint.h @@ -1,4 +1,4 @@ -/* $NetBSD: lint.h,v 1.40 2023/07/08 09:35:35 rillig Exp $ */ +/* $NetBSD: lint.h,v 1.41 2023/07/08 16:13:00 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -95,9 +95,14 @@ typedef enum { typedef struct { #ifdef IS_LINT1 unsigned int tt_size_in_bits; - unsigned int tt_rank; /* relative size of the type; depends on - * portable mode, as well as on whether sizeof - * has type 'int' or 'long' */ + enum rank_kind { + RK_NONE, + RK_INTEGER, + RK_FLOATING, + RK_COMPLEX, + } tt_rank_kind; + unsigned int tt_rank_value; /* relative size of the type; depends + * on pflag and PTRDIFF_TSPEC */ #endif tspec_t tt_signed_counterpart; tspec_t tt_unsigned_counterpart; diff --git a/usr.bin/xlint/lint1/decl.c b/usr.bin/xlint/lint1/decl.c index 3bf459d9f8b..8b116d8f878 100644 --- a/usr.bin/xlint/lint1/decl.c +++ b/usr.bin/xlint/lint1/decl.c @@ -1,4 +1,4 @@ -/* $NetBSD: decl.c,v 1.344 2023/07/08 09:35:35 rillig Exp $ */ +/* $NetBSD: decl.c,v 1.345 2023/07/08 16:13:00 rillig Exp $ */ /* * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. @@ -38,7 +38,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: decl.c,v 1.344 2023/07/08 09:35:35 rillig Exp $"); +__RCSID("$NetBSD: decl.c,v 1.345 2023/07/08 16:13:00 rillig Exp $"); #endif #include <sys/param.h> @@ -99,8 +99,13 @@ initdecl(void) dcs->d_last_dlsym = &dcs->d_first_dlsym; if (!pflag) { - for (size_t i = 0; i < NTSPEC; i++) - ttab[i].tt_rank = ttab[i].tt_size_in_bits; + for (size_t i = 0; i < NTSPEC; i++) { + if (ttab[i].tt_rank_kind != RK_NONE) + ttab[i].tt_rank_value = + ttab[i].tt_size_in_bits; + } + ttab[BOOL].tt_rank_kind = RK_INTEGER; + ttab[BOOL].tt_rank_value = 1; } if (Tflag) { diff --git a/usr.bin/xlint/lint1/tree.c b/usr.bin/xlint/lint1/tree.c index 9da4e6c1e9f..d6109cdc165 100644 --- a/usr.bin/xlint/lint1/tree.c +++ b/usr.bin/xlint/lint1/tree.c @@ -1,4 +1,4 @@ -/* $NetBSD: tree.c,v 1.553 2023/07/08 15:26:25 rillig Exp $ */ +/* $NetBSD: tree.c,v 1.554 2023/07/08 16:13:00 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -37,7 +37,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: tree.c,v 1.553 2023/07/08 15:26:25 rillig Exp $"); +__RCSID("$NetBSD: tree.c,v 1.554 2023/07/08 16:13:00 rillig Exp $"); #endif #include <float.h> @@ -100,9 +100,11 @@ width_in_bits(const type_t *tp) static int portable_rank_cmp(tspec_t t1, tspec_t t2) { - unsigned int r1 = type_properties(t1)->tt_rank; - unsigned int r2 = type_properties(t2)->tt_rank; - return (int)r1 - (int)r2; + const ttab_t *p1 = type_properties(t1), *p2 = type_properties(t2); + lint_assert(p1->tt_rank_kind == p2->tt_rank_kind); + lint_assert(p1->tt_rank_value > 0); + lint_assert(p2->tt_rank_value > 0); + return (int)p1->tt_rank_value - (int)p2->tt_rank_value; } static bool @@ -3541,8 +3543,6 @@ should_warn_about_pointer_cast(const type_t *nstp, tspec_t nst, /* Allow cast between pointers to sockaddr variants. */ if (nst == STRUCT && ost == STRUCT) { - debug_type(nstp); - debug_type(ostp); const sym_t *nmem = nstp->t_sou->sou_first_member; const sym_t *omem = ostp->t_sou->sou_first_member; while (nmem != NULL && omem != NULL && @@ -3564,7 +3564,12 @@ should_warn_about_pointer_cast(const type_t *nstp, tspec_t nst, return false; } - if (is_struct_or_union(nst) && nstp->t_sou != ostp->t_sou) + if (is_struct_or_union(nst) && is_struct_or_union(ost)) + return nstp->t_sou != ostp->t_sou; + + enum rank_kind rk1 = type_properties(nst)->tt_rank_kind; + enum rank_kind rk2 = type_properties(ost)->tt_rank_kind; + if (rk1 != rk2 || rk1 == RK_NONE) return true; return portable_rank_cmp(nst, ost) != 0; |
