From e5d710cac54ffc472cd839060a7a18ddc563a608 Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Mon, 25 May 2020 23:10:53 +0200 Subject: show-mod: add helper to show the modifiers but without ending space modifier_string() returns either "" or a string with one or several modifiers separated by a space. In this last case the string has also a trailing space. This trailing space is sometimes desired (for example when composed with identifier name: "%s%s") but is also sometimes not desired (for example when only the modifiers must be displayed). So, create a variant of modifier_string() which doesn't add the ending space: modifier_name(). Signed-off-by: Luc Van Oostenryck --- show-parse.c | 18 +++++++++++++++++- symbol.h | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/show-parse.c b/show-parse.c index 51a15191..17a4de8b 100644 --- a/show-parse.c +++ b/show-parse.c @@ -107,7 +107,7 @@ void debug_symbol(struct symbol *sym) * Symbol type printout. The type system is by far the most * complicated part of C - everything else is trivial. */ -const char *modifier_string(unsigned long mod) +static const char *show_modifiers(unsigned long mod, int term) { static char buffer[100]; int len = 0; @@ -155,10 +155,26 @@ const char *modifier_string(unsigned long mod) buffer[len++] = ' '; } } + if (len && !term) // strip the trailing space + --len; buffer[len] = 0; return buffer; } +/// +// show the modifiers, terminated by a space if not empty +const char *modifier_string(unsigned long mod) +{ + return show_modifiers(mod, 1); +} + +/// +// show the modifiers, without an ending space +const char *modifier_name(unsigned long mod) +{ + return show_modifiers(mod, 0); +} + static void show_struct_member(struct symbol *sym) { printf("\t%s:%d:%ld at offset %ld.%d", show_ident(sym->ident), sym->bit_size, sym->ctype.alignment, sym->offset, sym->bit_offset); diff --git a/symbol.h b/symbol.h index c2b60ce9..4792b008 100644 --- a/symbol.h +++ b/symbol.h @@ -327,6 +327,7 @@ extern void init_linearized_builtins(int stream); extern void init_ctype(void); extern struct symbol *alloc_symbol(struct position, int type); extern void show_type(struct symbol *); +extern const char *modifier_name(unsigned long mod); extern const char *modifier_string(unsigned long mod); extern void show_symbol(struct symbol *); extern int show_symbol_expr_init(struct symbol *sym); -- cgit 1.2.3-korg From 1eaabedb4c8afc56156acbc4acc9547eb918440f Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Mon, 25 May 2020 23:20:03 +0200 Subject: show-mod: no ending space when showing a single modifier Signed-off-by: Luc Van Oostenryck --- parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parse.c b/parse.c index cc5dbd52..cc46f1a6 100644 --- a/parse.c +++ b/parse.c @@ -1151,7 +1151,7 @@ static struct token *attribute_aligned(struct token *token, struct symbol *attr, static void apply_mod(struct position *pos, unsigned long *mods, unsigned long mod) { if (*mods & mod & ~MOD_DUP_OK) - warning(*pos, "duplicate %s", modifier_string(mod)); + warning(*pos, "duplicate %s", modifier_name(mod)); *mods |= mod; } -- cgit 1.2.3-korg From 39644bf3fe36090ad97d10d6301f3b75def9d3e2 Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Mon, 25 May 2020 23:22:16 +0200 Subject: show-mod: no extra space when showing modifiers + ident Signed-off-by: Luc Van Oostenryck --- show-parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/show-parse.c b/show-parse.c index 17a4de8b..0546a7b9 100644 --- a/show-parse.c +++ b/show-parse.c @@ -70,7 +70,7 @@ static void do_debug_symbol(struct symbol *sym, int indent) if (!sym) return; - fprintf(stderr, "%.*s%s%3d:%lu %s %s (as: %s) %p (%s:%d:%d) %s\n", + fprintf(stderr, "%.*s%s%3d:%lu %s%s (as: %s) %p (%s:%d:%d) %s\n", indent, indent_string, typestr[sym->type], sym->bit_size, sym->ctype.alignment, modifier_string(sym->ctype.modifiers), show_ident(sym->ident), -- cgit 1.2.3-korg From e7dad08db283421a46c138f6aaee19505a96bc19 Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Fri, 17 Jul 2020 03:59:47 +0200 Subject: use lookup_keyword() for qualifiers When handling qualifiers, the corresponding symbol is looked-up with lookup_symbol() then it's checked if the symbol's type is SYM_KEYWORD. But, only if the identifier is a keyword (struct ident::keyword) can the symbol be a SYM_KEYWORD. Thus, non-keyword can be filtered-out early by using lookup_keyword(). So change the call to lookup_symbol() by a call to lookup_keyword(). Signed-off-by: Luc Van Oostenryck --- parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parse.c b/parse.c index b07237ee..19520eae 100644 --- a/parse.c +++ b/parse.c @@ -1618,7 +1618,7 @@ struct symbol *ctype_integer(int size, int want_unsigned) static struct token *handle_qualifiers(struct token *t, struct decl_state *ctx) { while (token_type(t) == TOKEN_IDENT) { - struct symbol *s = lookup_symbol(t->ident, NS_TYPEDEF); + struct symbol *s = lookup_keyword(t->ident, NS_TYPEDEF); if (!s) break; if (s->type != SYM_KEYWORD) -- cgit 1.2.3-korg From c6b40f4538f8fb3c55ef65f31808b8905a375b6e Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Sat, 13 Jun 2020 13:01:17 +0200 Subject: attribute: split handle_asm_name() from handle_attributes() handle_attributes() handles attributes but also the asm names. These asm names must occur before the attributes and only once while the attributes may occur multiple time. Also, these asm names are not allowed everywhere attributes, only in declarations. It's maybe handy to process both in the same function but it's also slightly confusing. So, move the handling of the asm names in a separate function. Signed-off-by: Luc Van Oostenryck --- parse.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/parse.c b/parse.c index 19520eae..cf897e5d 100644 --- a/parse.c +++ b/parse.c @@ -1742,6 +1742,20 @@ static struct token *parameter_type_list(struct token *, struct symbol *); static struct token *identifier_list(struct token *, struct symbol *); static struct token *declarator(struct token *token, struct decl_state *ctx); +static struct token *handle_asm_name(struct token *token, struct decl_state *ctx) +{ + struct symbol *keyword; + + if (token_type(token) != TOKEN_IDENT) + return token; + keyword = lookup_keyword(token->ident, NS_KEYWORD); + if (!keyword || keyword->type != SYM_KEYWORD) + return token; + if (!(keyword->op->type & KW_ASM)) + return token; + return keyword->op->declarator(token->next, ctx); +} + static struct token *skip_attribute(struct token *token) { token = token->next; @@ -1798,7 +1812,6 @@ static struct token *handle_attributes(struct token *token, struct decl_state *c if (!(keyword->op->type & keywords)) break; token = keyword->op->declarator(token->next, ctx); - keywords &= KW_ATTRIBUTE; } return token; } @@ -3018,7 +3031,8 @@ struct token *external_declaration(struct token *token, struct symbol_list **lis saved = ctx.ctype; token = declarator(token, &ctx); - token = handle_attributes(token, &ctx, KW_ATTRIBUTE | KW_ASM); + token = handle_asm_name(token, &ctx); + token = handle_attributes(token, &ctx, KW_ATTRIBUTE); apply_modifiers(token->pos, &ctx); decl->ctype = ctx.ctype; @@ -3142,7 +3156,8 @@ struct token *external_declaration(struct token *token, struct symbol_list **lis ctx.ctype = saved; token = handle_attributes(token, &ctx, KW_ATTRIBUTE); token = declarator(token, &ctx); - token = handle_attributes(token, &ctx, KW_ATTRIBUTE | KW_ASM); + token = handle_asm_name(token, &ctx); + token = handle_attributes(token, &ctx, KW_ATTRIBUTE); apply_modifiers(token->pos, &ctx); decl->ctype = ctx.ctype; decl->ctype.modifiers |= mod; -- cgit 1.2.3-korg From e31f8759b06c20a0e1c26ef94bdb8950326e243e Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Wed, 15 Jul 2020 14:34:42 +0200 Subject: attribute: fold parse_asm_declarator() into handle_asm_name() An asm name is not really a declarator, it must only be placed *after* a declarator and is directly handled by handle_asm_name(). It's thus not needed and possibly confusing to treat it like a generic declarator. So, fold parse_asm_declarator() into handle_asm_name() and remove it. Signed-off-by: Luc Van Oostenryck --- parse.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/parse.c b/parse.c index cf897e5d..73ec579c 100644 --- a/parse.c +++ b/parse.c @@ -54,7 +54,7 @@ static struct token *handle_attributes(struct token *token, struct decl_state *c typedef struct token *declarator_t(struct token *, struct decl_state *); static declarator_t struct_specifier, union_specifier, enum_specifier, - attribute_specifier, typeof_specifier, parse_asm_declarator, + attribute_specifier, typeof_specifier, typedef_specifier, inline_specifier, auto_specifier, register_specifier, static_specifier, extern_specifier, thread_specifier, const_qualifier, volatile_qualifier; @@ -363,7 +363,6 @@ static struct symbol_op range_op = { static struct symbol_op asm_op = { .type = KW_ASM, - .declarator = parse_asm_declarator, .statement = parse_asm_statement, .toplevel = toplevel_asm_declaration, }; @@ -1744,6 +1743,7 @@ static struct token *declarator(struct token *token, struct decl_state *ctx); static struct token *handle_asm_name(struct token *token, struct decl_state *ctx) { + struct expression *expr; struct symbol *keyword; if (token_type(token) != TOKEN_IDENT) @@ -1753,7 +1753,12 @@ static struct token *handle_asm_name(struct token *token, struct decl_state *ctx return token; if (!(keyword->op->type & KW_ASM)) return token; - return keyword->op->declarator(token->next, ctx); + + token = token->next; + token = expect(token, '(', "after asm"); + token = string_expression(token, &expr, "asm name"); + token = expect(token, ')', "after asm"); + return token; } static struct token *skip_attribute(struct token *token) @@ -2181,15 +2186,6 @@ static struct token *parse_asm_statement(struct token *token, struct statement * return expect(token, ';', "at end of asm-statement"); } -static struct token *parse_asm_declarator(struct token *token, struct decl_state *ctx) -{ - struct expression *expr; - token = expect(token, '(', "after asm"); - token = string_expression(token, &expr, "inline asm"); - token = expect(token, ')', "after asm"); - return token; -} - static struct token *parse_static_assert(struct token *token, struct symbol_list **unused) { struct expression *cond = NULL, *message = NULL; -- cgit 1.2.3-korg From 1069b76d5bef127e98beb600cf279bba1fbd6163 Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Wed, 15 Jul 2020 14:25:26 +0200 Subject: attribute: remove argument 'keywords' from handle_attributes() Now that the asm names are handled in handle_asm(), the 'keywords' argument of handle_attributes() is no more needed since it always must be 'KW_ATTRIBUTE'. So, remove this argument. Note: this is preparation work to later make the distinction between function/variable/type/label/... attributes. Signed-off-by: Luc Van Oostenryck --- parse.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/parse.c b/parse.c index 73ec579c..ec675f20 100644 --- a/parse.c +++ b/parse.c @@ -49,7 +49,7 @@ struct symbol_list *function_computed_target_list; struct statement_list *function_computed_goto_list; static struct token *statement(struct token *token, struct statement **tree); -static struct token *handle_attributes(struct token *token, struct decl_state *ctx, unsigned int keywords); +static struct token *handle_attributes(struct token *token, struct decl_state *ctx); typedef struct token *declarator_t(struct token *, struct decl_state *); static declarator_t @@ -756,7 +756,7 @@ static struct token *struct_union_enum_specifier(enum type type, struct symbol *sym; struct position *repos; - token = handle_attributes(token, ctx, KW_ATTRIBUTE); + token = handle_attributes(token, ctx); if (token_type(token) == TOKEN_IDENT) { sym = lookup_symbol(token->ident, NS_STRUCT); if (!sym || @@ -956,7 +956,7 @@ static struct token *parse_enum_declaration(struct token *token, struct symbol * struct symbol *sym; // FIXME: only 'deprecated' should be accepted - next = handle_attributes(next, &ctx, KW_ATTRIBUTE); + next = handle_attributes(next, &ctx); if (match_op(next, '=')) { next = constant_expression(next->next, &expr); @@ -1805,7 +1805,7 @@ static struct token *skip_attributes(struct token *token) return token; } -static struct token *handle_attributes(struct token *token, struct decl_state *ctx, unsigned int keywords) +static struct token *handle_attributes(struct token *token, struct decl_state *ctx) { struct symbol *keyword; for (;;) { @@ -1814,7 +1814,7 @@ static struct token *handle_attributes(struct token *token, struct decl_state *c keyword = lookup_keyword(token->ident, NS_KEYWORD | NS_TYPEDEF); if (!keyword || keyword->type != SYM_KEYWORD) break; - if (!(keyword->op->type & keywords)) + if (!(keyword->op->type & KW_ATTRIBUTE)) break; token = keyword->op->declarator(token->next, ctx); } @@ -1903,8 +1903,7 @@ static struct token *direct_declarator(struct token *token, struct decl_state *c is_nested(token, &next, ctx->prefer_abstract)) { struct symbol *base_type = ctype->base_type; if (token->next != next) - next = handle_attributes(token->next, ctx, - KW_ATTRIBUTE); + next = handle_attributes(token->next, ctx); token = declarator(next, ctx); token = expect(token, ')', "in nested declarator"); while (ctype->base_type != base_type) @@ -2027,7 +2026,7 @@ static struct token *declaration_list(struct token *token, struct symbol_list ** if (match_op(token, ':')) token = handle_bitfield(token, &ctx); - token = handle_attributes(token, &ctx, KW_ATTRIBUTE); + token = handle_attributes(token, &ctx); apply_modifiers(token->pos, &ctx); decl->ctype = ctx.ctype; @@ -2067,7 +2066,7 @@ static struct token *parameter_declaration(struct token *token, struct symbol *s token = declaration_specifiers(token, &ctx); ctx.ident = &sym->ident; token = declarator(token, &ctx); - token = handle_attributes(token, &ctx, KW_ATTRIBUTE); + token = handle_attributes(token, &ctx); apply_modifiers(token->pos, &ctx); sym->ctype = ctx.ctype; sym->ctype.modifiers |= decl_modifiers(&ctx); @@ -2567,7 +2566,7 @@ static struct token *handle_label_attributes(struct token *token, struct symbol { struct decl_state ctx = { }; - token = handle_attributes(token, &ctx, KW_ATTRIBUTE); + token = handle_attributes(token, &ctx); label->label_modifiers = ctx.ctype.modifiers; return token; } @@ -3028,7 +3027,7 @@ struct token *external_declaration(struct token *token, struct symbol_list **lis saved = ctx.ctype; token = declarator(token, &ctx); token = handle_asm_name(token, &ctx); - token = handle_attributes(token, &ctx, KW_ATTRIBUTE); + token = handle_attributes(token, &ctx); apply_modifiers(token->pos, &ctx); decl->ctype = ctx.ctype; @@ -3150,10 +3149,10 @@ struct token *external_declaration(struct token *token, struct symbol_list **lis ident = NULL; decl = alloc_symbol(token->pos, SYM_NODE); ctx.ctype = saved; - token = handle_attributes(token, &ctx, KW_ATTRIBUTE); + token = handle_attributes(token, &ctx); token = declarator(token, &ctx); token = handle_asm_name(token, &ctx); - token = handle_attributes(token, &ctx, KW_ATTRIBUTE); + token = handle_attributes(token, &ctx); apply_modifiers(token->pos, &ctx); decl->ctype = ctx.ctype; decl->ctype.modifiers |= mod; -- cgit 1.2.3-korg From 3ba7f29e393c28861e15e113ed3c9698bd00ef6f Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Wed, 15 Jul 2020 14:38:46 +0200 Subject: attribute: directly use attribute_specifier() to handle attributes handle_attributes() used to also handle asm names and so used the declarator method associated to the taken. But now, asm names are handled in a separated function. So, directly use attribute_specifier() to handle the attributes instead of using it via the declarator method. Signed-off-by: Luc Van Oostenryck --- parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parse.c b/parse.c index ec675f20..14b1746d 100644 --- a/parse.c +++ b/parse.c @@ -1816,7 +1816,7 @@ static struct token *handle_attributes(struct token *token, struct decl_state *c break; if (!(keyword->op->type & KW_ATTRIBUTE)) break; - token = keyword->op->declarator(token->next, ctx); + token = attribute_specifier(token->next, ctx); } return token; } -- cgit 1.2.3-korg From 49fc08a0378a482e1d7db8ddc508bed11a3787ae Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Thu, 16 Jul 2020 18:26:21 +0200 Subject: attribute: factorize matching of '__attribute__' Matching the keyword '__attribute__' (or '__attribute') needs several tests and this matching is needed to handle attributes or to skip them. So, create an helper, match_attribute(), and use it in the loops to handle and to skip attributes. Signed-off-by: Luc Van Oostenryck --- parse.c | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/parse.c b/parse.c index 14b1746d..681d98e4 100644 --- a/parse.c +++ b/parse.c @@ -1761,6 +1761,20 @@ static struct token *handle_asm_name(struct token *token, struct decl_state *ctx return token; } +/// +// test if @token is '__attribute__' (or one of its variant) +static bool match_attribute(struct token *token) +{ + struct symbol *sym; + + if (token_type(token) != TOKEN_IDENT) + return false; + sym = lookup_keyword(token->ident, NS_KEYWORD | NS_TYPEDEF); + if (!sym || sym->type != SYM_KEYWORD) + return false; + return sym->op->type & KW_ATTRIBUTE; +} + static struct token *skip_attribute(struct token *token) { token = token->next; @@ -1782,15 +1796,7 @@ static struct token *skip_attribute(struct token *token) static struct token *skip_attributes(struct token *token) { - struct symbol *keyword; - for (;;) { - if (token_type(token) != TOKEN_IDENT) - break; - keyword = lookup_keyword(token->ident, NS_KEYWORD | NS_TYPEDEF); - if (!keyword || keyword->type != SYM_KEYWORD) - break; - if (!(keyword->op->type & KW_ATTRIBUTE)) - break; + while (match_attribute(token)) { token = expect(token->next, '(', "after attribute"); token = expect(token, '(', "after attribute"); while (token_type(token) == TOKEN_IDENT) { @@ -1807,17 +1813,8 @@ static struct token *skip_attributes(struct token *token) static struct token *handle_attributes(struct token *token, struct decl_state *ctx) { - struct symbol *keyword; - for (;;) { - if (token_type(token) != TOKEN_IDENT) - break; - keyword = lookup_keyword(token->ident, NS_KEYWORD | NS_TYPEDEF); - if (!keyword || keyword->type != SYM_KEYWORD) - break; - if (!(keyword->op->type & KW_ATTRIBUTE)) - break; + while (match_attribute(token)) token = attribute_specifier(token->next, ctx); - } return token; } -- cgit 1.2.3-korg From 99f8202a62d33c76285a516aaec4aaefe9585223 Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Thu, 16 Jul 2020 18:50:40 +0200 Subject: attribute: no need to lookup '__attribute__' in NS_KEYWORD Since '__attribute__' is in NS_TYPEDEF, it's not useful to look it up also in NS_KEYWORD. So, remove NS_KEYWORD from the mask while looking up '__attribute__'. Signed-off-by: Luc Van Oostenryck --- parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parse.c b/parse.c index 681d98e4..f2fdbc9b 100644 --- a/parse.c +++ b/parse.c @@ -1769,7 +1769,7 @@ static bool match_attribute(struct token *token) if (token_type(token) != TOKEN_IDENT) return false; - sym = lookup_keyword(token->ident, NS_KEYWORD | NS_TYPEDEF); + sym = lookup_keyword(token->ident, NS_TYPEDEF); if (!sym || sym->type != SYM_KEYWORD) return false; return sym->op->type & KW_ATTRIBUTE; -- cgit 1.2.3-korg From f009179a05f74118549e4810c0681b4848e374d6 Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Sun, 19 Jul 2020 16:45:19 +0200 Subject: testing for SYM_KEYWORD is unneeded for lookup_keyword() All symbols returned by lookup_keyword() are of type SYM_KEYWORD, because either: 1) it's in NS_KEYWORD (and all symbol in NS_KEYWORD are SYM_KEYWORD) 2) it's in NS_TYPEDEF and all *keywords* in NS_TYPEDEF are reserved and so can't be user defined and so must be SYM_KEYWORD. It's thus unneeded to test it. So, remove the unneeded test. Signed-off-by: Luc Van Oostenryck --- parse.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/parse.c b/parse.c index f2fdbc9b..2b7ef2ae 100644 --- a/parse.c +++ b/parse.c @@ -1620,8 +1620,6 @@ static struct token *handle_qualifiers(struct token *t, struct decl_state *ctx) struct symbol *s = lookup_keyword(t->ident, NS_TYPEDEF); if (!s) break; - if (s->type != SYM_KEYWORD) - break; if (!(s->op->type & (KW_ATTRIBUTE | KW_QUALIFIER))) break; t = t->next; @@ -1749,7 +1747,7 @@ static struct token *handle_asm_name(struct token *token, struct decl_state *ctx if (token_type(token) != TOKEN_IDENT) return token; keyword = lookup_keyword(token->ident, NS_KEYWORD); - if (!keyword || keyword->type != SYM_KEYWORD) + if (!keyword) return token; if (!(keyword->op->type & KW_ASM)) return token; @@ -1770,7 +1768,7 @@ static bool match_attribute(struct token *token) if (token_type(token) != TOKEN_IDENT) return false; sym = lookup_keyword(token->ident, NS_TYPEDEF); - if (!sym || sym->type != SYM_KEYWORD) + if (!sym) return false; return sym->op->type & KW_ATTRIBUTE; } -- cgit 1.2.3-korg From 3832167298fa0e9329bf1dd4d78cb47e6179493d Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Sun, 19 Jul 2020 16:45:19 +0200 Subject: testing for sym->op is unneeded for lookup_keyword() All symbols returned by lookup_keyword() are of type SYM_KEYWORD, because either: 1) it's in NS_KEYWORD (and all symbol in NS_KEYWORD are SYM_KEYWORD) 2) it's in NS_TYPEDEF and all *keywords* in NS_TYPEDEF are reserved and so can't be user defined and so must be SYM_KEYWORD. Thus, they all have a symbol_op associated to them and it's unneeded to test it. So, remove the unneeded test. Signed-off-by: Luc Van Oostenryck --- parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parse.c b/parse.c index 2b7ef2ae..d378f125 100644 --- a/parse.c +++ b/parse.c @@ -2160,7 +2160,7 @@ static struct token *parse_asm_statement(struct token *token, struct statement * stmt->type = STMT_ASM; while (token_type(token) == TOKEN_IDENT) { struct symbol *s = lookup_keyword(token->ident, NS_TYPEDEF); - if (s && s->op && s->op->asm_modifier) + if (s && s->op->asm_modifier) s->op->asm_modifier(token, &mods); else if (token->ident == &goto_ident) asm_modifier(token, &mods, MOD_ASM_GOTO); -- cgit 1.2.3-korg From 6b53fc26ca9b625670fd02e12463e8fc3aed646f Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Sun, 19 Jul 2020 17:12:23 +0200 Subject: keyword type is a bitmask and must be tested so The keyword's type is a bitmask because depending on the context the same keyword can be of different type (for example 'const' as qualifier and the attribute 'const' , a variant of 'pure'). Thus, it's an error to test this type for equality, instead it's a specific (set of) bit(s) that must be tested. So, change a test ' x == KW_...' into 'x & KW_...'. Signed-off-by: Luc Van Oostenryck --- parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parse.c b/parse.c index d378f125..e1a5cce4 100644 --- a/parse.c +++ b/parse.c @@ -1287,7 +1287,7 @@ static struct token *attribute_mode(struct token *token, struct symbol *attr, st 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) + if (mode && mode->op->type & KW_MODE) ctx->mode = mode->op; else sparse_error(token->pos, "unknown mode attribute %s", show_ident(token->ident)); -- cgit 1.2.3-korg From bc9fc82e7771a3b2dc55db36b8d654243eb2d187 Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Mon, 20 Jul 2020 01:17:09 +0200 Subject: parse: rework handling of storage_class The handling of the storage class modifiers is done differently than the other modifiers: * they don't use MOD_... but their own enums * consequently they can't use modifier_string() and have their own string table to display them. * the attribute 'force' is considered as a kind of storage class. Fine, but it means that 'register' or '__tls' can't be used with 'force' (which is probably very fine but seems more as a side-effect than something really desired). The real justification for these difference seems to be that storage class modifiers *must* be treated differently than the other modifiers because they don't apply at the same level. For example, in a declaration like: static const int a[N]; 'static' applies to the array/the whole object, while 'const' only applies to the (type of the) elements of the array. Storage class specifiers must thus be parsed, stored aside and only be applied after the whole declarator have been parsed. But other modifiers are also in the same situation (for example, '__noreturn' or '__pure' for functions). So, use the generic keyword/attribute handling of modifiers for storage class specifiers but for simplicity, store them separately in decl_state to easily do duplication tests on them. Signed-off-by: Luc Van Oostenryck --- parse.c | 71 ++++++++++++++++++++-------------------------------------------- symbol.h | 4 +++- 2 files changed, 25 insertions(+), 50 deletions(-) diff --git a/parse.c b/parse.c index cc46f1a6..2711022a 100644 --- a/parse.c +++ b/parse.c @@ -116,10 +116,6 @@ enum { CInt = 0, CSInt, CUInt, CReal, }; -enum { - SNone = 0, STypedef, SAuto, SRegister, SExtern, SStatic, SForced, SMax, -}; - static void asm_modifier(struct token *token, unsigned long *mods, unsigned long mod) { if (*mods & mod) @@ -1389,85 +1385,67 @@ static struct token *attribute_specifier(struct token *token, struct decl_state return token; } -static const char *storage_class[] = -{ - [STypedef] = "typedef", - [SAuto] = "auto", - [SExtern] = "extern", - [SStatic] = "static", - [SRegister] = "register", - [SForced] = "[force]" -}; - static unsigned long decl_modifiers(struct decl_state *ctx) { - static unsigned long mod[SMax] = - { - [SAuto] = MOD_AUTO, - [SExtern] = MOD_EXTERN, - [SStatic] = MOD_STATIC, - [SRegister] = MOD_REGISTER - }; unsigned long mods = ctx->ctype.modifiers & MOD_DECLARE; ctx->ctype.modifiers &= ~MOD_DECLARE; - return mod[ctx->storage_class] | mods; + return ctx->storage_class | mods; } -static void set_storage_class(struct position *pos, struct decl_state *ctx, int class) +static void set_storage_class(struct position *pos, struct decl_state *ctx, unsigned long class) { int is_tls = ctx->ctype.modifiers & MOD_TLS; + const char *storage = modifier_string(class); + /* __thread can be used alone, or with extern or static */ - if (is_tls && (class != SStatic && class != SExtern)) { + if (is_tls && (class & ~(MOD_STATIC|MOD_EXTERN))) { sparse_error(*pos, "__thread can only be used alone, or with " "extern or static"); return; } - if (!ctx->storage_class) { + if (!ctx->storage_class) ctx->storage_class = class; - return; - } - if (ctx->storage_class == class) - sparse_error(*pos, "duplicate %s", storage_class[class]); + else if (ctx->storage_class == class) + sparse_error(*pos, "duplicate %s", storage); else sparse_error(*pos, "multiple storage classes"); } static struct token *typedef_specifier(struct token *next, struct decl_state *ctx) { - set_storage_class(&next->pos, ctx, STypedef); + set_storage_class(&next->pos, ctx, MOD_USERTYPE); return next; } static struct token *auto_specifier(struct token *next, struct decl_state *ctx) { - set_storage_class(&next->pos, ctx, SAuto); + set_storage_class(&next->pos, ctx, MOD_AUTO); return next; } static struct token *register_specifier(struct token *next, struct decl_state *ctx) { - set_storage_class(&next->pos, ctx, SRegister); + set_storage_class(&next->pos, ctx, MOD_REGISTER); return next; } static struct token *static_specifier(struct token *next, struct decl_state *ctx) { - set_storage_class(&next->pos, ctx, SStatic); + set_storage_class(&next->pos, ctx, MOD_STATIC); return next; } static struct token *extern_specifier(struct token *next, struct decl_state *ctx) { - set_storage_class(&next->pos, ctx, SExtern); + set_storage_class(&next->pos, ctx, MOD_EXTERN); return next; } static struct token *thread_specifier(struct token *next, struct decl_state *ctx) { /* This GCC extension can be used alone, or with extern or static */ - if (!ctx->storage_class || ctx->storage_class == SStatic - || ctx->storage_class == SExtern) { + if (!(ctx->storage_class & ~(MOD_STATIC|MOD_EXTERN))) { apply_qualifier(&next->pos, &ctx->ctype, MOD_TLS); } else { sparse_error(next->pos, "__thread can only be used alone, or " @@ -1479,7 +1457,7 @@ static struct token *thread_specifier(struct token *next, struct decl_state *ctx static struct token *attribute_force(struct token *token, struct symbol *attr, struct decl_state *ctx) { - set_storage_class(&token->pos, ctx, SForced); + ctx->forced = 1; return token; } @@ -2070,14 +2048,14 @@ static struct token *parameter_declaration(struct token *token, struct symbol *s sym->ctype = ctx.ctype; sym->ctype.modifiers |= decl_modifiers(&ctx); sym->endpos = token->pos; - sym->forced_arg = ctx.storage_class == SForced; + sym->forced_arg = ctx.forced; return token; } struct token *typename(struct token *token, struct symbol **p, int *forced) { struct decl_state ctx = {.prefer_abstract = 1}; - int class; + unsigned long class; struct symbol *sym = alloc_symbol(token->pos, SYM_NODE); *p = sym; token = declaration_specifiers(token, &ctx); @@ -2086,16 +2064,11 @@ struct token *typename(struct token *token, struct symbol **p, int *forced) sym->ctype = ctx.ctype; sym->endpos = token->pos; class = ctx.storage_class; - if (forced) { - *forced = 0; - if (class == SForced) { - *forced = 1; - class = 0; - } - } + if (forced) + *forced = ctx.forced; if (class) - warning(sym->pos, "storage class in typename (%s %s)", - storage_class[class], show_typename(sym)); + warning(sym->pos, "storage class in typename (%s%s)", + modifier_string(class), show_typename(sym)); return token; } @@ -3048,7 +3021,7 @@ struct token *external_declaration(struct token *token, struct symbol_list **lis } /* type define declaration? */ - is_typedef = ctx.storage_class == STypedef; + is_typedef = ctx.storage_class == MOD_USERTYPE; /* Typedefs don't have meaningful storage */ if (is_typedef) diff --git a/symbol.h b/symbol.h index 4792b008..d2ca3d2d 100644 --- a/symbol.h +++ b/symbol.h @@ -108,8 +108,10 @@ struct decl_state { struct ident **ident; struct symbol_op *mode; unsigned long f_modifiers; // function attributes - unsigned char prefer_abstract, storage_class; + unsigned long storage_class; + unsigned char prefer_abstract; unsigned char autotype; + unsigned char forced; }; struct pseudo; -- cgit 1.2.3-korg From c27f83b3f13484c925a7af02f95b56090f6476d0 Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Mon, 20 Jul 2020 01:47:48 +0200 Subject: parse: associate modifiers with their keyword A significant number of declarators need to set or simply use the modifier associated with the corresponding keyword but this is open-coded for each of them. As result, almost all keywords corresponding to a declaration need their own specific method. Make this more generic by adding the associated modifier to the ctype associated to keywords and passing the result of the keyword lookup to the declarator methods. This way, these methods can be made generic by getting the modifier from the ctype, like it was already done for attributes. Signed-off-by: Luc Van Oostenryck --- parse.c | 156 +++++++++++++++++++-------------------------------------------- symbol.h | 2 +- 2 files changed, 48 insertions(+), 110 deletions(-) diff --git a/parse.c b/parse.c index 2711022a..37fe90c0 100644 --- a/parse.c +++ b/parse.c @@ -51,15 +51,12 @@ struct statement_list *function_computed_goto_list; static struct token *statement(struct token *token, struct statement **tree); static struct token *handle_attributes(struct token *token, struct decl_state *ctx, unsigned int keywords); -typedef struct token *declarator_t(struct token *, struct decl_state *); +typedef struct token *declarator_t(struct token *, struct symbol *, struct decl_state *); static declarator_t struct_specifier, union_specifier, enum_specifier, attribute_specifier, typeof_specifier, parse_asm_declarator, - typedef_specifier, inline_specifier, auto_specifier, - register_specifier, static_specifier, extern_specifier, - thread_specifier, const_qualifier, volatile_qualifier; -static declarator_t restrict_qualifier; -static declarator_t atomic_qualifier; + storage_specifier, thread_specifier; +static declarator_t generic_qualifier; static declarator_t autotype_specifier; static struct token *parse_if_statement(struct token *token, struct statement *stmt); @@ -135,19 +132,18 @@ static void asm_modifier_inline(struct token *token, unsigned long *mods) static struct symbol_op typedef_op = { .type = KW_MODIFIER, - .declarator = typedef_specifier, + .declarator = storage_specifier, }; static struct symbol_op inline_op = { .type = KW_MODIFIER, - .declarator = inline_specifier, + .declarator = generic_qualifier, .asm_modifier = asm_modifier_inline, }; -static declarator_t noreturn_specifier; static struct symbol_op noreturn_op = { .type = KW_MODIFIER, - .declarator = noreturn_specifier, + .declarator = generic_qualifier, }; static declarator_t alignas_specifier; @@ -158,22 +154,22 @@ static struct symbol_op alignas_op = { static struct symbol_op auto_op = { .type = KW_MODIFIER, - .declarator = auto_specifier, + .declarator = storage_specifier, }; static struct symbol_op register_op = { .type = KW_MODIFIER, - .declarator = register_specifier, + .declarator = storage_specifier, }; static struct symbol_op static_op = { .type = KW_MODIFIER, - .declarator = static_specifier, + .declarator = storage_specifier, }; static struct symbol_op extern_op = { .type = KW_MODIFIER, - .declarator = extern_specifier, + .declarator = storage_specifier, }; static struct symbol_op thread_op = { @@ -183,23 +179,23 @@ static struct symbol_op thread_op = { static struct symbol_op const_op = { .type = KW_QUALIFIER, - .declarator = const_qualifier, + .declarator = generic_qualifier, }; static struct symbol_op volatile_op = { .type = KW_QUALIFIER, - .declarator = volatile_qualifier, + .declarator = generic_qualifier, .asm_modifier = asm_modifier_volatile, }; static struct symbol_op restrict_op = { .type = KW_QUALIFIER, - .declarator = restrict_qualifier, + .declarator = generic_qualifier, }; static struct symbol_op atomic_op = { .type = KW_QUALIFIER, - .declarator = atomic_qualifier, + .declarator = generic_qualifier, }; static struct symbol_op typeof_op = { @@ -478,27 +474,27 @@ static struct init_keyword { #define U(I, O,...) N("__" I,O,##__VA_ARGS__), \ N("__" I "__",O,##__VA_ARGS__) /* Storage classes */ - N("auto", &auto_op), - N("register", ®ister_op), - N("static", &static_op), - N("extern", &extern_op), + N("auto", &auto_op, .mods = MOD_AUTO), + N("register", ®ister_op, .mods = MOD_REGISTER), + N("static", &static_op, .mods = MOD_STATIC), + N("extern", &extern_op, .mods = MOD_EXTERN), N("__thread", &thread_op), N("_Thread_local", &thread_op), - A("inline", &inline_op), + A("inline", &inline_op, .mods = MOD_INLINE), /* Typedef ... */ - N("typedef", &typedef_op), + N("typedef", &typedef_op, .mods = MOD_USERTYPE), A("typeof", &typeof_op), N("__auto_type", &autotype_op), /* Type qualifiers */ - A("const", &const_op), - A("volatile", &volatile_op), - A("restrict", &restrict_op), + A("const", &const_op, .mods = MOD_CONST), + A("volatile", &volatile_op, .mods = MOD_VOLATILE), + A("restrict", &restrict_op, .mods = MOD_RESTRICT), - N("_Atomic", &atomic_op), - N("_Noreturn", &noreturn_op), + N("_Atomic", &atomic_op, .mods = MOD_ATOMIC), + N("_Noreturn", &noreturn_op, .mods = MOD_NORETURN), N("_Alignas", &alignas_op), U("attribute", &attribute_op), @@ -826,12 +822,12 @@ static struct token *parse_union_declaration(struct token *token, struct symbol return struct_declaration_list(token, &sym->symbol_list); } -static struct token *struct_specifier(struct token *token, struct decl_state *ctx) +static struct token *struct_specifier(struct token *token, struct symbol *sym, struct decl_state *ctx) { return struct_union_enum_specifier(SYM_STRUCT, token, ctx, parse_struct_declaration); } -static struct token *union_specifier(struct token *token, struct decl_state *ctx) +static struct token *union_specifier(struct token *token, struct symbol *sym, struct decl_state *ctx) { return struct_union_enum_specifier(SYM_UNION, token, ctx, parse_union_declaration); } @@ -1065,7 +1061,7 @@ static struct token *parse_enum_declaration(struct token *token, struct symbol * return token; } -static struct token *enum_specifier(struct token *token, struct decl_state *ctx) +static struct token *enum_specifier(struct token *token, struct symbol *sym, struct decl_state *ctx) { struct token *ret = struct_union_enum_specifier(SYM_ENUM, token, ctx, parse_enum_declaration); struct ctype *ctype = &ctx->ctype.base_type->ctype; @@ -1078,15 +1074,15 @@ static struct token *enum_specifier(struct token *token, struct decl_state *ctx) static void apply_ctype(struct position pos, struct ctype *thistype, struct ctype *ctype); -static struct token *typeof_specifier(struct token *token, struct decl_state *ctx) +static struct token *typeof_specifier(struct token *token, struct symbol *sym, struct decl_state *ctx) { - struct symbol *sym; if (!match_op(token, '(')) { sparse_error(token->pos, "expected '(' after typeof"); return token; } if (lookup_type(token->next)) { + struct symbol *sym; token = typename(token->next, &sym, NULL); ctx->ctype.base_type = sym->ctype.base_type; apply_ctype(token->pos, &sym->ctype, &ctx->ctype); @@ -1104,7 +1100,7 @@ static struct token *typeof_specifier(struct token *token, struct decl_state *ct return expect(token, ')', "after typeof"); } -static struct token *autotype_specifier(struct token *token, struct decl_state *ctx) +static struct token *autotype_specifier(struct token *token, struct symbol *sym, struct decl_state *ctx) { ctx->ctype.base_type = &autotype_ctype; ctx->autotype = 1; @@ -1158,7 +1154,7 @@ static void apply_qualifier(struct position *pos, struct ctype *ctx, unsigned lo static struct token *attribute_modifier(struct token *token, struct symbol *attr, struct decl_state *ctx) { - apply_qualifier(&token->pos, &ctx->ctype, attr->ctype.modifiers); + apply_mod(&token->pos, &ctx->ctype.modifiers, attr->ctype.modifiers); return token; } @@ -1353,7 +1349,7 @@ static struct token *recover_unknown_attribute(struct token *token) return token; } -static struct token *attribute_specifier(struct token *token, struct decl_state *ctx) +static struct token *attribute_specifier(struct token *token, struct symbol *sym, struct decl_state *ctx) { token = expect(token, '(', "after attribute"); token = expect(token, '(', "after attribute"); @@ -1392,57 +1388,29 @@ static unsigned long decl_modifiers(struct decl_state *ctx) return ctx->storage_class | mods; } -static void set_storage_class(struct position *pos, struct decl_state *ctx, unsigned long class) +static struct token *storage_specifier(struct token *next, struct symbol *sym, struct decl_state *ctx) { int is_tls = ctx->ctype.modifiers & MOD_TLS; + unsigned long class = sym->ctype.modifiers; const char *storage = modifier_string(class); /* __thread can be used alone, or with extern or static */ if (is_tls && (class & ~(MOD_STATIC|MOD_EXTERN))) { - sparse_error(*pos, "__thread can only be used alone, or with " + sparse_error(next->pos, "__thread can only be used alone, or with " "extern or static"); - return; + return next; } if (!ctx->storage_class) ctx->storage_class = class; else if (ctx->storage_class == class) - sparse_error(*pos, "duplicate %s", storage); + sparse_error(next->pos, "duplicate %s", storage); else - sparse_error(*pos, "multiple storage classes"); -} - -static struct token *typedef_specifier(struct token *next, struct decl_state *ctx) -{ - set_storage_class(&next->pos, ctx, MOD_USERTYPE); - return next; -} - -static struct token *auto_specifier(struct token *next, struct decl_state *ctx) -{ - set_storage_class(&next->pos, ctx, MOD_AUTO); - return next; -} - -static struct token *register_specifier(struct token *next, struct decl_state *ctx) -{ - set_storage_class(&next->pos, ctx, MOD_REGISTER); - return next; -} - -static struct token *static_specifier(struct token *next, struct decl_state *ctx) -{ - set_storage_class(&next->pos, ctx, MOD_STATIC); - return next; -} - -static struct token *extern_specifier(struct token *next, struct decl_state *ctx) -{ - set_storage_class(&next->pos, ctx, MOD_EXTERN); + sparse_error(next->pos, "multiple storage classes"); return next; } -static struct token *thread_specifier(struct token *next, struct decl_state *ctx) +static struct token *thread_specifier(struct token *next, struct symbol *sym, struct decl_state *ctx) { /* This GCC extension can be used alone, or with extern or static */ if (!(ctx->storage_class & ~(MOD_STATIC|MOD_EXTERN))) { @@ -1461,19 +1429,7 @@ static struct token *attribute_force(struct token *token, struct symbol *attr, s return token; } -static struct token *inline_specifier(struct token *next, struct decl_state *ctx) -{ - apply_qualifier(&next->pos, &ctx->ctype, MOD_INLINE); - return next; -} - -static struct token *noreturn_specifier(struct token *next, struct decl_state *ctx) -{ - apply_qualifier(&next->pos, &ctx->ctype, MOD_NORETURN); - return next; -} - -static struct token *alignas_specifier(struct token *token, struct decl_state *ctx) +static struct token *alignas_specifier(struct token *token, struct symbol *sym, struct decl_state *ctx) { int alignment = 0; @@ -1508,27 +1464,9 @@ static struct token *alignas_specifier(struct token *token, struct decl_state *c return token; } -static struct token *const_qualifier(struct token *next, struct decl_state *ctx) -{ - apply_qualifier(&next->pos, &ctx->ctype, MOD_CONST); - return next; -} - -static struct token *volatile_qualifier(struct token *next, struct decl_state *ctx) -{ - apply_qualifier(&next->pos, &ctx->ctype, MOD_VOLATILE); - return next; -} - -static struct token *restrict_qualifier(struct token *next, struct decl_state *ctx) -{ - apply_qualifier(&next->pos, &ctx->ctype, MOD_RESTRICT); - return next; -} - -static struct token *atomic_qualifier(struct token *next, struct decl_state *ctx) +static struct token *generic_qualifier(struct token *next, struct symbol *sym, struct decl_state *ctx) { - apply_qualifier(&next->pos, &ctx->ctype, MOD_ATOMIC); + apply_qualifier(&next->pos, &ctx->ctype, sym->ctype.modifiers); return next; } @@ -1615,7 +1553,7 @@ static struct token *handle_qualifiers(struct token *t, struct decl_state *ctx) break; t = t->next; if (s->op->declarator) - t = s->op->declarator(t, ctx); + t = s->op->declarator(t, s, ctx); } return t; } @@ -1667,7 +1605,7 @@ static struct token *declaration_specifiers(struct token *token, struct decl_sta } token = token->next; if (s->op->declarator) // Note: this eats attributes - token = s->op->declarator(token, ctx); + token = s->op->declarator(token, s, ctx); if (s->op->type & KW_EXACT) { ctx->ctype.base_type = s->ctype.base_type; ctx->ctype.modifiers |= s->ctype.modifiers; @@ -1791,7 +1729,7 @@ static struct token *handle_attributes(struct token *token, struct decl_state *c break; if (!(keyword->op->type & keywords)) break; - token = keyword->op->declarator(token->next, ctx); + token = keyword->op->declarator(token->next, keyword, ctx); keywords &= KW_ATTRIBUTE; } return token; @@ -2157,7 +2095,7 @@ static struct token *parse_asm_statement(struct token *token, struct statement * return expect(token, ';', "at end of asm-statement"); } -static struct token *parse_asm_declarator(struct token *token, struct decl_state *ctx) +static struct token *parse_asm_declarator(struct token *token, struct symbol *sym, struct decl_state *ctx) { struct expression *expr; token = expect(token, '(', "after asm"); diff --git a/symbol.h b/symbol.h index d2ca3d2d..657a6e0f 100644 --- a/symbol.h +++ b/symbol.h @@ -126,7 +126,7 @@ struct symbol_op { struct pseudo *(*linearize)(struct entrypoint *, struct expression *); /* keywords */ - struct token *(*declarator)(struct token *token, struct decl_state *ctx); + struct token *(*declarator)(struct token *token, struct symbol *, struct decl_state *ctx); 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); -- cgit 1.2.3-korg From 9b4d0862315ec49673a5015bc79669f60eadff06 Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Mon, 20 Jul 2020 01:32:30 +0200 Subject: parse: let asm_modifier() use the keyword modifier Now that 'MOD_INLINE' & 'MOD_VOLATILE' are associated with their corresponding keyword, a single asm_modifier() method can cover both cases. So, replace asm_modifier_inline() & asm_modifier_volatile() by a single, generic version: asm_modifier(). Signed-off-by: Luc Van Oostenryck --- parse.c | 16 +++------------- symbol.h | 2 +- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/parse.c b/parse.c index 37fe90c0..fad41d36 100644 --- a/parse.c +++ b/parse.c @@ -120,16 +120,6 @@ static void asm_modifier(struct token *token, unsigned long *mods, unsigned long *mods |= mod; } -static void asm_modifier_volatile(struct token *token, unsigned long *mods) -{ - asm_modifier(token, mods, MOD_VOLATILE); -} - -static void asm_modifier_inline(struct token *token, unsigned long *mods) -{ - asm_modifier(token, mods, MOD_INLINE); -} - static struct symbol_op typedef_op = { .type = KW_MODIFIER, .declarator = storage_specifier, @@ -138,7 +128,7 @@ static struct symbol_op typedef_op = { static struct symbol_op inline_op = { .type = KW_MODIFIER, .declarator = generic_qualifier, - .asm_modifier = asm_modifier_inline, + .asm_modifier = asm_modifier, }; static struct symbol_op noreturn_op = { @@ -185,7 +175,7 @@ static struct symbol_op const_op = { static struct symbol_op volatile_op = { .type = KW_QUALIFIER, .declarator = generic_qualifier, - .asm_modifier = asm_modifier_volatile, + .asm_modifier = asm_modifier, }; static struct symbol_op restrict_op = { @@ -2076,7 +2066,7 @@ static struct token *parse_asm_statement(struct token *token, struct statement * while (token_type(token) == TOKEN_IDENT) { struct symbol *s = lookup_keyword(token->ident, NS_TYPEDEF); if (s && s->op && s->op->asm_modifier) - s->op->asm_modifier(token, &mods); + s->op->asm_modifier(token, &mods, s->ctype.modifiers); else if (token->ident == &goto_ident) asm_modifier(token, &mods, MOD_ASM_GOTO); token = token->next; diff --git a/symbol.h b/symbol.h index 657a6e0f..4f9dd741 100644 --- a/symbol.h +++ b/symbol.h @@ -131,7 +131,7 @@ struct symbol_op { 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 *); - void (*asm_modifier)(struct token *token, unsigned long *mods); + void (*asm_modifier)(struct token *token, unsigned long *mods, unsigned long mod); int test, set, class; }; -- cgit 1.2.3-korg From 35c853cc17f32cac571480af6fd7883c9c128672 Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Fri, 24 Jul 2020 02:16:55 +0200 Subject: parse: improve error messages concerning storage specifiers Signed-off-by: Luc Van Oostenryck --- parse.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/parse.c b/parse.c index fad41d36..92ca1b66 100644 --- a/parse.c +++ b/parse.c @@ -1382,12 +1382,11 @@ static struct token *storage_specifier(struct token *next, struct symbol *sym, s { int is_tls = ctx->ctype.modifiers & MOD_TLS; unsigned long class = sym->ctype.modifiers; - const char *storage = modifier_string(class); + const char *storage = modifier_name(class); /* __thread can be used alone, or with extern or static */ if (is_tls && (class & ~(MOD_STATIC|MOD_EXTERN))) { - sparse_error(next->pos, "__thread can only be used alone, or with " - "extern or static"); + sparse_error(next->pos, "__thread cannot be used with '%s'", storage); return next; } @@ -1406,8 +1405,8 @@ static struct token *thread_specifier(struct token *next, struct symbol *sym, st if (!(ctx->storage_class & ~(MOD_STATIC|MOD_EXTERN))) { apply_qualifier(&next->pos, &ctx->ctype, MOD_TLS); } else { - sparse_error(next->pos, "__thread can only be used alone, or " - "with extern or static"); + sparse_error(next->pos, "__thread cannot be used with '%s'", + modifier_name(ctx->storage_class)); } return next; -- cgit 1.2.3-korg From f31c401c5f036231e4e07bb08f57ce2d027b0831 Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Sat, 25 Jul 2020 23:03:23 +0200 Subject: parse: simplify set_storage_class() The second test is now made as the else part of the first test, saving a 'return' that is otherwise not needed. Signed-off-by: Luc Van Oostenryck --- parse.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/parse.c b/parse.c index 92ca1b66..f3f33790 100644 --- a/parse.c +++ b/parse.c @@ -1385,12 +1385,9 @@ static struct token *storage_specifier(struct token *next, struct symbol *sym, s const char *storage = modifier_name(class); /* __thread can be used alone, or with extern or static */ - if (is_tls && (class & ~(MOD_STATIC|MOD_EXTERN))) { + if (is_tls && (class & ~(MOD_STATIC|MOD_EXTERN))) sparse_error(next->pos, "__thread cannot be used with '%s'", storage); - return next; - } - - if (!ctx->storage_class) + else if (!ctx->storage_class) ctx->storage_class = class; else if (ctx->storage_class == class) sparse_error(next->pos, "duplicate %s", storage); -- cgit 1.2.3-korg