| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: func.c,v 1.151 2023/03/28 20:01:21 rillig Exp $ */ | | 1 | /* $NetBSD: func.c,v 1.152 2023/04/15 10:32:46 rillig Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1994, 1995 Jochen Pohl | | 4 | * Copyright (c) 1994, 1995 Jochen Pohl |
5 | * All Rights Reserved. | | 5 | * All Rights Reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
| @@ -27,27 +27,27 @@ | | | @@ -27,27 +27,27 @@ |
27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
32 | */ | | 32 | */ |
33 | | | 33 | |
34 | #if HAVE_NBTOOL_CONFIG_H | | 34 | #if HAVE_NBTOOL_CONFIG_H |
35 | #include "nbtool_config.h" | | 35 | #include "nbtool_config.h" |
36 | #endif | | 36 | #endif |
37 | | | 37 | |
38 | #include <sys/cdefs.h> | | 38 | #include <sys/cdefs.h> |
39 | #if defined(__RCSID) | | 39 | #if defined(__RCSID) |
40 | __RCSID("$NetBSD: func.c,v 1.151 2023/03/28 20:01:21 rillig Exp $"); | | 40 | __RCSID("$NetBSD: func.c,v 1.152 2023/04/15 10:32:46 rillig Exp $"); |
41 | #endif | | 41 | #endif |
42 | | | 42 | |
43 | #include <stdlib.h> | | 43 | #include <stdlib.h> |
44 | #include <string.h> | | 44 | #include <string.h> |
45 | | | 45 | |
46 | #include "lint1.h" | | 46 | #include "lint1.h" |
47 | #include "cgram.h" | | 47 | #include "cgram.h" |
48 | | | 48 | |
49 | /* | | 49 | /* |
50 | * Contains a pointer to the symbol table entry of the current function | | 50 | * Contains a pointer to the symbol table entry of the current function |
51 | * definition. | | 51 | * definition. |
52 | */ | | 52 | */ |
53 | sym_t *funcsym; | | 53 | sym_t *funcsym; |
| @@ -1037,38 +1037,61 @@ do_continue(void) | | | @@ -1037,38 +1037,61 @@ do_continue(void) |
1037 | if (cs == NULL) { | | 1037 | if (cs == NULL) { |
1038 | /* continue outside loop */ | | 1038 | /* continue outside loop */ |
1039 | error(209); | | 1039 | error(209); |
1040 | } else { | | 1040 | } else { |
1041 | /* TODO: only if reachable, for symmetry with c_break */ | | 1041 | /* TODO: only if reachable, for symmetry with c_break */ |
1042 | cs->c_continue = true; | | 1042 | cs->c_continue = true; |
1043 | } | | 1043 | } |
1044 | | | 1044 | |
1045 | check_statement_reachable(); | | 1045 | check_statement_reachable(); |
1046 | | | 1046 | |
1047 | set_reached(false); | | 1047 | set_reached(false); |
1048 | } | | 1048 | } |
1049 | | | 1049 | |
| | | 1050 | static void |
| | | 1051 | check_return_value(bool sys, tnode_t *tn) |
| | | 1052 | { |
| | | 1053 | /* Create a temporary node for the left side */ |
| | | 1054 | tnode_t *ln = expr_zero_alloc(sizeof(*ln)); |
| | | 1055 | ln->tn_op = NAME; |
| | | 1056 | ln->tn_type = expr_unqualified_type(funcsym->s_type->t_subt); |
| | | 1057 | ln->tn_lvalue = true; |
| | | 1058 | ln->tn_sym = funcsym; /* better than nothing */ |
| | | 1059 | |
| | | 1060 | tnode_t *retn = build_binary(ln, RETURN, sys, tn); |
| | | 1061 | |
| | | 1062 | if (retn != NULL) { |
| | | 1063 | const tnode_t *rn = retn->tn_right; |
| | | 1064 | while (rn->tn_op == CVT || rn->tn_op == PLUS) |
| | | 1065 | rn = rn->tn_left; |
| | | 1066 | if (rn->tn_op == ADDR && rn->tn_left->tn_op == NAME && |
| | | 1067 | rn->tn_left->tn_sym->s_scl == AUTO) { |
| | | 1068 | /* '%s' returns pointer to automatic object */ |
| | | 1069 | warning(302, funcsym->s_name); |
| | | 1070 | } |
| | | 1071 | } |
| | | 1072 | |
| | | 1073 | expr(retn, true, false, true, false); |
| | | 1074 | } |
| | | 1075 | |
1050 | /* | | 1076 | /* |
1051 | * T_RETURN T_SEMI | | 1077 | * T_RETURN T_SEMI |
1052 | * T_RETURN expr T_SEMI | | 1078 | * T_RETURN expr T_SEMI |
1053 | */ | | 1079 | */ |
1054 | void | | 1080 | void |
1055 | do_return(bool sys, tnode_t *tn) | | 1081 | do_return(bool sys, tnode_t *tn) |
1056 | { | | 1082 | { |
1057 | tnode_t *ln, *rn; | | 1083 | control_statement *cs = cstmt; |
1058 | control_statement *cs; | | | |
1059 | op_t op; | | | |
1060 | | | 1084 | |
1061 | cs = cstmt; | | | |
1062 | if (cs == NULL) { | | 1085 | if (cs == NULL) { |
1063 | /* syntax error '%s' */ | | 1086 | /* syntax error '%s' */ |
1064 | error(249, "return outside function"); | | 1087 | error(249, "return outside function"); |
1065 | return; | | 1088 | return; |
1066 | } | | 1089 | } |
1067 | | | 1090 | |
1068 | for (; cs->c_surrounding != NULL; cs = cs->c_surrounding) | | 1091 | for (; cs->c_surrounding != NULL; cs = cs->c_surrounding) |
1069 | continue; | | 1092 | continue; |
1070 | | | 1093 | |
1071 | if (tn != NULL) | | 1094 | if (tn != NULL) |
1072 | cs->c_had_return_value = true; | | 1095 | cs->c_had_return_value = true; |
1073 | else | | 1096 | else |
1074 | cs->c_had_return_noval = true; | | 1097 | cs->c_had_return_noval = true; |
| @@ -1078,56 +1101,31 @@ do_return(bool sys, tnode_t *tn) | | | @@ -1078,56 +1101,31 @@ do_return(bool sys, tnode_t *tn) |
1078 | error(213, funcsym->s_name); | | 1101 | error(213, funcsym->s_name); |
1079 | expr_free_all(); | | 1102 | expr_free_all(); |
1080 | tn = NULL; | | 1103 | tn = NULL; |
1081 | } else if (tn == NULL && funcsym->s_type->t_subt->t_tspec != VOID) { | | 1104 | } else if (tn == NULL && funcsym->s_type->t_subt->t_tspec != VOID) { |
1082 | /* | | 1105 | /* |
1083 | * Assume that the function has a return value only if it | | 1106 | * Assume that the function has a return value only if it |
1084 | * is explicitly declared. | | 1107 | * is explicitly declared. |
1085 | */ | | 1108 | */ |
1086 | if (!funcsym->s_return_type_implicit_int) | | 1109 | if (!funcsym->s_return_type_implicit_int) |
1087 | /* function '%s' expects to return value */ | | 1110 | /* function '%s' expects to return value */ |
1088 | warning(214, funcsym->s_name); | | 1111 | warning(214, funcsym->s_name); |
1089 | } | | 1112 | } |
1090 | | | 1113 | |
1091 | if (tn != NULL) { | | 1114 | if (tn != NULL) |
1092 | | | 1115 | check_return_value(sys, tn); |
1093 | /* Create a temporary node for the left side */ | | 1116 | else |
1094 | ln = expr_zero_alloc(sizeof(*ln)); | | | |
1095 | ln->tn_op = NAME; | | | |
1096 | ln->tn_type = expr_unqualified_type(funcsym->s_type->t_subt); | | | |
1097 | ln->tn_lvalue = true; | | | |
1098 | ln->tn_sym = funcsym; /* better than nothing */ | | | |
1099 | | | | |
1100 | tn = build_binary(ln, RETURN, sys, tn); | | | |
1101 | | | | |
1102 | if (tn != NULL) { | | | |
1103 | rn = tn->tn_right; | | | |
1104 | while ((op = rn->tn_op) == CVT || op == PLUS) | | | |
1105 | rn = rn->tn_left; | | | |
1106 | if (rn->tn_op == ADDR && rn->tn_left->tn_op == NAME && | | | |
1107 | rn->tn_left->tn_sym->s_scl == AUTO) { | | | |
1108 | /* '%s' returns pointer to automatic object */ | | | |
1109 | warning(302, funcsym->s_name); | | | |
1110 | } | | | |
1111 | } | | | |
1112 | | | | |
1113 | expr(tn, true, false, true, false); | | | |
1114 | | | | |
1115 | } else { | | | |
1116 | | | | |
1117 | check_statement_reachable(); | | 1117 | check_statement_reachable(); |
1118 | | | 1118 | |
1119 | } | | | |
1120 | | | | |
1121 | set_reached(false); | | 1119 | set_reached(false); |
1122 | } | | 1120 | } |
1123 | | | 1121 | |
1124 | /* | | 1122 | /* |
1125 | * Do some cleanup after a global declaration or definition. | | 1123 | * Do some cleanup after a global declaration or definition. |
1126 | * Especially remove information about unused lint comments. | | 1124 | * Especially remove information about unused lint comments. |
1127 | */ | | 1125 | */ |
1128 | void | | 1126 | void |
1129 | global_clean_up_decl(bool silent) | | 1127 | global_clean_up_decl(bool silent) |
1130 | { | | 1128 | { |
1131 | | | 1129 | |
1132 | if (nargusg != -1) { | | 1130 | if (nargusg != -1) { |
1133 | if (!silent) { | | 1131 | if (!silent) { |