Module Name:    src
Committed By:   rillig
Date:           Tue Mar 19 23:19:04 UTC 2024

Modified Files:
        src/usr.bin/xlint/lint1: ckctype.c ckgetopt.c debug.c emit1.c tree.c

Log Message:
lint: keep invalid arguments in function calls

Previously, arguments of incomplete type or 'void' cleared all arguments
of the function call expression, requiring extra checks in later checks.

Invalid function calls are now exported to the .ln files, but that's
irrelevant in practice as these invalid function calls make lint1 fail,
after which xlint removes the .ln file.


To generate a diff of this commit:
cvs rdiff -u -r1.11 -r1.12 src/usr.bin/xlint/lint1/ckctype.c
cvs rdiff -u -r1.26 -r1.27 src/usr.bin/xlint/lint1/ckgetopt.c
cvs rdiff -u -r1.73 -r1.74 src/usr.bin/xlint/lint1/debug.c
cvs rdiff -u -r1.92 -r1.93 src/usr.bin/xlint/lint1/emit1.c
cvs rdiff -u -r1.624 -r1.625 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/ckctype.c
diff -u src/usr.bin/xlint/lint1/ckctype.c:1.11 src/usr.bin/xlint/lint1/ckctype.c:1.12
--- src/usr.bin/xlint/lint1/ckctype.c:1.11	Sat Mar  9 13:54:47 2024
+++ src/usr.bin/xlint/lint1/ckctype.c	Tue Mar 19 23:19:03 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: ckctype.c,v 1.11 2024/03/09 13:54:47 rillig Exp $ */
+/* $NetBSD: ckctype.c,v 1.12 2024/03/19 23:19:03 rillig Exp $ */
 
 /*-
  * Copyright (c) 2021 The NetBSD Foundation, Inc.
@@ -36,7 +36,7 @@
 #include <sys/cdefs.h>
 
 #if defined(__RCSID)
-__RCSID("$NetBSD: ckctype.c,v 1.11 2024/03/09 13:54:47 rillig Exp $");
+__RCSID("$NetBSD: ckctype.c,v 1.12 2024/03/19 23:19:03 rillig Exp $");
 #endif
 
 #include <string.h>
@@ -123,7 +123,7 @@ void
 check_ctype_function_call(const function_call *call)
 {
 
-	if (call->args_len == 1 && call->args != NULL &&
+	if (call->args_len == 1 &&
 	    call->func->tn_op == NAME &&
 	    is_ctype_function(call->func->u.sym->s_name))
 		check_ctype_arg(call->func->u.sym->s_name, call->args[0]);

Index: src/usr.bin/xlint/lint1/ckgetopt.c
diff -u src/usr.bin/xlint/lint1/ckgetopt.c:1.26 src/usr.bin/xlint/lint1/ckgetopt.c:1.27
--- src/usr.bin/xlint/lint1/ckgetopt.c:1.26	Sat Mar  9 13:54:47 2024
+++ src/usr.bin/xlint/lint1/ckgetopt.c	Tue Mar 19 23:19:03 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: ckgetopt.c,v 1.26 2024/03/09 13:54:47 rillig Exp $ */
+/* $NetBSD: ckgetopt.c,v 1.27 2024/03/19 23:19:03 rillig Exp $ */
 
 /*-
  * Copyright (c) 2021 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
 
 #include <sys/cdefs.h>
 #if defined(__RCSID)
-__RCSID("$NetBSD: ckgetopt.c,v 1.26 2024/03/09 13:54:47 rillig Exp $");
+__RCSID("$NetBSD: ckgetopt.c,v 1.27 2024/03/19 23:19:03 rillig Exp $");
 #endif
 
 #include <stdbool.h>
@@ -96,8 +96,6 @@ is_getopt_condition(const tnode_t *tn, c
 	    && call->func->u.ops.left->tn_op == NAME
 	    && strcmp(call->func->u.ops.left->u.sym->s_name, "getopt") == 0
 	    && call->args_len == 3
-	    && call->args != NULL
-
 	    && (last_arg = call->args[2]) != NULL
 	    && last_arg->tn_op == CVT
 	    && last_arg->u.ops.left->tn_op == ADDR

Index: src/usr.bin/xlint/lint1/debug.c
diff -u src/usr.bin/xlint/lint1/debug.c:1.73 src/usr.bin/xlint/lint1/debug.c:1.74
--- src/usr.bin/xlint/lint1/debug.c:1.73	Sat Mar  9 13:54:47 2024
+++ src/usr.bin/xlint/lint1/debug.c	Tue Mar 19 23:19:03 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: debug.c,v 1.73 2024/03/09 13:54:47 rillig Exp $ */
+/* $NetBSD: debug.c,v 1.74 2024/03/19 23:19:03 rillig Exp $ */
 
 /*-
  * Copyright (c) 2021 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
 
 #include <sys/cdefs.h>
 #if defined(__RCSID)
-__RCSID("$NetBSD: debug.c,v 1.73 2024/03/09 13:54:47 rillig Exp $");
+__RCSID("$NetBSD: debug.c,v 1.74 2024/03/19 23:19:03 rillig Exp $");
 #endif
 
 #include <stdlib.h>
@@ -247,11 +247,8 @@ debug_node(const tnode_t *tn) // NOLINT(
 		debug_indent_inc();
 		const function_call *call = tn->u.call;
 		debug_node(call->func);
-		if (call->args != NULL) {
-			for (size_t i = 0; i < call->args_len; i++)
-				debug_node(call->args[i]);
-		} else
-			debug_step("error in arguments");
+		for (size_t i = 0, n = call->args_len; i < n; i++)
+			debug_node(call->args[i]);
 		debug_indent_dec();
 		break;
 	default:

Index: src/usr.bin/xlint/lint1/emit1.c
diff -u src/usr.bin/xlint/lint1/emit1.c:1.92 src/usr.bin/xlint/lint1/emit1.c:1.93
--- src/usr.bin/xlint/lint1/emit1.c:1.92	Sat Mar  9 13:54:47 2024
+++ src/usr.bin/xlint/lint1/emit1.c	Tue Mar 19 23:19:03 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: emit1.c,v 1.92 2024/03/09 13:54:47 rillig Exp $ */
+/* $NetBSD: emit1.c,v 1.93 2024/03/19 23:19:03 rillig Exp $ */
 
 /*
  * Copyright (c) 1996 Christopher G. Demetriou.  All Rights Reserved.
@@ -38,7 +38,7 @@
 
 #include <sys/cdefs.h>
 #if defined(__RCSID)
-__RCSID("$NetBSD: emit1.c,v 1.92 2024/03/09 13:54:47 rillig Exp $");
+__RCSID("$NetBSD: emit1.c,v 1.93 2024/03/19 23:19:03 rillig Exp $");
 #endif
 
 #include <stdlib.h>
@@ -337,9 +337,8 @@ outcall(const tnode_t *tn, bool retval_u
 	 */
 	const function_call *call = tn->u.call;
 
