aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2010-10-20 01:39:34 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-04-13 20:54:38 -0400
commitef2e777c1bda3fbb2b00c9332e1bf40d24afc136 (patch)
treed314ba209b8f1e812d6f03cbb127acb3fba0052d
parent65a4e2fc656aa6e99604358056d8599a1823a8bc (diff)
downloadsparse-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.c98
-rw-r--r--validation/__func__.c15
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
+ */