`11506 smatch resync`
```*** 27,36 ****
--- 27,38 ----
{
struct symbol *ret;

if (!sym)
return NULL;
+         if (sym->type == SYM_BASETYPE)
+                 return sym;
ret = get_base_type(sym);
if (!ret)
return NULL;
if (ret->type == SYM_RESTRICT || ret->type == SYM_NODE)
return get_real_base_type(ret);
*** 73,82 ****
--- 75,88 ----
}
right = get_type(expr->right);
if (!right)
return NULL;

+         if (expr->op == '-' &&
+             (is_ptr_type(left) && is_ptr_type(right)))
+                 return ssize_t_ctype;
+
if (left->type == SYM_PTR || left->type == SYM_ARRAY)
return left;
if (right->type == SYM_PTR || right->type == SYM_ARRAY)
return right;

*** 267,276 ****
--- 273,285 ----
ret = &ulong_ctype;
break;
case EXPR_LOGICAL:
ret = &int_ctype;
break;
+         case EXPR_OFFSETOF:
+                 ret = &ulong_ctype;
+                 break;
default:
return NULL;
}

if (ret && ret->type == SYM_TYPEOF)
*** 281,324 ****
}

static struct symbol *get_final_type_helper(struct expression *expr)
{
/*
!          * I'm not totally positive I understand types...
*
-          * So, when you're doing pointer math, and you do a subtraction, then
-          * the sval_binop() and whatever need to know the type of the pointer
-          * so they can figure out the alignment.  But the result is going to be
-          * and ssize_t.  So get_operation_type() gives you the pointer type
-          * and get_type() gives you ssize_t.
-          *
-          * Most of the time the operation type and the final type are the same
-          * but this just handles the few places where they are different.
-          *
*/

expr = strip_parens(expr);
if (!expr)
return NULL;

!         switch (expr->type) {
!         case EXPR_COMPARE:
return &int_ctype;
-         case EXPR_BINOP: {
-                 struct symbol *left, *right;

-                 if (expr->op != '-')
return NULL;
-
-                 left = get_type(expr->left);
-                 right = get_type(expr->right);
-                 if (type_is_ptr(left) || type_is_ptr(right))
-                         return ssize_t_ctype;
-                 }
-         }
-
-         return NULL;
}

struct symbol *get_type(struct expression *expr)
{
return get_type_helper(expr);
--- 290,314 ----
}

static struct symbol *get_final_type_helper(struct expression *expr)
{
/*
!          * The problem is that I wrote a bunch of Smatch to think that
!          * you could do get_type() on an expression and it would give
!          * you what the comparison was type promoted to.  This is wrong
!          * but fixing it is a big of work...  Hence this horrible hack.
*
*/

expr = strip_parens(expr);
if (!expr)
return NULL;

!         if (expr->type == EXPR_COMPARE)
return &int_ctype;

return NULL;
}

struct symbol *get_type(struct expression *expr)
{
return get_type_helper(expr);
*** 395,414 ****
return type_unsigned(sym);
}

int is_pointer(struct expression *expr)
{
!         struct symbol *sym;
!
!         sym = get_type(expr);
!         if (!sym)
!                 return 0;
!         if (sym == &string_ctype)
!                 return 0;
!         if (sym->type == SYM_PTR)
!                 return 1;
!         return 0;
}

int returns_pointer(struct symbol *sym)
{
if (!sym)
--- 385,395 ----
return type_unsigned(sym);
}

int is_pointer(struct expression *expr)
{
!         return type_is_ptr(get_type(expr));
}

int returns_pointer(struct symbol *sym)
{
if (!sym)
*** 440,450 ****

if (!base_type || !type_bits(base_type))
base_type = &llong_ctype;
ret.type = base_type;

!         if (type_unsigned(base_type)) {
ret.value = 0;
return ret;
}

ret.value = (~0ULL) << type_positive_bits(base_type);
--- 421,431 ----

if (!base_type || !type_bits(base_type))
base_type = &llong_ctype;
ret.type = base_type;

!         if (type_unsigned(base_type) || is_ptr_type(base_type)) {
ret.value = 0;
return ret;
}

ret.value = (~0ULL) << type_positive_bits(base_type);
*** 602,612 ****
struct symbol *tmp, *sub;
int chunk_len;

if (strncmp(name, ".", 1) == 0)
name += 1;
!         if (strncmp(name, "->", 2) == 0)
name += 2;

FOR_EACH_PTR(symbol_list, tmp) {
if (!tmp->ident) {
sub = get_real_base_type(tmp);
--- 583,593 ----
struct symbol *tmp, *sub;
int chunk_len;

if (strncmp(name, ".", 1) == 0)
name += 1;
!         else if (strncmp(name, "->", 2) == 0)
name += 2;

FOR_EACH_PTR(symbol_list, tmp) {
if (!tmp->ident) {
sub = get_real_base_type(tmp);
*** 617,630 ****
}

if (strcmp(tmp->ident->name, name) == 0)
return tmp;

!                 chunk_len = strlen(tmp->ident->name);
if (strncmp(tmp->ident->name, name, chunk_len) == 0 &&
(name[chunk_len] == '.' || name[chunk_len] == '-')) {
sub = get_real_base_type(tmp);
return get_member_from_string(sub->symbol_list, name + chunk_len);
}

} END_FOR_EACH_PTR(tmp);

--- 598,613 ----
}

if (strcmp(tmp->ident->name, name) == 0)
return tmp;

!                 chunk_len = tmp->ident->len;
if (strncmp(tmp->ident->name, name, chunk_len) == 0 &&
(name[chunk_len] == '.' || name[chunk_len] == '-')) {
sub = get_real_base_type(tmp);
+                         if (sub->type == SYM_PTR)
+                                 sub = get_real_base_type(sub);
return get_member_from_string(sub->symbol_list, name + chunk_len);
}

} END_FOR_EACH_PTR(tmp);

*** 739,749 ****

if (!type)
return snprintf(buf, size, "<unknown>");

if (type->type == SYM_BASETYPE) {
!                 return snprintf(buf, size, base_type_str(type));
} else if (type->type == SYM_PTR) {
type = get_real_base_type(type);
n = type_str_helper(buf, size, type);
if (n > size)
return n;
--- 722,732 ----

if (!type)
return snprintf(buf, size, "<unknown>");

if (type->type == SYM_BASETYPE) {
!                 return snprintf(buf, size, "%s", base_type_str(type));
} else if (type->type == SYM_PTR) {
type = get_real_base_type(type);
n = type_str_helper(buf, size, type);
if (n > size)
return n;
*** 793,802 ****
--- 776,787 ----
type = get_real_base_type(type);
n += type_str_helper(buf + n, size - n, type);
if (n > size)
return n;
return n + snprintf(buf + n, size - n, "}");
+         } else if (type->type == SYM_ENUM) {
+                 return snprintf(buf, size, "enum %s", type->ident ? type->ident->name : "<unknown>");
} else {
return snprintf(buf, size, "<type %d>", type->type);
}
}

```