-	/* information about arguments */
-	for (size_t n = 1; call->args != NULL && n <= call->args_len; n++) {
-		const tnode_t *arg = call->args[n - 1];
+	for (size_t i = 0, n = call->args_len; i < n; i++) {
+		const tnode_t *arg = call->args[i];
 		if (arg->tn_op == CON) {
 			tspec_t t = arg->tn_type->t_tspec;
 			if (is_integer(t)) {
@@ -357,7 +356,7 @@ outcall(const tnode_t *tn, bool retval_u
 				else
 					/* negative if cast to signed */
 					outchar('n');
-				outint((int)n);
+				outint((int)i + 1);
 			}
 		} else if (arg->tn_op == ADDR &&
 		    arg->u.ops.left->tn_op == STRING &&
@@ -370,7 +369,7 @@ outcall(const tnode_t *tn, bool retval_u
 
 			/* string literal, write all format specifiers */
 			outchar('s');
-			outint((int)n);
+			outint((int)i + 1);
 			outfstrg(buf.data);
 			free(buf.data);
 		}
@@ -382,7 +381,7 @@ outcall(const tnode_t *tn, bool retval_u
 	/* types of arguments */
 	outchar('f');
 	outint((int)call->args_len);
-	for (size_t i = 0; call->args != NULL && i < call->args_len; i++)
+	for (size_t i = 0, n = call->args_len; i < n; i++)
 		outtype(call->args[i]->tn_type);
 	/* expected type of return value */
 	outtype(tn->tn_type);

Index: src/usr.bin/xlint/lint1/tree.c
diff -u src/usr.bin/xlint/lint1/tree.c:1.624 src/usr.bin/xlint/lint1/tree.c:1.625
--- src/usr.bin/xlint/lint1/tree.c:1.624	Tue Mar 12 07:56:08 2024
+++ src/usr.bin/xlint/lint1/tree.c	Tue Mar 19 23:19:04 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: tree.c,v 1.624 2024/03/12 07:56:08 rillig Exp $	*/
+/*	$NetBSD: tree.c,v 1.625 2024/03/19 23:19:04 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.624 2024/03/12 07:56:08 rillig Exp $");
+__RCSID("$NetBSD: tree.c,v 1.625 2024/03/19 23:19:04 rillig Exp $");
 #endif
 
 #include <float.h>
@@ -1710,9 +1710,8 @@ use(const tnode_t *tn)
 	case CALL:
 	case ICALL:;
 		const function_call *call = tn->u.call;
-		if (call->args != NULL)
-			for (size_t i = 0, n = call->args_len; i < n; i++)
-				use(call->args[i]);
+		for (size_t i = 0, n = call->args_len; i < n; i++)
+			use(call->args[i]);
 		break;
 	default:
 		lint_assert(has_operands(tn));
@@ -2694,28 +2693,12 @@ is_const_char_pointer(const tnode_t *tn)
 }
 
 static bool
-is_first_arg_const_char_pointer(const tnode_t *tn)
-{
-	return tn->u.call->args != NULL
-	    && tn->u.call->args_len >= 1
-	    && is_const_char_pointer(tn->u.call->args[0]);
-}
-
-static bool
 is_const_pointer(const tnode_t *tn)
 {
 	const type_t *tp = before_conversion(tn)->tn_type;
 	return tp->t_tspec == PTR && tp->t_subt->t_const;
 }
 
-static bool
-is_second_arg_const_pointer(const tnode_t *tn)
-{
-	return tn->u.call->args_len >= 2
-	    && tn->u.call->args != NULL
-	    && is_const_pointer(tn->u.call->args[1]);
-}
-
 static void
 check_unconst_function(const type_t *lstp, const tnode_t *rn)
 {
@@ -2724,7 +2707,8 @@ check_unconst_function(const type_t *lst
 	if (lstp->t_tspec == CHAR && !lstp->t_const &&
 	    is_direct_function_call(rn, &function_name) &&
 	    is_unconst_function(function_name) &&
-	    is_first_arg_const_char_pointer(rn)) {
+	    rn->u.call->args_len >= 1 &&
+	    is_const_char_pointer(rn->u.call->args[0])) {
 		/* call to '%s' effectively discards 'const' from argument */
 		warning(346, function_name);
 	}
@@ -2732,7 +2716,8 @@ check_unconst_function(const type_t *lst
 	if (!lstp->t_const &&
 	    is_direct_function_call(rn, &function_name) &&
 	    strcmp(function_name, "bsearch") == 0 &&
-	    is_second_arg_const_pointer(rn)) {
+	    rn->u.call->args_len >= 2 &&
+	    is_const_pointer(rn->u.call->args[1])) {
 		/* call to '%s' effectively discards 'const' from argument */
 		warning(346, function_name);
 	}
@@ -4220,7 +4205,7 @@ check_prototype_argument(
  * Check types of all function arguments and insert conversions,
  * if necessary.
  */
-static bool
+static void
 check_function_arguments(const function_call *call)
 {
 	type_t *ftp = call->func->tn_type->t_subt;
@@ -4239,42 +4224,40 @@ check_function_arguments(const function_
 		param = NULL;
 	}
 
-	for (int n = 1; n <= narg; n++) {
-		tnode_t *arg = call->args[n - 1];
+	for (int i = 0; i < narg; i++) {
+		tnode_t *arg = call->args[i];
 
 		/* some things which are always not allowed */
 		tspec_t at = arg->tn_type->t_tspec;
 		if (at == VOID) {
 			/* void expressions may not be arguments, arg #%d */
-			error(151, n);
-			return false;
+			error(151, i + 1);
+			return;
 		}
 		if (is_struct_or_union(at) &&
 		    is_incomplete(arg->tn_type)) {
 			/* argument cannot have unknown size, arg #%d */
-			error(152, n);
-			return false;
+			error(152, i + 1);
+			return;
 		}
 		if (is_integer(at) &&
 		    arg->tn_type->t_is_enum &&
 		    is_incomplete(arg->tn_type)) {
 			/* argument cannot have unknown size, arg #%d */
-			warning(152, n);
+			warning(152, i + 1);
 		}
 
 		arg = cconv(arg);
-		call->args[n - 1] = arg;
+		call->args[i] = arg;
 
 		arg = param != NULL
-		    ? check_prototype_argument(n, param->s_type, arg)
+		    ? check_prototype_argument(i + 1, param->s_type, arg)
 		    : promote(NOOP, true, arg);
-		call->args[n - 1] = arg;
+		call->args[i] = arg;
 
 		if (param != NULL)
 			param = param->s_next;
 	}
-
-	return true;
 }
 
 tnode_t *
@@ -4284,7 +4267,7 @@ build_function_call(tnode_t *func, bool 
 	if (func == NULL)
 		return NULL;
 
-	op_t fcop = func->tn_op == NAME && func->tn_type->t_tspec == FUNC
+	op_t op = func->tn_op == NAME && func->tn_type->t_tspec == FUNC
 	    ? CALL : ICALL;
 
 	call->func = func;
@@ -4300,11 +4283,10 @@ build_function_call(tnode_t *func, bool 
 		return NULL;
 	}
 
-	if (!check_function_arguments(call))
-		call->args = NULL;
+	check_function_arguments(call);
 
 	tnode_t *ntn = expr_alloc_tnode();
-	ntn->tn_op = fcop;
+	ntn->tn_op = op;
 	ntn->tn_type = func->tn_type->t_subt->t_subt;
 	ntn->tn_sys = sys;
 	ntn->u.call = call;
@@ -4592,11 +4574,9 @@ check_expr_misc(const tnode_t *tn, bool 
 		bool discard = op == CVT && tn->tn_type->t_tspec == VOID;
 		check_expr_misc(call->func, false, false, false, op == CALL,
 		    discard, szof);
-		if (call->args != NULL) {
-			for (size_t i = 0, n = call->args_len; i < n; i++)
-				check_expr_misc(call->args[i],
-				    false, false, false, false, false, szof);
-		}
+		for (size_t i = 0, n = call->args_len; i < n; i++)
+			check_expr_misc(call->args[i],
+			    false, false, false, false, false, szof);
 		return;
 	}
 

Reply via email to