Module Name: src Committed By: rillig Date: Thu Sep 2 19:19:18 UTC 2021
Modified Files: src/usr.bin/xlint/lint1: tree.c Log Message: lint: split check_assign_types_compatible into separate functions No functional change. To generate a diff of this commit: cvs rdiff -u -r1.368 -r1.369 src/usr.bin/xlint/lint1/tree.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.bin/xlint/lint1/tree.c diff -u src/usr.bin/xlint/lint1/tree.c:1.368 src/usr.bin/xlint/lint1/tree.c:1.369 --- src/usr.bin/xlint/lint1/tree.c:1.368 Thu Sep 2 17:29:19 2021 +++ src/usr.bin/xlint/lint1/tree.c Thu Sep 2 19:19:17 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: tree.c,v 1.368 2021/09/02 17:29:19 rillig Exp $ */ +/* $NetBSD: tree.c,v 1.369 2021/09/02 19:19:17 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -37,7 +37,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) && !defined(lint) -__RCSID("$NetBSD: tree.c,v 1.368 2021/09/02 17:29:19 rillig Exp $"); +__RCSID("$NetBSD: tree.c,v 1.369 2021/09/02 19:19:17 rillig Exp $"); #endif #include <float.h> @@ -1449,136 +1449,142 @@ check_unconst_function(const type_t *lst } } -/* - * Checks type compatibility for ASSIGN, INIT, FARG and RETURN - * and prints warnings/errors if necessary. - * If the types are (almost) compatible, 1 is returned, otherwise 0. - */ -static bool -check_assign_types_compatible(op_t op, int arg, - const tnode_t *ln, const tnode_t *rn) +static void +check_assign_void_pointer(op_t op, int arg, + tspec_t lt, tspec_t lst, + tspec_t rt, tspec_t rst) { - tspec_t lt, rt, lst = NOTSPEC, rst = NOTSPEC; - type_t *ltp, *rtp, *lstp = NULL, *rstp = NULL; - const mod_t *mp; - const char *lts, *rts; - - if ((lt = (ltp = ln->tn_type)->t_tspec) == PTR) - lst = (lstp = ltp->t_subt)->t_tspec; - if ((rt = (rtp = rn->tn_type)->t_tspec) == PTR) - rst = (rstp = rtp->t_subt)->t_tspec; - mp = &modtab[op]; - - if (lt == BOOL && is_scalar(rt)) /* C99 6.3.1.2 */ - return true; + const char *lts, *rts; - if (is_arithmetic(lt) && (is_arithmetic(rt) || rt == BOOL)) - return true; - - if ((lt == STRUCT || lt == UNION) && (rt == STRUCT || rt == UNION)) - /* both are struct or union */ - return ltp->t_str == rtp->t_str; - - /* a null pointer may be assigned to any pointer */ - if (lt == PTR && is_null_pointer(rn)) - return true; - - if (lt == PTR && rt == PTR && (lst == VOID || rst == VOID)) { - /* two pointers, at least one pointer to void */ - if (sflag && (lst == FUNC || rst == FUNC)) { - /* comb. of ptr to func and ptr to void */ - *(lst == FUNC ? <s : &rts) = "function pointer"; - *(lst == VOID ? <s : &rts) = "'void *'"; - switch (op) { - case INIT: - case RETURN: - /* ANSI C forbids conversion of %s to %s */ - warning(303, rts, lts); - break; - case FARG: - /* ANSI C forbids conv. of %s to %s, arg #%d */ - warning(304, rts, lts, arg); - break; - default: - /* ANSI C forbids conv. of %s to %s, op %s */ - warning(305, rts, lts, mp->m_name); - break; - } - } - } + if (!(lt == PTR && rt == PTR && (lst == VOID || rst == VOID))) + return; + /* two pointers, at least one pointer to void */ - if (lt == PTR && rt == PTR && (lst == VOID || rst == VOID || - eqtype(lstp, rstp, true, false, NULL))) { - /* compatible pointer types (qualifiers ignored) */ - if (!tflag && - ((!lstp->t_const && rstp->t_const) || - (!lstp->t_volatile && rstp->t_volatile))) { - /* left side has not all qualifiers of right */ - switch (op) { - case INIT: - case RETURN: - /* incompatible pointer types (%s != %s) */ - warning(182, type_name(lstp), type_name(rstp)); - break; - case FARG: - /* converting '%s' to incompatible '%s' ... */ - warning(153, - type_name(rtp), type_name(ltp), arg); - break; - default: - /* operands have incompatible pointer type... */ - warning(128, mp->m_name, - type_name(lstp), type_name(rstp)); - break; - } - } + if (!(sflag && (lst == FUNC || rst == FUNC))) + return; + /* comb. of ptr to func and ptr to void */ - if (!tflag) - check_unconst_function(lstp, rn, rstp); + *(lst == FUNC ? <s : &rts) = "function pointer"; + *(lst == VOID ? <s : &rts) = "'void *'"; - return true; + switch (op) { + case INIT: + case RETURN: + /* ANSI C forbids conversion of %s to %s */ + warning(303, rts, lts); + break; + case FARG: + /* ANSI C forbids conv. of %s to %s, arg #%d */ + warning(304, rts, lts, arg); + break; + default: + /* ANSI C forbids conv. of %s to %s, op %s */ + warning(305, rts, lts, op_name(op)); + break; } +} - if ((lt == PTR && is_integer(rt)) || (is_integer(lt) && rt == PTR)) { - const char *lx = lt == PTR ? "pointer" : "integer"; - const char *rx = rt == PTR ? "pointer" : "integer"; +static bool +check_assign_void_pointer_compat(op_t op, int arg, + const type_t *const ltp, tspec_t const lt, + const type_t *const lstp, tspec_t const lst, + const tnode_t *const rn, + const type_t *const rtp, tspec_t const rt, + const type_t *const rstp, tspec_t const rst) +{ + if (!(lt == PTR && rt == PTR && (lst == VOID || rst == VOID || + eqtype(lstp, rstp, true, false, NULL)))) + return false; + /* compatible pointer types (qualifiers ignored) */ + if (!tflag && + ((!lstp->t_const && rstp->t_const) || + (!lstp->t_volatile && rstp->t_volatile))) { + /* left side has not all qualifiers of right */ switch (op) { case INIT: case RETURN: - /* illegal combination of %s (%s) and %s (%s) */ - warning(183, lx, type_name(ltp), rx, type_name(rtp)); + /* incompatible pointer types (%s != %s) */ + warning(182, type_name(lstp), type_name(rstp)); break; case FARG: - /* illegal comb. of %s (%s) and %s (%s), arg #%d */ - warning(154, - lx, type_name(ltp), rx, type_name(rtp), arg); + /* converting '%s' to incompatible '%s' ... */ + warning(153, + type_name(rtp), type_name(ltp), arg); break; default: - /* illegal combination of %s (%s) and %s (%s), op %s */ - warning(123, - lx, type_name(ltp), rx, type_name(rtp), mp->m_name); + /* operands have incompatible pointer type... */ + warning(128, op_name(op), + type_name(lstp), type_name(rstp)); break; } - return true; } - if (lt == PTR && rt == PTR) { - switch (op) { - case RETURN: - warn_incompatible_pointers(NULL, ltp, rtp); - break; - case FARG: - /* converting '%s' to incompatible '%s' for ... */ - warning(153, type_name(rtp), type_name(ltp), arg); - break; - default: - warn_incompatible_pointers(mp, ltp, rtp); - break; - } - return true; + if (!tflag) + check_unconst_function(lstp, rn, rstp); + + return true; +} + +static bool +check_assign_pointer_integer(op_t op, int arg, + const type_t *const ltp, tspec_t const lt, + const type_t *const rtp, tspec_t const rt) +{ + if (!((lt == PTR && is_integer(rt)) || (is_integer(lt) && rt == PTR))) + return false; + + const char *lx = lt == PTR ? "pointer" : "integer"; + const char *rx = rt == PTR ? "pointer" : "integer"; + + switch (op) { + case INIT: + case RETURN: + /* illegal combination of %s (%s) and %s (%s) */ + warning(183, lx, type_name(ltp), rx, type_name(rtp)); + break; + case FARG: + /* illegal comb. of %s (%s) and %s (%s), arg #%d */ + warning(154, + lx, type_name(ltp), rx, type_name(rtp), arg); + break; + default: + /* illegal combination of %s (%s) and %s (%s), op %s */ + warning(123, + lx, type_name(ltp), rx, type_name(rtp), op_name(op)); + break; + } + return true; +} + +static bool +check_assign_pointer(op_t op, int arg, + const type_t *ltp, tspec_t lt, + const type_t *rtp, tspec_t rt) +{ + if (!(lt == PTR && rt == PTR)) + return false; + + switch (op) { + case RETURN: + warn_incompatible_pointers(NULL, ltp, rtp); + break; + case FARG: + /* converting '%s' to incompatible '%s' for ... */ + warning(153, type_name(rtp), type_name(ltp), arg); + break; + default: + warn_incompatible_pointers(&modtab[op], ltp, rtp); + break; } + return true; +} +static void +warn_assign(op_t op, int arg, + const type_t *ltp, tspec_t lt, + const type_t *rtp, tspec_t rt) +{ switch (op) { case INIT: /* cannot initialize '%s' from '%s' */ @@ -1596,7 +1602,52 @@ check_assign_types_compatible(op_t op, i warn_incompatible_types(op, ltp, lt, rtp, rt); break; } +} + +/* + * Checks type compatibility for ASSIGN, INIT, FARG and RETURN + * and prints warnings/errors if necessary. + * Returns whether the types are (almost) compatible. + */ +static bool +check_assign_types_compatible(op_t op, int arg, + const tnode_t *ln, const tnode_t *rn) +{ + tspec_t lt, rt, lst = NOTSPEC, rst = NOTSPEC; + type_t *ltp, *rtp, *lstp = NULL, *rstp = NULL; + + if ((lt = (ltp = ln->tn_type)->t_tspec) == PTR) + lst = (lstp = ltp->t_subt)->t_tspec; + if ((rt = (rtp = rn->tn_type)->t_tspec) == PTR) + rst = (rstp = rtp->t_subt)->t_tspec; + + if (lt == BOOL && is_scalar(rt)) /* C99 6.3.1.2 */ + return true; + + if (is_arithmetic(lt) && (is_arithmetic(rt) || rt == BOOL)) + return true; + + if ((lt == STRUCT || lt == UNION) && (rt == STRUCT || rt == UNION)) + /* both are struct or union */ + return ltp->t_str == rtp->t_str; + + /* a null pointer may be assigned to any pointer */ + if (lt == PTR && is_null_pointer(rn)) + return true; + + check_assign_void_pointer(op, arg, lt, lst, rt, rst); + + if (check_assign_void_pointer_compat(op, arg, + ltp, lt, lstp, lst, rn, rtp, rt, rstp, rst)) + return true; + + if (check_assign_pointer_integer(op, arg, ltp, lt, rtp, rt)) + return true; + + if (check_assign_pointer(op, arg, ltp, lt, rtp, rt)) + return true; + warn_assign(op, arg, ltp, lt, rtp, rt); return false; }