aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
authorLinus Torvalds <torvalds@penguin.transmeta.com>2003-03-25 18:34:15 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-07 20:59:47 -0700
commit38795344d7b03fc340b5cabb0a38e22d327836d9 (patch)
tree3a77611bca58b5dbd620b2bf4dd9f285d2b185d5
parentada22defe98209bfc1c4285f1b76a548552e28cf (diff)
downloadsparse-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.c26
-rw-r--r--parse.c47
-rw-r--r--show-parse.c26
-rw-r--r--symbol.c62
-rw-r--r--symbol.h2
-rw-r--r--target.h2
-rw-r--r--test-parsing.c10
7 files changed, 104 insertions, 71 deletions
diff --git a/evaluate.c b/evaluate.c
index effa1868..2f4663bc 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -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;
}
diff --git a/parse.c b/parse.c
index 319889bb..d9aec7f4 100644
--- a/parse.c
+++ b/parse.c
@@ -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");
}
diff --git a/symbol.c b/symbol.c
index 8818d66f..42454de7 100644
--- a/symbol.c
+++ b/symbol.c
@@ -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;
diff --git a/symbol.h b/symbol.h
index 25f7f224..b8f02a58 100644
--- a/symbol.h
+++ b/symbol.h
@@ -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;
};
};
};
diff --git a/target.h b/target.h
index 1b77d0f1..5b9c5dcd 100644
--- a/target.h
+++ b/target.h
@@ -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);
}
}