flow: don't call scope_guard hooks twice at the end of functions
[smatch.git] / smatch_type.c
blob33f035130bf1c1a74b675786b8ee580c207af61b
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 struct symbol *type;
122 if (!expr || expr->type != EXPR_SYMBOL || !expr->symbol)
123 return NULL;
125 type = get_real_base_type(expr->symbol);
126 if (type == &autotype_ctype)
127 return get_type(expr->symbol->initializer);
128 return type;
131 static struct symbol *get_member_symbol(struct symbol_list *symbol_list, struct ident *member)
133 struct symbol *tmp, *sub;
135 FOR_EACH_PTR(symbol_list, tmp) {
136 if (!tmp->ident) {
137 sub = get_real_base_type(tmp);
138 sub = get_member_symbol(sub->symbol_list, member);
139 if (sub)
140 return sub;
141 continue;
143 if (tmp->ident == member)
144 return tmp;
145 } END_FOR_EACH_PTR(tmp);
147 return NULL;
150 static struct symbol *get_symbol_from_deref(struct expression *expr)
152 struct ident *member;
153 struct symbol *sym;
155 if (!expr || expr->type != EXPR_DEREF)
156 return NULL;
158 member = expr->member;
159 sym = get_type(expr->deref);
160 if (!sym) {
161 // sm_msg("could not find struct type");
162 return NULL;
164 if (sym->type == SYM_PTR)
165 sym = get_real_base_type(sym);
166 sym = get_member_symbol(sym->symbol_list, member);
167 if (!sym)
168 return NULL;
169 return get_real_base_type(sym);
172 static struct symbol *handle__builtin_choose_expr(struct expression *expr)
174 struct expression *const_expr, *expr1, *expr2;
175 sval_t sval;
177 const_expr = get_argument_from_call_expr(expr->args, 0);
178 expr1 = get_argument_from_call_expr(expr->args, 1);
179 expr2 = get_argument_from_call_expr(expr->args, 2);
181 if (!get_value(const_expr, &sval) || !expr1 || !expr2)
182 return NULL;
183 if (sval.value)
184 return get_type(expr1);
185 else
186 return get_type(expr2);
189 static struct symbol *get_return_type(struct expression *expr)
191 struct symbol *tmp;
193 if (sym_name_is("__builtin_choose_expr", expr->fn))
194 return handle__builtin_choose_expr(expr);
196 tmp = get_type(expr->fn);
197 if (!tmp)
198 return NULL;
199 /* this is to handle __builtin_constant_p() */
200 if (tmp->type != SYM_FN)
201 tmp = get_base_type(tmp);
202 return get_real_base_type(tmp);
205 static struct symbol *get_expr_stmt_type(struct statement *stmt)
207 if (stmt->type != STMT_COMPOUND)
208 return NULL;
209 stmt = last_ptr_list((struct ptr_list *)stmt->stmts);
210 if (stmt->type == STMT_LABEL)
211 stmt = stmt->label_statement;
212 if (stmt->type != STMT_EXPRESSION)
213 return NULL;
214 return get_type(stmt->expression);
217 static struct symbol *get_select_type(struct expression *expr)
219 struct symbol *one, *two;
221 one = get_type(expr->cond_true);
222 two = get_type(expr->cond_false);
223 if (!one || !two)
224 return NULL;
226 * This is a hack. If the types are not equiv then we
227 * really don't know the type. But I think guessing is
228 * probably Ok here.
230 if (type_positive_bits(one) > type_positive_bits(two))
231 return one;
232 return two;
235 struct symbol *get_pointer_type(struct expression *expr)
237 struct symbol *sym;
239 sym = get_type(expr);
240 if (!sym)
241 return NULL;
242 if (sym->type == SYM_NODE) {
243 sym = get_real_base_type(sym);
244 if (!sym)
245 return NULL;
247 if (sym->type != SYM_PTR && sym->type != SYM_ARRAY)
248 return NULL;
249 return get_real_base_type(sym);
252 static struct symbol *fake_pointer_sym(struct expression *expr)
254 struct symbol *sym;
255 struct symbol *base;
257 sym = alloc_symbol(expr->pos, SYM_PTR);
258 expr = expr->unop;
259 base = get_type(expr);
260 if (!base)
261 return NULL;
262 sym->ctype.base_type = base;
263 return sym;
266 static struct symbol *get_type_helper(struct expression *expr)
268 struct symbol *ret;
270 expr = strip_parens(expr);
271 if (!expr)
272 return NULL;
274 if (expr->ctype)
275 return expr->ctype;
277 switch (expr->type) {
278 case EXPR_STRING:
279 ret = &string_ctype;
280 break;
281 case EXPR_SYMBOL:
282 ret = get_type_symbol(expr);
283 break;
284 case EXPR_DEREF:
285 ret = get_symbol_from_deref(expr);
286 break;
287 case EXPR_PREOP:
288 case EXPR_POSTOP:
289 if (expr->op == '&')
290 ret = fake_pointer_sym(expr);
291 else if (expr->op == '*')
292 ret = get_pointer_type(expr->unop);
293 else
294 ret = get_type(expr->unop);
295 break;
296 case EXPR_ASSIGNMENT:
297 ret = get_type(expr->left);
298 break;
299 case EXPR_CAST:
300 case EXPR_FORCE_CAST:
301 case EXPR_IMPLIED_CAST:
302 ret = get_real_base_type(expr->cast_type);
303 break;
304 case EXPR_COMPARE:
305 case EXPR_BINOP:
306 ret = get_binop_type(expr);
307 break;
308 case EXPR_CALL:
309 ret = get_return_type(expr);
310 break;
311 case EXPR_STATEMENT:
312 ret = get_expr_stmt_type(expr->statement);
313 break;
314 case EXPR_CONDITIONAL:
315 case EXPR_SELECT:
316 ret = get_select_type(expr);
317 break;
318 case EXPR_SIZEOF:
319 ret = &ulong_ctype;
320 break;
321 case EXPR_LOGICAL:
322 ret = &int_ctype;
323 break;
324 case EXPR_OFFSETOF:
325 ret = &ulong_ctype;
326 break;
327 case EXPR_GENERIC:
328 return get_type_helper(strip_Generic(expr));
329 case EXPR_COMMA:
330 return get_type_helper(expr->right);
331 default:
332 return NULL;
335 if (ret && ret->type == SYM_TYPEOF)
336 ret = get_type(ret->initializer);
338 expr->ctype = ret;
339 return ret;
342 static struct symbol *get_final_type_helper(struct expression *expr)
345 * The problem is that I wrote a bunch of Smatch to think that
346 * you could do get_type() on an expression and it would give
347 * you what the comparison was type promoted to. This is wrong
348 * but fixing it is a big of work... Hence this horrible hack.
352 expr = strip_parens(expr);
353 if (!expr)
354 return NULL;
356 if (expr->type == EXPR_COMPARE)
357 return &int_ctype;
358 if (expr->type == EXPR_PREOP && expr->op == '!')
359 return &int_ctype;
361 return NULL;
364 struct symbol *get_type(struct expression *expr)
366 return get_type_helper(expr);
369 struct symbol *get_comparison_type(struct expression *expr)
372 * Eventually we will probably have to figure out how to make get_type()
373 * return &int_ctype so let's create a helper function to transition to.
375 return get_type_helper(expr);
378 struct symbol *get_final_type(struct expression *expr)
380 struct symbol *ret;
382 ret = get_final_type_helper(expr);
383 if (ret)
384 return ret;
385 return get_type_helper(expr);
388 struct symbol *get_promoted_type(struct symbol *left, struct symbol *right)
390 struct symbol *ret = &int_ctype;
392 if (type_positive_bits(left) > type_positive_bits(ret))
393 ret = left;
394 if (type_positive_bits(right) > type_positive_bits(ret))
395 ret = right;
397 if (type_is_ptr(left))
398 ret = left;
399 if (type_is_ptr(right))
400 ret = right;
402 return ret;
405 int type_signed(struct symbol *base_type)
407 if (!base_type)
408 return 0;
409 if (base_type->ctype.modifiers & MOD_SIGNED)
410 return 1;
411 return 0;
414 int expr_unsigned(struct expression *expr)
416 struct symbol *sym;
418 sym = get_type(expr);
419 if (!sym)
420 return 0;
421 if (type_unsigned(sym))
422 return 1;
423 return 0;
426 int expr_signed(struct expression *expr)
428 struct symbol *sym;
430 sym = get_type(expr);
431 if (!sym)
432 return 0;
433 if (type_signed(sym))
434 return 1;
435 return 0;
438 int returns_unsigned(struct symbol *sym)
440 if (!sym)
441 return 0;
442 sym = get_base_type(sym);
443 if (!sym || sym->type != SYM_FN)
444 return 0;
445 sym = get_base_type(sym);
446 return type_unsigned(sym);
449 int is_pointer(struct expression *expr)
451 return type_is_ptr(get_final_type(expr));
454 bool is_void_ptr(struct symbol *type)
456 if (!type)
457 return false;
458 if (type->type != SYM_PTR)
459 return false;
460 type = get_real_base_type(type);
462 return types_equiv(type, &void_ctype);
465 int returns_pointer(struct symbol *sym)
467 if (!sym)
468 return 0;
469 sym = get_base_type(sym);
470 if (!sym || sym->type != SYM_FN)
471 return 0;
472 sym = get_base_type(sym);
473 if (sym && sym->type == SYM_PTR)
474 return 1;
475 return 0;
478 static sval_t fp_max(struct symbol *type)
480 sval_t ret = { .type = type };
482 if (type == &float_ctype)
483 ret.fvalue = FLT_MAX;
484 else if (type == &double_ctype)
485 ret.dvalue = DBL_MAX;
486 else
487 ret.ldvalue = LDBL_MAX;
489 return ret;
492 sval_t sval_type_max(struct symbol *base_type)
494 sval_t ret;
496 if (type_is_fp(base_type))
497 return fp_max(base_type);
499 if (!base_type || !type_bits(base_type))
500 base_type = &llong_ctype;
501 ret.type = base_type;
503 ret.value = (~0ULL) >> (64 - type_positive_bits(base_type));
504 return ret;
507 static sval_t fp_min(struct symbol *type)
509 sval_t ret = { .type = type };
511 if (type == &float_ctype)
512 ret.fvalue = -FLT_MAX;
513 else if (type == &double_ctype)
514 ret.dvalue = -DBL_MAX;
515 else
516 ret.ldvalue = -LDBL_MAX;
518 return ret;
521 sval_t sval_type_min(struct symbol *base_type)
523 sval_t ret;
525 if (type_is_fp(base_type))
526 return fp_min(base_type);
528 if (!base_type || !type_bits(base_type))
529 base_type = &llong_ctype;
530 ret.type = base_type;
532 if (type_unsigned(base_type) || is_ptr_type(base_type)) {
533 ret.value = 0;
534 return ret;
537 ret.value = (~0ULL) << type_positive_bits(base_type);
539 return ret;
542 int nr_bits(struct expression *expr)
544 struct symbol *type;
546 type = get_type(expr);
547 if (!type)
548 return 0;
549 return type_bits(type);
552 int is_void_pointer(struct expression *expr)
554 struct symbol *type;
556 type = get_type(expr);
557 if (!type || type->type != SYM_PTR)
558 return 0;
559 type = get_real_base_type(type);
560 if (type == &void_ctype)
561 return 1;
562 return 0;
565 int is_char_pointer(struct expression *expr)
567 struct symbol *type;
569 type = get_type(expr);
570 if (!type || type->type != SYM_PTR)
571 return 0;
572 type = get_real_base_type(type);
573 if (type == &char_ctype)
574 return 1;
575 return 0;
578 int is_string(struct expression *expr)
580 expr = strip_expr(expr);
581 if (!expr || expr->type != EXPR_STRING)
582 return 0;
583 if (expr->string)
584 return 1;
585 return 0;
588 bool is_struct_ptr(struct symbol *type)
590 if (!type || type->type != SYM_PTR)
591 return false;
592 type = get_real_base_type(type);
593 if (!type || type->type != SYM_STRUCT)
594 return false;
595 return true;
598 int is_static(struct expression *expr)
600 char *name;
601 struct symbol *sym;
602 int ret = 0;
604 name = expr_to_str_sym(expr, &sym);
605 if (!name || !sym)
606 goto free;
608 if (sym->ctype.modifiers & MOD_STATIC)
609 ret = 1;
610 free:
611 free_string(name);
612 return ret;
615 static struct expression *get_symbol_expr(struct expression *expr)
617 if (!expr)
618 return NULL;
619 while (expr && expr->type == EXPR_DEREF && expr->op == '.')
620 expr = strip_expr(expr->deref);
621 return expr;
624 bool is_local_variable(struct expression *expr)
626 struct symbol *sym;
628 expr = get_symbol_expr(expr);
629 if (!expr || expr->type != EXPR_SYMBOL || !expr->symbol)
630 return false;
631 sym = expr->symbol;
632 if (!(sym->ctype.modifiers & MOD_TOPLEVEL))
633 return true;
634 return false;
637 int types_equiv(struct symbol *one, struct symbol *two)
639 if (!one && !two)
640 return 1;
641 if (!one || !two)
642 return 0;
643 if (one->type != two->type)
644 return 0;
645 if (one->type == SYM_PTR)
646 return types_equiv(get_real_base_type(one), get_real_base_type(two));
647 if (type_positive_bits(one) != type_positive_bits(two))
648 return 0;
649 return 1;
652 bool type_fits(struct symbol *type, struct symbol *test)
654 if (!type || !test)
655 return false;
657 if (type == test)
658 return true;
660 if (type_bits(test) > type_bits(type))
661 return false;
662 if (type_signed(test) && !type_signed(type))
663 return false;
664 if (type_positive_bits(test) > type_positive_bits(type))
665 return false;
666 return true;
669 int fn_static(void)
671 return !!(cur_func_sym->ctype.modifiers & MOD_STATIC);
674 const char *global_static(void)
676 if (cur_func_sym->ctype.modifiers & MOD_STATIC)
677 return "static";
678 else
679 return "global";
682 struct symbol *cur_func_return_type(void)
684 struct symbol *sym;
686 sym = get_real_base_type(cur_func_sym);
687 if (!sym || sym->type != SYM_FN)
688 return NULL;
689 sym = get_real_base_type(sym);
690 return sym;
693 struct symbol *get_arg_type(struct expression *fn, int arg)
695 struct symbol *fn_type;
696 struct symbol *tmp;
697 struct symbol *arg_type;
698 int i;
700 fn_type = get_type(fn);
701 if (!fn_type)
702 return NULL;
703 if (fn_type->type == SYM_PTR)
704 fn_type = get_real_base_type(fn_type);
705 if (fn_type->type != SYM_FN)
706 return NULL;
708 i = 0;
709 FOR_EACH_PTR(fn_type->arguments, tmp) {
710 arg_type = get_real_base_type(tmp);
711 if (i == arg) {
712 return arg_type;
714 i++;
715 } END_FOR_EACH_PTR(tmp);
717 return NULL;
720 static struct symbol *get_member_from_string(struct symbol_list *symbol_list, const char *name)
722 struct symbol *tmp, *sub;
723 int chunk_len;
725 if (strncmp(name, ".", 1) == 0)
726 name += 1;
727 else if (strncmp(name, "->", 2) == 0)
728 name += 2;
730 FOR_EACH_PTR(symbol_list, tmp) {
731 if (!tmp->ident) {
732 sub = get_real_base_type(tmp);
733 sub = get_member_from_string(sub->symbol_list, name);
734 if (sub)
735 return sub;
736 continue;
739 if (strcmp(tmp->ident->name, name) == 0)
740 return tmp;
742 chunk_len = tmp->ident->len;
743 if (strncmp(tmp->ident->name, name, chunk_len) == 0 &&
744 (name[chunk_len] == '.' || name[chunk_len] == '-')) {
745 sub = get_real_base_type(tmp);
746 if (sub->type == SYM_PTR)
747 sub = get_real_base_type(sub);
748 return get_member_from_string(sub->symbol_list, name + chunk_len);
751 } END_FOR_EACH_PTR(tmp);
753 return NULL;
756 static struct symbol *get_type_from_container_of_key(struct expression *expr, const char *key)
758 char *new_key;
760 expr = map_container_of_to_simpler_expr_key(expr, key, &new_key);
761 if (!expr)
762 return NULL;
763 return get_member_type_from_key(expr, new_key);
766 struct symbol *get_member_type_from_key(struct expression *expr, const char *key)
768 struct symbol *sym;
769 int star = 0;
770 int i;
772 if (strcmp(key, "$") == 0)
773 return get_type(expr);
775 if (strcmp(key, "*$") == 0) {
776 sym = get_type(expr);
777 if (!sym)
778 return NULL;
779 if (sym->type != SYM_PTR && sym->type != SYM_ARRAY)
780 return NULL;
781 return get_real_base_type(sym);
784 if (strstr(key, "<~$"))
785 return get_type_from_container_of_key(expr, key);
787 sym = get_type(expr);
788 if (!sym)
789 return NULL;
790 if (sym->type == SYM_PTR)
791 sym = get_real_base_type(sym);
793 while (*key == '*') {
794 key++;
795 star++;
798 if (*key != '$')
799 return NULL;
800 key++;
802 sym = get_member_from_string(sym->symbol_list, key);
803 if (!sym)
804 return NULL;
805 if (sym->type == SYM_RESTRICT || sym->type == SYM_NODE)
806 sym = get_real_base_type(sym);
807 for (i = 0; i < star; i++) {
808 if (!sym || sym->type != SYM_PTR)
809 return NULL;
810 sym = get_real_base_type(sym);
812 return sym;
815 struct symbol *get_arg_type_from_key(struct expression *fn, int param, struct expression *arg, const char *key)
817 struct symbol *type;
819 if (!key)
820 return NULL;
821 if (strcmp(key, "$") == 0)
822 return get_arg_type(fn, param);
823 if (strcmp(key, "*$") == 0) {
824 type = get_arg_type(fn, param);
825 if (!type || type->type != SYM_PTR)
826 return NULL;
827 return get_real_base_type(type);
829 return get_member_type_from_key(arg, key);
832 int is_struct(struct expression *expr)
834 struct symbol *type;
836 type = get_type(expr);
837 if (type && type->type == SYM_STRUCT)
838 return 1;
839 return 0;
842 static struct {
843 struct symbol *sym;
844 const char *name;
845 } base_types[] = {
846 {&bool_ctype, "bool"},
847 {&void_ctype, "void"},
848 {&type_ctype, "type"},
849 {&char_ctype, "char"},
850 {&schar_ctype, "schar"},
851 {&uchar_ctype, "uchar"},
852 {&short_ctype, "short"},
853 {&sshort_ctype, "sshort"},
854 {&ushort_ctype, "ushort"},
855 {&int_ctype, "int"},
856 {&sint_ctype, "sint"},
857 {&uint_ctype, "uint"},
858 {&long_ctype, "long"},
859 {&slong_ctype, "slong"},
860 {&ulong_ctype, "ulong"},
861 {&llong_ctype, "llong"},
862 {&sllong_ctype, "sllong"},
863 {&ullong_ctype, "ullong"},
864 {&int128_ctype, "lllong"},
865 {&sint128_ctype, "slllong"},
866 {&uint128_ctype, "ulllong"},
867 {&float_ctype, "float"},
868 {&double_ctype, "double"},
869 {&ldouble_ctype, "ldouble"},
870 {&string_ctype, "string"},
871 {&ptr_ctype, "ptr"},
872 {&lazy_ptr_ctype, "lazy_ptr"},
873 {&incomplete_ctype, "incomplete"},
874 {&label_ctype, "label"},
875 {&bad_ctype, "bad"},
876 {&null_ctype, "null"},
879 static const char *base_type_str(struct symbol *sym)
881 int i;
883 for (i = 0; i < ARRAY_SIZE(base_types); i++) {
884 if (sym == base_types[i].sym)
885 return base_types[i].name;
887 return "<unknown>";
890 static int type_str_helper(char *buf, int size, struct symbol *type)
892 int n;
894 if (!type)
895 return snprintf(buf, size, "<null type>");
897 if (type->type == SYM_BASETYPE) {
898 return snprintf(buf, size, "%s", base_type_str(type));
899 } else if (type->type == SYM_PTR) {
900 type = get_real_base_type(type);
901 n = type_str_helper(buf, size, type);
902 if (n > size)
903 return n;
904 return n + snprintf(buf + n, size - n, "*");
905 } else if (type->type == SYM_ARRAY) {
906 type = get_real_base_type(type);
907 n = type_str_helper(buf, size, type);
908 if (n > size)
909 return n;
910 return n + snprintf(buf + n, size - n, "[]");
911 } else if (type->type == SYM_STRUCT) {
912 return snprintf(buf, size, "struct %s", type->ident ? type->ident->name : "");
913 } else if (type->type == SYM_UNION) {
914 if (type->ident)
915 return snprintf(buf, size, "union %s", type->ident->name);
916 else
917 return snprintf(buf, size, "anonymous union");
918 } else if (type->type == SYM_FN) {
919 struct symbol *arg, *return_type, *arg_type;
920 int i;
922 return_type = get_real_base_type(type);
923 n = type_str_helper(buf, size, return_type);
924 if (n > size)
925 return n;
926 n += snprintf(buf + n, size - n, "(*)(");
927 if (n > size)
928 return n;
930 i = 0;
931 FOR_EACH_PTR(type->arguments, arg) {
932 if (i++)
933 n += snprintf(buf + n, size - n, ", ");
934 if (n > size)
935 return n;
936 arg_type = get_real_base_type(arg);
937 n += type_str_helper(buf + n, size - n, arg_type);
938 if (n > size)
939 return n;
940 } END_FOR_EACH_PTR(arg);
942 return n + snprintf(buf + n, size - n, ")");
943 } else if (type->type == SYM_NODE) {
944 n = snprintf(buf, size, "node {");
945 if (n > size)
946 return n;
947 type = get_real_base_type(type);
948 n += type_str_helper(buf + n, size - n, type);
949 if (n > size)
950 return n;
951 return n + snprintf(buf + n, size - n, "}");
952 } else if (type->type == SYM_ENUM) {
953 return snprintf(buf, size, "enum %s", type->ident ? type->ident->name : "<unknown>");
954 } else {
955 return snprintf(buf, size, "<type %d>", type->type);
959 char *type_to_str(struct symbol *type)
961 static char buf[256];
963 buf[0] = '\0';
964 type_str_helper(buf, sizeof(buf), type);
965 return alloc_sname(buf);