From 70364d9a8d1c57da490e0187421ae94af42bf579 Mon Sep 17 00:00:00 2001 From: Amine Najahi Date: Fri, 11 Mar 2016 17:54:11 +0100 Subject: [PATCH] Fix duplicate case values bug. --- tccgen.c | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/tccgen.c b/tccgen.c index 3cd28ed..ef4b2e6 100644 --- a/tccgen.c +++ b/tccgen.c @@ -80,7 +80,7 @@ static int parse_btype(CType *type, AttributeDef *ad); static void type_decl(CType *type, AttributeDef *ad, int *v, int td); static void parse_expr_type(CType *type); static void decl_initializer(CType *type, Section *sec, unsigned long c, int first, int size_only); -static void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg, int is_expr); +static void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg, int is_expr, void*** cases, int* cases_cnt); static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, int scope); static int decl0(int l, int is_for_loop_init); static void expr_eq(void); @@ -3848,7 +3848,7 @@ ST_FUNC void unary(void) save_regs(0); /* statement expression : we do not accept break/continue inside as GCC does */ - block(NULL, NULL, NULL, NULL, 0, 1); + block(NULL, NULL, NULL, NULL, 0, 1, NULL, 0); skip(')'); } else { gexpr(); @@ -4816,7 +4816,7 @@ static void label_or_decl(int l) } static void block(int *bsym, int *csym, int *case_sym, int *def_sym, - int case_reg, int is_expr) + int case_reg, int is_expr, void*** cases, int* cases_cnt) { int a, b, c, d; Sym *s, *frame_bottom; @@ -4842,13 +4842,13 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, gexpr(); skip(')'); a = gvtst(1, 0); - block(bsym, csym, case_sym, def_sym, case_reg, 0); + block(bsym, csym, case_sym, def_sym, case_reg, 0, cases, cases_cnt); c = tok; if (c == TOK_ELSE) { next(); d = gjmp(0); gsym(a); - block(bsym, csym, case_sym, def_sym, case_reg, 0); + block(bsym, csym, case_sym, def_sym, case_reg, 0, cases, cases_cnt); gsym(d); /* patch else jmp */ } else gsym(a); @@ -4861,7 +4861,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, skip(')'); a = gvtst(1, 0); b = 0; - block(&a, &b, case_sym, def_sym, case_reg, 0); + block(&a, &b, case_sym, def_sym, case_reg, 0, cases, cases_cnt); gjmp_addr(d); gsym(a); gsym_addr(b, d); @@ -4898,7 +4898,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, if (tok != '}') { if (is_expr) vpop(); - block(bsym, csym, case_sym, def_sym, case_reg, is_expr); + block(bsym, csym, case_sym, def_sym, case_reg, is_expr, cases, cases_cnt); } } /* pop locally defined labels */ @@ -5053,7 +5053,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, gsym(e); } skip(')'); - block(&a, &b, case_sym, def_sym, case_reg, 0); + block(&a, &b, case_sym, def_sym, case_reg, 0, cases, cases_cnt); gjmp_addr(c); gsym(a); gsym_addr(b, c); @@ -5066,7 +5066,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, b = 0; d = ind; vla_sp_restore(); - block(&a, &b, case_sym, def_sym, case_reg, 0); + block(&a, &b, case_sym, def_sym, case_reg, 0, cases, cases_cnt); skip(TOK_WHILE); skip('('); gsym(b); @@ -5078,6 +5078,8 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, skip(';'); } else if (tok == TOK_SWITCH) { + void** new_cases = NULL; + int new_cases_cnt = 0; next(); skip('('); gexpr(); @@ -5088,7 +5090,8 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, a = 0; b = gjmp(0); /* jump to first case */ c = 0; - block(&a, csym, &b, &c, case_reg, 0); + block(&a, csym, &b, &c, case_reg, 0, &new_cases, &new_cases_cnt); + dynarray_reset(&new_cases, &new_cases_cnt); /* if no default, jmp after switch */ if (c == 0) c = ind; @@ -5098,11 +5101,18 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, gsym(a); } else if (tok == TOK_CASE) { - int v1, v2; + int i, v1, v2, *case_value; + void** pp; if (!case_sym) expect("switch"); next(); v1 = expr_const(); + for (i = 0, pp=*cases; i < *cases_cnt; ++i, ++pp) + if (v1 == **(int **) pp) + tcc_error("duplicate case value '%d'", v1); + case_value = tcc_malloc ( sizeof ( int ) ); + *case_value = v1; + dynarray_add(cases, cases_cnt, case_value); v2 = v1; if (gnu_ext && tok == TOK_DOTS) { next(); @@ -5197,7 +5207,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, } else { if (is_expr) vpop(); - block(bsym, csym, case_sym, def_sym, case_reg, is_expr); + block(bsym, csym, case_sym, def_sym, case_reg, is_expr, cases, cases_cnt); } } else { /* expression case */ @@ -6105,7 +6115,7 @@ static void gen_function(Sym *sym) } #endif rsym = 0; - block(NULL, NULL, NULL, NULL, 0, 0); + block(NULL, NULL, NULL, NULL, 0, 0, NULL, 0); gsym(rsym); gfunc_epilog(); cur_text_section->data_offset = ind; -- 2.7.0