Now we are really parsing the attribute rather than build the
expression tree first.

Signed-Off-By: Christopher Li <[EMAIL PROTECTED]>

Index: sparse/parse.h
===================================================================
Index: sparse/symbol.c
===================================================================
Index: sparse/parse.c
===================================================================
--- sparse.orig/parse.c 2007-03-07 01:18:31.000000000 -0800
+++ sparse/parse.c      2007-03-07 02:16:09.000000000 -0800
@@ -55,8 +55,19 @@ static struct token *parse_do_statement(
 static struct token *parse_goto_statement(struct token *token, struct 
statement *stmt);
 static struct token *parse_context_statement(struct token *token, struct 
statement *stmt);
 static struct token *parse_range_statement(struct token *token, struct 
statement *stmt);
-static struct token *parse_asm(struct token *token, struct statement *stmt);
+static struct token *parse_asm_statement(struct token *token, struct statement 
*stmt);
 static struct token *toplevel_asm_declaration(struct token *token, struct 
symbol_list **list);
+static struct token *parse_asm_declarator(struct token *token, struct ctype 
*ctype);
+
+
+static struct token *attribute_packed(struct token *token, struct symbol 
*attr, struct ctype *ctype);
+static struct token *attribute_modifier(struct token *token, struct symbol 
*attr, struct ctype *ctype);
+static struct token *attribute_address_space(struct token *token, struct 
symbol *attr, struct ctype *ctype);
+static struct token *attribute_aligned(struct token *token, struct symbol 
*attr, struct ctype *ctype);
+static struct token *attribute_mode(struct token *token, struct symbol *attr, 
struct ctype *ctype);
+static struct token *attribute_context(struct token *token, struct symbol 
*attr, struct ctype *ctype);
+static struct token *attribute_transparent_union(struct token *token, struct 
symbol *attr, struct ctype *ctype);
+static struct token *ignore_attribute(struct token *token, struct symbol 
*attr, struct ctype *ctype);
 
 
 static struct symbol_op modifier_op = {
@@ -134,7 +145,7 @@ static struct symbol_op goto_op = {
        .statement = parse_goto_statement,
 };
 
-static struct symbol_op context_op = {
+static struct symbol_op __context___op = {
        .statement = parse_context_statement,
 };
 
@@ -143,10 +154,48 @@ static struct symbol_op range_op = {
 };
 
 static struct symbol_op asm_op = {
-       .statement = parse_asm,
+       .type = KW_ASM,
+       .declarator = parse_asm_declarator,
+       .statement = parse_asm_statement,
        .toplevel = toplevel_asm_declaration,
 };
 
+static struct symbol_op packed_op = {
+       .attribute = attribute_packed,
+};
+
+static struct symbol_op aligned_op = {
+       .attribute = attribute_aligned,
+};
+
+static struct symbol_op attr_mod_op = {
+       .attribute = attribute_modifier,
+};
+
+static struct symbol_op address_space_op = {
+       .attribute = attribute_address_space,
+};
+
+static struct symbol_op mode_op = {
+       .attribute = attribute_mode,
+};
+
+static struct symbol_op context_op = {
+       .attribute = attribute_context,
+};
+
+static struct symbol_op transparent_union_op = {
+       .attribute = attribute_transparent_union,
+};
+
+static struct symbol_op ignore_attr_op = {
+       .attribute = ignore_attribute,
+};
+
+static struct symbol_op mode_spec_op = {
+       .type = KW_MODE,
+};
+
 static struct init_keyword {
        const char *name;
        enum namespace ns;
@@ -196,12 +245,83 @@ static struct init_keyword {
        { "while",      NS_KEYWORD, .op = &while_op },
        { "do",         NS_KEYWORD, .op = &do_op },
        { "goto",       NS_KEYWORD, .op = &goto_op },
-       { "__context__",NS_KEYWORD, .op = &context_op },
+       { "__context__",NS_KEYWORD, .op = &__context___op },
        { "__range__",  NS_KEYWORD, .op = &range_op },
        { "asm",        NS_KEYWORD, .op = &asm_op },
        { "__asm",      NS_KEYWORD, .op = &asm_op },
        { "__asm__",    NS_KEYWORD, .op = &asm_op },
 
+       /* Attribute */
+       { "packed",     NS_KEYWORD, .op = &packed_op },
+       { "__packed__", NS_KEYWORD, .op = &packed_op },
+       { "aligned",    NS_KEYWORD, .op = &aligned_op },
+       { "__aligned__",NS_KEYWORD, .op = &aligned_op },
+       { "nocast",     NS_KEYWORD,     MOD_NOCAST,     .op = &attr_mod_op },
+       { "noderef",    NS_KEYWORD,     MOD_NODEREF,    .op = &attr_mod_op },
+       { "safe",       NS_KEYWORD,     MOD_SAFE,       .op = &attr_mod_op },
+       { "force",      NS_KEYWORD,     MOD_FORCE,      .op = &attr_mod_op },
+       { "bitwise",    NS_KEYWORD,     MOD_BITWISE,    .op = &attr_mod_op },
+       { "__bitwise__",NS_KEYWORD,     MOD_BITWISE,    .op = &attr_mod_op },
+       { "address_space",NS_KEYWORD,   .op = &address_space_op },
+       { "mode",       NS_KEYWORD,     .op = &mode_op },
+       { "context",    NS_KEYWORD,     .op = &context_op },
+       { "__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 },
+
+       /* Ignored attributes */
+       { "nothrow",    NS_KEYWORD,     .op = &ignore_attr_op },
+       { "__nothrow",  NS_KEYWORD,     .op = &ignore_attr_op },
+       { "__nothrow__",        NS_KEYWORD,     .op = &ignore_attr_op },
+       { "__malloc__", NS_KEYWORD,     .op = &ignore_attr_op },
+       { "nonnull",    NS_KEYWORD,     .op = &ignore_attr_op },
+       { "__nonnull",  NS_KEYWORD,     .op = &ignore_attr_op },
+       { "__nonnull__",        NS_KEYWORD,     .op = &ignore_attr_op },
+       { "format",     NS_KEYWORD,     .op = &ignore_attr_op },
+       { "__format__", NS_KEYWORD,     .op = &ignore_attr_op },
+       { "__format_arg__",     NS_KEYWORD,     .op = &ignore_attr_op },
+       { "section",    NS_KEYWORD,     .op = &ignore_attr_op },
+       { "__section__",NS_KEYWORD,     .op = &ignore_attr_op },
+       { "unused",     NS_KEYWORD,     .op = &ignore_attr_op },
+       { "__unused__", NS_KEYWORD,     .op = &ignore_attr_op },
+       { "const",      NS_KEYWORD,     .op = &ignore_attr_op },
+       { "__const",    NS_KEYWORD,     .op = &ignore_attr_op },
+       { "__const__",  NS_KEYWORD,     .op = &ignore_attr_op },
+       { "noreturn",   NS_KEYWORD,     .op = &ignore_attr_op },
+       { "__noreturn__",       NS_KEYWORD,     .op = &ignore_attr_op },
+       { "no_instrument_function",     NS_KEYWORD,     .op = &ignore_attr_op },
+       { "__no_instrument_function__", NS_KEYWORD,     .op = &ignore_attr_op },
+       { "sentinel",   NS_KEYWORD,     .op = &ignore_attr_op },
+       { "__sentinel__",       NS_KEYWORD,     .op = &ignore_attr_op },
+       { "regparm",    NS_KEYWORD,     .op = &ignore_attr_op },
+       { "weak",       NS_KEYWORD,     .op = &ignore_attr_op },
+       { "__weak__",   NS_KEYWORD,     .op = &ignore_attr_op },
+       { "alias",      NS_KEYWORD,     .op = &ignore_attr_op },
+       { "__alias__",  NS_KEYWORD,     .op = &ignore_attr_op },
+       { "pure",       NS_KEYWORD,     .op = &ignore_attr_op },
+       { "__pure__",   NS_KEYWORD,     .op = &ignore_attr_op },
+       { "always_inline",      NS_KEYWORD,     .op = &ignore_attr_op },
+       { "syscall_linkage",    NS_KEYWORD,     .op = &ignore_attr_op },
+       { "visibility", NS_KEYWORD,     .op = &ignore_attr_op },
+       { "__visibility__",     NS_KEYWORD,     .op = &ignore_attr_op },
+       { "deprecated", NS_KEYWORD,     .op = &ignore_attr_op },
+       { "__deprecated__",     NS_KEYWORD,     .op = &ignore_attr_op },
+       { "noinline",   NS_KEYWORD,     .op = &ignore_attr_op },
+       { "__used__",   NS_KEYWORD,     .op = &ignore_attr_op },
+       { "warn_unused_result", NS_KEYWORD,     .op = &ignore_attr_op },
+       { "__warn_unused_result__",     NS_KEYWORD,     .op = &ignore_attr_op },
+       { "model",      NS_KEYWORD,     .op = &ignore_attr_op },
+       { "__model__",  NS_KEYWORD,     .op = &ignore_attr_op },
 };
 
 void init_parser(int stream)
@@ -621,180 +741,124 @@ static struct token *typeof_specifier(st
        return expect(token, ')', "after typeof");
 }
 
-static const char * handle_attribute(struct ctype *ctype, struct ident 
*attribute, struct expression *expr)
+static struct token *ignore_attribute(struct token *token, struct symbol 
*attr, struct ctype *ctype)
 {
-       if (attribute == &packed_ident ||
-           attribute == &__packed___ident) {
-               ctype->alignment = 1;
-               return NULL;
-       }
-       if (attribute == &aligned_ident ||
-           attribute == &__aligned___ident) {
-               int alignment = max_alignment;
+       struct expression *expr = NULL;
+       if (match_op(token, '('))
+               token = parens_expression(token, &expr, "in attribute");
+       return token;
+}
+
+static struct token *attribute_packed(struct token *token, struct symbol 
*attr, struct ctype *ctype)
+{
+       ctype->alignment = 1;
+       return token;
+}
+
+static struct token *attribute_aligned(struct token *token, struct symbol 
*attr, struct ctype *ctype)
+{
+       int alignment = max_alignment;
+       struct expression *expr = NULL;
+
+       if (match_op(token, '(')) {
+               token = parens_expression(token, &expr, "in attribute");
                if (expr)
                        alignment = get_expression_value(expr);
-               ctype->alignment = alignment;
-               return NULL;
        }
-       if (attribute == &nocast_ident) {
-               ctype->modifiers |= MOD_NOCAST;
-               return NULL;
-       }
-       if (attribute == &noderef_ident) {
-               ctype->modifiers |= MOD_NODEREF;
-               return NULL;
-       }
-       if (attribute == &safe_ident) {
-               ctype->modifiers |= MOD_SAFE;
-               return NULL;
-       }
-       if (attribute == &force_ident) {
-               ctype->modifiers |= MOD_FORCE;
-               return NULL;
-       }
-       if (attribute == &bitwise_ident ||
-            attribute == &__bitwise___ident) {
-               if (Wbitwise)
-                       ctype->modifiers |= MOD_BITWISE;
-               return NULL;
-       }
-       if (attribute == &address_space_ident) {
-               if (!expr)
-                       return "expected address space number";
+       ctype->alignment = alignment;
+       return token;
+}
+
+static struct token *attribute_modifier(struct token *token, struct symbol 
*attr, struct ctype *ctype)
+{
+       ctype->modifiers |= attr->ctype.modifiers;
+       return token;
+}
+
+static struct token *attribute_address_space(struct token *token, struct 
symbol *attr, struct ctype *ctype)
+{
+       struct expression *expr = NULL;
+       token = expect(token, '(', "after address_space attribute");
+       token = conditional_expression(token, &expr);
+       if (expr)
                ctype->as = get_expression_value(expr);
-               return NULL;
-       }
-       if (attribute == &context_ident) {
-               if (expr && expr->type == EXPR_COMMA) {
-                       struct context *context = alloc_context();
-                       if(expr->left->type == EXPR_COMMA) {
-                               context->context = expr->left->left;
-                               context->in = get_expression_value(
-                                       expr->left->right);
-                       } else {
-                               context->context = NULL;
-                               context->in = get_expression_value(expr->left);
-                       }
-                       context->out = get_expression_value(expr->right);
-                       add_ptr_list(&ctype->contexts, context);
-                       return NULL;
-               }
-               return "expected context input/output values";
-       }
-       if (attribute == &mode_ident ||
-           attribute == &__mode___ident) {
-               if (expr && expr->type == EXPR_SYMBOL) {
-                       struct ident *ident = expr->symbol_name;
+       token = expect(token, ')', "after address_space attribute");
+       return token;
+}
 
-                       /*
-                        * Match against __QI__/__HI__/__SI__/__DI__
-                        *
-                        * FIXME! This is broken - we don't actually get
-                        * the type information updated properly at this
-                        * stage for some reason.
-                        */
-                       if (ident == &__QI___ident ||
-                           ident == &QI_ident) {
-                               ctype->modifiers |= MOD_CHAR;
-                               return NULL;
-                       }
-                       if (ident == &__HI___ident ||
-                           ident == &HI_ident) {
-                               ctype->modifiers |= MOD_SHORT;
-                               return NULL;
-                       }
-                       if (ident == &__SI___ident ||
-                           ident == &SI_ident) {
-                               /* Nothing? */
-                               return NULL;
-                       }
-                       if (ident == &__DI___ident ||
-                           ident == &DI_ident) {
-                               ctype->modifiers |= MOD_LONGLONG;
-                               return NULL;
-                       }
-                       if (ident == &__word___ident ||
-                           ident == &word_ident) {
-                               ctype->modifiers |= MOD_LONG;
-                               return NULL;
-                       }
-                       return "unknown mode attribute";
+static struct token *attribute_mode(struct token *token, struct symbol *attr, 
struct ctype *ctype)
+{
+       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)
+                       ctype->modifiers |= mode->ctype.modifiers;
+               else
+                       sparse_error(token->pos, "unknown mode attribute %s\n", 
show_ident(token->ident));
+               token = token->next;
+       } else 
+               sparse_error(token->pos, "expect attribute mode symbol\n");
+       token = expect(token, ')', "after mode attribute");
+       return token;
+}
+
+static struct token *attribute_context(struct token *token, struct symbol 
*attr, struct ctype *ctype)
+{
+       struct context *context = alloc_context();
+       int argc = 0;
+
+       token = expect(token, '(', "after context attribute");
+       while (!match_op(token, ')')) {
+               struct expression *expr = NULL;
+               token = conditional_expression(token, &expr);
+               if (!expr)
+                       break;
+               switch(++argc) {
+               case 1:
+                       context->context = expr;
+                       break;
+               case 2:
+                       context->in = get_expression_value(expr);
+                       break;
+               case 3:
+                       context->out = get_expression_value(expr);
+                       break;
                }
-               return "expected attribute mode symbol";
+               if (!match_op(token, ','))
+                       break;
+               token = token->next;
        }
-
-       /* Throw away for now.. */
-       if (attribute == &__transparent_union___ident) {
-               if (Wtransparent_union)
-                   return "ignoring attribute __transparent_union__";
-               return NULL;
+       
+       if (argc == 1) {
+               context->in = get_expression_value(context->context);
+               context->context = NULL;
        }
-       if (attribute == &nothrow_ident ||
-           attribute == &__nothrow_ident ||
-           attribute == &__nothrow___ident)
-               return NULL;
-       if (attribute == &__malloc___ident)
-               return NULL;
-       if (attribute == &nonnull_ident ||
-           attribute == &__nonnull_ident ||
-           attribute == &__nonnull___ident)
-               return NULL;
-       if (attribute == &format_ident ||
-           attribute == &__format___ident ||
-           attribute == &__format_arg___ident)
-               return NULL;
-       if (attribute == &section_ident ||
-           attribute == &__section___ident)
-               return NULL;
-       if (attribute == &unused_ident ||
-           attribute == &__unused___ident)
-               return NULL;
-       if (attribute == &const_ident ||
-           attribute == &__const_ident ||
-           attribute == &__const___ident)
-               return NULL;
-       if (attribute == &noreturn_ident ||
-           attribute == &__noreturn___ident)
-               return NULL;
-       if (attribute == &no_instrument_function_ident ||
-           attribute == &__no_instrument_function___ident)
-               return NULL;
-       if (attribute == &sentinel_ident ||
-           attribute == &__sentinel___ident)
-               return NULL;
-       if (attribute == &regparm_ident)
-               return NULL;
-       if (attribute == &weak_ident ||
-           attribute == &__weak___ident)
-               return NULL;
-       if (attribute == &alias_ident ||
-           attribute == &__alias___ident)
-               return NULL;
-       if (attribute == &pure_ident ||
-           attribute == &__pure___ident)
-               return NULL;
-       if (attribute == &always_inline_ident)
-               return NULL;
-       if (attribute == &syscall_linkage_ident)
-               return NULL;
-       if (attribute == &visibility_ident ||
-           attribute == &__visibility___ident)
-               return NULL;
-       if (attribute == &deprecated_ident ||
-           attribute == &__deprecated___ident)
-               return NULL;
-       if (attribute == &noinline_ident)
-               return NULL;
-       if (attribute == &__used___ident)
-               return NULL;
-       if (attribute == &warn_unused_result_ident ||
-           attribute == &__warn_unused_result___ident)
-               return NULL;
-       if (attribute == &model_ident ||
-           attribute == &__model___ident)
-               return NULL;
 
-       return "unknown attribute";
+       if (argc)
+               add_ptr_list(&ctype->contexts, context);
+       else
+               sparse_error(token->pos, "expected context input/output 
values");
+
+       token = expect(token, ')', "after context attribute");
+       return token;
+}
+
+static struct token *attribute_transparent_union(struct token *token, struct 
symbol *attr, struct ctype *ctype)
+{
+       if (Wtransparent_union)
+               sparse_error(token->pos, "ignoring attribute 
__transparent_union__");
+       return token;
+}
+
+static struct token *recover_unknown_attribute(struct token *token)
+{
+       struct expression *expr = NULL;
+
+       sparse_error(token->pos, "attribute '%s': unknown attribute", 
show_ident(token->ident));
+       token = token->next;
+       if (match_op(token, '('))
+               token = parens_expression(token, &expr, "in attribute");
+       return token;
 }
 
 static struct token *attribute_specifier(struct token *token, struct ctype 
*ctype)
@@ -804,9 +868,8 @@ static struct token *attribute_specifier
        token = expect(token, '(', "after attribute");
 
        for (;;) {
-               const char *error_str;
                struct ident *attribute_name;
-               struct expression *attribute_expr;
+               struct symbol *attr;
 
                if (eof_token(token))
                        break;
@@ -815,13 +878,12 @@ static struct token *attribute_specifier
                if (token_type(token) != TOKEN_IDENT)
                        break;
                attribute_name = token->ident;
-               token = token->next;
-               attribute_expr = NULL;
-               if (match_op(token, '('))
-                       token = parens_expression(token, &attribute_expr, "in 
attribute");
-               error_str = handle_attribute(ctype, attribute_name, 
attribute_expr);
-               if (error_str)
-                       sparse_error(token->pos, "attribute '%s': %s", 
show_ident(attribute_name), error_str);
+               attr = lookup_keyword(attribute_name, NS_KEYWORD);
+               if (attr && attr->op->attribute)
+                       token = attr->op->attribute(token->next, attr, ctype);
+               else
+                       token = recover_unknown_attribute(token);
+       
                if (!match_op(token, ','))
                        break;
                token = token->next;
@@ -1030,23 +1092,18 @@ static struct token *declarator(struct t
 
 static struct token *handle_attributes(struct token *token, struct ctype 
*ctype)
 {
+       struct symbol *keyword;
        for (;;) {
+               struct ctype thistype = { 0, };
                if (token_type(token) != TOKEN_IDENT)
                        break;
-               if (match_idents(token, &__attribute___ident, 
&__attribute_ident, NULL)) {
-                       struct ctype thistype = { 0, };
-                       token = attribute_specifier(token->next, &thistype);
-                       apply_ctype(token->pos, &thistype, ctype);
-                       continue;
-               }
-               if (match_idents(token, &asm_ident, &__asm_ident, 
&__asm___ident, NULL)) {
-                       struct expression *expr;
-                       token = expect(token->next, '(', "after asm");
-                       token = parse_expression(token->next, &expr);
-                       token = expect(token, ')', "after asm");
-                       continue;
-               }
-               break;
+               keyword = lookup_keyword(token->ident, NS_KEYWORD | NS_TYPEDEF);
+               if (!keyword || keyword->type != SYM_KEYWORD)
+                       break;
+               if (!(keyword->op->type & (KW_ATTRIBUTE | KW_ASM)))
+                       break;
+               token = keyword->op->declarator(token->next, &thistype);
+               apply_ctype(token->pos, &thistype, ctype);
        }
        return token;
 }
@@ -1294,7 +1351,7 @@ static struct token *parse_asm_clobbers(
        return token;
 }
 
-static struct token *parse_asm(struct token *token, struct statement *stmt)
+static struct token *parse_asm_statement(struct token *token, struct statement 
*stmt)
 {
        token = token->next;
        stmt->type = STMT_ASM;
@@ -1313,6 +1370,15 @@ static struct token *parse_asm(struct to
        return expect(token, ';', "at end of asm-statement");
 }
 
+static struct token *parse_asm_declarator(struct token *token, struct ctype 
*ctype)
+{
+       struct expression *expr;
+       token = expect(token, '(', "after asm");
+       token = parse_expression(token->next, &expr);
+       token = expect(token, ')', "after asm");
+       return token;
+}
+
 /* Make a statement out of an expression */
 static struct statement *make_statement(struct expression *expr)
 {
@@ -1964,7 +2030,7 @@ static struct token *toplevel_asm_declar
        stmt = alloc_statement(token->pos, STMT_NONE);
        fn->stmt = stmt;
        
-       token = parse_asm(token, stmt);
+       token = parse_asm_statement(token, stmt);
 
        add_symbol(list, anon);
        return token;
Index: sparse/symbol.h
===================================================================
--- sparse.orig/symbol.h        2007-03-07 01:18:31.000000000 -0800
+++ sparse/symbol.h     2007-03-07 01:18:31.000000000 -0800
@@ -65,6 +65,8 @@ enum keyword {
        KW_ATTRIBUTE    = 1 << 3,
        KW_TYPEOF       = 1 << 4,
        KW_STATEMENT    = 1 << 5,
+       KW_ASM          = 1 << 6,
+       KW_MODE         = 1 << 7,
 };
 
 struct context {
@@ -94,6 +96,7 @@ struct symbol_op {
        struct token *(*declarator)(struct token *token, struct ctype *ctype);
        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 ctype *ctype);
 };     
 
 extern int expand_safe_p(struct expression *expr, int cost);
Index: sparse/lib.c
===================================================================
Index: sparse/ident-list.h
===================================================================
-
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to