diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2010-10-20 01:39:34 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-04-13 20:54:38 -0400 |
commit | ef2e777c1bda3fbb2b00c9332e1bf40d24afc136 (patch) | |
tree | d314ba209b8f1e812d6f03cbb127acb3fba0052d | |
parent | 65a4e2fc656aa6e99604358056d8599a1823a8bc (diff) | |
download | sparse-ef2e777c1bda3fbb2b00c9332e1bf40d24afc136.tar.gz |
Fix handling of __func__
It's not a string literal, it's a static array
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | expression.c | 98 | ||||
-rw-r--r-- | validation/__func__.c | 15 |
2 files changed, 60 insertions, 53 deletions
diff --git a/expression.c b/expression.c index 0ae3a60c..b8fab8f3 100644 --- a/expression.c +++ b/expression.c @@ -64,53 +64,50 @@ struct token *parens_expression(struct token *token, struct expression **expr, c * Handle __func__, __FUNCTION__ and __PRETTY_FUNCTION__ token * conversion */ -static int convert_one_fn_token(struct token *token) +static struct symbol *handle_func(struct token *token) { - struct symbol *sym = current_fn; - - if (sym) { - struct ident *ident = sym->ident; - if (ident) { - int len = ident->len; - struct string *string; - - string = __alloc_string(len+1); - memcpy(string->data, ident->name, len); - string->data[len] = 0; - string->length = len+1; - token_type(token) = TOKEN_STRING; - token->string = string; - return 1; - } - } - return 0; -} - -static int convert_function(struct token *next) -{ - int retval = 0; - for (;;) { - struct token *token = next; - next = next->next; - switch (token_type(token)) { - case TOKEN_STRING: - continue; - case TOKEN_IDENT: - if (token->ident == &__func___ident || - token->ident == &__FUNCTION___ident || - token->ident == &__PRETTY_FUNCTION___ident) { - if (!convert_one_fn_token(token)) - break; - retval = 1; - continue; - } - /* Fall through */ - default: - break; - } - break; - } - return retval; + struct ident *ident = token->ident; + struct symbol *decl, *array; + struct string *string; + int len; + + if (ident != &__func___ident && + ident != &__FUNCTION___ident && + ident != &__PRETTY_FUNCTION___ident) + return NULL; + + if (!current_fn) + return NULL; + + /* OK, it's one of ours */ + array = alloc_symbol(token->pos, SYM_ARRAY); + array->ctype.base_type = &char_ctype; + array->ctype.alignment = 1; + array->endpos = token->pos; + decl = alloc_symbol(token->pos, SYM_NODE); + decl->ctype.base_type = array; + decl->ctype.alignment = 1; + decl->ctype.modifiers = MOD_STATIC; + decl->endpos = token->pos; + + /* function-scope, but in NS_SYMBOL */ + bind_symbol(decl, ident, NS_LABEL); + decl->namespace = NS_SYMBOL; + + len = current_fn->ident->len; + string = __alloc_string(len + 1); + memcpy(string->data, current_fn->ident->name, len); + string->data[len] = 0; + string->length = len + 1; + + decl->initializer = alloc_expression(token->pos, EXPR_STRING); + decl->initializer->string = string; + decl->initializer->ctype = decl; + decl->array_size = alloc_const_expression(token->pos, len + 1); + array->array_size = decl->array_size; + decl->bit_size = array->bit_size = bytes_to_bits(len + 1); + + return decl; } static struct token *parse_type(struct token *token, struct expression **tree) @@ -226,8 +223,6 @@ static struct token *string_expression(struct token *token, struct expression *e struct token *next = token->next; int stringtype = token_type(token); - convert_function(token); - if (token_type(next) == stringtype) { int totlen = string->length-1; char *data; @@ -434,8 +429,7 @@ struct token *primary_expression(struct token *token, struct expression **tree) struct token *next = token->next; if (!sym) { - if (convert_function(token)) - goto handle_string; + sym = handle_func(token); if (token->ident == &__builtin_types_compatible_p_ident) { token = builtin_types_compatible_p_expr(token, &expr); break; @@ -473,13 +467,11 @@ struct token *primary_expression(struct token *token, struct expression **tree) } case TOKEN_STRING: - case TOKEN_WIDE_STRING: { - handle_string: + case TOKEN_WIDE_STRING: expr = alloc_expression(token->pos, EXPR_STRING); expr->wide = token_type(token) == TOKEN_WIDE_STRING; token = string_expression(token, expr); break; - } case TOKEN_SPECIAL: if (token->special == '(') { diff --git a/validation/__func__.c b/validation/__func__.c new file mode 100644 index 00000000..65ce9282 --- /dev/null +++ b/validation/__func__.c @@ -0,0 +1,15 @@ +static void f(void) +{ + char *s1 = __func__; + char arr[2 * (sizeof __func__ == 2) - 1]; + char *s2 = __func__ __func__; +} +/* + * check-name: __func__ + * check-command: sparse -Wall $file + * + * check-error-start +__func__.c:5:29: error: Expected ; at end of declaration +__func__.c:5:29: error: got __func__ + * check-error-end + */ |