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;
}