flow: handle EXPR_OFFSETOF and EXPR_ALIGNOF
[smatch.git] / check_or_vs_and.c
blobb885b41d5f34bb60b873108aaaed2ef3640b776f
1 /*
2 * sparse/check_or_vs_and.c
4 * Copyright (C) 2012 Oracle.
6 * Licensed under the Open Software License version 1.1
8 */
10 #include "smatch.h"
12 static int my_id;
14 static int does_inc_dec(struct expression *expr)
16 if (expr->type == EXPR_PREOP || expr->type == EXPR_POSTOP) {
17 if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT)
18 return 1;
19 return does_inc_dec(expr->unop);
21 return 0;
24 static int expr_equiv(struct expression *one, struct expression *two)
26 struct symbol *one_sym, *two_sym;
27 char *one_name = NULL;
28 char *two_name = NULL;
29 int ret = 0;
31 if (does_inc_dec(one) || does_inc_dec(two))
32 return 0;
34 one_name = get_variable_from_expr_complex(one, &one_sym);
35 if (!one_name || !one_sym)
36 goto free;
37 two_name = get_variable_from_expr_complex(two, &two_sym);
38 if (!two_name || !two_sym)
39 goto free;
40 if (one_sym != two_sym)
41 goto free;
42 if (strcmp(one_name, two_name) == 0)
43 ret = 1;
44 free:
45 free_string(one_name);
46 free_string(two_name);
47 return ret;
50 static int inconsistent_check(struct expression *left, struct expression *right)
52 long long val;
54 if (get_value(left->left, &val)) {
55 if (get_value(right->left, &val))
56 return expr_equiv(left->right, right->right);
57 if (get_value(right->right, &val))
58 return expr_equiv(left->right, right->left);
59 return 0;
61 if (get_value(left->right, &val)) {
62 if (get_value(right->left, &val))
63 return expr_equiv(left->left, right->right);
64 if (get_value(right->right, &val))
65 return expr_equiv(left->left, right->left);
66 return 0;
69 return 0;
72 static void check_or(struct expression *expr)
74 if (expr->left->type != EXPR_COMPARE ||
75 expr->left->op != SPECIAL_NOTEQUAL)
76 return;
77 if (expr->right->type != EXPR_COMPARE ||
78 expr->right->op != SPECIAL_NOTEQUAL)
79 return;
80 if (!inconsistent_check(expr->left, expr->right))
81 return;
83 sm_msg("warn: was && intended here instead of ||?");
86 static void check_and(struct expression *expr)
88 if (expr->left->type != EXPR_COMPARE ||
89 expr->left->op != SPECIAL_EQUAL)
90 return;
91 if (expr->right->type != EXPR_COMPARE ||
92 expr->right->op != SPECIAL_EQUAL)
93 return;
94 if (!inconsistent_check(expr->left, expr->right))
95 return;
97 sm_msg("warn: was || intended here instead of &&?");
100 static void match_logic(struct expression *expr)
102 if (expr->type != EXPR_LOGICAL)
103 return;
105 if (expr->op == SPECIAL_LOGICAL_OR)
106 check_or(expr);
107 if (expr->op == SPECIAL_LOGICAL_AND)
108 check_and(expr);
111 void check_or_vs_and(int id)
113 my_id = id;
115 add_hook(&match_logic, LOGIC_HOOK);