bogus_address_param: warn about passing a bogus address
[smatch.git] / smatch_type.c
blob6bdcf531338156bd5225010de6aef6cb65ce24c2
1 /*
2 * Copyright (C) 2009 Dan Carpenter.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
19 * The idea here is that you have an expression and you
20 * want to know what the type is for that.
23 #include <ctype.h>
24 #include "smatch.h"
25 #include "smatch_slist.h"
27 struct symbol *get_real_base_type(struct symbol *sym)
29 struct symbol *ret;
31 if (!sym)
32 return NULL;
33 if (sym->type == SYM_BASETYPE)
34 return sym;
35 ret = get_base_type(sym);
36 if (!ret)
37 return NULL;
38 if (ret->type == SYM_RESTRICT || ret->type == SYM_NODE)
39 return get_real_base_type(ret);
40 return ret;
43 int type_bytes(struct symbol *type)
45 int bits;
47 if (type && type->type == SYM_ARRAY)
48 return array_bytes(type);
50 bits = type_bits(type);
51 if (bits < 0)
52 return 0;
53 return bits_to_bytes(bits);
56 int array_bytes(struct symbol *type)
58 if (!type || type->type != SYM_ARRAY)
59 return 0;
60 if (!type->array_size)
61 return 0;
62 return bits_to_bytes(type->bit_size);
65 static struct symbol *get_binop_type(struct expression *expr)
67 struct symbol *left, *right;
69 left = get_type(expr->left);
70 if (!left)
71 return NULL;
73 if (expr->op == SPECIAL_LEFTSHIFT ||
74 expr->op == SPECIAL_RIGHTSHIFT) {
75 if (type_positive_bits(left) < 31)
76 return &int_ctype;
77 return left;
79 right = get_type(expr->right);
80 if (!right)
81 return NULL;
83 if (type_is_fp(left)) {
84 if (type_is_fp(right)) {
85 if (type_bits(left) > type_bits(right))
86 return left;
87 return right;
89 return left;
92 if (type_is_fp(right)) {
93 if (type_is_fp(left)) {
94 if (type_bits(right) > type_bits(left))
95 return right;
96 return left;
98 return right;
101 if (expr->op == '-' &&
102 (is_ptr_type(left) && is_ptr_type(right)))
103 return ssize_t_ctype;
105 if (left->type == SYM_PTR || left->type == SYM_ARRAY)
106 return left;
107 if (right->type == SYM_PTR || right->type == SYM_ARRAY)
108 return right;
110 if (type_positive_bits(left) < 31 && type_positive_bits(right) < 31)
111 return &int_ctype;
113 if (type_positive_bits(left) > type_positive_bits(right))
114 return left;
115 return right;
118 static struct symbol *get_type_symbol(struct expression *expr)
120 if (!expr || expr->type != EXPR_SYMBOL || !expr->symbol)
121 return NULL;
123 return get_real_base_type(expr->symbol);
126 static struct symbol *get_member_symbol(struct symbol_list *symbol_list, struct ident *member)
128 struct symbol *tmp, *sub;
130 FOR_EACH_PTR(symbol_list, tmp) {
131 if (!tmp->ident) {
132 sub = get_real_base_type(tmp);
133 sub = get_member_symbol(sub->symbol_list, member);
134 if (sub)
135 return sub;
136 continue;
138 if (tmp->ident == member)
139 return tmp;
140 } END_FOR_EACH_PTR(tmp);
142 return NULL;
145 static struct symbol *get_symbol_from_deref(struct expression *expr)
147 struct ident *member;
148 struct symbol *sym;
150 if (!expr || expr->type != EXPR_DEREF)
151 return NULL;
153 member = expr->member;
154 sym = get_type(expr->deref);
155 if (!sym) {
156 // sm_msg("could not find struct type");
157 return NULL;
159 if (sym->type == SYM_PTR)
160 sym = get_real_base_type(sym);
161 sym = get_member_symbol(sym->symbol_list, member);
162 if (!sym)
163 return NULL;
164 return get_real_base_type(sym);
167 static struct symbol *handle__builtin_choose_expr(struct expression *expr)
169 struct expression *const_expr, *expr1, *expr2;
170 sval_t sval;
172 const_expr = get_argument_from_call_expr(expr->args, 0);
173 expr1 = get_argument_from_call_expr(expr->args, 1);
174 expr2 = get_argument_from_call_expr(expr->args, 2);
176 if (!get_value(const_expr, &sval) || !expr1 || !expr2)
177 return NULL;
178 if (sval.value)
179 return get_type(expr1);
180 else
181 return get_type(expr2);
184 static struct symbol *get_return_type(struct expression *expr)
186 struct symbol *tmp;
188 if (sym_name_is("__builtin_choose_expr", expr->fn))
189 return handle__builtin_choose_expr(expr);
191 tmp = get_type(expr->fn);
192 if (!tmp)
193 return NULL;
194 /* this is to handle __builtin_constant_p() */
195 if (tmp->type != SYM_FN)
196 tmp = get_base_type(tmp);
197 return get_real_base_type(tmp);
200 static struct symbol *get_expr_stmt_type(struct statement *stmt)
202 if (stmt->type != STMT_COMPOUND)
203 return NULL;
204 stmt = last_ptr_list((struct ptr_list *)stmt->stmts);
205 if (stmt->type == STMT_LABEL)
206 stmt = stmt->label_statement;
207 if (stmt->type != STMT_EXPRESSION)
208 return NULL;
209 return get_type(stmt->expression);
212 static struct symbol *get_select_type(struct expression *expr)
214 struct symbol *one, *two;
216 one = get_type(expr->cond_true);
217 two = get_type(expr->cond_false);
218 if (!one || !two)
219 return NULL;
221 * This is a hack. If the types are not equiv then we
222 * really don't know the type. But I think guessing is
223 * probably Ok here.
225 if (type_positive_bits(one) > type_positive_bits(two))
226 return one;
227 return two;
230 struct symbol *get_pointer_type(struct expression *expr)
232 struct symbol *sym;
234 sym = get_type(expr);
235 if (!sym)
236 return NULL;
237 if (sym->type == SYM_NODE) {
238 sym = get_real_base_type(sym);
239 if (!sym)
240 return NULL;
242 if (sym->type != SYM_PTR && sym->type != SYM_ARRAY)
243 return NULL;
244 return get_real_base_type(sym);
247 static struct symbol *fake_pointer_sym(struct expression *expr)
249 struct symbol *sym;
250 struct symbol *base;
252 sym = alloc_symbol(expr->pos, SYM_PTR);
253 expr = expr->unop;
254 base = get_type(expr);
255 if (!base)
256 return NULL;
257 sym->ctype.base_type = base;
258 return sym;
261 static struct symbol *get_type_helper(struct expression *expr)
263 struct symbol *ret;
265 expr = strip_parens(expr);
266 if (!expr)
267 return NULL;
269 if (expr->ctype)
270 return expr->ctype;
272 switch (expr->type) {
273 case EXPR_STRING:
274 ret = &string_ctype;
275 break;
276 case EXPR_SYMBOL:
277 ret = get_type_symbol(expr);
278 break;
279 case EXPR_DEREF:
280 ret = get_symbol_from_deref(expr);
281 break;
282 case EXPR_PREOP:
283 case EXPR_POSTOP:
284 if (expr->op == '&')
285 ret = fake_pointer_sym(expr);
286 else if (expr->op == '*')
287 ret = get_pointer_type(expr->unop);
288 else
289 ret = get_type(expr->unop);
290 break;
291 case EXPR_ASSIGNMENT:
292 ret = get_type(expr->left);
293 break;
294 case EXPR_CAST:
295 case EXPR_FORCE_CAST:
296 case EXPR_IMPLIED_CAST:
297 ret = get_real_base_type(expr->cast_type);
298 break;
299 case EXPR_COMPARE:
300 case EXPR_BINOP:
301 ret = get_binop_type(expr);
302 break;
303 case EXPR_CALL:
304 ret = get_return_type(expr);
305 break;
306 case EXPR_STATEMENT:
307 ret = get_expr_stmt_type(expr->statement);
308 break;
309 case EXPR_CONDITIONAL:
310 case EXPR_SELECT:
311 ret = get_select_type(expr);
312 break;
313 case EXPR_SIZEOF:
314 ret = &ulong_ctype;
315 break;
316 case EXPR_LOGICAL:
317 ret = &int_ctype;
318 break;
319 case EXPR_OFFSETOF:
320 ret = &ulong_ctype;
321 break;
322 case EXPR_GENERIC:
323 return get_type_helper(strip_Generic(expr));
324 default:
325 return NULL;
328 if (ret && ret->type == SYM_TYPEOF)
329 ret = get_type(ret->initializer);
331 expr->ctype = ret;
332 return ret;
335 static struct symbol *get_final_type_helper(struct expression *expr)
338 * The problem is that I wrote a bunch of Smatch to think that
339 * you could do get_type() on an expression and it would give
340 * you what the comparison was type promoted to. This is wrong
341 * but fixing it is a big of work... Hence this horrible hack.
345 expr = strip_parens(expr);
346 if (!expr)
347 return NULL;
349 if (expr->type == EXPR_COMPARE)
350 return &int_ctype;
351 if (expr->type == EXPR_PREOP && expr->op == '!')
352 return &int_ctype;
354 return NULL;
357 struct symbol *get_type(struct expression *expr)
359 return get_type_helper(expr);
362 struct symbol *get_comparison_type(struct expression *expr)
365 * Eventually we will probably have to figure out how to make get_type()
366 * return &int_ctype so let's create a helper function to transition to.
368 return get_type_helper(expr);
371 struct symbol *get_final_type(struct expression *expr)
373 struct symbol *ret;
375 ret = get_final_type_helper(expr);
376 if (ret)
377 return ret;
378 return get_type_helper(expr);
381 struct symbol *get_promoted_type(struct symbol *left, struct symbol *right)
383 struct symbol *ret = &int_ctype;
385 if (type_positive_bits(left) > type_positive_bits(ret))
386 ret = left;
387 if (type_positive_bits(right) > type_positive_bits(ret))
388 ret = right;
390 if (type_is_ptr(left))
391 ret = left;
392 if (type_is_ptr(right))
393 ret = right;
395 return ret;
398 int type_signed(struct symbol *base_type)
400 if (!base_type)
401 return 0;
402 if (base_type->ctype.modifiers & MOD_SIGNED)
403 return 1;
404 return 0;
407 int expr_unsigned(struct expression *expr)
409 struct symbol *sym;
411 sym = get_type(expr);
412 if (!sym)
413 return 0;
414 if (type_unsigned(sym))
415 return 1;
416 return 0;
419 int expr_signed(struct expression *expr)
421 struct symbol *sym;
423 sym = get_type(expr);
424 if (!sym)
425 return 0;
426 if (type_signed(sym))
427 return 1;
428 return 0;
431 int returns_unsigned(struct symbol *sym)
433 if (!sym)
434 return 0;
435 sym = get_base_type(sym);
436 if (!sym || sym->type != SYM_FN)
437 return 0;
438 sym = get_base_type(sym);
439 return type_unsigned(sym);
442 int is_pointer(struct expression *expr)
444 return type_is_ptr(get_final_type(expr));
447 bool is_void_ptr(struct symbol *type)
449 if (!type)
450 return false;
451 if (type->type != SYM_PTR)
452 return false;
453 type = get_real_base_type(type);
455 return types_equiv(type, &void_ctype);
458 int returns_pointer(struct symbol *sym)
460 if (!sym)
461 return 0;
462 sym = get_base_type(sym);
463 if (!sym || sym->type != SYM_FN)
464 return 0;
465 sym = get_base_type(sym);
466 if (sym && sym->type == SYM_PTR)
467 return 1;
468 return 0;
471 static sval_t fp_max(struct symbol *type)
473 sval_t ret = { .type = type };
475 if (type == &float_ctype)
476 ret.fvalue = FLT_MAX;
477 else if (type == &double_ctype)
478 ret.dvalue = DBL_MAX;
479 else
480 ret.ldvalue = LDBL_MAX;
482 return ret;
485 sval_t sval_type_max(struct symbol *base_type)
487 sval_t ret;
489 if (type_is_fp(base_type))
490 return fp_max(base_type);
492 if (!base_type || !type_bits(base_type))
493 base_type = &llong_ctype;
494 ret.type = base_type;
496 ret.value = (~0ULL) >> (64 - type_positive_bits(base_type));
497 return ret;
500 static sval_t fp_min(struct symbol *type)
502 sval_t ret = { .type = type };
504 if (type == &float_ctype)
505 ret.fvalue = -FLT_MAX;
506 else if (type == &double_ctype)
507 ret.dvalue = -DBL_MAX;
508 else
509 ret.ldvalue = -LDBL_MAX;
511 return ret;
514 sval_t sval_type_min(struct symbol *base_type)
516 sval_t ret;
518 if (type_is_fp(base_type))
519 return fp_min(base_type);
521 if (!base_type || !type_bits(base_type))
522 base_type = &llong_ctype;
523 ret.type = base_type;
525 if (type_unsigned(base_type) || is_ptr_type(base_type)) {
526 ret.value = 0;
527 return ret;
530 ret.value = (~0ULL) << type_positive_bits(base_type);
532 return ret;
535 int nr_bits(struct expression *expr)
537 struct symbol *type;
539 type = get_type(expr);
540 if (!type)
541 return 0;
542 return type_bits(type);
545 int is_void_pointer(struct expression *expr)
547 struct symbol *type;
549 type = get_type(expr);
550 if (!type || type->type != SYM_PTR)
551 return 0;
552 type = get_real_base_type(type);
553 if (type == &void_ctype)
554 return 1;
555 return 0;
558 int is_char_pointer(struct expression *expr)
560 struct symbol *type;
562 type = get_type(expr);
563 if (!type || type->type != SYM_PTR)
564 return 0;
565 type = get_real_base_type(type);
566 if (type == &char_ctype)
567 return 1;
568 return 0;
571 int is_string(struct expression *expr)
573 expr = strip_expr(expr);
574 if (!expr || expr->type != EXPR_STRING)
575 return 0;
576 if (expr->string)
577 return 1;
578 return 0;
581 bool is_struct_ptr(struct symbol *type)
583 if (!type || type->type != SYM_PTR)
584 return false;
585 type = get_real_base_type(type);
586 if (!type || type->type != SYM_STRUCT)
587 return false;
588 return true;
591 int is_static(struct expression *expr)
593 char *name;
594 struct symbol *sym;
595 int ret = 0;
597 name = expr_to_str_sym(expr, &sym);
598 if (!name || !sym)
599 goto free;
601 if (sym->ctype.modifiers & MOD_STATIC)
602 ret = 1;
603 free:
604 free_string(name);
605 return ret;
608 static struct expression *get_symbol_expr(struct expression *expr)
610 if (!expr)
611 return NULL;
612 while (expr && expr->type == EXPR_DEREF && expr->op == '.')
613 expr = strip_expr(expr->deref);
614 return expr;
617 bool is_local_variable(struct expression *expr)
619 struct symbol *sym;
621 expr = get_symbol_expr(expr);
622 if (!expr || expr->type != EXPR_SYMBOL || !expr->symbol)
623 return false;
624 sym = expr->symbol;
625 if (!(sym->ctype.modifiers & MOD_TOPLEVEL))
626 return true;
627 return false;
630 int types_equiv(struct symbol *one, struct symbol *two)
632 if (!one && !two)
633 return 1;
634 if (!one || !two)
635 return 0;
636 if (one->type != two->type)
637 return 0;
638 if (one->type == SYM_PTR)
639 return types_equiv(get_real_base_type(one), get_real_base_type(two));
640 if (type_positive_bits(one) != type_positive_bits(two))
641 return 0;
642 return 1;
645 bool type_fits(struct symbol *type, struct symbol *test)
647 if (!type || !test)
648 return false;
650 if (type == test)
651 return true;
653 if (type_bits(test) > type_bits(type))
654 return false;
655 if (type_signed(test) && !type_signed(type))
656 return false;
657 if (type_positive_bits(test) > type_positive_bits(type))
658 return false;
659 return true;
662 int fn_static(void)
664 return !!(cur_func_sym->ctype.modifiers & MOD_STATIC);
667 const char *global_static(void)
669 if (cur_func_sym->ctype.modifiers & MOD_STATIC)
670 return "static";
671 else
672 return "global";
675 struct symbol *cur_func_return_type(void)
677 struct symbol *sym;
679 sym = get_real_base_type(cur_func_sym);
680 if (!sym || sym->type != SYM_FN)
681 return NULL;
682 sym = get_real_base_type(sym);
683 return sym;
686 struct symbol *get_arg_type(struct expression *fn, int arg)
688 struct symbol *fn_type;
689 struct symbol *tmp;
690 struct symbol *arg_type;
691 int i;
693 fn_type = get_type(fn);
694 if (!fn_type)
695 return NULL;
696 if (fn_type->type == SYM_PTR)
697 fn_type = get_real_base_type(fn_type);
698 if (fn_type->type != SYM_FN)
699 return NULL;
701 i = 0;
702 FOR_EACH_PTR(fn_type->arguments, tmp) {
703 arg_type = get_real_base_type(tmp);
704 if (i == arg) {
705 return arg_type;
707 i++;
708 } END_FOR_EACH_PTR(tmp);
710 return NULL;
713 static struct symbol *get_member_from_string(struct symbol_list *symbol_list, const char *name)
715 struct symbol *tmp, *sub;
716 int chunk_len;
718 if (strncmp(name, ".", 1) == 0)
719 name += 1;
720 else if (strncmp(name, "->", 2) == 0)
721 name += 2;
723 FOR_EACH_PTR(symbol_list, tmp) {
724 if (!tmp->ident) {
725 sub = get_real_base_type(tmp);
726 sub = get_member_from_string(sub->symbol_list, name);
727 if (sub)
728 return sub;
729 continue;
732 if (strcmp(tmp->ident->name, name) == 0)
733 return tmp;
735 chunk_len = tmp->ident->len;
736 if (strncmp(tmp->ident->name, name, chunk_len) == 0 &&
737 (name[chunk_len] == '.' || name[chunk_len] == '-')) {
738 sub = get_real_base_type(tmp);
739 if (sub->type == SYM_PTR)
740 sub = get_real_base_type(sub);
741 return get_member_from_string(sub->symbol_list, name + chunk_len);
744 } END_FOR_EACH_PTR(tmp);
746 return NULL;
749 static struct symbol *get_type_from_container_of_key(struct expression *expr, const char *key)
751 char *new_key;
753 expr = map_container_of_to_simpler_expr_key(expr, key, &new_key);
754 if (!expr)
755 return NULL;
756 return get_member_type_from_key(expr, new_key);
759 struct symbol *get_member_type_from_key(struct expression *expr, const char *key)
761 struct symbol *sym;
762 int star = 0;
763 int i;
765 if (strcmp(key, "$") == 0)
766 return get_type(expr);
768 if (strcmp(key, "*$") == 0) {
769 sym = get_type(expr);
770 if (!sym)
771 return NULL;
772 if (sym->type != SYM_PTR && sym->type != SYM_ARRAY)
773 return NULL;
774 return get_real_base_type(sym);
777 if (strstr(key, "<~$"))
778 return get_type_from_container_of_key(expr, key);
780 sym = get_type(expr);
781 if (!sym)
782 return NULL;
783 if (sym->type == SYM_PTR)
784 sym = get_real_base_type(sym);
786 while (*key == '*') {
787 key++;
788 star++;
791 if (*key != '$')
792 return NULL;
793 key++;
795 sym = get_member_from_string(sym->symbol_list, key);
796 if (!sym)
797 return NULL;
798 if (sym->type == SYM_RESTRICT || sym->type == SYM_NODE)
799 sym = get_real_base_type(sym);
800 for (i = 0; i < star; i++) {
801 if (!sym || sym->type != SYM_PTR)
802 return NULL;
803 sym = get_real_base_type(sym);
805 return sym;
808 struct symbol *get_arg_type_from_key(struct expression *fn, int param, struct expression *arg, const char *key)
810 struct symbol *type;
812 if (!key)
813 return NULL;
814 if (strcmp(key, "$") == 0)
815 return get_arg_type(fn, param);
816 if (strcmp(key, "*$") == 0) {
817 type = get_arg_type(fn, param);
818 if (!type || type->type != SYM_PTR)
819 return NULL;
820 return get_real_base_type(type);
822 return get_member_type_from_key(arg, key);
825 int is_struct(struct expression *expr)
827 struct symbol *type;
829 type = get_type(expr);
830 if (type && type->type == SYM_STRUCT)
831 return 1;
832 return 0;
835 static struct {
836 struct symbol *sym;
837 const char *name;
838 } base_types[] = {
839 {&bool_ctype, "bool"},
840 {&void_ctype, "void"},
841 {&type_ctype, "type"},
842 {&char_ctype, "char"},
843 {&schar_ctype, "schar"},
844 {&uchar_ctype, "uchar"},
845 {&short_ctype, "short"},
846 {&sshort_ctype, "sshort"},
847 {&ushort_ctype, "ushort"},
848 {&int_ctype, "int"},
849 {&sint_ctype, "sint"},
850 {&uint_ctype, "uint"},
851 {&long_ctype, "long"},
852 {&slong_ctype, "slong"},
853 {&ulong_ctype, "ulong"},
854 {&llong_ctype, "llong"},
855 {&sllong_ctype, "sllong"},
856 {&ullong_ctype, "ullong"},
857 {&int128_ctype, "lllong"},
858 {&sint128_ctype, "slllong"},
859 {&uint128_ctype, "ulllong"},
860 {&float_ctype, "float"},
861 {&double_ctype, "double"},
862 {&ldouble_ctype, "ldouble"},
863 {&string_ctype, "string"},
864 {&ptr_ctype, "ptr"},
865 {&lazy_ptr_ctype, "lazy_ptr"},
866 {&incomplete_ctype, "incomplete"},
867 {&label_ctype, "label"},
868 {&bad_ctype, "bad"},
869 {&null_ctype, "null"},
872 static const char *base_type_str(struct symbol *sym)
874 int i;
876 for (i = 0; i < ARRAY_SIZE(base_types); i++) {
877 if (sym == base_types[i].sym)
878 return base_types[i].name;
880 return "<unknown>";
883 static int type_str_helper(char *buf, int size, struct symbol *type)
885 int n;
887 if (!type)
888 return snprintf(buf, size, "<null type>");
890 if (type->type == SYM_BASETYPE) {
891 return snprintf(buf, size, "%s", base_type_str(type));
892 } else if (type->type == SYM_PTR) {
893 type = get_real_base_type(type);
894 n = type_str_helper(buf, size, type);
895 if (n > size)
896 return n;
897 return n + snprintf(buf + n, size - n, "*");
898 } else if (type->type == SYM_ARRAY) {
899 type = get_real_base_type(type);
900 n = type_str_helper(buf, size, type);
901 if (n > size)
902 return n;
903 return n + snprintf(buf + n, size - n, "[]");
904 } else if (type->type == SYM_STRUCT) {
905 return snprintf(buf, size, "struct %s", type->ident ? type->ident->name : "");
906 } else if (type->type == SYM_UNION) {
907 if (type->ident)
908 return snprintf(buf, size, "union %s", type->ident->name);
909 else
910 return snprintf(buf, size, "anonymous union");
911 } else if (type->type == SYM_FN) {
912 struct symbol *arg, *return_type, *arg_type;
913 int i;
915 return_type = get_real_base_type(type);
916 n = type_str_helper(buf, size, return_type);
917 if (n > size)
918 return n;
919 n += snprintf(buf + n, size - n, "(*)(");
920 if (n > size)
921 return n;
923 i = 0;
924 FOR_EACH_PTR(type->arguments, arg) {
925 if (i++)
926 n += snprintf(buf + n, size - n, ", ");
927 if (n > size)
928 return n;
929 arg_type = get_real_base_type(arg);
930 n += type_str_helper(buf + n, size - n, arg_type);
931 if (n > size)
932 return n;
933 } END_FOR_EACH_PTR(arg);
935 return n + snprintf(buf + n, size - n, ")");
936 } else if (type->type == SYM_NODE) {
937 n = snprintf(buf, size, "node {");
938 if (n > size)
939 return n;
940 type = get_real_base_type(type);
941 n += type_str_helper(buf + n, size - n, type);
942 if (n > size)
943 return n;
944 return n + snprintf(buf + n, size - n, "}");
945 } else if (type->type == SYM_ENUM) {
946 return snprintf(buf, size, "enum %s", type->ident ? type->ident->name : "<unknown>");
947 } else {
948 return snprintf(buf, size, "<type %d>", type->type);
952 char *type_to_str(struct symbol *type)
954 static char buf[256];
956 buf[0] = '\0';
957 type_str_helper(buf, sizeof(buf), type);
958 return alloc_sname(buf);