diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-10-18 16:35:54 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-07 21:03:36 -0700 |
commit | d16c7a0d4290dcc5a033710e6a5139031c88a323 (patch) | |
tree | 53288cba1e5b76525644d33402ddd7b39bff31b6 /expression.c | |
parent | Mark more identifiers reserved. (diff) | |
download | sparse-d16c7a0d4290dcc5a033710e6a5139031c88a323.tar.gz sparse-d16c7a0d4290dcc5a033710e6a5139031c88a323.tar.bz2 sparse-d16c7a0d4290dcc5a033710e6a5139031c88a323.zip |
Add __sizeof_ptr__ that looks at a pointer expression and
returns the size of the underlying object.
This is different from "sizeof(*expr)" for arrays, where
the array would degenerate to a pointer to one member, and
thus "sizeof(*expr)" gives the size of one entry in the
array.
Why do this? It's useful for things like
#define memset(a,b,c) ({ \
(void) __builtin_warning(__sizeof_ptr__(a) > 1, __sizeof_ptr__(a) != (c), "check memset size"); \
memset(a, b, c); })
where we really want to check the size of the object we're
doing the "memset()" on, but the regular sizeof() just doesn't
cut it.
Diffstat (limited to 'expression.c')
-rw-r--r-- | expression.c | 78 |
1 files changed, 47 insertions, 31 deletions
diff --git a/expression.c b/expression.c index b450b67..67d0a02 100644 --- a/expression.c +++ b/expression.c @@ -446,40 +446,56 @@ static struct token *postfix_expression(struct token *token, struct expression * } static struct token *cast_expression(struct token *token, struct expression **tree); -static struct token *unary_expression(struct token *token, struct expression **tree) +static struct token *unary_expression(struct token *token, struct expression **tree); + +static struct token *type_info_expression(struct token *token, + struct expression **tree, int type) { - if (token_type(token) == TOKEN_IDENT) { - if (token->ident == &sizeof_ident) { - struct expression *sizeof_ex - = alloc_expression(token->pos, EXPR_SIZEOF); - *tree = sizeof_ex; - tree = &sizeof_ex->unop; - token = token->next; - if (!match_op(token, '(') || !lookup_type(token->next)) - return unary_expression(token, &sizeof_ex->cast_expression); - token = typename(token->next, &sizeof_ex->cast_type); + struct expression *expr = alloc_expression(token->pos, type); - if (!match_op(token, ')')) - return expect(token, ')', "at end of sizeof type-name"); + *tree = expr; + token = token->next; + if (!match_op(token, '(') || !lookup_type(token->next)) + return unary_expression(token, &expr->cast_expression); + token = typename(token->next, &expr->cast_type); + + if (!match_op(token, ')')) { + static const char * error[] = { + [EXPR_SIZEOF] = "at end of sizeof", + [EXPR_ALIGNOF] = "at end of __alignof__", + [EXPR_PTRSIZEOF] = "at end of __sizeof_ptr__" + }; + return expect(token, ')', error[type]); + } - token = token->next; - /* - * C99 ambiguity: the typename might have been the beginning - * of a typed initializer expression.. - */ - if (match_op(token, '{')) - token = initializer(&sizeof_ex->cast_expression, token); - return token; - } else if (token->ident == &__alignof___ident) { - struct expression *alignof_ex - = alloc_expression(token->pos, EXPR_ALIGNOF); - *tree = alignof_ex; - tree = &alignof_ex->unop; - token = token->next; - if (!match_op(token, '(') || !lookup_type(token->next)) - return unary_expression(token, &alignof_ex->cast_expression); - token = typename(token->next, &alignof_ex->cast_type); - return expect(token, ')', "at end of alignof type-name"); + token = token->next; + /* + * C99 ambiguity: the typename might have been the beginning + * of a typed initializer expression.. + */ + if (match_op(token, '{')) + token = initializer(&expr->cast_expression, token); + return token; +} + +static struct token *unary_expression(struct token *token, struct expression **tree) +{ + if (token_type(token) == TOKEN_IDENT) { + struct ident *ident = token->ident; + if (ident->reserved) { + static const struct { + struct ident *id; + int type; + } type_information[] = { + { &sizeof_ident, EXPR_SIZEOF }, + { &__alignof___ident, EXPR_ALIGNOF }, + { &__sizeof_ptr___ident, EXPR_PTRSIZEOF }, + }; + int i; + for (i = 0; i < 3; i++) { + if (ident == type_information[i].id) + return type_info_expression(token, tree, type_information[i].type); + } } } |