2 * Copyright (C) 2022 Dan Carpenter.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
20 #include "smatch_extra.h"
21 #include "smatch_slist.h"
25 static struct statement
*get_if_statement(struct expression
*expr
)
27 struct statement
*stmt
;
29 stmt
= get_parent_stmt(expr
);
30 if (!stmt
|| stmt
->type
!= STMT_RETURN
)
32 stmt
= stmt_get_parent_stmt(stmt
);
33 if (stmt
&& stmt
->type
== STMT_COMPOUND
)
34 stmt
= stmt_get_parent_stmt(stmt
);
38 if (stmt
->type
!= STMT_IF
)
44 static bool condition_matches(struct expression
*cond
, struct expression
*expr
)
46 expr
= strip_expr(expr
);
47 cond
= strip_expr(cond
);
50 if (cond
->type
== EXPR_PREOP
&&
51 (cond
->op
== '(' || cond
->op
== '!')) {
52 cond
= strip_expr(cond
->unop
);
55 if (cond
->type
== EXPR_COMPARE
&&
56 (cond
->op
== SPECIAL_EQUAL
|| cond
->op
== SPECIAL_NOTEQUAL
) &&
57 expr_is_zero(cond
->right
)) {
58 cond
= strip_expr(cond
->left
);
64 if (expr_equiv(cond
, expr
))
70 static struct expression
*get_orig_call(struct expression
*expr
)
72 struct expression
*orig
;
74 orig
= get_assigned_expr(expr
);
75 if (!orig
|| orig
->type
!= EXPR_CALL
)
81 static void match_return(struct expression
*expr
)
83 struct expression
*call
;
84 struct statement
*stmt
;
88 if (!expr
|| expr
->type
!= EXPR_SYMBOL
)
91 if (get_type(expr
) != &int_ctype
)
94 if (!get_implied_value(expr
, &sval
) || sval
.value
!= 0)
97 stmt
= get_if_statement(expr
);
100 if (condition_matches(stmt
->if_conditional
, expr
))
103 call
= get_orig_call(expr
);
107 if (call
->pos
.line
>= stmt
->pos
.line
)
110 if (call
->pos
.line
+ 5 >= expr
->pos
.line
)
113 name
= expr_to_str(expr
);
114 sm_warning("missing error code? '%s'", name
);
118 void check_missing_error_code2(int id
)
122 add_hook(&match_return
, RETURN_HOOK
);