diff options
| author | Linus Torvalds <torvalds@penguin.transmeta.com> | 2003-03-25 18:34:15 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-07 20:59:47 -0700 |
| commit | 38795344d7b03fc340b5cabb0a38e22d327836d9 (patch) | |
| tree | 3a77611bca58b5dbd620b2bf4dd9f285d2b185d5 | |
| parent | ada22defe98209bfc1c4285f1b76a548552e28cf (diff) | |
| download | sparse-dev-38795344d7b03fc340b5cabb0a38e22d327836d9.tar.gz | |
Fix indirect type parsing (functions, arrays, bitfields). Update
users to match.
Examine array type sizes.
Evaluate 'sizeof()', and realize that you can dereference arrays
as well as pointers.
| -rw-r--r-- | evaluate.c | 26 | ||||
| -rw-r--r-- | parse.c | 47 | ||||
| -rw-r--r-- | show-parse.c | 26 | ||||
| -rw-r--r-- | symbol.c | 62 | ||||
| -rw-r--r-- | symbol.h | 2 | ||||
| -rw-r--r-- | target.h | 2 | ||||
| -rw-r--r-- | test-parsing.c | 10 |
7 files changed, 104 insertions, 71 deletions
@@ -156,7 +156,7 @@ static int evaluate_preop(struct expression *expr) return 1; case '*': - if (ctype->type != SYM_PTR) { + if (ctype->type != SYM_PTR && ctype->type != SYM_ARRAY) { warn(expr->token, "cannot derefence this type"); return 0; } @@ -188,6 +188,28 @@ static int evaluate_postop(struct expression *expr) return 0; } +static int evaluate_sizeof(struct expression *expr) +{ + int size; + + if (expr->cast_type) { + examine_symbol_type(expr->cast_type); + size = expr->cast_type->bit_size; + } else { + if (!evaluate_expression(expr->cast_expression)) + return 0; + size = expr->cast_expression->ctype->bit_size; + } + if (size & 7) { + warn(expr->token, "cannot size expression"); + return 0; + } + expr->type = EXPR_VALUE; + expr->value = size >> 3; + expr->ctype = size_t_ctype; + return 1; +} + int evaluate_expression(struct expression *expr) { if (!expr) @@ -219,6 +241,8 @@ int evaluate_expression(struct expression *expr) return 1; expr->ctype = expr->cast_type; return 1; + case EXPR_SIZEOF: + return evaluate_sizeof(expr); default: break; } @@ -30,21 +30,15 @@ struct statement *alloc_statement(struct token * token, int type) static struct token *struct_declaration_list(struct token *token, struct symbol_list **list); -static void force_default_type(struct ctype *type) -{ - if (!type->base_type) - type->base_type = &int_type; -} - -static struct symbol *indirect(struct token *token, struct symbol *base, int type) +static struct symbol * indirect(struct token *token, struct symbol *base, int type) { struct symbol *sym = alloc_symbol(token, type); - unsigned long mod = base->ctype.modifiers; - sym->ctype.base_type = base; - sym->ctype.modifiers = mod & MOD_STORAGE; - base->ctype.modifiers = mod & ~MOD_STORAGE; - force_default_type(&sym->ctype); + sym->ctype.base_type = base->ctype.base_type; + sym->ctype.modifiers = base->ctype.modifiers & ~MOD_STORAGE; + + base->ctype.base_type = sym; + base->ctype.modifiers &= MOD_STORAGE; return sym; } @@ -320,12 +314,11 @@ static struct token *declaration_specifiers(struct token *next, struct ctype *ct return token; } -static struct token *abstract_array_declarator(struct token *token, struct symbol **tree) +static struct token *abstract_array_declarator(struct token *token, struct symbol *sym) { struct expression *expr = NULL; - struct symbol *sym = *tree; - token = parse_expression(token, &expr); + token = parse_expression(token, &expr); if (expr) sym->array_size = get_expression_value(expr); else @@ -360,6 +353,7 @@ static struct token *direct_declarator(struct token *token, struct symbol **tree * list if it is empty or starts with a type. */ if (token->special == '(') { + struct symbol *sym; struct token *next = token->next; int fn = (p && *p) || match_op(next, ')') || lookup_type(next); @@ -369,21 +363,23 @@ static struct token *direct_declarator(struct token *token, struct symbol **tree continue; } - *tree = indirect(token, *tree, SYM_FN); - token = parameter_type_list(next, &(*tree)->arguments); + sym = indirect(token, *tree, SYM_FN); + token = parameter_type_list(next, &sym->arguments); token = expect(token, ')', "in function declarator"); continue; } if (token->special == '[') { - *tree = indirect(token, *tree, SYM_ARRAY); - token = abstract_array_declarator(token->next, tree); + struct symbol *ctype = indirect(token, *tree, SYM_ARRAY); + token = abstract_array_declarator(token->next, ctype); token = expect(token, ']', "in abstract_array_declarator"); continue; } if (token->special == ':') { + struct symbol *bitfield; struct expression *expr; - *tree = indirect(token, *tree, SYM_BITFIELD); + bitfield = indirect(token, *tree, SYM_BITFIELD); token = conditional_expression(token->next, &expr); + bitfield->fieldwidth = get_expression_value(expr); continue; } break; @@ -400,7 +396,6 @@ static struct token *pointer(struct token *token, struct ctype *ctype) unsigned long modifiers; struct symbol *base_type; - force_default_type(ctype); modifiers = ctype->modifiers & ~(MOD_TYPEDEF | MOD_ATTRIBUTE); base_type = ctype->base_type; @@ -769,6 +764,7 @@ static struct token *external_declaration(struct token *token, struct symbol_lis struct token *ident = NULL; struct symbol *decl; struct ctype ctype = { 0, }; + struct symbol *base_type; /* Parse declaration-specifiers, if any */ token = declaration_specifiers(token, &ctype); @@ -791,11 +787,12 @@ static struct token *external_declaration(struct token *token, struct symbol_lis bind_symbol(decl, ident->ident, NS_SYMBOL); } - if (decl->type == SYM_FN && match_op(token, '{')) { - decl->stmt = alloc_statement(token, STMT_COMPOUND); + base_type = decl->ctype.base_type; + if (base_type && base_type->type == SYM_FN && match_op(token, '{')) { + base_type->stmt = alloc_statement(token, STMT_COMPOUND); start_symbol_scope(); - symbol_iterate(decl->arguments, declare_argument, decl); - token = compound_statement(token->next, decl->stmt); + symbol_iterate(base_type->arguments, declare_argument, decl); + token = compound_statement(token->next, base_type->stmt); end_symbol_scope(); return expect(token, '}', "at end of function"); } diff --git a/show-parse.c b/show-parse.c index 72b35529..b5d233da 100644 --- a/show-parse.c +++ b/show-parse.c @@ -168,12 +168,19 @@ void show_type(struct symbol *sym) void show_symbol(struct symbol *sym) { + struct symbol *type; + + if (sym->type != SYM_NODE) + *(int *)0 = 0; show_type(sym); + type = sym->ctype.base_type; + if (!type) + return; /* * Show actual implementation information */ - switch (sym->type) { + switch (type->type) { case SYM_STRUCT: symbol_iterate(sym->symbol_list, show_struct_member, NULL); return; @@ -184,9 +191,13 @@ void show_symbol(struct symbol *sym) case SYM_FN: printf("("); - show_symbol_list(sym->arguments, ", "); + show_symbol_list(type->arguments, ", "); printf(")\n"); - show_statement(sym->stmt); + show_statement(type->stmt); + return; + + case SYM_ARRAY: + printf("[%d]\n", type->array_size); return; default: @@ -379,6 +390,15 @@ void show_expression(struct expression *expr) case EXPR_VALUE: printf("(%lld)", expr->value); break; + case EXPR_SIZEOF: + printf("sizeof("); + if (expr->cast_type) + show_type(expr->cast_type); + else + show_expression(expr->cast_expression); + printf(")"); + break; + default: printf("WTF"); } @@ -82,6 +82,21 @@ static void examine_struct_union_type(struct symbol *sym, int advance) sym->alignment = info.max_align; } +static void examine_array_type(struct symbol *sym) +{ + struct symbol *base_type = sym->ctype.base_type; + unsigned long bit_size, alignment; + + if (!base_type) + return; + examine_symbol_type(base_type); + bit_size = base_type->bit_size * sym->array_size; + alignment = base_type->alignment; + if (!sym->alignment) + sym->alignment = alignment; + sym->bit_size = bit_size; +} + /* * Fill in type size and alignment information for * regular SYM_TYPE things. @@ -100,6 +115,9 @@ void examine_symbol_type(struct symbol * sym) return; switch (sym->type) { + case SYM_ARRAY: + examine_array_type(sym); + return; case SYM_STRUCT: examine_struct_union_type(sym, 1); return; @@ -119,39 +137,19 @@ void examine_symbol_type(struct symbol * sym) if (!sym->alignment) sym->alignment = ENUM_ALIGNMENT; return; - + case SYM_BASETYPE: + /* Size and alignment had better already be set up */ + return; + default: break; } + /* SYM_NODE - figure out what the type of the node was.. */ base_type = sym->ctype.base_type; modifiers = sym->ctype.modifiers; - if (base_type == &int_type) { - bit_size = BITS_IN_INT; - if (modifiers & MOD_LONGLONG) { - bit_size = BITS_IN_LONGLONG; - } else if (modifiers & MOD_LONG) { - bit_size = BITS_IN_LONG; - } else if (modifiers & MOD_SHORT) { - bit_size = BITS_IN_SHORT; - } else if (modifiers & MOD_CHAR) { - bit_size = BITS_IN_CHAR; - } - alignment = bit_size >> 3; - if (alignment > MAX_INT_ALIGNMENT) - alignment = MAX_INT_ALIGNMENT; - } else if (base_type == &fp_type) { - bit_size = BITS_IN_FLOAT; - if (modifiers & MOD_LONGLONG) { - bit_size = BITS_IN_LONGDOUBLE; - } else if (modifiers & MOD_LONG) { - bit_size = BITS_IN_DOUBLE; - } - alignment = bit_size >> 3; - if (alignment > MAX_FP_ALIGNMENT) - alignment = MAX_FP_ALIGNMENT; - } else if (base_type) { + if (base_type) { examine_symbol_type(base_type); bit_size = base_type->bit_size; @@ -159,18 +157,6 @@ void examine_symbol_type(struct symbol * sym) } else bit_size = 0; - if (!bit_size) { - warn(sym->token, "unknown type %d", sym->type); - return; - } - - if (sym->type == SYM_ARRAY) { - int array_size = sym->array_size; - bit_size *= sym->array_size; - if (array_size == -1) - bit_size = -1; - } - if (!sym->alignment) sym->alignment = alignment; sym->bit_size = bit_size; @@ -31,6 +31,7 @@ enum namespace { }; enum type { + SYM_BASETYPE, SYM_NODE, SYM_PTR, SYM_FN, @@ -74,6 +75,7 @@ struct symbol { struct statement *stmt; struct symbol_list *symbol_list; long long value; /* Initial value */ + int fieldwidth; }; }; }; @@ -1,6 +1,8 @@ #ifndef TARGET_H #define TARGET_H +#define size_t_ctype (&ulong_ctype) + /* * Integer data types */ diff --git a/test-parsing.c b/test-parsing.c index 9f05e9f9..bc083979 100644 --- a/test-parsing.c +++ b/test-parsing.c @@ -56,12 +56,14 @@ static void clean_up_statement(struct statement *stmt, void *_parent, int flags) static void clean_up_symbol(struct symbol *sym, void *_parent, int flags) { struct symbol *parent = _parent; + struct symbol *type; examine_symbol_type(sym); - if (sym->type == SYM_FN) { - symbol_iterate(sym->arguments, clean_up_symbol, parent); - if (sym->stmt) - simplify_statement(sym->stmt, sym); + type = sym->ctype.base_type; + if (type && type->type == SYM_FN) { + symbol_iterate(type->arguments, clean_up_symbol, parent); + if (type->stmt) + simplify_statement(type->stmt, sym); } } |
