From 1286bea26d1b6cfc13eb65c4a98e8196facecbe9 Mon Sep 17 00:00:00 2001 From: Michael Beck Date: Wed, 19 Dec 2007 13:37:56 +0000 Subject: [PATCH] - GCC case A ... E: extention implemented [r18801] --- ast.c | 4 ++++ ast2firm.c | 31 ++++++++++++++++++++++--------- ast_t.h | 3 ++- parser.c | 7 +++++++ 4 files changed, 35 insertions(+), 10 deletions(-) diff --git a/ast.c b/ast.c index df07b01..d10dc02 100644 --- a/ast.c +++ b/ast.c @@ -845,6 +845,10 @@ static void print_case_label(const case_label_statement_t *statement) } else { fputs("case ", out); print_expression(statement->expression); + if (statement->end_range != NULL) { + fputs(" ... ", out); + print_expression(statement->end_range); + } fputs(":\n", out); } ++indent; diff --git a/ast2firm.c b/ast2firm.c index 4cc9da6..7c030b0 100644 --- a/ast2firm.c +++ b/ast2firm.c @@ -3450,26 +3450,39 @@ static void case_label_to_firm(const case_label_statement_t *statement) /* let's create a node and hope firm constant folding creates a Const * node... */ ir_node *proj; - set_cur_block(get_nodes_block(current_switch_cond)); - if(statement->expression) { - long pn = fold_constant(statement->expression); - if(pn == MAGIC_DEFAULT_PN_NUMBER) { - /* oops someone detected our cheating... */ - panic("magic default pn used"); + ir_node *old_block = get_nodes_block(current_switch_cond); + ir_node *block = new_immBlock(); + + set_cur_block(old_block); + if(statement->expression != NULL) { + long start_pn = fold_constant(statement->expression); + long end_pn = start_pn; + if (statement->end_range != NULL) { + end_pn = fold_constant(statement->end_range); + } + assert(start_pn <= end_pn); + /* create jumps for all cases in the given range */ + for (long pn = start_pn; pn <= end_pn; ++pn) { + if(pn == MAGIC_DEFAULT_PN_NUMBER) { + /* oops someone detected our cheating... */ + panic("magic default pn used"); + } + proj = new_d_Proj(dbgi, current_switch_cond, mode_X, pn); + add_immBlock_pred(block, proj); } - proj = new_d_Proj(dbgi, current_switch_cond, mode_X, pn); } else { saw_default_label = true; proj = new_d_defaultProj(dbgi, current_switch_cond, MAGIC_DEFAULT_PN_NUMBER); + + add_immBlock_pred(block, proj); } - ir_node *block = new_immBlock(); if (fallthrough != NULL) { add_immBlock_pred(block, fallthrough); } - add_immBlock_pred(block, proj); mature_immBlock(block); + set_cur_block(block); if(statement->statement != NULL) { statement_to_firm(statement->statement); diff --git a/ast_t.h b/ast_t.h index 1debd43..915181a 100644 --- a/ast_t.h +++ b/ast_t.h @@ -483,7 +483,8 @@ struct goto_statement_t { struct case_label_statement_t { statement_base_t base; - expression_t *expression; + expression_t *expression; /**< The case label expression, NULL for default label. */ + expression_t *end_range; /**< For GNUC case a .. b: the end range expression, NULL else. */ statement_t *statement; case_label_statement_t *next; /**< link to the next case label in switch */ }; diff --git a/parser.c b/parser.c index 1875684..07e93ac 100644 --- a/parser.c +++ b/parser.c @@ -5114,6 +5114,13 @@ static statement_t *parse_case_statement(void) statement->base.source_position = token.source_position; statement->case_label.expression = parse_expression(); + if (c_mode & _GNUC) { + if (token.type == T_DOTDOTDOT) { + next_token(); + statement->case_label.end_range = parse_expression(); + } + } + expect(':'); if (! is_constant_expression(statement->case_label.expression)) { -- 2.20.1