Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/xlint/lint1 lint: fix query for redundant cast befor...



details:   https://anonhg.NetBSD.org/src/rev/57929c3ed368
branches:  trunk
changeset: 368386:57929c3ed368
user:      rillig <rillig%NetBSD.org@localhost>
date:      Fri Jul 08 20:27:36 2022 +0000

description:
lint: fix query for redundant cast before assignment

Previously, 'i = (int)dbl' was marked as redundant, even though it
performs a value conversion.

diffstat:

 tests/usr.bin/xlint/lint1/queries.c |  131 ++++++++++++++++++++++++++++++++---
 usr.bin/xlint/lint1/README.md       |   21 +++--
 usr.bin/xlint/lint1/tree.c          |   65 ++++++++++++++---
 3 files changed, 182 insertions(+), 35 deletions(-)

diffs (truncated from 325 to 300 lines):

diff -r 315c7497dab3 -r 57929c3ed368 tests/usr.bin/xlint/lint1/queries.c
--- a/tests/usr.bin/xlint/lint1/queries.c       Fri Jul 08 17:47:47 2022 +0000
+++ b/tests/usr.bin/xlint/lint1/queries.c       Fri Jul 08 20:27:36 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: queries.c,v 1.1 2022/07/05 22:50:41 rillig Exp $       */
+/*     $NetBSD: queries.c,v 1.2 2022/07/08 20:27:36 rillig Exp $       */
 # 3 "queries.c"
 
 /*
@@ -17,6 +17,50 @@
 
 /* lint1-extra-flags: -q 1,2,3,4,5,6,7 */
 
+typedef unsigned char u8_t;
+typedef unsigned short u16_t;
+typedef unsigned int u32_t;
+typedef unsigned long long u64_t;
+typedef signed char s8_t;
+typedef signed short s16_t;
+typedef signed int s32_t;
+typedef signed long long s64_t;
+
+typedef float f32_t;
+typedef double f64_t;
+typedef float _Complex c32_t;
+typedef double _Complex c64_t;
+
+u8_t u8;
+u16_t u16;
+u32_t u32;
+u64_t u64;
+
+s8_t s8;
+s16_t s16;
+s32_t s32;
+s64_t s64;
+
+struct {
+       unsigned u8:8;
+       unsigned u9:9;
+       unsigned u10:10;
+       unsigned u32:32;
+       int s8:8;
+       int s9:9;
+       int s10:10;
+       int s32:32;
+} bits;
+
+f32_t f32;
+f64_t f64;
+
+c32_t c32;
+c64_t c64;
+
+char *str;
+const char *cstr;
+
 int
 Q1(double dbl)
 {
@@ -27,8 +71,7 @@
 int
 Q2(double dbl)
 {
-       /* expect+2: cast from floating point 'double' to integer 'int' [Q2] */
-       /* expect+1: redundant cast from 'double' to 'int' before assignment [Q7] */
+       /* expect+1: cast from floating point 'double' to integer 'int' [Q2] */
        return (int)dbl;
 }
 
@@ -83,19 +126,85 @@
        i = (int)i + 1;
 }
 
-extern void *allocate(unsigned long);
+extern void *allocate(void);
 
