aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2004-10-18 16:35:54 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-07 21:03:36 -0700
commitd16c7a0d4290dcc5a033710e6a5139031c88a323 (patch)
tree53288cba1e5b76525644d33402ddd7b39bff31b6 /expression.c
parentMark more identifiers reserved. (diff)
downloadsparse-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.c78
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);
+ }
}
}