diff options
| author | Josh Triplett <josht@vnet.ibm.com> | 2006-07-05 15:09:21 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-07-05 15:32:30 -0700 |
| commit | 1c294832c10de9842170f1a9518d9fc04c0262f3 (patch) | |
| tree | 0d9cd26975d83b6334648c0acad4ef4cd5dfbe75 | |
| parent | b33b1404376051fb2657c65d36f7708c4dd19867 (diff) | |
| download | sparse-dev-1c294832c10de9842170f1a9518d9fc04c0262f3.tar.gz | |
[PATCH] Add support for GCC's __builtin_types_compatible_p extension
Parse and support GCC's __builtin_types_compatible_p extension, which takes
two types as arguments, and returns 1 for compatible types or 0 for
incompatible types. Since sparse already supports comparisons with types as
the operands, just transform __builtin_types_compatible_p(a, b) into the
comparison a == b.
Signed-off-by: Josh Triplett <josh@freedesktop.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
| -rw-r--r-- | expression.c | 49 | ||||
| -rw-r--r-- | ident-list.h | 1 |
2 files changed, 48 insertions, 2 deletions
diff --git a/expression.c b/expression.c index aabea6cb..b1ffa6c4 100644 --- a/expression.c +++ b/expression.c @@ -114,6 +114,45 @@ static int convert_function(struct token *next) return retval; } +static struct token *parse_type(struct token *token, struct expression **tree) +{ + struct symbol *sym; + *tree = alloc_expression(token->pos, EXPR_TYPE); + token = typename(token, &sym); + if (sym->ident) + sparse_error(token->pos, + "type expression should not include identifier " + "\"%s\"", sym->ident->name); + (*tree)->symbol = sym; + return token; +} + +static struct token *builtin_types_compatible_p_expr(struct token *token, + struct expression **tree) +{ + struct expression *expr = alloc_expression( + token->pos, EXPR_COMPARE); + expr->op = SPECIAL_EQUAL; + token = token->next; + if (!match_op(token, '(')) + return expect(token, '(', + "after __builtin_types_compatible_p"); + token = token->next; + token = parse_type(token, &expr->left); + if (!match_op(token, ',')) + return expect(token, ',', + "in __builtin_types_compatible_p"); + token = token->next; + token = parse_type(token, &expr->right); + if (!match_op(token, ')')) + return expect(token, ')', + "at end of __builtin_types_compatible_p"); + token = token->next; + + *tree = expr; + return token; +} + static struct token *string_expression(struct token *token, struct expression *expr) { struct string *string = token->string; @@ -314,8 +353,14 @@ struct token *primary_expression(struct token *token, struct expression **tree) struct symbol *sym = lookup_symbol(token->ident, NS_SYMBOL | NS_TYPEDEF); struct token *next = token->next; - if (!sym && convert_function(token)) - goto handle_string; + if (!sym) { + if (convert_function(token)) + goto handle_string; + if (token->ident == &__builtin_types_compatible_p_ident) { + token = builtin_types_compatible_p_expr(token, &expr); + break; + } + } expr = alloc_expression(token->pos, EXPR_SYMBOL); diff --git a/ident-list.h b/ident-list.h index 3051e561..4381a4bd 100644 --- a/ident-list.h +++ b/ident-list.h @@ -35,6 +35,7 @@ IDENT_RESERVED(__asm); IDENT_RESERVED(__alignof); IDENT_RESERVED(__alignof__); IDENT_RESERVED(__sizeof_ptr__); +IDENT_RESERVED(__builtin_types_compatible_p); /* Attribute names */ IDENT(defined); IDENT(packed); IDENT(__packed__); |
