From e966e1154dd7bda1b0bfcdbc6ccc606612fe5a8a Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 16 Apr 2003 15:51:06 -0700 Subject: [PATCH] Make functions degenerate to function pointers, and fix the array degeneration too. Check function arguments too when matching types. Make assignment degenerate arrays and functions. --- evaluate.c | 53 +++++++++++++++++++++++++++++++++++++++++------------ lib.h | 6 ++++-- 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/evaluate.c b/evaluate.c index ef946ee1..c205107f 100644 --- a/evaluate.c +++ b/evaluate.c @@ -304,11 +304,13 @@ static struct symbol *degenerate(struct expression *expr, struct symbol *ctype, if (ctype->type == SYM_NODE) base = ctype->ctype.base_type; - if (base->type == SYM_ARRAY) { + if (base->type == SYM_ARRAY || base->type == SYM_FN) { struct symbol *sym = alloc_symbol(expr->pos, SYM_PTR); struct expression *ptr; merge_type(sym, ctype); + if (base->type == SYM_FN) + base = ctype; merge_type(sym, base); sym->bit_size = BITS_IN_POINTER; ctype = sym; @@ -324,7 +326,7 @@ static struct symbol *degenerate(struct expression *expr, struct symbol *ctype, */ if (!lvalue_expression(ptr)) warn(ptr->pos, "internal error: strange degenerate array case"); - ptr->ctype = ctype; + ptr->ctype = base; } return ctype; } @@ -448,6 +450,30 @@ static const char * type_difference(struct symbol *target, struct symbol *source } } + if (target->type == SYM_FN) { + int i; + struct symbol *arg1, *arg2; + if (target->variadic != source->variadic) + return "incompatible variadic arguments"; + PREPARE_PTR_LIST(target->arguments, arg1); + PREPARE_PTR_LIST(source->arguments, arg2); + i = 1; + for (;;) { + if (type_difference(arg1, arg2, 0, 0)) { + static char argdiff[30]; + sprintf(argdiff, "incompatible argument %d", i); + return argdiff; + } + if (!arg1) + break; + NEXT_PTR_LIST(arg1); + NEXT_PTR_LIST(arg2); + i++; + } + FINISH_PTR_LIST(arg2); + FINISH_PTR_LIST(arg1); + } + target = target->ctype.base_type; source = source->ctype.base_type; } @@ -771,12 +797,6 @@ static int compatible_assignment_types(struct expression *expr, struct symbol *t if (s == &void_ctype || t == &void_ctype) return 1; } - - if (s->type == SYM_FN) { - typediff = type_difference(t->ctype.base_type, s, 0, 0); - if (!typediff) - return 1; - } } // FIXME!! Cast it? @@ -835,6 +855,8 @@ static struct symbol *evaluate_assignment(struct expression *expr) return NULL; } + rtype = degenerate(right, rtype, &expr->right); + if (!compatible_assignment_types(expr, ltype, &expr->right, rtype, "assignment")) return 0; @@ -1175,7 +1197,7 @@ static int evaluate_arguments(struct symbol *fn, struct expression_list *head) i++; NEXT_PTR_LIST(argtype); } END_FOR_EACH_PTR; - FINISH_PTR_LIST; + FINISH_PTR_LIST(argtype); return 1; } @@ -1237,7 +1259,7 @@ static int evaluate_struct_or_union_initializer(struct symbol *ctype, struct exp NEXT_PTR_LIST(sym); } END_FOR_EACH_PTR; - FINISH_PTR_LIST; + FINISH_PTR_LIST(sym); return 0; } @@ -1259,6 +1281,13 @@ static int evaluate_initializer(struct symbol *ctype, struct expression **ep, un struct symbol *rtype = evaluate_expression(expr); if (rtype) { struct expression *pos; + struct symbol *fn = rtype; + if (rtype->type == SYM_NODE) + fn = rtype->ctype.base_type; + if (fn->type == SYM_FN) { + rtype = degenerate(expr, rtype, ep); + expr = *ep; + } compatible_assignment_types(expr, ctype, ep, rtype, "initializer"); /* strings are special: char arrays */ if (rtype->type == SYM_ARRAY) @@ -1462,9 +1491,9 @@ static void check_duplicates(struct symbol *sym) evaluate_symbol(next); typediff = type_difference(sym, next, 0, 0); if (typediff) { - warn(sym->pos, "symbol '%s' redeclared with different type (originally declared at %s:%d)", + warn(sym->pos, "symbol '%s' redeclared with different type (originally declared at %s:%d) - %s", show_ident(sym->ident), - input_streams[next->pos.stream].name, next->pos.line); + input_streams[next->pos.stream].name, next->pos.line, typediff); return; } } diff --git a/lib.h b/lib.h index 15667126..4239e0ad 100644 --- a/lib.h +++ b/lib.h @@ -101,7 +101,8 @@ static inline void expression_iterate(struct expression_list *list, void (*callb struct ptr_list *__head##ptr = (struct ptr_list *) (head); \ struct ptr_list *__list##ptr = __head##ptr; \ int __nr##ptr = 0; \ - if (__head##ptr) ptr = (__typeof__(ptr)) __head##ptr->list[0] + if (__head##ptr) ptr = (__typeof__(ptr)) __head##ptr->list[0]; \ + else ptr = NULL #define NEXT_PTR_LIST(ptr) \ if (ptr) { \ @@ -123,7 +124,8 @@ static inline void expression_iterate(struct expression_list *list, void (*callb } while (0) -#define FINISH_PTR_LIST \ +#define FINISH_PTR_LIST(ptr) \ + (void)(__nr##ptr); /* Sanity-check nesting */ \ } while (0) #define FOR_EACH_PTR(head, ptr) do { \ -- 2.11.4.GIT