-char *
+void
 Q7(void)
 {
-       /* expect+1: redundant cast from 'pointer to void' to 'pointer to char' before assignment [Q7] */
-       char *str = (char *)allocate(64);
+
+       /* expect+2: no-op cast from 'unsigned char' to 'unsigned char' [Q6] */
+       /* expect+1: redundant cast from 'unsigned char' to 'unsigned char' before assignment [Q7] */
+       u8 = (u8_t)u8;
+       u8 = (u8_t)u16;
+       u8 = (u16_t)u8;
+       /* expect+1: no-op cast from 'unsigned short' to 'unsigned short' [Q6] */
+       u8 = (u16_t)u16;
+       /* expect+1: no-op cast from 'unsigned char' to 'unsigned char' [Q6] */
+       u16 = (u8_t)u8;
+       u16 = (u8_t)u16;
+       /* expect+1: redundant cast from 'unsigned char' to 'unsigned short' before assignment [Q7] */
+       u16 = (u16_t)u8;
+       /* expect+2: no-op cast from 'unsigned short' to 'unsigned short' [Q6] */
+       /* expect+1: redundant cast from 'unsigned short' to 'unsigned short' before assignment [Q7] */
+       u16 = (u16_t)u16;
+
+       /* Mixing signed and unsigned types. */
+       u8 = (u8_t)s8;
+       s8 = (s8_t)u8;
+       /* expect+1: redundant cast from 'unsigned char' to 'short' before assignment [Q7] */
+       s16 = (s16_t)u8;
+       /* expect+1: redundant cast from 'signed char' to 'short' before assignment [Q7] */
+       s16 = (s16_t)s8;
+
+
+       /*
+        * Neither GCC nor Clang accept typeof(bit-field), as that would add
+        * unnecessary complexity.  Lint accepts it but silently discards the
+        * bit-field portion from the type; see add_type.
+        */
+       /* expect+1: redundant cast from 'unsigned char' to 'unsigned int' before assignment [Q7] */
+       bits.u9 = (typeof(bits.u9))u8;
+
 
-       if (str == (void *)0)
-               /* expect+1: redundant cast from 'pointer to void' to 'pointer to char' before assignment [Q7] */
-               str = (char *)allocate(64);
+       /* expect+2: no-op cast from 'float' to 'float' [Q6] */
+       /* expect+1: redundant cast from 'float' to 'float' before assignment [Q7] */
+       f32 = (f32_t)f32;
+       f32 = (f32_t)f64;
+       f32 = (f64_t)f32;
+       /* expect+1: no-op cast from 'double' to 'double' [Q6] */
+       f32 = (f64_t)f64;
+       /* expect+1: no-op cast from 'float' to 'float' [Q6] */
+       f64 = (f32_t)f32;
+       f64 = (f32_t)f64;
+       /* expect+1: redundant cast from 'float' to 'double' before assignment [Q7] */
+       f64 = (f64_t)f32;
+       /* expect+2: no-op cast from 'double' to 'double' [Q6] */
+       /* expect+1: redundant cast from 'double' to 'double' before assignment [Q7] */
+       f64 = (f64_t)f64;
+
 
-       return str;
+       /* expect+2: no-op cast from 'float _Complex' to 'float _Complex' [Q6] */
+       /* expect+1: redundant cast from 'float _Complex' to 'float _Complex' before assignment [Q7] */
+       c32 = (c32_t)c32;
+       c32 = (c32_t)c64;
+       c32 = (c64_t)c32;
+       /* expect+1: no-op cast from 'double _Complex' to 'double _Complex' [Q6] */
+       c32 = (c64_t)c64;
+       /* expect+1: no-op cast from 'float _Complex' to 'float _Complex' [Q6] */
+       c64 = (c32_t)c32;
+       c64 = (c32_t)c64;
+       /* expect+1: redundant cast from 'float _Complex' to 'double _Complex' before assignment [Q7] */
+       c64 = (c64_t)c32;
+       /* expect+2: no-op cast from 'double _Complex' to 'double _Complex' [Q6] */
+       /* expect+1: redundant cast from 'double _Complex' to 'double _Complex' before assignment [Q7] */
+       c64 = (c64_t)c64;
+
+
+       /* expect+1: redundant cast from 'pointer to void' to 'pointer to char' before assignment [Q7] */
+       str = (char *)allocate();
+       /* expect+1: redundant cast from 'pointer to void' to 'pointer to const char' before assignment [Q7] */
+       cstr = (const char *)allocate();
+       cstr = (char *)allocate();
 }
 
 
