diff options
| -rw-r--r-- | parse.c | 34 | ||||
| -rw-r--r-- | symbol.h | 2 | ||||
| -rw-r--r-- | validation/asm-inline.c | 52 |
3 files changed, 81 insertions, 7 deletions
@@ -118,6 +118,23 @@ 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) + warning(token->pos, "duplicated asm modifier"); + *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 = typedef_specifier, @@ -126,6 +143,7 @@ static struct symbol_op typedef_op = { static struct symbol_op inline_op = { .type = KW_MODIFIER, .declarator = inline_specifier, + .asm_modifier = asm_modifier_inline, }; static declarator_t noreturn_specifier; @@ -173,6 +191,7 @@ static struct symbol_op const_op = { static struct symbol_op volatile_op = { .type = KW_QUALIFIER, .declarator = volatile_qualifier, + .asm_modifier = asm_modifier_volatile, }; static struct symbol_op restrict_op = { @@ -2069,15 +2088,16 @@ static struct token *parse_asm_labels(struct token *token, struct statement *stm static struct token *parse_asm_statement(struct token *token, struct statement *stmt) { - int is_goto = 0; + unsigned long mods = 0; token = token->next; stmt->type = STMT_ASM; - if (match_idents(token, &__volatile___ident, &__volatile_ident, &volatile_ident, NULL)) { - token = token->next; - } - if (token_type(token) == TOKEN_IDENT && token->ident == &goto_ident) { - is_goto = 1; + 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); + else if (token->ident == &goto_ident) + asm_modifier(token, &mods, MOD_ASM_GOTO); token = token->next; } token = expect(token, '(', "after asm"); @@ -2088,7 +2108,7 @@ static struct token *parse_asm_statement(struct token *token, struct statement * token = parse_asm_operands(token, stmt, &stmt->asm_inputs); if (match_op(token, ':')) token = parse_asm_clobbers(token, stmt, &stmt->asm_clobbers); - if (is_goto && match_op(token, ':')) + if (match_op(token, ':') && (mods & MOD_ASM_GOTO)) token = parse_asm_labels(token, stmt, &stmt->asm_labels); token = expect(token, ')', "after asm"); return expect(token, ';', "at end of asm-statement"); @@ -124,6 +124,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); int test, set, class; }; @@ -207,6 +208,7 @@ struct symbol { #define MOD_EXTERN 0x00000008 #define MOD_TOPLEVEL 0x00000010 // scoping.. #define MOD_TLS 0x00000020 +#define MOD_ASM_GOTO MOD_TLS // never used together #define MOD_INLINE 0x00000040 #define MOD_ASSIGNED 0x00000080 diff --git a/validation/asm-inline.c b/validation/asm-inline.c new file mode 100644 index 00000000..186286b3 --- /dev/null +++ b/validation/asm-inline.c @@ -0,0 +1,52 @@ +static void foo(void) +{ + asm(""); + asm volatile ("v"); + asm inline ("i"); + asm volatile inline ("vi"); + asm inline volatile ("iv"); + + asm goto ("g" :::: label); + asm volatile goto ("vg" :::: label); + asm inline goto ("ig" :::: label); + asm volatile inline goto ("vig" :::: label); + asm inline volatile goto ("ivg" :::: label); + + asm goto volatile ("gv" :::: label); + asm goto inline ("gi" :::: label); + asm goto volatile inline ("gvi" :::: label); + asm goto inline volatile ("giv" :::: label); + asm volatile goto inline ("vgi" :::: label); + asm inline goto volatile ("giv" :::: label); + + // warn on duplicates + asm volatile volatile ("vv"); + asm inline inline ("ii"); + asm goto goto ("gg" :::: label); + + asm inline volatile inline ("ivi"); + asm inline goto inline ("igi" :::: label); + asm goto inline goto ("gig" :::: label); + asm goto volatile goto ("gvg" :::: label); + asm volatile inline volatile ("viv"); + asm volatile goto volatile ("vgv" :::: label); + +label: + ; +} + +/* + * check-name: asm-inline + * + * check-error-start +asm-inline.c:23:22: warning: duplicated asm modifier +asm-inline.c:24:20: warning: duplicated asm modifier +asm-inline.c:25:18: warning: duplicated asm modifier +asm-inline.c:27:29: warning: duplicated asm modifier +asm-inline.c:28:25: warning: duplicated asm modifier +asm-inline.c:29:25: warning: duplicated asm modifier +asm-inline.c:30:27: warning: duplicated asm modifier +asm-inline.c:31:29: warning: duplicated asm modifier +asm-inline.c:32:27: warning: duplicated asm modifier + * check-error-end + */ |
