11f5207b7SJohn Levon /* 21f5207b7SJohn Levon * Copyright (C) 2009 Dan Carpenter. 31f5207b7SJohn Levon * 41f5207b7SJohn Levon * This program is free software; you can redistribute it and/or 51f5207b7SJohn Levon * modify it under the terms of the GNU General Public License 61f5207b7SJohn Levon * as published by the Free Software Foundation; either version 2 71f5207b7SJohn Levon * of the License, or (at your option) any later version. 81f5207b7SJohn Levon * 91f5207b7SJohn Levon * This program is distributed in the hope that it will be useful, 101f5207b7SJohn Levon * but WITHOUT ANY WARRANTY; without even the implied warranty of 111f5207b7SJohn Levon * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 121f5207b7SJohn Levon * GNU General Public License for more details. 131f5207b7SJohn Levon * 141f5207b7SJohn Levon * You should have received a copy of the GNU General Public License 151f5207b7SJohn Levon * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt 161f5207b7SJohn Levon */ 171f5207b7SJohn Levon 181f5207b7SJohn Levon /* 191f5207b7SJohn Levon * The idea here is that you have an expression and you 201f5207b7SJohn Levon * want to know what the type is for that. 211f5207b7SJohn Levon */ 221f5207b7SJohn Levon 231f5207b7SJohn Levon #include "smatch.h" 241f5207b7SJohn Levon #include "smatch_slist.h" 251f5207b7SJohn Levon 261f5207b7SJohn Levon struct symbol *get_real_base_type(struct symbol *sym) 271f5207b7SJohn Levon { 281f5207b7SJohn Levon struct symbol *ret; 291f5207b7SJohn Levon 301f5207b7SJohn Levon if (!sym) 311f5207b7SJohn Levon return NULL; 32efe51d0cSJohn Levon if (sym->type == SYM_BASETYPE) 33efe51d0cSJohn Levon return sym; 341f5207b7SJohn Levon ret = get_base_type(sym); 351f5207b7SJohn Levon if (!ret) 361f5207b7SJohn Levon return NULL; 371f5207b7SJohn Levon if (ret->type == SYM_RESTRICT || ret->type == SYM_NODE) 381f5207b7SJohn Levon return get_real_base_type(ret); 391f5207b7SJohn Levon return ret; 401f5207b7SJohn Levon } 411f5207b7SJohn Levon 421f5207b7SJohn Levon int type_bytes(struct symbol *type) 431f5207b7SJohn Levon { 441f5207b7SJohn Levon int bits; 451f5207b7SJohn Levon 461f5207b7SJohn Levon if (type && type->type == SYM_ARRAY) 471f5207b7SJohn Levon return array_bytes(type); 481f5207b7SJohn Levon 491f5207b7SJohn Levon bits = type_bits(type); 501f5207b7SJohn Levon if (bits < 0) 511f5207b7SJohn Levon return 0; 521f5207b7SJohn Levon return bits_to_bytes(bits); 531f5207b7SJohn Levon } 541f5207b7SJohn Levon 551f5207b7SJohn Levon int array_bytes(struct symbol *type) 561f5207b7SJohn Levon { 571f5207b7SJohn Levon if (!type || type->type != SYM_ARRAY) 581f5207b7SJohn Levon return 0; 591f5207b7SJohn Levon return bits_to_bytes(type->bit_size); 601f5207b7SJohn Levon } 611f5207b7SJohn Levon 621f5207b7SJohn Levon static struct symbol *get_binop_type(struct expression *expr) 631f5207b7SJohn Levon { 641f5207b7SJohn Levon struct symbol *left, *right; 651f5207b7SJohn Levon 661f5207b7SJohn Levon left = get_type(expr->left); 671f5207b7SJohn Levon if (!left) 681f5207b7SJohn Levon return NULL; 691f5207b7SJohn Levon 701f5207b7SJohn Levon if (expr->op == SPECIAL_LEFTSHIFT || 711f5207b7SJohn Levon expr->op == SPECIAL_RIGHTSHIFT) { 721f5207b7SJohn Levon if (type_positive_bits(left) < 31) 731f5207b7SJohn Levon return &int_ctype; 741f5207b7SJohn Levon return left; 751f5207b7SJohn Levon } 761f5207b7SJohn Levon right = get_type(expr->right); 771f5207b7SJohn Levon if (!right) 781f5207b7SJohn Levon return NULL; 791f5207b7SJohn Levon 80*5a0e240fSJohn Levon if (type_is_fp(left)) { 81*5a0e240fSJohn Levon if (type_is_fp(right)) { 82*5a0e240fSJohn Levon if (type_bits(left) > type_bits(right)) 83*5a0e240fSJohn Levon return left; 84*5a0e240fSJohn Levon return right; 85*5a0e240fSJohn Levon } 86*5a0e240fSJohn Levon return left; 87*5a0e240fSJohn Levon } 88*5a0e240fSJohn Levon 89*5a0e240fSJohn Levon if (type_is_fp(right)) { 90*5a0e240fSJohn Levon if (type_is_fp(left)) { 91*5a0e240fSJohn Levon if (type_bits(right) > type_bits(left)) 92*5a0e240fSJohn Levon return right; 93*5a0e240fSJohn Levon return left; 94*5a0e240fSJohn Levon } 95*5a0e240fSJohn Levon return right; 96*5a0e240fSJohn Levon } 97*5a0e240fSJohn Levon 98efe51d0cSJohn Levon if (expr->op == '-' && 99efe51d0cSJohn Levon (is_ptr_type(left) && is_ptr_type(right))) 100efe51d0cSJohn Levon return ssize_t_ctype; 101efe51d0cSJohn Levon 1021f5207b7SJohn Levon if (left->type == SYM_PTR || left->type == SYM_ARRAY) 1031f5207b7SJohn Levon return left; 1041f5207b7SJohn Levon if (right->type == SYM_PTR || right->type == SYM_ARRAY) 1051f5207b7SJohn Levon return right; 1061f5207b7SJohn Levon 1071f5207b7SJohn Levon if (type_positive_bits(left) < 31 && type_positive_bits(right) < 31) 1081f5207b7SJohn Levon return &int_ctype; 1091f5207b7SJohn Levon 1101f5207b7SJohn Levon if (type_positive_bits(left) > type_positive_bits(right)) 1111f5207b7SJohn Levon return left; 1121f5207b7SJohn Levon return right; 1131f5207b7SJohn Levon } 1141f5207b7SJohn Levon 1151f5207b7SJohn Levon static struct symbol *get_type_symbol(struct expression *expr) 1161f5207b7SJohn Levon { 1171f5207b7SJohn Levon if (!expr || expr->type != EXPR_SYMBOL || !expr->symbol) 1181f5207b7SJohn Levon return NULL; 1191f5207b7SJohn Levon 1201f5207b7SJohn Levon return get_real_base_type(expr->symbol); 1211f5207b7SJohn Levon } 1221f5207b7SJohn Levon 1231f5207b7SJohn Levon static struct symbol *get_member_symbol(struct symbol_list *symbol_list, struct ident *member) 1241f5207b7SJohn Levon { 1251f5207b7SJohn Levon struct symbol *tmp, *sub; 1261f5207b7SJohn Levon 1271f5207b7SJohn Levon FOR_EACH_PTR(symbol_list, tmp) { 1281f5207b7SJohn Levon if (!tmp->ident) { 1291f5207b7SJohn Levon sub = get_real_base_type(tmp); 1301f5207b7SJohn Levon sub = get_member_symbol(sub->symbol_list, member); 1311f5207b7SJohn Levon if (sub) 1321f5207b7SJohn Levon return sub; 1331f5207b7SJohn Levon continue; 1341f5207b7SJohn Levon } 1351f5207b7SJohn Levon if (tmp->ident == member) 1361f5207b7SJohn Levon return tmp; 1371f5207b7SJohn Levon } END_FOR_EACH_PTR(tmp); 1381f5207b7SJohn Levon 1391f5207b7SJohn Levon return NULL; 1401f5207b7SJohn Levon } 1411f5207b7SJohn Levon 1421f5207b7SJohn Levon static struct symbol *get_symbol_from_deref(struct expression *expr) 1431f5207b7SJohn Levon { 1441f5207b7SJohn Levon struct ident *member; 1451f5207b7SJohn Levon struct symbol *sym; 1461f5207b7SJohn Levon 1471f5207b7SJohn Levon if (!expr || expr->type != EXPR_DEREF) 1481f5207b7SJohn Levon return NULL; 1491f5207b7SJohn Levon 1501f5207b7SJohn Levon member = expr->member; 1511f5207b7SJohn Levon sym = get_type(expr->deref); 1521f5207b7SJohn Levon if (!sym) { 1531f5207b7SJohn Levon // sm_msg("could not find struct type"); 1541f5207b7SJohn Levon return NULL; 1551f5207b7SJohn Levon } 1561f5207b7SJohn Levon if (sym->type == SYM_PTR) 1571f5207b7SJohn Levon sym = get_real_base_type(sym); 1581f5207b7SJohn Levon sym = get_member_symbol(sym->symbol_list, member); 1591f5207b7SJohn Levon if (!sym) 1601f5207b7SJohn Levon return NULL; 1611f5207b7SJohn Levon return get_real_base_type(sym); 1621f5207b7SJohn Levon } 1631f5207b7SJohn Levon 164*5a0e240fSJohn Levon static struct symbol *handle__builtin_choose_expr(struct expression *expr) 165*5a0e240fSJohn Levon { 166*5a0e240fSJohn Levon struct expression *const_expr, *expr1, *expr2; 167*5a0e240fSJohn Levon sval_t sval; 168*5a0e240fSJohn Levon 169*5a0e240fSJohn Levon const_expr = get_argument_from_call_expr(expr->args, 0); 170*5a0e240fSJohn Levon expr1 = get_argument_from_call_expr(expr->args, 1); 171*5a0e240fSJohn Levon expr2 = get_argument_from_call_expr(expr->args, 2); 172*5a0e240fSJohn Levon 173*5a0e240fSJohn Levon if (!get_value(const_expr, &sval) || !expr1 || !expr2) 174*5a0e240fSJohn Levon return NULL; 175*5a0e240fSJohn Levon if (sval.value) 176*5a0e240fSJohn Levon return get_type(expr1); 177*5a0e240fSJohn Levon else 178*5a0e240fSJohn Levon return get_type(expr2); 179*5a0e240fSJohn Levon } 180*5a0e240fSJohn Levon 1811f5207b7SJohn Levon static struct symbol *get_return_type(struct expression *expr) 1821f5207b7SJohn Levon { 1831f5207b7SJohn Levon struct symbol *tmp; 1841f5207b7SJohn Levon 185*5a0e240fSJohn Levon if (sym_name_is("__builtin_choose_expr", expr->fn)) 186*5a0e240fSJohn Levon return handle__builtin_choose_expr(expr); 187*5a0e240fSJohn Levon 1881f5207b7SJohn Levon tmp = get_type(expr->fn); 1891f5207b7SJohn Levon if (!tmp) 1901f5207b7SJohn Levon return NULL; 1911f5207b7SJohn Levon /* this is to handle __builtin_constant_p() */ 1921f5207b7SJohn Levon if (tmp->type != SYM_FN) 1931f5207b7SJohn Levon tmp = get_base_type(tmp); 1941f5207b7SJohn Levon return get_real_base_type(tmp); 1951f5207b7SJohn Levon } 1961f5207b7SJohn Levon 1971f5207b7SJohn Levon static struct symbol *get_expr_stmt_type(struct statement *stmt) 1981f5207b7SJohn Levon { 1991f5207b7SJohn Levon if (stmt->type != STMT_COMPOUND) 2001f5207b7SJohn Levon return NULL; 2011f5207b7SJohn Levon stmt = last_ptr_list((struct ptr_list *)stmt->stmts); 2021f5207b7SJohn Levon if (stmt->type == STMT_LABEL) 2031f5207b7SJohn Levon stmt = stmt->label_statement; 2041f5207b7SJohn Levon if (stmt->type != STMT_EXPRESSION) 2051f5207b7SJohn Levon return NULL; 2061f5207b7SJohn Levon return get_type(stmt->expression); 2071f5207b7SJohn Levon } 2081f5207b7SJohn Levon 2091f5207b7SJohn Levon static struct symbol *get_select_type(struct expression *expr) 2101f5207b7SJohn Levon { 2111f5207b7SJohn Levon struct symbol *one, *two; 2121f5207b7SJohn Levon 2131f5207b7SJohn Levon one = get_type(expr->cond_true); 2141f5207b7SJohn Levon two = get_type(expr->cond_false); 2151f5207b7SJohn Levon if (!one || !two) 2161f5207b7SJohn Levon return NULL; 2171f5207b7SJohn Levon /* 2181f5207b7SJohn Levon * This is a hack. If the types are not equiv then we 2191f5207b7SJohn Levon * really don't know the type. But I think guessing is 2201f5207b7SJohn Levon * probably Ok here. 2211f5207b7SJohn Levon */ 2221f5207b7SJohn Levon if (type_positive_bits(one) > type_positive_bits(two)) 2231f5207b7SJohn Levon return one; 2241f5207b7SJohn Levon return two; 2251f5207b7SJohn Levon } 2261f5207b7SJohn Levon 2271f5207b7SJohn Levon struct symbol *get_pointer_type(struct expression *expr) 2281f5207b7SJohn Levon { 2291f5207b7SJohn Levon struct symbol *sym; 2301f5207b7SJohn Levon 2311f5207b7SJohn Levon sym = get_type(expr); 2321f5207b7SJohn Levon if (!sym) 2331f5207b7SJohn Levon return NULL; 2341f5207b7SJohn Levon if (sym->type == SYM_NODE) { 2351f5207b7SJohn Levon sym = get_real_base_type(sym); 2361f5207b7SJohn Levon if (!sym) 2371f5207b7SJohn Levon return NULL; 2381f5207b7SJohn Levon } 2391f5207b7SJohn Levon if (sym->type != SYM_PTR && sym->type != SYM_ARRAY) 2401f5207b7SJohn Levon return NULL; 2411f5207b7SJohn Levon return get_real_base_type(sym); 2421f5207b7SJohn Levon } 2431f5207b7SJohn Levon 2441f5207b7SJohn Levon static struct symbol *fake_pointer_sym(struct expression *expr) 2451f5207b7SJohn Levon { 2461f5207b7SJohn Levon struct symbol *sym; 2471f5207b7SJohn Levon struct symbol *base; 2481f5207b7SJohn Levon 2491f5207b7SJohn Levon sym = alloc_symbol(expr->pos, SYM_PTR); 2501f5207b7SJohn Levon expr = expr->unop; 2511f5207b7SJohn Levon base = get_type(expr); 2521f5207b7SJohn Levon if (!base) 2531f5207b7SJohn Levon return NULL; 2541f5207b7SJohn Levon sym->ctype.base_type = base; 2551f5207b7SJohn Levon return sym; 2561f5207b7SJohn Levon } 2571f5207b7SJohn Levon 2581f5207b7SJohn Levon static struct symbol *get_type_helper(struct expression *expr) 2591f5207b7SJohn Levon { 2601f5207b7SJohn Levon struct symbol *ret; 2611f5207b7SJohn Levon 2621f5207b7SJohn Levon expr = strip_parens(expr); 2631f5207b7SJohn Levon if (!expr) 2641f5207b7SJohn Levon return NULL; 2651f5207b7SJohn Levon 2661f5207b7SJohn Levon if (expr->ctype) 2671f5207b7SJohn Levon return expr->ctype; 2681f5207b7SJohn Levon 2691f5207b7SJohn Levon switch (expr->type) { 2701f5207b7SJohn Levon case EXPR_STRING: 2711f5207b7SJohn Levon ret = &string_ctype; 2721f5207b7SJohn Levon break; 2731f5207b7SJohn Levon case EXPR_SYMBOL: 2741f5207b7SJohn Levon ret = get_type_symbol(expr); 2751f5207b7SJohn Levon break; 2761f5207b7SJohn Levon case EXPR_DEREF: 2771f5207b7SJohn Levon ret = get_symbol_from_deref(expr); 2781f5207b7SJohn Levon break; 2791f5207b7SJohn Levon case EXPR_PREOP: 2801f5207b7SJohn Levon case EXPR_POSTOP: 2811f5207b7SJohn Levon if (expr->op == '&') 2821f5207b7SJohn Levon ret = fake_pointer_sym(expr); 2831f5207b7SJohn Levon else if (expr->op == '*') 2841f5207b7SJohn Levon ret = get_pointer_type(expr->unop); 2851f5207b7SJohn Levon else 2861f5207b7SJohn Levon ret = get_type(expr->unop); 2871f5207b7SJohn Levon break; 2881f5207b7SJohn Levon case EXPR_ASSIGNMENT: 2891f5207b7SJohn Levon ret = get_type(expr->left); 2901f5207b7SJohn Levon break; 2911f5207b7SJohn Levon case EXPR_CAST: 2921f5207b7SJohn Levon case EXPR_FORCE_CAST: 2931f5207b7SJohn Levon case EXPR_IMPLIED_CAST: 2941f5207b7SJohn Levon ret = get_real_base_type(expr->cast_type); 2951f5207b7SJohn Levon break; 2961f5207b7SJohn Levon case EXPR_COMPARE: 2971f5207b7SJohn Levon case EXPR_BINOP: 2981f5207b7SJohn Levon ret = get_binop_type(expr); 2991f5207b7SJohn Levon break; 3001f5207b7SJohn Levon case EXPR_CALL: 3011f5207b7SJohn Levon ret = get_return_type(expr); 3021f5207b7SJohn Levon break; 3031f5207b7SJohn Levon case EXPR_STATEMENT: 3041f5207b7SJohn Levon ret = get_expr_stmt_type(expr->statement); 3051f5207b7SJohn Levon break; 3061f5207b7SJohn Levon case EXPR_CONDITIONAL: 3071f5207b7SJohn Levon case EXPR_SELECT: 3081f5207b7SJohn Levon ret = get_select_type(expr); 3091f5207b7SJohn Levon break; 3101f5207b7SJohn Levon case EXPR_SIZEOF: 3111f5207b7SJohn Levon ret = &ulong_ctype; 3121f5207b7SJohn Levon break; 3131f5207b7SJohn Levon case EXPR_LOGICAL: 3141f5207b7SJohn Levon ret = &int_ctype; 3151f5207b7SJohn Levon break; 316efe51d0cSJohn Levon case EXPR_OFFSETOF: 317efe51d0cSJohn Levon ret = &ulong_ctype; 318efe51d0cSJohn Levon break; 3191f5207b7SJohn Levon default: 3201f5207b7SJohn Levon return NULL; 3211f5207b7SJohn Levon } 3221f5207b7SJohn Levon 3231f5207b7SJohn Levon if (ret && ret->type == SYM_TYPEOF) 3241f5207b7SJohn Levon ret = get_type(ret->initializer); 3251f5207b7SJohn Levon 3261f5207b7SJohn Levon expr->ctype = ret; 3271f5207b7SJohn Levon return ret; 3281f5207b7SJohn Levon } 3291f5207b7SJohn Levon 3301f5207b7SJohn Levon static struct symbol *get_final_type_helper(struct expression *expr) 3311f5207b7SJohn Levon { 3321f5207b7SJohn Levon /* 333efe51d0cSJohn Levon * The problem is that I wrote a bunch of Smatch to think that 334efe51d0cSJohn Levon * you could do get_type() on an expression and it would give 335efe51d0cSJohn Levon * you what the comparison was type promoted to. This is wrong 336efe51d0cSJohn Levon * but fixing it is a big of work... Hence this horrible hack. 3371f5207b7SJohn Levon * 3381f5207b7SJohn Levon */ 3391f5207b7SJohn Levon 3401f5207b7SJohn Levon expr = strip_parens(expr); 3411f5207b7SJohn Levon if (!expr) 3421f5207b7SJohn Levon return NULL; 3431f5207b7SJohn Levon 344efe51d0cSJohn Levon if (expr->type == EXPR_COMPARE) 3451f5207b7SJohn Levon return &int_ctype; 3461f5207b7SJohn Levon 3471f5207b7SJohn Levon return NULL; 3481f5207b7SJohn Levon } 3491f5207b7SJohn Levon 3501f5207b7SJohn Levon struct symbol *get_type(struct expression *expr) 3511f5207b7SJohn Levon { 3521f5207b7SJohn Levon return get_type_helper(expr); 3531f5207b7SJohn Levon } 3541f5207b7SJohn Levon 3551f5207b7SJohn Levon struct symbol *get_final_type(struct expression *expr) 3561f5207b7SJohn Levon { 3571f5207b7SJohn Levon struct symbol *ret; 3581f5207b7SJohn Levon 3591f5207b7SJohn Levon ret = get_final_type_helper(expr); 3601f5207b7SJohn Levon if (ret) 3611f5207b7SJohn Levon return ret; 3621f5207b7SJohn Levon return get_type_helper(expr); 3631f5207b7SJohn Levon } 3641f5207b7SJohn Levon 3651f5207b7SJohn Levon struct symbol *get_promoted_type(struct symbol *left, struct symbol *right) 3661f5207b7SJohn Levon { 3671f5207b7SJohn Levon struct symbol *ret = &int_ctype; 3681f5207b7SJohn Levon 3691f5207b7SJohn Levon if (type_positive_bits(left) > type_positive_bits(ret)) 3701f5207b7SJohn Levon ret = left; 3711f5207b7SJohn Levon if (type_positive_bits(right) > type_positive_bits(ret)) 3721f5207b7SJohn Levon ret = right; 3731f5207b7SJohn Levon 3741f5207b7SJohn Levon if (type_is_ptr(left)) 3751f5207b7SJohn Levon ret = left; 3761f5207b7SJohn Levon if (type_is_ptr(right)) 3771f5207b7SJohn Levon ret = right; 3781f5207b7SJohn Levon 3791f5207b7SJohn Levon return ret; 3801f5207b7SJohn Levon } 3811f5207b7SJohn Levon 3821f5207b7SJohn Levon int type_signed(struct symbol *base_type) 3831f5207b7SJohn Levon { 3841f5207b7SJohn Levon if (!base_type) 3851f5207b7SJohn Levon return 0; 3861f5207b7SJohn Levon if (base_type->ctype.modifiers & MOD_SIGNED) 3871f5207b7SJohn Levon return 1; 3881f5207b7SJohn Levon return 0; 3891f5207b7SJohn Levon } 3901f5207b7SJohn Levon 3911f5207b7SJohn Levon int expr_unsigned(struct expression *expr) 3921f5207b7SJohn Levon { 3931f5207b7SJohn Levon struct symbol *sym; 3941f5207b7SJohn Levon 3951f5207b7SJohn Levon sym = get_type(expr); 3961f5207b7SJohn Levon if (!sym) 3971f5207b7SJohn Levon return 0; 3981f5207b7SJohn Levon if (type_unsigned(sym)) 3991f5207b7SJohn Levon return 1; 4001f5207b7SJohn Levon return 0; 4011f5207b7SJohn Levon } 4021f5207b7SJohn Levon 4031f5207b7SJohn Levon int expr_signed(struct expression *expr) 4041f5207b7SJohn Levon { 4051f5207b7SJohn Levon struct symbol *sym; 4061f5207b7SJohn Levon 4071f5207b7SJohn Levon sym = get_type(expr); 4081f5207b7SJohn Levon if (!sym) 4091f5207b7SJohn Levon return 0; 4101f5207b7SJohn Levon if (type_signed(sym)) 4111f5207b7SJohn Levon return 1; 4121f5207b7SJohn Levon return 0; 4131f5207b7SJohn Levon } 4141f5207b7SJohn Levon 4151f5207b7SJohn Levon int returns_unsigned(struct symbol *sym) 4161f5207b7SJohn Levon { 4171f5207b7SJohn Levon if (!sym) 4181f5207b7SJohn Levon return 0; 4191f5207b7SJohn Levon sym = get_base_type(sym); 4201f5207b7SJohn Levon if (!sym || sym->type != SYM_FN) 4211f5207b7SJohn Levon return 0; 4221f5207b7SJohn Levon sym = get_base_type(sym); 4231f5207b7SJohn Levon return type_unsigned(sym); 4241f5207b7SJohn Levon } 4251f5207b7SJohn Levon 4261f5207b7SJohn Levon int is_pointer(struct expression *expr) 4271f5207b7SJohn Levon { 428efe51d0cSJohn Levon return type_is_ptr(get_type(expr)); 4291f5207b7SJohn Levon } 4301f5207b7SJohn Levon 4311f5207b7SJohn Levon int returns_pointer(struct symbol *sym) 4321f5207b7SJohn Levon { 4331f5207b7SJohn Levon if (!sym) 4341f5207b7SJohn Levon return 0; 4351f5207b7SJohn Levon sym = get_base_type(sym); 4361f5207b7SJohn Levon if (!sym || sym->type != SYM_FN) 4371f5207b7SJohn Levon return 0; 4381f5207b7SJohn Levon sym = get_base_type(sym); 439c85f09ccSJohn Levon if (sym && sym->type == SYM_PTR) 4401f5207b7SJohn Levon return 1; 4411f5207b7SJohn Levon return 0; 4421f5207b7SJohn Levon } 4431f5207b7SJohn Levon 444*5a0e240fSJohn Levon static sval_t fp_max(struct symbol *type) 445*5a0e240fSJohn Levon { 446*5a0e240fSJohn Levon sval_t ret = { .type = type }; 447*5a0e240fSJohn Levon 448*5a0e240fSJohn Levon if (type == &float_ctype) 449*5a0e240fSJohn Levon ret.fvalue = FLT_MAX; 450*5a0e240fSJohn Levon else if (type == &double_ctype) 451*5a0e240fSJohn Levon ret.dvalue = DBL_MAX; 452*5a0e240fSJohn Levon else 453*5a0e240fSJohn Levon ret.ldvalue = LDBL_MAX; 454*5a0e240fSJohn Levon 455*5a0e240fSJohn Levon return ret; 456*5a0e240fSJohn Levon } 457*5a0e240fSJohn Levon 4581f5207b7SJohn Levon sval_t sval_type_max(struct symbol *base_type) 4591f5207b7SJohn Levon { 4601f5207b7SJohn Levon sval_t ret; 4611f5207b7SJohn Levon 462*5a0e240fSJohn Levon if (type_is_fp(base_type)) 463*5a0e240fSJohn Levon return fp_max(base_type); 464*5a0e240fSJohn Levon 4651f5207b7SJohn Levon if (!base_type || !type_bits(base_type)) 4661f5207b7SJohn Levon base_type = &llong_ctype; 4671f5207b7SJohn Levon ret.type = base_type; 4681f5207b7SJohn Levon 4691f5207b7SJohn Levon ret.value = (~0ULL) >> (64 - type_positive_bits(base_type)); 4701f5207b7SJohn Levon return ret; 4711f5207b7SJohn Levon } 4721f5207b7SJohn Levon 473*5a0e240fSJohn Levon static sval_t fp_min(struct symbol *type) 474*5a0e240fSJohn Levon { 475*5a0e240fSJohn Levon sval_t ret = { .type = type }; 476*5a0e240fSJohn Levon 477*5a0e240fSJohn Levon if (type == &float_ctype) 478*5a0e240fSJohn Levon ret.fvalue = -FLT_MAX; 479*5a0e240fSJohn Levon else if (type == &double_ctype) 480*5a0e240fSJohn Levon ret.dvalue = -DBL_MAX; 481*5a0e240fSJohn Levon else 482*5a0e240fSJohn Levon ret.ldvalue = -LDBL_MAX; 483*5a0e240fSJohn Levon 484*5a0e240fSJohn Levon return ret; 485*5a0e240fSJohn Levon } 486*5a0e240fSJohn Levon 4871f5207b7SJohn Levon sval_t sval_type_min(struct symbol *base_type) 4881f5207b7SJohn Levon { 4891f5207b7SJohn Levon sval_t ret; 4901f5207b7SJohn Levon 491*5a0e240fSJohn Levon if (type_is_fp(base_type)) 492*5a0e240fSJohn Levon return fp_min(base_type); 493*5a0e240fSJohn Levon 4941f5207b7SJohn Levon if (!base_type || !type_bits(base_type)) 4951f5207b7SJohn Levon base_type = &llong_ctype; 4961f5207b7SJohn Levon ret.type = base_type; 4971f5207b7SJohn Levon 498efe51d0cSJohn Levon if (type_unsigned(base_type) || is_ptr_type(base_type)) { 4991f5207b7SJohn Levon ret.value = 0; 5001f5207b7SJohn Levon return ret; 5011f5207b7SJohn Levon } 5021f5207b7SJohn Levon 5031f5207b7SJohn Levon ret.value = (~0ULL) << type_positive_bits(base_type); 5041f5207b7SJohn Levon 5051f5207b7SJohn Levon return ret; 5061f5207b7SJohn Levon } 5071f5207b7SJohn Levon 5081f5207b7SJohn Levon int nr_bits(struct expression *expr) 5091f5207b7SJohn Levon { 5101f5207b7SJohn Levon struct symbol *type; 5111f5207b7SJohn Levon 5121f5207b7SJohn Levon type = get_type(expr); 5131f5207b7SJohn Levon if (!type) 5141f5207b7SJohn Levon return 0; 5151f5207b7SJohn Levon return type_bits(type); 5161f5207b7SJohn Levon } 5171f5207b7SJohn Levon 5181f5207b7SJohn Levon int is_void_pointer(struct expression *expr) 5191f5207b7SJohn Levon { 5201f5207b7SJohn Levon struct symbol *type; 5211f5207b7SJohn Levon 5221f5207b7SJohn Levon type = get_type(expr); 5231f5207b7SJohn Levon if (!type || type->type != SYM_PTR) 5241f5207b7SJohn Levon return 0; 5251f5207b7SJohn Levon type = get_real_base_type(type); 5261f5207b7SJohn Levon if (type == &void_ctype) 5271f5207b7SJohn Levon return 1; 5281f5207b7SJohn Levon return 0; 5291f5207b7SJohn Levon } 5301f5207b7SJohn Levon 5311f5207b7SJohn Levon int is_char_pointer(struct expression *expr) 5321f5207b7SJohn Levon { 5331f5207b7SJohn Levon struct symbol *type; 5341f5207b7SJohn Levon 5351f5207b7SJohn Levon type = get_type(expr); 5361f5207b7SJohn Levon if (!type || type->type != SYM_PTR) 5371f5207b7SJohn Levon return 0; 5381f5207b7SJohn Levon type = get_real_base_type(type); 5391f5207b7SJohn Levon if (type == &char_ctype) 5401f5207b7SJohn Levon return 1; 5411f5207b7SJohn Levon return 0; 5421f5207b7SJohn Levon } 5431f5207b7SJohn Levon 5441f5207b7SJohn Levon int is_string(struct expression *expr) 5451f5207b7SJohn Levon { 5461f5207b7SJohn Levon expr = strip_expr(expr); 5471f5207b7SJohn Levon if (!expr || expr->type != EXPR_STRING) 5481f5207b7SJohn Levon return 0; 5491f5207b7SJohn Levon if (expr->string) 5501f5207b7SJohn Levon return 1; 5511f5207b7SJohn Levon return 0; 5521f5207b7SJohn Levon } 5531f5207b7SJohn Levon 5541f5207b7SJohn Levon int is_static(struct expression *expr) 5551f5207b7SJohn Levon { 5561f5207b7SJohn Levon char *name; 5571f5207b7SJohn Levon struct symbol *sym; 5581f5207b7SJohn Levon int ret = 0; 5591f5207b7SJohn Levon 5601f5207b7SJohn Levon name = expr_to_str_sym(expr, &sym); 5611f5207b7SJohn Levon if (!name || !sym) 5621f5207b7SJohn Levon goto free; 5631f5207b7SJohn Levon 5641f5207b7SJohn Levon if (sym->ctype.modifiers & MOD_STATIC) 5651f5207b7SJohn Levon ret = 1; 5661f5207b7SJohn Levon free: 5671f5207b7SJohn Levon free_string(name); 5681f5207b7SJohn Levon return ret; 5691f5207b7SJohn Levon } 5701f5207b7SJohn Levon 571c85f09ccSJohn Levon bool is_local_variable(struct expression *expr) 5721f5207b7SJohn Levon { 5731f5207b7SJohn Levon struct symbol *sym; 5741f5207b7SJohn Levon 575c85f09ccSJohn Levon if (!expr || expr->type != EXPR_SYMBOL || !expr->symbol) 576c85f09ccSJohn Levon return false; 577c85f09ccSJohn Levon sym = expr->symbol; 578c85f09ccSJohn Levon if (!(sym->ctype.modifiers & MOD_TOPLEVEL)) 579c85f09ccSJohn Levon return true; 580c85f09ccSJohn Levon return false; 5811f5207b7SJohn Levon } 5821f5207b7SJohn Levon 5831f5207b7SJohn Levon int types_equiv(struct symbol *one, struct symbol *two) 5841f5207b7SJohn Levon { 5851f5207b7SJohn Levon if (!one && !two) 5861f5207b7SJohn Levon return 1; 5871f5207b7SJohn Levon if (!one || !two) 5881f5207b7SJohn Levon return 0; 5891f5207b7SJohn Levon if (one->type != two->type) 5901f5207b7SJohn Levon return 0; 5911f5207b7SJohn Levon if (one->type == SYM_PTR) 5921f5207b7SJohn Levon return types_equiv(get_real_base_type(one), get_real_base_type(two)); 5931f5207b7SJohn Levon if (type_positive_bits(one) != type_positive_bits(two)) 5941f5207b7SJohn Levon return 0; 5951f5207b7SJohn Levon return 1; 5961f5207b7SJohn Levon } 5971f5207b7SJohn Levon 5981f5207b7SJohn Levon int fn_static(void) 5991f5207b7SJohn Levon { 6001f5207b7SJohn Levon return !!(cur_func_sym->ctype.modifiers & MOD_STATIC); 6011f5207b7SJohn Levon } 6021f5207b7SJohn Levon 6031f5207b7SJohn Levon const char *global_static(void) 6041f5207b7SJohn Levon { 6051f5207b7SJohn Levon if (cur_func_sym->ctype.modifiers & MOD_STATIC) 6061f5207b7SJohn Levon return "static"; 6071f5207b7SJohn Levon else 6081f5207b7SJohn Levon return "global"; 6091f5207b7SJohn Levon } 6101f5207b7SJohn Levon 6111f5207b7SJohn Levon struct symbol *cur_func_return_type(void) 6121f5207b7SJohn Levon { 6131f5207b7SJohn Levon struct symbol *sym; 6141f5207b7SJohn Levon 6151f5207b7SJohn Levon sym = get_real_base_type(cur_func_sym); 6161f5207b7SJohn Levon if (!sym || sym->type != SYM_FN) 6171f5207b7SJohn Levon return NULL; 6181f5207b7SJohn Levon sym = get_real_base_type(sym); 6191f5207b7SJohn Levon return sym; 6201f5207b7SJohn Levon } 6211f5207b7SJohn Levon 6221f5207b7SJohn Levon struct symbol *get_arg_type(struct expression *fn, int arg) 6231f5207b7SJohn Levon { 6241f5207b7SJohn Levon struct symbol *fn_type; 6251f5207b7SJohn Levon struct symbol *tmp; 6261f5207b7SJohn Levon struct symbol *arg_type; 6271f5207b7SJohn Levon int i; 6281f5207b7SJohn Levon 6291f5207b7SJohn Levon fn_type = get_type(fn); 6301f5207b7SJohn Levon if (!fn_type) 6311f5207b7SJohn Levon return NULL; 6321f5207b7SJohn Levon if (fn_type->type == SYM_PTR) 6331f5207b7SJohn Levon fn_type = get_real_base_type(fn_type); 6341f5207b7SJohn Levon if (fn_type->type != SYM_FN) 6351f5207b7SJohn Levon return NULL; 6361f5207b7SJohn Levon 6371f5207b7SJohn Levon i = 0; 6381f5207b7SJohn Levon FOR_EACH_PTR(fn_type->arguments, tmp) { 6391f5207b7SJohn Levon arg_type = get_real_base_type(tmp); 6401f5207b7SJohn Levon if (i == arg) { 6411f5207b7SJohn Levon return arg_type; 6421f5207b7SJohn Levon } 6431f5207b7SJohn Levon i++; 6441f5207b7SJohn Levon } END_FOR_EACH_PTR(tmp); 6451f5207b7SJohn Levon 6461f5207b7SJohn Levon return NULL; 6471f5207b7SJohn Levon } 6481f5207b7SJohn Levon 6491f5207b7SJohn Levon static struct symbol *get_member_from_string(struct symbol_list *symbol_list, const char *name) 6501f5207b7SJohn Levon { 6511f5207b7SJohn Levon struct symbol *tmp, *sub; 6521f5207b7SJohn Levon int chunk_len; 6531f5207b7SJohn Levon 6541f5207b7SJohn Levon if (strncmp(name, ".", 1) == 0) 6551f5207b7SJohn Levon name += 1; 656efe51d0cSJohn Levon else if (strncmp(name, "->", 2) == 0) 6571f5207b7SJohn Levon name += 2; 6581f5207b7SJohn Levon 6591f5207b7SJohn Levon FOR_EACH_PTR(symbol_list, tmp) { 6601f5207b7SJohn Levon if (!tmp->ident) { 6611f5207b7SJohn Levon sub = get_real_base_type(tmp); 6621f5207b7SJohn Levon sub = get_member_from_string(sub->symbol_list, name); 6631f5207b7SJohn Levon if (sub) 6641f5207b7SJohn Levon return sub; 6651f5207b7SJohn Levon continue; 6661f5207b7SJohn Levon } 6671f5207b7SJohn Levon 6681f5207b7SJohn Levon if (strcmp(tmp->ident->name, name) == 0) 6691f5207b7SJohn Levon return tmp; 6701f5207b7SJohn Levon 671efe51d0cSJohn Levon chunk_len = tmp->ident->len; 6721f5207b7SJohn Levon if (strncmp(tmp->ident->name, name, chunk_len) == 0 && 6731f5207b7SJohn Levon (name[chunk_len] == '.' || name[chunk_len] == '-')) { 6741f5207b7SJohn Levon sub = get_real_base_type(tmp); 675efe51d0cSJohn Levon if (sub->type == SYM_PTR) 676efe51d0cSJohn Levon sub = get_real_base_type(sub); 6771f5207b7SJohn Levon return get_member_from_string(sub->symbol_list, name + chunk_len); 6781f5207b7SJohn Levon } 6791f5207b7SJohn Levon 6801f5207b7SJohn Levon } END_FOR_EACH_PTR(tmp); 6811f5207b7SJohn Levon 6821f5207b7SJohn Levon return NULL; 6831f5207b7SJohn Levon } 6841f5207b7SJohn Levon 6851f5207b7SJohn Levon struct symbol *get_member_type_from_key(struct expression *expr, const char *key) 6861f5207b7SJohn Levon { 6871f5207b7SJohn Levon struct symbol *sym; 6881f5207b7SJohn Levon 6891f5207b7SJohn Levon if (strcmp(key, "$") == 0) 6901f5207b7SJohn Levon return get_type(expr); 6911f5207b7SJohn Levon 6921f5207b7SJohn Levon if (strcmp(key, "*$") == 0) { 6931f5207b7SJohn Levon sym = get_type(expr); 6941f5207b7SJohn Levon if (!sym || sym->type != SYM_PTR) 6951f5207b7SJohn Levon return NULL; 6961f5207b7SJohn Levon return get_real_base_type(sym); 6971f5207b7SJohn Levon } 6981f5207b7SJohn Levon 6991f5207b7SJohn Levon sym = get_type(expr); 7001f5207b7SJohn Levon if (!sym) 7011f5207b7SJohn Levon return NULL; 7021f5207b7SJohn Levon if (sym->type == SYM_PTR) 7031f5207b7SJohn Levon sym = get_real_base_type(sym); 7041f5207b7SJohn Levon 7051f5207b7SJohn Levon key = key + 1; 7061f5207b7SJohn Levon sym = get_member_from_string(sym->symbol_list, key); 7071f5207b7SJohn Levon if (!sym) 7081f5207b7SJohn Levon return NULL; 7091f5207b7SJohn Levon return get_real_base_type(sym); 7101f5207b7SJohn Levon } 7111f5207b7SJohn Levon 7121f5207b7SJohn Levon struct symbol *get_arg_type_from_key(struct expression *fn, int param, struct expression *arg, const char *key) 7131f5207b7SJohn Levon { 7141f5207b7SJohn Levon struct symbol *type; 7151f5207b7SJohn Levon 7161f5207b7SJohn Levon if (!key) 7171f5207b7SJohn Levon return NULL; 7181f5207b7SJohn Levon if (strcmp(key, "$") == 0) 7191f5207b7SJohn Levon return get_arg_type(fn, param); 7201f5207b7SJohn Levon if (strcmp(key, "*$") == 0) { 7211f5207b7SJohn Levon type = get_arg_type(fn, param); 7221f5207b7SJohn Levon if (!type || type->type != SYM_PTR) 7231f5207b7SJohn Levon return NULL; 7241f5207b7SJohn Levon return get_real_base_type(type); 7251f5207b7SJohn Levon } 7261f5207b7SJohn Levon return get_member_type_from_key(arg, key); 7271f5207b7SJohn Levon } 7281f5207b7SJohn Levon 7291f5207b7SJohn Levon int is_struct(struct expression *expr) 7301f5207b7SJohn Levon { 7311f5207b7SJohn Levon struct symbol *type; 7321f5207b7SJohn Levon 7331f5207b7SJohn Levon type = get_type(expr); 7341f5207b7SJohn Levon if (type && type->type == SYM_STRUCT) 7351f5207b7SJohn Levon return 1; 7361f5207b7SJohn Levon return 0; 7371f5207b7SJohn Levon } 7381f5207b7SJohn Levon 7391f5207b7SJohn Levon static struct { 7401f5207b7SJohn Levon struct symbol *sym; 7411f5207b7SJohn Levon const char *name; 7421f5207b7SJohn Levon } base_types[] = { 7431f5207b7SJohn Levon {&bool_ctype, "bool"}, 7441f5207b7SJohn Levon {&void_ctype, "void"}, 7451f5207b7SJohn Levon {&type_ctype, "type"}, 7461f5207b7SJohn Levon {&char_ctype, "char"}, 7471f5207b7SJohn Levon {&schar_ctype, "schar"}, 7481f5207b7SJohn Levon {&uchar_ctype, "uchar"}, 7491f5207b7SJohn Levon {&short_ctype, "short"}, 7501f5207b7SJohn Levon {&sshort_ctype, "sshort"}, 7511f5207b7SJohn Levon {&ushort_ctype, "ushort"}, 7521f5207b7SJohn Levon {&int_ctype, "int"}, 7531f5207b7SJohn Levon {&sint_ctype, "sint"}, 7541f5207b7SJohn Levon {&uint_ctype, "uint"}, 7551f5207b7SJohn Levon {&long_ctype, "long"}, 7561f5207b7SJohn Levon {&slong_ctype, "slong"}, 7571f5207b7SJohn Levon {&ulong_ctype, "ulong"}, 7581f5207b7SJohn Levon {&llong_ctype, "llong"}, 7591f5207b7SJohn Levon {&sllong_ctype, "sllong"}, 7601f5207b7SJohn Levon {&ullong_ctype, "ullong"}, 7611f5207b7SJohn Levon {&lllong_ctype, "lllong"}, 7621f5207b7SJohn Levon {&slllong_ctype, "slllong"}, 7631f5207b7SJohn Levon {&ulllong_ctype, "ulllong"}, 7641f5207b7SJohn Levon {&float_ctype, "float"}, 7651f5207b7SJohn Levon {&double_ctype, "double"}, 7661f5207b7SJohn Levon {&ldouble_ctype, "ldouble"}, 7671f5207b7SJohn Levon {&string_ctype, "string"}, 7681f5207b7SJohn Levon {&ptr_ctype, "ptr"}, 7691f5207b7SJohn Levon {&lazy_ptr_ctype, "lazy_ptr"}, 7701f5207b7SJohn Levon {&incomplete_ctype, "incomplete"}, 7711f5207b7SJohn Levon {&label_ctype, "label"}, 7721f5207b7SJohn Levon {&bad_ctype, "bad"}, 7731f5207b7SJohn Levon {&null_ctype, "null"}, 7741f5207b7SJohn Levon }; 7751f5207b7SJohn Levon 7761f5207b7SJohn Levon static const char *base_type_str(struct symbol *sym) 7771f5207b7SJohn Levon { 7781f5207b7SJohn Levon int i; 7791f5207b7SJohn Levon 7801f5207b7SJohn Levon for (i = 0; i < ARRAY_SIZE(base_types); i++) { 7811f5207b7SJohn Levon if (sym == base_types[i].sym) 7821f5207b7SJohn Levon return base_types[i].name; 7831f5207b7SJohn Levon } 7841f5207b7SJohn Levon return "<unknown>"; 7851f5207b7SJohn Levon } 7861f5207b7SJohn Levon 7871f5207b7SJohn Levon static int type_str_helper(char *buf, int size, struct symbol *type) 7881f5207b7SJohn Levon { 7891f5207b7SJohn Levon int n; 7901f5207b7SJohn Levon 7911f5207b7SJohn Levon if (!type) 7921f5207b7SJohn Levon return snprintf(buf, size, "<unknown>"); 7931f5207b7SJohn Levon 7941f5207b7SJohn Levon if (type->type == SYM_BASETYPE) { 795efe51d0cSJohn Levon return snprintf(buf, size, "%s", base_type_str(type)); 7961f5207b7SJohn Levon } else if (type->type == SYM_PTR) { 7971f5207b7SJohn Levon type = get_real_base_type(type); 7981f5207b7SJohn Levon n = type_str_helper(buf, size, type); 7991f5207b7SJohn Levon if (n > size) 8001f5207b7SJohn Levon return n; 8011f5207b7SJohn Levon return n + snprintf(buf + n, size - n, "*"); 8021f5207b7SJohn Levon } else if (type->type == SYM_ARRAY) { 8031f5207b7SJohn Levon type = get_real_base_type(type); 8041f5207b7SJohn Levon n = type_str_helper(buf, size, type); 8051f5207b7SJohn Levon if (n > size) 8061f5207b7SJohn Levon return n; 8071f5207b7SJohn Levon return n + snprintf(buf + n, size - n, "[]"); 8081f5207b7SJohn Levon } else if (type->type == SYM_STRUCT) { 8091f5207b7SJohn Levon return snprintf(buf, size, "struct %s", type->ident ? type->ident->name : ""); 8101f5207b7SJohn Levon } else if (type->type == SYM_UNION) { 8111f5207b7SJohn Levon if (type->ident) 8121f5207b7SJohn Levon return snprintf(buf, size, "union %s", type->ident->name); 8131f5207b7SJohn Levon else 8141f5207b7SJohn Levon return snprintf(buf, size, "anonymous union"); 8151f5207b7SJohn Levon } else if (type->type == SYM_FN) { 8161f5207b7SJohn Levon struct symbol *arg, *return_type, *arg_type; 8171f5207b7SJohn Levon int i; 8181f5207b7SJohn Levon 8191f5207b7SJohn Levon return_type = get_real_base_type(type); 8201f5207b7SJohn Levon n = type_str_helper(buf, size, return_type); 8211f5207b7SJohn Levon if (n > size) 8221f5207b7SJohn Levon return n; 8231f5207b7SJohn Levon n += snprintf(buf + n, size - n, "(*)("); 8241f5207b7SJohn Levon if (n > size) 8251f5207b7SJohn Levon return n; 8261f5207b7SJohn Levon 8271f5207b7SJohn Levon i = 0; 8281f5207b7SJohn Levon FOR_EACH_PTR(type->arguments, arg) { 8291f5207b7SJohn Levon if (i++) 8301f5207b7SJohn Levon n += snprintf(buf + n, size - n, ", "); 8311f5207b7SJohn Levon if (n > size) 8321f5207b7SJohn Levon return n; 8331f5207b7SJohn Levon arg_type = get_real_base_type(arg); 8341f5207b7SJohn Levon n += type_str_helper(buf + n, size - n, arg_type); 8351f5207b7SJohn Levon if (n > size) 8361f5207b7SJohn Levon return n; 8371f5207b7SJohn Levon } END_FOR_EACH_PTR(arg); 8381f5207b7SJohn Levon 8391f5207b7SJohn Levon return n + snprintf(buf + n, size - n, ")"); 8401f5207b7SJohn Levon } else if (type->type == SYM_NODE) { 8411f5207b7SJohn Levon n = snprintf(buf, size, "node {"); 8421f5207b7SJohn Levon if (n > size) 8431f5207b7SJohn Levon return n; 8441f5207b7SJohn Levon type = get_real_base_type(type); 8451f5207b7SJohn Levon n += type_str_helper(buf + n, size - n, type); 8461f5207b7SJohn Levon if (n > size) 8471f5207b7SJohn Levon return n; 8481f5207b7SJohn Levon return n + snprintf(buf + n, size - n, "}"); 849efe51d0cSJohn Levon } else if (type->type == SYM_ENUM) { 850efe51d0cSJohn Levon return snprintf(buf, size, "enum %s", type->ident ? type->ident->name : "<unknown>"); 8511f5207b7SJohn Levon } else { 8521f5207b7SJohn Levon return snprintf(buf, size, "<type %d>", type->type); 8531f5207b7SJohn Levon } 8541f5207b7SJohn Levon } 8551f5207b7SJohn Levon 8561f5207b7SJohn Levon char *type_to_str(struct symbol *type) 8571f5207b7SJohn Levon { 8581f5207b7SJohn Levon static char buf[256]; 8591f5207b7SJohn Levon 8601f5207b7SJohn Levon buf[0] = '\0'; 8611f5207b7SJohn Levon type_str_helper(buf, sizeof(buf), type); 8621f5207b7SJohn Levon return buf; 8631f5207b7SJohn Levon } 864