- GCC case A ... E: extention implemented
authorMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Wed, 19 Dec 2007 13:37:56 +0000 (13:37 +0000)
committerMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Wed, 19 Dec 2007 13:37:56 +0000 (13:37 +0000)
[r18801]

ast.c
ast2firm.c
ast_t.h
parser.c

diff --git a/ast.c b/ast.c
index df07b01..d10dc02 100644 (file)
--- 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;
index 4cc9da6..7c030b0 100644 (file)
@@ -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 (file)
--- 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 */
 };
index 1875684..07e93ac 100644 (file)
--- 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)) {