aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAl Viro <viro@ftp.linux.org.uk>2009-03-09 07:13:08 +0000
committerChristopher Li <sparse@chrisli.org>2009-07-18 05:30:09 +0000
commit1aae3184cb1dbf95e1e07b4ac85cd3c70784fd32 (patch)
tree97633774fffd1f6f7949de43ae8f9f67daa11406
parentPass decl_state down to ->attribute() (diff)
downloadsparse-1aae3184cb1dbf95e1e07b4ac85cd3c70784fd32.tar.gz
sparse-1aae3184cb1dbf95e1e07b4ac85cd3c70784fd32.tar.bz2
sparse-1aae3184cb1dbf95e1e07b4ac85cd3c70784fd32.zip
Restore __attribute__((mode)) handling
... at least to the extent we used to do it. It still does _not_ cover the perversions gcc can do with that, but at least it deals with regressions. Full solution will have to wait for full-blown imitation of what gcc people call __attribute__ semantics, the bastards... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Christopher Li <sparse@chrisli.org>
-rw-r--r--parse.c118
-rw-r--r--symbol.h4
-rw-r--r--validation/nested-declarator2.c1
3 files changed, 101 insertions, 22 deletions
diff --git a/parse.c b/parse.c
index 5970540..4b75637 100644
--- a/parse.c
+++ b/parse.c
@@ -67,6 +67,11 @@ static attr_t
attribute_transparent_union, ignore_attribute,
attribute_mode;
+typedef struct symbol *to_mode_t(struct symbol *);
+
+static to_mode_t
+ to_QI_mode, to_HI_mode, to_SI_mode, to_DI_mode, to_word_mode;
+
enum {
Set_T = 1,
Set_S = 2,
@@ -309,8 +314,29 @@ static struct symbol_op ignore_attr_op = {
.attribute = ignore_attribute,
};
-static struct symbol_op mode_spec_op = {
+static struct symbol_op mode_QI_op = {
+ .type = KW_MODE,
+ .to_mode = to_QI_mode
+};
+
+static struct symbol_op mode_HI_op = {
.type = KW_MODE,
+ .to_mode = to_HI_mode
+};
+
+static struct symbol_op mode_SI_op = {
+ .type = KW_MODE,
+ .to_mode = to_SI_mode
+};
+
+static struct symbol_op mode_DI_op = {
+ .type = KW_MODE,
+ .to_mode = to_DI_mode
+};
+
+static struct symbol_op mode_word_op = {
+ .type = KW_MODE,
+ .to_mode = to_word_mode
};
static struct init_keyword {
@@ -411,16 +437,16 @@ static struct init_keyword {
{ "__transparent_union__", NS_KEYWORD, .op = &transparent_union_op },
{ "__mode__", NS_KEYWORD, .op = &mode_op },
- { "QI", NS_KEYWORD, MOD_CHAR, .op = &mode_spec_op },
- { "__QI__", NS_KEYWORD, MOD_CHAR, .op = &mode_spec_op },
- { "HI", NS_KEYWORD, MOD_SHORT, .op = &mode_spec_op },
- { "__HI__", NS_KEYWORD, MOD_SHORT, .op = &mode_spec_op },
- { "SI", NS_KEYWORD, .op = &mode_spec_op },
- { "__SI__", NS_KEYWORD, .op = &mode_spec_op },
- { "DI", NS_KEYWORD, MOD_LONGLONG, .op = &mode_spec_op },
- { "__DI__", NS_KEYWORD, MOD_LONGLONG, .op = &mode_spec_op },
- { "word", NS_KEYWORD, MOD_LONG, .op = &mode_spec_op },
- { "__word__", NS_KEYWORD, MOD_LONG, .op = &mode_spec_op },
+ { "QI", NS_KEYWORD, MOD_CHAR, .op = &mode_QI_op },
+ { "__QI__", NS_KEYWORD, MOD_CHAR, .op = &mode_QI_op },
+ { "HI", NS_KEYWORD, MOD_SHORT, .op = &mode_HI_op },
+ { "__HI__", NS_KEYWORD, MOD_SHORT, .op = &mode_HI_op },
+ { "SI", NS_KEYWORD, .op = &mode_SI_op },
+ { "__SI__", NS_KEYWORD, .op = &mode_SI_op },
+ { "DI", NS_KEYWORD, MOD_LONGLONG, .op = &mode_DI_op },
+ { "__DI__", NS_KEYWORD, MOD_LONGLONG, .op = &mode_DI_op },
+ { "word", NS_KEYWORD, MOD_LONG, .op = &mode_word_op },
+ { "__word__", NS_KEYWORD, MOD_LONG, .op = &mode_word_op },
/* Ignored attributes */
{ "nothrow", NS_KEYWORD, .op = &ignore_attr_op },
@@ -542,10 +568,18 @@ struct statement *alloc_statement(struct position pos, int type)
static struct token *struct_declaration_list(struct token *token, struct symbol_list **list);
-static int apply_modifiers(struct position pos, struct ctype *ctype)
+static void apply_modifiers(struct position pos, struct decl_state *ctx)
{
- /* not removing it; application of delayed attributes will be here */
- return 0;
+ struct symbol *ctype;
+ if (!ctx->mode)
+ return;
+ ctype = ctx->mode->to_mode(ctx->ctype.base_type);
+ if (!ctype)
+ sparse_error(pos, "don't know how to apply mode to %s",
+ show_typename(ctx->ctype.base_type));
+ else
+ ctx->ctype.base_type = ctype;
+
}
static struct symbol * alloc_indirect_symbol(struct position pos, struct ctype *ctype, int type)
@@ -974,13 +1008,55 @@ static struct token *attribute_address_space(struct token *token, struct symbol
return token;
}
+static struct symbol *to_QI_mode(struct symbol *ctype)
+{
+ if (ctype->ctype.base_type != &int_type)
+ return NULL;
+ if (ctype == &char_ctype)
+ return ctype;
+ return ctype->ctype.modifiers & MOD_UNSIGNED ? &uchar_ctype
+ : &schar_ctype;
+}
+
+static struct symbol *to_HI_mode(struct symbol *ctype)
+{
+ if (ctype->ctype.base_type != &int_type)
+ return NULL;
+ return ctype->ctype.modifiers & MOD_UNSIGNED ? &ushort_ctype
+ : &sshort_ctype;
+}
+
+static struct symbol *to_SI_mode(struct symbol *ctype)
+{
+ if (ctype->ctype.base_type != &int_type)
+ return NULL;
+ return ctype->ctype.modifiers & MOD_UNSIGNED ? &uint_ctype
+ : &sint_ctype;
+}
+
+static struct symbol *to_DI_mode(struct symbol *ctype)
+{
+ if (ctype->ctype.base_type != &int_type)
+ return NULL;
+ return ctype->ctype.modifiers & MOD_UNSIGNED ? &ullong_ctype
+ : &sllong_ctype;
+}
+
+static struct symbol *to_word_mode(struct symbol *ctype)
+{
+ if (ctype->ctype.base_type != &int_type)
+ return NULL;
+ return ctype->ctype.modifiers & MOD_UNSIGNED ? &ulong_ctype
+ : &slong_ctype;
+}
+
static struct token *attribute_mode(struct token *token, struct symbol *attr, struct decl_state *ctx)
{
token = expect(token, '(', "after mode attribute");
if (token_type(token) == TOKEN_IDENT) {
struct symbol *mode = lookup_keyword(token->ident, NS_KEYWORD);
if (mode && mode->op->type == KW_MODE)
- ctx->ctype.modifiers |= mode->ctype.modifiers;
+ ctx->mode = mode->op;
else
sparse_error(token->pos, "unknown mode attribute %s\n", show_ident(token->ident));
token = token->next;
@@ -1608,7 +1684,7 @@ static struct token *declaration_list(struct token *token, struct symbol_list **
token = handle_bitfield(token, &ctx);
token = handle_attributes(token, &ctx, KW_ATTRIBUTE);
- apply_modifiers(token->pos, &ctx.ctype);
+ apply_modifiers(token->pos, &ctx);
decl->ctype = ctx.ctype;
decl->endpos = token->pos;
@@ -1643,7 +1719,7 @@ static struct token *parameter_declaration(struct token *token, struct symbol *s
ctx.ident = &sym->ident;
token = declarator(token, &ctx);
token = handle_attributes(token, &ctx, KW_ATTRIBUTE);
- apply_modifiers(token->pos, &ctx.ctype);
+ apply_modifiers(token->pos, &ctx);
sym->ctype = ctx.ctype;
sym->endpos = token->pos;
return token;
@@ -1656,7 +1732,7 @@ struct token *typename(struct token *token, struct symbol **p, int mod)
*p = sym;
token = declaration_specifiers(token, &ctx);
token = declarator(token, &ctx);
- apply_modifiers(token->pos, &ctx.ctype);
+ apply_modifiers(token->pos, &ctx);
if (ctx.ctype.modifiers & MOD_STORAGE & ~mod)
warning(sym->pos, "storage class in typename (%s)",
show_typename(sym));
@@ -2435,14 +2511,14 @@ struct token *external_declaration(struct token *token, struct symbol_list **lis
decl = alloc_symbol(token->pos, SYM_NODE);
/* Just a type declaration? */
if (match_op(token, ';')) {
- apply_modifiers(token->pos, &ctx.ctype);
+ apply_modifiers(token->pos, &ctx);
return token->next;
}
saved = ctx.ctype;
token = declarator(token, &ctx);
token = handle_attributes(token, &ctx, KW_ATTRIBUTE | KW_ASM);
- apply_modifiers(token->pos, &ctx.ctype);
+ apply_modifiers(token->pos, &ctx);
decl->ctype = ctx.ctype;
decl->endpos = token->pos;
@@ -2518,7 +2594,7 @@ struct token *external_declaration(struct token *token, struct symbol_list **lis
token = handle_attributes(token, &ctx, KW_ATTRIBUTE);
token = declarator(token, &ctx);
token = handle_attributes(token, &ctx, KW_ATTRIBUTE | KW_ASM);
- apply_modifiers(token->pos, &ctx.ctype);
+ apply_modifiers(token->pos, &ctx);
decl->ctype = ctx.ctype;
decl->endpos = token->pos;
if (!ident) {
diff --git a/symbol.h b/symbol.h
index b74ab0c..f9944bf 100644
--- a/symbol.h
+++ b/symbol.h
@@ -91,8 +91,9 @@ struct ctype {
struct decl_state {
struct ctype ctype;
- int prefer_abstract;
struct ident **ident;
+ int prefer_abstract;
+ struct symbol_op *mode;
};
struct symbol_op {
@@ -106,6 +107,7 @@ struct symbol_op {
struct token *(*statement)(struct token *token, struct statement *stmt);
struct token *(*toplevel)(struct token *token, struct symbol_list **list);
struct token *(*attribute)(struct token *token, struct symbol *attr, struct decl_state *ctx);
+ struct symbol *(*to_mode)(struct symbol *);
int test, set, class;
};
diff --git a/validation/nested-declarator2.c b/validation/nested-declarator2.c
index cd22853..345a04b 100644
--- a/validation/nested-declarator2.c
+++ b/validation/nested-declarator2.c
@@ -32,6 +32,7 @@ nested-declarator2.c:17:1: warning: non-ANSI definition of function 'w1'
nested-declarator2.c:21:21: warning: non-ANSI function declaration of function '<noident>'
nested-declarator2.c:22:16: warning: variadic functions must have one named argument
nested-declarator2.c:24:21: warning: identifier list not in definition
+nested-declarator2.c:25:45: error: don't know how to apply mode to incomplete type
nested-declarator2.c:26:13: error: Expected ) in nested declarator
nested-declarator2.c:26:13: error: got -
nested-declarator2.c:27:16: error: Expected ; at the end of type declaration