Print this page
11506 smatch resync
@@ -79,18 +79,30 @@
state = __alloc_smatch_state(0);
state->name = alloc_string(name);
return state;
}
+struct smatch_state *merge_str_state(struct smatch_state *s1, struct smatch_state *s2)
+{
+ if (!s1->name || !s2->name)
+ return &merged;
+ if (strcmp(s1->name, s2->name) == 0)
+ return s1;
+ return &merged;
+}
+
struct smatch_state *alloc_state_expr(struct expression *expr)
{
struct smatch_state *state;
char *name;
- state = __alloc_smatch_state(0);
expr = strip_expr(expr);
name = expr_to_str(expr);
+ if (!name)
+ return NULL;
+
+ state = __alloc_smatch_state(0);
state->name = alloc_sname(name);
free_string(name);
state->data = expr;
return state;
}
@@ -164,20 +176,20 @@
struct expression *deref;
int op;
deref = expr->deref;
op = deref->op;
- if (op == '*') {
+ if (deref->type == EXPR_PREOP && op == '*') {
struct expression *unop = strip_expr(deref->unop);
if (unop->type == EXPR_PREOP && unop->op == '&') {
deref = unop->unop;
op = '.';
} else {
- deref = deref->unop;
- if (!is_pointer(deref))
+ if (!is_pointer(deref) && !is_pointer(deref->unop))
op = '.';
+ deref = deref->unop;
}
}
__get_variable_from_expr(sym_ptr, buf, deref, len, complicated, no_parens);
@@ -525,11 +537,11 @@
name = expr_to_var_sym(expr, &tmp);
if (name && tmp) {
if (sym)
*sym = tmp;
if (vsl)
- *vsl = expr_to_vsl(expr);
+ add_var_sym(vsl, name, tmp);
return name;
}
free_string(name);
score = get_complication_score(expr);
@@ -867,12 +879,56 @@
snprintf(buf, sizeof(buf), "(union %s)->%s",
sym->ident ? sym->ident->name : "anonymous",
expr->member->name);
return alloc_string(buf);
}
- if (!sym->ident)
+ if (!sym->ident) {
+ struct expression *deref;
+ char *full, *outer;
+ int len;
+
+ /*
+ * If we're in an anonymous struct then maybe we can find an
+ * outer struct name to use as a name. This code should be
+ * recursive and cleaner. I am not very proud of it.
+ *
+ */
+
+ deref = expr->deref;
+ if (deref->type != EXPR_DEREF || !deref->member)
return NULL;
+ sym = get_type(deref->deref);
+ if (!sym || sym->type != SYM_STRUCT || !sym->ident)
+ return NULL;
+
+ full = expr_to_str(expr);
+ if (!full)
+ return NULL;
+ deref = deref->deref;
+ if (deref->type == EXPR_PREOP && deref->op == '*')
+ deref = deref->unop;
+ outer = expr_to_str(deref);
+ if (!outer) {
+ free_string(full);
+ return NULL;
+ }
+ len = strlen(outer);
+ if (strncmp(outer, full, len) != 0) {
+ free_string(full);
+ free_string(outer);
+ return NULL;
+ }
+ if (full[len] == '-' && full[len + 1] == '>')
+ len += 2;
+ if (full[len] == '.')
+ len++;
+ snprintf(buf, sizeof(buf), "(struct %s)->%s", sym->ident->name, full + len);
+ free_string(outer);
+ free_string(full);
+
+ return alloc_string(buf);
+ }
snprintf(buf, sizeof(buf), "(struct %s)->%s", sym->ident->name, expr->member->name);
return alloc_string(buf);
}
int cmp_pos(struct position pos1, struct position pos2)
@@ -1052,10 +1108,38 @@
return SPECIAL_LEFTSHIFT;
}
return 0;
}
+int op_remove_assign(int op)
+{
+ switch (op) {
+ case SPECIAL_ADD_ASSIGN:
+ return '+';
+ case SPECIAL_SUB_ASSIGN:
+ return '-';
+ case SPECIAL_MUL_ASSIGN:
+ return '*';
+ case SPECIAL_DIV_ASSIGN:
+ return '/';
+ case SPECIAL_MOD_ASSIGN:
+ return '%';
+ case SPECIAL_AND_ASSIGN:
+ return '&';
+ case SPECIAL_OR_ASSIGN:
+ return '|';
+ case SPECIAL_XOR_ASSIGN:
+ return '^';
+ case SPECIAL_SHL_ASSIGN:
+ return SPECIAL_LEFTSHIFT;
+ case SPECIAL_SHR_ASSIGN:
+ return SPECIAL_RIGHTSHIFT;
+ default:
+ return op;
+ }
+}
+
int expr_equiv(struct expression *one, struct expression *two)
{
struct symbol *one_sym = NULL;
struct symbol *two_sym = NULL;
char *one_name = NULL;