Module Name: src Committed By: rillig Date: Mon Feb 5 23:11:23 UTC 2024
Modified Files: src/usr.bin/xlint/lint1: README.md cgram.y ckctype.c ckgetopt.c debug.c emit1.c externs1.h lint1.h op.h oper.c tree.c Log Message: lint: make function call arguments directly accessible Previously, the arguments of a function call expression were arranged in a linear tree structure, from right to left. To allow easier access to the arguments, store them in an array instead. To generate a diff of this commit: cvs rdiff -u -r1.14 -r1.15 src/usr.bin/xlint/lint1/README.md \ src/usr.bin/xlint/lint1/oper.c cvs rdiff -u -r1.486 -r1.487 src/usr.bin/xlint/lint1/cgram.y cvs rdiff -u -r1.9 -r1.10 src/usr.bin/xlint/lint1/ckctype.c cvs rdiff -u -r1.22 -r1.23 src/usr.bin/xlint/lint1/ckgetopt.c cvs rdiff -u -r1.70 -r1.71 src/usr.bin/xlint/lint1/debug.c cvs rdiff -u -r1.85 -r1.86 src/usr.bin/xlint/lint1/emit1.c cvs rdiff -u -r1.215 -r1.216 src/usr.bin/xlint/lint1/externs1.h cvs rdiff -u -r1.213 -r1.214 src/usr.bin/xlint/lint1/lint1.h cvs rdiff -u -r1.26 -r1.27 src/usr.bin/xlint/lint1/op.h cvs rdiff -u -r1.602 -r1.603 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/README.md diff -u src/usr.bin/xlint/lint1/README.md:1.14 src/usr.bin/xlint/lint1/README.md:1.15 --- src/usr.bin/xlint/lint1/README.md:1.14 Thu Sep 14 21:08:12 2023 +++ src/usr.bin/xlint/lint1/README.md Mon Feb 5 23:11:22 2024 @@ -1,4 +1,4 @@ -[//]: # ($NetBSD: README.md,v 1.14 2023/09/14 21:08:12 rillig Exp $) +[//]: # ($NetBSD: README.md,v 1.15 2024/02/05 23:11:22 rillig Exp $) # Introduction @@ -123,34 +123,31 @@ structure: ~~~text 1: 'call' type 'int' - 2: '&' type 'pointer to function(pointer to const char, pointer to const char) returning int' - 3: 'name' 'strcmp' with extern 'function(pointer to const char, pointer to const char) returning int' - 4: 'push' type 'pointer to const char' - 5: 'convert' type 'pointer to const char' - 6: '&' type 'pointer to char' - 7: 'string' type 'array[5] of char', lvalue, length 4, "name" - 8: 'push' type 'pointer to const char' - 9: 'load' type 'pointer to const char' -10: '*' type 'pointer to const char', lvalue -11: '+' type 'pointer to pointer to const char' -12: 'load' type 'pointer to pointer to const char' -13: 'name' 'names' with auto 'pointer to pointer to const char', lvalue -14: '*' type 'long' -15: 'convert' type 'long' -16: 'load' type 'int' -17: 'name' 'i' with auto 'int', lvalue -18: 'constant' type 'long', value 8 + 2: '&' type 'pointer to function(pointer to const char, pointer to const char) returning int' + 3: 'name' 'strcmp' with extern 'function(pointer to const char, pointer to const char) returning int' + 4: 'load' type 'pointer to const char' + 5: '*' type 'pointer to const char', lvalue + 6: '+' type 'pointer to pointer to const char' + 7: 'load' type 'pointer to pointer to const char' + 8: 'name' 'names' with auto 'pointer to pointer to const char', lvalue + 9: '*' type 'long' +10: 'convert' type 'long' +11: 'load' type 'int' +12: 'name' 'i' with auto 'int', lvalue +13: 'constant' type 'long', value 8 +14: 'convert' type 'pointer to const char' +15: '&' type 'pointer to char' +16: 'string' type 'array[5] of char', lvalue, "name" ~~~ -| Lines | Notes | -|--------|------------------------------------------------------------------| -| 4, 8 | Each argument of the function call corresponds to a `PUSH` node. | -| 5, 9 | The left operand of a `PUSH` node is the actual argument. | -| 8 | The right operand is the `PUSH` node of the previous argument. | -| 5, 9 | The arguments of a call are ordered from right to left. | -| 10, 11 | Array access is represented as `*(left + right)`. | -| 14, 18 | Array and struct offsets are in premultiplied form. | -| 18 | The size of a pointer on this platform is 8 bytes. | +| Lines | Notes | +|------------|-------------------------------------------------------------| +| 1, 2, 4, 7 | A function call consists of the function and its arguments. | +| 4, 14 | The arguments of a call are ordered from left to right. | +| 5, 6 | Array access is represented as `*(left + right)`. | +| 9, 13 | Array and struct offsets are in premultiplied form. | +| 9 | The type `ptrdiff_t` on this platform is `long`, not `int`. | +| 13 | The size of a pointer on this platform is 8 bytes. | See `debug_node` for how to interpret the members of `tnode_t`. Index: src/usr.bin/xlint/lint1/oper.c diff -u src/usr.bin/xlint/lint1/oper.c:1.14 src/usr.bin/xlint/lint1/oper.c:1.15 --- src/usr.bin/xlint/lint1/oper.c:1.14 Thu Sep 14 22:20:08 2023 +++ src/usr.bin/xlint/lint1/oper.c Mon Feb 5 23:11:22 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: oper.c,v 1.14 2023/09/14 22:20:08 rillig Exp $ */ +/* $NetBSD: oper.c,v 1.15 2024/02/05 23:11:22 rillig Exp $ */ /*- * Copyright (c) 2021 The NetBSD Foundation, Inc. @@ -121,12 +121,11 @@ const mod_t modtab[NOPS] = { {_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_, "constant" }, {_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_, "string" }, {_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,X, "fsel" }, - {X,_,_,_,_,_,_,_,_,_,_,X,_,_,_,_,_,_,_,X, "call" }, + {_,_,_,_,_,_,_,_,_,_,_,X,_,_,_,_,_,_,_,_, "call" }, {X,_,X,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,X,X, "," }, {_,_,_,_,_,_,_,_,_,X,_,_,_,_,_,_,_,_,_,X, "convert" }, - {X,_,_,_,_,_,_,_,_,_,_,X,_,_,_,_,_,_,_,X, "icall" }, + {_,_,_,_,_,_,_,_,_,_,_,X,_,_,_,_,_,_,_,_, "icall" }, {_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,X, "load" }, - {_,_,_,_,_,_,_,_,_,X,_,_,_,_,_,_,_,_,_,X, "push" }, {X,_,X,_,_,_,_,_,_,_,_,X,_,_,_,_,X,_,_,X, "return" }, {_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,X, "real" }, {_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,X, "imag" }, Index: src/usr.bin/xlint/lint1/cgram.y diff -u src/usr.bin/xlint/lint1/cgram.y:1.486 src/usr.bin/xlint/lint1/cgram.y:1.487 --- src/usr.bin/xlint/lint1/cgram.y:1.486 Fri Feb 2 16:05:37 2024 +++ src/usr.bin/xlint/lint1/cgram.y Mon Feb 5 23:11:22 2024 @@ -1,5 +1,5 @@ %{ -/* $NetBSD: cgram.y,v 1.486 2024/02/02 16:05:37 rillig Exp $ */ +/* $NetBSD: cgram.y,v 1.487 2024/02/05 23:11:22 rillig Exp $ */ /* * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. @@ -35,7 +35,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: cgram.y,v 1.486 2024/02/02 16:05:37 rillig Exp $"); +__RCSID("$NetBSD: cgram.y,v 1.487 2024/02/05 23:11:22 rillig Exp $"); #endif #include <limits.h> @@ -145,6 +145,7 @@ is_either(const char *s, const char *a, type_qualifiers y_type_qualifiers; function_specifier y_function_specifier; struct parameter_list y_parameter_list; + function_call *y_arguments; type_t *y_type; tnode_t *y_tnode; range_t y_range; @@ -298,7 +299,7 @@ is_either(const char *s, const char *a, %type <y_tnode> gcc_statement_expr_list %type <y_tnode> gcc_statement_expr_item %type <y_op> point_or_arrow -%type <y_tnode> argument_expression_list +%type <y_arguments> argument_expression_list %type <y_tnode> unary_expression %type <y_tnode> cast_expression %type <y_tnode> expression_opt @@ -558,7 +559,9 @@ postfix_expression: $$ = build_unary(INDIR, $3, build_binary($1, PLUS, $3, $4)); } | postfix_expression T_LPAREN sys T_RPAREN { - $$ = build_function_call($1, $3, NULL); + function_call *call = + expr_zero_alloc(sizeof(*call), "function_call"); + $$ = build_function_call($1, $3, call); } | postfix_expression T_LPAREN sys argument_expression_list T_RPAREN { $$ = build_function_call($1, $3, $4); @@ -643,10 +646,11 @@ point_or_arrow: /* helper for 'postfix /* K&R 7.1, C90 ???, C99 6.5.2, C11 6.5.2 */ argument_expression_list: assignment_expression { - $$ = build_function_argument(NULL, $1); + $$ = expr_zero_alloc(sizeof(*$$), "function_call"); + add_function_argument($$, $1); } | argument_expression_list T_COMMA assignment_expression { - $$ = build_function_argument($1, $3); + add_function_argument($1, $3); } ; Index: src/usr.bin/xlint/lint1/ckctype.c diff -u src/usr.bin/xlint/lint1/ckctype.c:1.9 src/usr.bin/xlint/lint1/ckctype.c:1.10 --- src/usr.bin/xlint/lint1/ckctype.c:1.9 Sun Dec 3 13:12:40 2023 +++ src/usr.bin/xlint/lint1/ckctype.c Mon Feb 5 23:11:22 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: ckctype.c,v 1.9 2023/12/03 13:12:40 rillig Exp $ */ +/* $NetBSD: ckctype.c,v 1.10 2024/02/05 23:11:22 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.9 2023/12/03 13:12:40 rillig Exp $"); +__RCSID("$NetBSD: ckctype.c,v 1.10 2024/02/05 23:11:22 rillig Exp $"); #endif #include <string.h> @@ -120,15 +120,13 @@ check_ctype_arg(const char *func, const } void -check_ctype_function_call(const tnode_t *func, const tnode_t *args) +check_ctype_function_call(const function_call *call) { - if (func->tn_op == NAME && - is_ctype_function(func->tn_sym->s_name) && - args != NULL && - tn_ck_left(args) != NULL && - args->tn_right == NULL) - check_ctype_arg(func->tn_sym->s_name, args->tn_left); + if (call->args_len == 1 && call->args != NULL && + call->func->tn_op == NAME && + is_ctype_function(call->func->tn_sym->s_name)) + check_ctype_arg(call->func->tn_sym->s_name, call->args[0]); } void Index: src/usr.bin/xlint/lint1/ckgetopt.c diff -u src/usr.bin/xlint/lint1/ckgetopt.c:1.22 src/usr.bin/xlint/lint1/ckgetopt.c:1.23 --- src/usr.bin/xlint/lint1/ckgetopt.c:1.22 Sat Feb 3 19:25:16 2024 +++ src/usr.bin/xlint/lint1/ckgetopt.c Mon Feb 5 23:11:22 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: ckgetopt.c,v 1.22 2024/02/03 19:25:16 rillig Exp $ */ +/* $NetBSD: ckgetopt.c,v 1.23 2024/02/05 23:11:22 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.22 2024/02/03 19:25:16 rillig Exp $"); +__RCSID("$NetBSD: ckgetopt.c,v 1.23 2024/02/05 23:11:22 rillig Exp $"); #endif #include <stdbool.h> @@ -79,24 +79,27 @@ static struct { static bool is_getopt_condition(const tnode_t *tn, char **out_options) { - const tnode_t *call, *last_arg; + const function_call *call; + const tnode_t *last_arg; const buffer *str; if (tn != NULL && tn->tn_op == NE - && tn->tn_left->tn_op == ASSIGN + && tn->tn_right->tn_op == CON && tn->tn_right->tn_u._tn_val.v_tspec == INT && tn->tn_right->tn_u._tn_val.u.integer == -1 - && (call = tn->tn_left->tn_right)->tn_op == CALL - && call->tn_left->tn_op == ADDR - && call->tn_left->tn_left->tn_op == NAME - && strcmp(call->tn_left->tn_left->tn_sym->s_name, "getopt") == 0 - - && call->tn_right->tn_op == PUSH + && tn->tn_left->tn_op == ASSIGN + && tn->tn_left->tn_right->tn_op == CALL + && (call = tn->tn_left->tn_right->tn_call)->func->tn_op == ADDR + && call->func->tn_left->tn_op == NAME + && strcmp(call->func->tn_left->tn_sym->s_name, "getopt") == 0 + && call->args_len == 3 + && call->args != NULL - && (last_arg = call->tn_right->tn_left)->tn_op == CVT + && (last_arg = call->args[2]) != NULL + && last_arg->tn_op == CVT && last_arg->tn_left->tn_op == ADDR && last_arg->tn_left->tn_left->tn_op == STRING && (str = last_arg->tn_left->tn_left->tn_string)->data != NULL) { Index: src/usr.bin/xlint/lint1/debug.c diff -u src/usr.bin/xlint/lint1/debug.c:1.70 src/usr.bin/xlint/lint1/debug.c:1.71 --- src/usr.bin/xlint/lint1/debug.c:1.70 Sat Feb 3 19:25:16 2024 +++ src/usr.bin/xlint/lint1/debug.c Mon Feb 5 23:11:22 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: debug.c,v 1.70 2024/02/03 19:25:16 rillig Exp $ */ +/* $NetBSD: debug.c,v 1.71 2024/02/05 23:11:22 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.70 2024/02/03 19:25:16 rillig Exp $"); +__RCSID("$NetBSD: debug.c,v 1.71 2024/02/05 23:11:22 rillig Exp $"); #endif #include <stdlib.h> @@ -240,6 +240,20 @@ debug_node(const tnode_t *tn) // NOLINT( else debug_printf(", length %zu\n", tn->tn_string->len); break; + case CALL: + case ICALL: + debug_printf("\n"); + + debug_indent_inc(); + const function_call *call = tn->tn_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"); + debug_indent_dec(); + break; default: debug_printf("\n"); @@ -249,7 +263,7 @@ debug_node(const tnode_t *tn) // NOLINT( debug_node(tn->tn_left); if (op != INCBEF && op != INCAFT && op != DECBEF && op != DECAFT - && op != CALL && op != ICALL && op != PUSH) + && op != CALL && op != ICALL) lint_assert(is_binary(tn) == (tn->tn_right != NULL)); if (tn->tn_right != NULL) debug_node(tn->tn_right); Index: src/usr.bin/xlint/lint1/emit1.c diff -u src/usr.bin/xlint/lint1/emit1.c:1.85 src/usr.bin/xlint/lint1/emit1.c:1.86 --- src/usr.bin/xlint/lint1/emit1.c:1.85 Sat Feb 3 19:25:16 2024 +++ src/usr.bin/xlint/lint1/emit1.c Mon Feb 5 23:11:22 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: emit1.c,v 1.85 2024/02/03 19:25:16 rillig Exp $ */ +/* $NetBSD: emit1.c,v 1.86 2024/02/05 23:11:22 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.85 2024/02/03 19:25:16 rillig Exp $"); +__RCSID("$NetBSD: emit1.c,v 1.86 2024/02/05 23:11:22 rillig Exp $"); #endif #include <stdlib.h> @@ -323,9 +323,6 @@ outfdef(const sym_t *fsym, const pos_t * void outcall(const tnode_t *tn, bool retval_used, bool retval_discarded) { - tnode_t *args, *arg; - int narg, i; - outint(csrc_pos.p_line); outchar('c'); /* function call */ outint(get_filename_id(curr_pos.p_file)); @@ -336,16 +333,11 @@ outcall(const tnode_t *tn, bool retval_u * flags; 'u' and 'i' must be last to make sure a letter is between the * numeric argument of a flag and the name of the function */ - narg = 0; - args = tn_ck_right(tn); - for (arg = args; arg != NULL; arg = tn_ck_right(arg)) - narg++; + const function_call *call = tn->tn_call; + /* information about arguments */ - for (int n = 1; n <= narg; n++) { - /* the last argument is the top one in the tree */ - for (i = narg, arg = args; i > n; i--, arg = arg->tn_right) - continue; - arg = arg->tn_left; + for (size_t n = 1; call->args != NULL && n <= call->args_len; n++) { + const tnode_t *arg = call->args[n - 1]; if (arg->tn_op == CON) { tspec_t t = arg->tn_type->t_tspec; if (is_integer(t)) { @@ -364,7 +356,7 @@ outcall(const tnode_t *tn, bool retval_u /* negative if cast to signed */ outchar('n'); } - outint(n); + outint((int)n); } } else if (arg->tn_op == ADDR && arg->tn_left->tn_op == STRING && @@ -377,25 +369,20 @@ outcall(const tnode_t *tn, bool retval_u /* string literal, write all format specifiers */ outchar('s'); - outint(n); + outint((int)n); outfstrg(buf.data); free(buf.data); } } outchar((char)(retval_discarded ? 'd' : retval_used ? 'u' : 'i')); - /* name of the called function */ - outname(tn_ck_left(tn->tn_left)->tn_sym->s_name); + outname(call->func->tn_left->tn_sym->s_name); /* types of arguments */ outchar('f'); - outint(narg); - for (int n = 1; n <= narg; n++) { - /* the last argument is the top one in the tree */ - for (i = narg, arg = args; i > n; i--, arg = arg->tn_right) - continue; - outtype(arg->tn_left->tn_type); - } + outint((int)call->args_len); + for (size_t i = 0; call->args != NULL && i < call->args_len; i++) + outtype(call->args[i]->tn_type); /* expected type of return value */ outtype(tn->tn_type); outchar('\n'); Index: src/usr.bin/xlint/lint1/externs1.h diff -u src/usr.bin/xlint/lint1/externs1.h:1.215 src/usr.bin/xlint/lint1/externs1.h:1.216 --- src/usr.bin/xlint/lint1/externs1.h:1.215 Sat Feb 3 19:25:16 2024 +++ src/usr.bin/xlint/lint1/externs1.h Mon Feb 5 23:11:22 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: externs1.h,v 1.215 2024/02/03 19:25:16 rillig Exp $ */ +/* $NetBSD: externs1.h,v 1.216 2024/02/05 23:11:22 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -292,8 +292,8 @@ tnode_t *build_sizeof(const type_t *); tnode_t *build_offsetof(const type_t *, designation); tnode_t *build_alignof(const type_t *); tnode_t *cast(tnode_t *, bool, type_t *); -tnode_t *build_function_argument(tnode_t *, tnode_t *); -tnode_t *build_function_call(tnode_t *, bool, tnode_t *); +void add_function_argument(function_call *, tnode_t *); +tnode_t *build_function_call(tnode_t *, bool, function_call *); val_t *integer_constant(tnode_t *, bool); void expr(tnode_t *, bool, bool, bool, bool); void check_expr_misc(const tnode_t *, bool, bool, bool, bool, bool, bool); @@ -408,7 +408,7 @@ bool fallback_symbol_strict_bool(sym_t * /* * ckctype.c */ -void check_ctype_function_call(const tnode_t *, const tnode_t *); +void check_ctype_function_call(const function_call *); void check_ctype_macro_invocation(const tnode_t *, const tnode_t *); /* Index: src/usr.bin/xlint/lint1/lint1.h diff -u src/usr.bin/xlint/lint1/lint1.h:1.213 src/usr.bin/xlint/lint1/lint1.h:1.214 --- src/usr.bin/xlint/lint1/lint1.h:1.213 Sat Feb 3 19:37:02 2024 +++ src/usr.bin/xlint/lint1/lint1.h Mon Feb 5 23:11:22 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: lint1.h,v 1.213 2024/02/03 19:37:02 rillig Exp $ */ +/* $NetBSD: lint1.h,v 1.214 2024/02/05 23:11:22 rillig Exp $ */ /* * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. @@ -288,6 +288,13 @@ typedef struct sbuf { } sbuf_t; +typedef struct { + struct tnode *func; + struct tnode **args; + size_t args_len; + size_t args_cap; +} function_call; + /* * tree node */ @@ -317,6 +324,7 @@ typedef struct tnode { * wide strings, 'data' is NULL and * 'len' is the number of resulting * characters */ + function_call *_tn_call; } tn_u; } tnode_t; @@ -325,6 +333,7 @@ typedef struct tnode { #define tn_sym tn_u._tn_sym #define tn_val tn_u._tn_val #define tn_string tn_u._tn_string +#define tn_call tn_u._tn_call struct generic_association { type_t *ga_arg; /* NULL means default or error */ Index: src/usr.bin/xlint/lint1/op.h diff -u src/usr.bin/xlint/lint1/op.h:1.26 src/usr.bin/xlint/lint1/op.h:1.27 --- src/usr.bin/xlint/lint1/op.h:1.26 Sun Dec 3 18:17:41 2023 +++ src/usr.bin/xlint/lint1/op.h Mon Feb 5 23:11:22 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: op.h,v 1.26 2023/12/03 18:17:41 rillig Exp $ */ +/* $NetBSD: op.h,v 1.27 2024/02/05 23:11:22 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -119,13 +119,6 @@ typedef enum { CVT, ICALL, LOAD, - /* - * PUSH is a virtual node that is used to concatenate arguments in a - * function call expression. The PUSH nodes are ordered from right to - * left. For example, the function call f(17, 23) is represented as - * CALL(f, PUSH(23, PUSH(17, NULL))). - */ - PUSH, RETURN, REAL, IMAG, Index: src/usr.bin/xlint/lint1/tree.c diff -u src/usr.bin/xlint/lint1/tree.c:1.602 src/usr.bin/xlint/lint1/tree.c:1.603 --- src/usr.bin/xlint/lint1/tree.c:1.602 Sat Feb 3 19:25:16 2024 +++ src/usr.bin/xlint/lint1/tree.c Mon Feb 5 23:11:22 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: tree.c,v 1.602 2024/02/03 19:25:16 rillig Exp $ */ +/* $NetBSD: tree.c,v 1.603 2024/02/05 23:11:22 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.602 2024/02/03 19:25:16 rillig Exp $"); +__RCSID("$NetBSD: tree.c,v 1.603 2024/02/05 23:11:22 rillig Exp $"); #endif #include <float.h> @@ -1629,10 +1629,17 @@ use(const tnode_t *tn) case CON: case STRING: break; + case CALL: + case ICALL:; + const function_call *call = tn->tn_call; + if (call->args != NULL) + for (size_t i = 0, n = call->args_len; i < n; i++) + use(call->args[i]); + break; default: lint_assert(has_operands(tn)); use(tn->tn_left); - if (is_binary(tn) || tn->tn_op == PUSH) + if (is_binary(tn)) use(tn->tn_right); } } @@ -2574,13 +2581,13 @@ static bool is_direct_function_call(const tnode_t *tn, const char **out_name) { - if (!(tn->tn_op == CALL && - tn->tn_left->tn_op == ADDR && - tn->tn_left->tn_left->tn_op == NAME)) - return false; - - *out_name = tn->tn_left->tn_left->tn_sym->s_name; - return true; + if (tn->tn_op == CALL + && tn->tn_call->func->tn_op == ADDR + && tn->tn_call->func->tn_left->tn_op == NAME) { + *out_name = tn->tn_call->func->tn_left->tn_sym->s_name; + return true; + } + return false; } static bool @@ -2622,14 +2629,9 @@ is_const_char_pointer(const tnode_t *tn) static bool is_first_arg_const_char_pointer(const tnode_t *tn) { - lint_assert(has_operands(tn)); - const tnode_t *an = tn->tn_right; - if (an == NULL) - return false; - - while (tn_ck_right(an) != NULL) - an = an->tn_right; - return is_const_char_pointer(an->tn_left); + return tn->tn_call->args != NULL + && tn->tn_call->args_len >= 1 + && is_const_char_pointer(tn->tn_call->args[0]); } static bool @@ -2642,13 +2644,9 @@ is_const_pointer(const tnode_t *tn) static bool is_second_arg_const_pointer(const tnode_t *tn) { - const tnode_t *an = tn_ck_right(tn); - if (an == NULL || tn_ck_right(an) == NULL) - return false; - - while (tn_ck_right(an->tn_right) != NULL) - an = an->tn_right; - return is_const_pointer(an->tn_left); + return tn->tn_call->args_len >= 2 + && tn->tn_call->args != NULL + && is_const_pointer(tn->tn_call->args[1]); } static void @@ -4110,14 +4108,8 @@ invalid_cast: return NULL; } -/* - * Create the node for a function argument. - * All necessary conversions and type checks are done in - * build_function_call because build_function_argument has no - * information about the expected parameter types. - */ -tnode_t * -build_function_argument(tnode_t *args, tnode_t *arg) +void +add_function_argument(function_call *call, tnode_t *arg) { /* * If there was a serious error in the expression for the argument, @@ -4127,7 +4119,16 @@ build_function_argument(tnode_t *args, t if (arg == NULL) arg = build_integer_constant(INT, 0); - return build_op(PUSH, arg->tn_sys, arg->tn_type, arg, args); + if (call->args_len >= call->args_cap) { + call->args_cap += 8; + tnode_t **new_args = expr_zero_alloc( + call->args_cap * sizeof(*call->args), + "function_call.args"); + memcpy(new_args, call->args, + call->args_len * sizeof(*call->args)); + call->args = new_args; + } + call->args[call->args_len++] = arg; } /* @@ -4159,18 +4160,17 @@ check_prototype_argument( * Check types of all function arguments and insert conversions, * if necessary. */ -static tnode_t * -check_function_arguments(type_t *ftp, tnode_t *args) +static bool +check_function_arguments(const function_call *call) { + type_t *ftp = call->func->tn_type->t_subt; + /* get # of parameters in the prototype */ int npar = 0; for (const sym_t *p = ftp->t_params; p != NULL; p = p->s_next) npar++; - /* get # of arguments in the function call */ - int narg = 0; - for (const tnode_t *arg = args; arg != NULL; arg = tn_ck_right(arg)) - narg++; + int narg = (int)call->args_len; const sym_t *param = ftp->t_params; if (ftp->t_proto && npar != narg && !(ftp->t_vararg && npar < narg)) { @@ -4180,50 +4180,45 @@ check_function_arguments(type_t *ftp, tn } for (int n = 1; n <= narg; n++) { - - // The rightmost argument starts the argument list. - tnode_t *arg = args; - for (int i = narg; i > n; i--, arg = arg->tn_right) - continue; + tnode_t *arg = call->args[n - 1]; /* some things which are always not allowed */ - tspec_t at = arg->tn_left->tn_type->t_tspec; + tspec_t at = arg->tn_type->t_tspec; if (at == VOID) { /* void expressions may not be arguments, arg #%d */ error(151, n); - return NULL; + return false; } if (is_struct_or_union(at) && - is_incomplete(arg->tn_left->tn_type)) { + is_incomplete(arg->tn_type)) { /* argument cannot have unknown size, arg #%d */ error(152, n); - return NULL; + return false; } if (is_integer(at) && - arg->tn_left->tn_type->t_is_enum && - is_incomplete(arg->tn_left->tn_type)) { + arg->tn_type->t_is_enum && + is_incomplete(arg->tn_type)) { /* argument cannot have unknown size, arg #%d */ warning(152, n); } - arg->tn_left = cconv(arg->tn_left); + arg = cconv(arg); + call->args[n - 1] = arg; - if (param != NULL) { - arg->tn_left = check_prototype_argument( - n, param->s_type, arg->tn_left); - } else - arg->tn_left = promote(NOOP, true, arg->tn_left); - arg->tn_type = arg->tn_left->tn_type; + arg = param != NULL + ? check_prototype_argument(n, param->s_type, arg) + : promote(NOOP, true, arg); + call->args[n - 1] = arg; if (param != NULL) param = param->s_next; } - return args; + return true; } tnode_t * -build_function_call(tnode_t *func, bool sys, tnode_t *args) +build_function_call(tnode_t *func, bool sys, function_call *call) { if (func == NULL) @@ -4232,9 +4227,11 @@ build_function_call(tnode_t *func, bool op_t fcop = func->tn_op == NAME && func->tn_type->t_tspec == FUNC ? CALL : ICALL; - check_ctype_function_call(func, args); + call->func = func; + check_ctype_function_call(call); func = cconv(func); + call->func = func; if (func->tn_type->t_tspec != PTR || func->tn_type->t_subt->t_tspec != FUNC) { @@ -4243,9 +4240,15 @@ build_function_call(tnode_t *func, bool return NULL; } - args = check_function_arguments(func->tn_type->t_subt, args); + if (!check_function_arguments(call)) + call->args = NULL; - return build_op(fcop, sys, func->tn_type->t_subt->t_subt, func, args); + tnode_t *ntn = expr_alloc_tnode(); + ntn->tn_op = fcop; + ntn->tn_type = func->tn_type->t_subt->t_subt; + ntn->tn_sys = sys; + ntn->tn_call = call; + return ntn; } /* @@ -4482,9 +4485,7 @@ check_expr_call(const tnode_t *tn, const } static void -check_expr_op(const tnode_t *tn, op_t op, const tnode_t *ln, - bool szof, bool fcall, bool vctx, bool cond, - bool retval_discarded, bool eqwarn) +check_expr_op(op_t op, const tnode_t *ln, bool szof, bool fcall, bool eqwarn) { switch (op) { case ADDR: @@ -4493,7 +4494,6 @@ check_expr_op(const tnode_t *tn, op_t op case LOAD: check_expr_load(ln); /* FALLTHROUGH */ - case PUSH: case INCBEF: case DECBEF: case INCAFT: @@ -4515,9 +4515,6 @@ check_expr_op(const tnode_t *tn, op_t op case ASSIGN: check_expr_assign(ln, szof); break; - case CALL: - check_expr_call(tn, ln, szof, vctx, cond, retval_discarded); - break; case EQ: if (hflag && eqwarn) /* operator '==' found where '=' was expected */ @@ -4552,12 +4549,26 @@ check_expr_misc(const tnode_t *tn, bool op_t op = tn->tn_op; if (op == NAME || op == CON || op == STRING) return; + if (op == CALL || op == ICALL) { + const function_call *call = tn->tn_call; + if (op == CALL) + check_expr_call(tn, call->func, + szof, vctx, cond, retval_discarded); + 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); + } + return; + } lint_assert(has_operands(tn)); tnode_t *ln = tn->tn_left; tnode_t *rn = tn->tn_right; - check_expr_op(tn, op, ln, - szof, fcall, vctx, cond, retval_discarded, eqwarn); + check_expr_op(op, ln, szof, fcall, eqwarn); const mod_t *mp = &modtab[op]; bool cvctx = mp->m_value_context; @@ -4579,11 +4590,6 @@ check_expr_misc(const tnode_t *tn, bool check_expr_misc(ln, cvctx, ccond, eq, op == CALL, discard, szof); switch (op) { - case PUSH: - if (rn != NULL) - check_expr_misc(rn, false, false, eq, false, false, - szof); - break; case LOGAND: case LOGOR: check_expr_misc(rn, false, true, eq, false, false, szof);