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@xxxxxxxxxxxxxxx> --- The Linux -rt tree uses this extension, so sparse needs this change in order to run on the -rt tree. expression.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- ident-list.h | 1 + 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/expression.c b/expression.c index aabea6c..b1ffa6c 100644 --- a/expression.c +++ b/expression.c @@ -114,6 +114,45 @@ static int convert_function(struct token 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 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 3051e56..4381a4b 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__); - To unsubscribe from this list: send the line "unsubscribe linux-sparse" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html