diff -r 315c7497dab3 -r 57929c3ed368 usr.bin/xlint/lint1/README.md
--- a/usr.bin/xlint/lint1/README.md     Fri Jul 08 17:47:47 2022 +0000
+++ b/usr.bin/xlint/lint1/README.md     Fri Jul 08 20:27:36 2022 +0000
@@ -1,4 +1,4 @@
-[//]: # ($NetBSD: README.md,v 1.8 2022/07/05 22:50:41 rillig Exp $)
+[//]: # ($NetBSD: README.md,v 1.9 2022/07/08 20:27:36 rillig Exp $)
 
 # Introduction
 
@@ -161,15 +161,16 @@
 
 Useful breakpoints are:
 
-| Function            | File   | Remarks                                              |
-|---------------------|--------|------------------------------------------------------|
-| build_binary        | tree.c | Creates an expression for a unary or binary operator |
-| initialization_expr | init.c | Checks a single initializer                          |
-| expr                | tree.c | Checks a full expression                             |
-| typeok              | tree.c | Checks two types for compatibility                   |
-| vwarning_at         | err.c  | Prints a warning                                     |
-| verror_at           | err.c  | Prints an error                                      |
-| assert_failed       | err.c  | Prints the location of a failed assertion            |
+| Function/Code       | File    | Remarks                                              |
+|---------------------|---------|------------------------------------------------------|
+| build_binary        | tree.c  | Creates an expression for a unary or binary operator |
+| initialization_expr | init.c  | Checks a single initializer                          |
+| expr                | tree.c  | Checks a full expression                             |
+| typeok              | tree.c  | Checks two types for compatibility                   |
+| vwarning_at         | err.c   | Prints a warning                                     |
+| verror_at           | err.c   | Prints an error                                      |
+| assert_failed       | err.c   | Prints the location of a failed assertion            |
+| `switch (yyn)`      | cgram.c | Reduction of a grammar rule                          |
 
 # Tests
 
diff -r 315c7497dab3 -r 57929c3ed368 usr.bin/xlint/lint1/tree.c
--- a/usr.bin/xlint/lint1/tree.c        Fri Jul 08 17:47:47 2022 +0000
+++ b/usr.bin/xlint/lint1/tree.c        Fri Jul 08 20:27:36 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: tree.c,v 1.472 2022/07/06 22:26:30 rillig Exp $        */
+/*     $NetBSD: tree.c,v 1.473 2022/07/08 20:27:36 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.472 2022/07/06 22:26:30 rillig Exp $");
+__RCSID("$NetBSD: tree.c,v 1.473 2022/07/08 20:27:36 rillig Exp $");
 #endif
 
 #include <float.h>
@@ -116,6 +116,14 @@
        return x;
 }
 
+static unsigned
+width_in_bits(const type_t *tp)
+{
+
+       lint_assert(is_integer(tp->t_tspec));
+       return tp->t_bitfield ? tp->t_flen : size_in_bits(tp->t_tspec);
+}
+
 static bool
 ic_maybe_signed(const type_t *tp, const integer_constraints *ic)
 {
@@ -124,20 +132,12 @@
            (ic->bclr & ((uint64_t)1 << 63)) == 0;
 }
 
-static unsigned
-ic_length_in_bits(const type_t *tp)
-{
-
-       lint_assert(is_integer(tp->t_tspec));
-       return tp->t_bitfield ? tp->t_flen : size_in_bits(tp->t_tspec);
-}
-
 static integer_constraints
 ic_any(const type_t *tp)
 {
        integer_constraints c;
 
-       uint64_t vbits = value_bits(ic_length_in_bits(tp));
+       uint64_t vbits = value_bits(width_in_bits(tp));
        if (is_uinteger(tp->t_tspec)) {
                c.smin = INT64_MIN;
                c.smax = INT64_MAX;
@@ -177,7 +177,7 @@
 ic_cvt(const type_t *ntp, const type_t *otp, integer_constraints a)
 {
 
-       if (ic_length_in_bits(ntp) > ic_length_in_bits(otp) &&
+       if (width_in_bits(ntp) > width_in_bits(otp) &&
            is_uinteger(otp->t_tspec))
                return a;
        return ic_any(ntp);
@@ -2476,7 +2476,7 @@
        debug_step("%s: type '%s'", __func__, type_name(tp));
        debug_node(tn);
 
-       uint64_t nmask = value_bits(ic_length_in_bits(tp));
+       uint64_t nmask = value_bits(width_in_bits(tp));
        if (!is_uinteger(tp->t_tspec))
                nmask >>= 1;
 
@@ -3351,6 +3351,42 @@
        return ntn;
 }
 
+static bool
+is_cast_redundant(const tnode_t *tn)
+{
+       const type_t *ntp = tn->tn_type, *otp = tn->tn_left->tn_type;
+       tspec_t nt = ntp->t_tspec, ot = otp->t_tspec;
+
+       if (nt == BOOL && ot == BOOL)
+               return true;
+
+       if (is_integer(nt) && is_integer(ot)) {
+               unsigned int nw = width_in_bits(ntp), ow = width_in_bits(otp);
+               if (is_uinteger(nt) == is_uinteger(ot))
+                      return nw >= ow;
+               return is_uinteger(ot) && nw > ow;
+       }
+
+       if (is_floating(nt) && is_floating(ot))
+               return size_in_bits(nt) >= size_in_bits(ot);
+
+       if (is_complex(nt) && is_complex(ot))
+               return size_in_bits(nt) >= size_in_bits(ot);
+
+       if (nt == PTR && ot == PTR) {
+               if (!ntp->t_subt->t_const && otp->t_subt->t_const)



Home | Main Index | Thread Index | Old Index