Print this page
12166 resync smatch to 0.6.1-rc1-il-3

*** 117,126 **** --- 117,131 ---- { struct symbol *type; struct ident *member; int offset; + /* + * FIXME: This doesn't handle foo.u.bar correctly. + * + */ + if (expr->type != EXPR_DEREF) /* hopefully, this doesn't happen */ return -1; if (expr->member_offset >= 0) return expr->member_offset;
*** 200,228 **** static struct range_list *where_allocated_rl(struct symbol *sym) { if (!sym) return NULL; return alloc_rl(valid_ptr_min_sval, valid_ptr_max_sval); } int get_address_rl(struct expression *expr, struct range_list **rl) { struct expression *unop; expr = strip_expr(expr); if (!expr) return 0; ! if (expr->type == EXPR_STRING) { ! *rl = alloc_rl(valid_ptr_min_sval, valid_ptr_max_sval); return 1; - } ! if (expr->type == EXPR_PREOP && expr->op == '&') expr = strip_expr(expr->unop); ! else { struct symbol *type; type = get_type(expr); if (!type || type->type != SYM_ARRAY) return 0; --- 205,274 ---- static struct range_list *where_allocated_rl(struct symbol *sym) { if (!sym) return NULL; + /* This should just be the mtag if it's not on the stack */ return alloc_rl(valid_ptr_min_sval, valid_ptr_max_sval); } + static bool handle_fn_address(struct expression *expr, struct range_list **rl) + { + struct symbol *type; + + if (expr->type == EXPR_PREOP && expr->op == '&') + expr = strip_expr(expr->unop); + + if (expr->type != EXPR_SYMBOL) + return false; + + type = get_type(expr); + if (!type || type->type != SYM_FN) + return false; + + *rl = alloc_rl(valid_ptr_min_sval, valid_ptr_max_sval); + return true; + } + int get_address_rl(struct expression *expr, struct range_list **rl) { struct expression *unop; + /* + * Ugh... This function is bad. It doesn't work where it's supposed to + * and it does more than it really should. It shouldn't handle string + * literals I think... + * + * There are several complications. For arrays and functions the "&foo" + * "foo" are equivalent. But the problem is that we're also passing in + * foo->array[] and foo->fn. + * + * Then, when we have foo->bar.baz.one.two; that needs to be handled + * correctly but right now, it is not. + * + */ + expr = strip_expr(expr); if (!expr) return 0; ! /* ! * For functions &fn and fn are equivalent. I don't know if this is ! * really the right place to handle it, but let's just get it out of the ! * way for now. ! * ! */ ! if (handle_fn_address(expr, rl)) return 1; ! /* ! * For arrays, &foo->array and foo->array are equivalent. ! * ! */ ! if (expr->type == EXPR_PREOP && expr->op == '&') { expr = strip_expr(expr->unop); ! } else { struct symbol *type; type = get_type(expr); if (!type || type->type != SYM_ARRAY) return 0;