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;