diff --git a/compiler2/ttcn3/Statement.cc b/compiler2/ttcn3/Statement.cc index 6d8e73c36decb75e3d39c1513dec0f0abaa680e6..5ce6b1ce0850bc4012ebda364381e83b18f32108 100644 --- a/compiler2/ttcn3/Statement.cc +++ b/compiler2/ttcn3/Statement.cc @@ -6014,12 +6014,12 @@ error: tmp_id.c_str(), expr_name); // We generate different code if the head is an integer and all the branches - // are foldable - bool int_gen_code = false; + // are foldable and not big integers + bool gen_switch_code = false; if (select.expr->get_my_governor()->is_compatible_tt(Type::T_INT, select.expr->is_asn1())) { - int_gen_code = select.scs->foldable_branches(); + gen_switch_code = select.scs->can_generate_switch(); } - if (int_gen_code) { + if (gen_switch_code) { str=select.scs->generate_code_switch(str, tmp_id.c_str()); } else { @@ -6386,11 +6386,11 @@ error: // We generate different code if the head is an integer and all the branches // are foldable - bool int_gen_code = false; + bool gen_switch_code = false; if (select.expr->get_my_governor()->is_compatible_tt(Type::T_INT, select.expr->is_asn1())) { - int_gen_code = select.scs->foldable_branches(); + gen_switch_code = select.scs->can_generate_switch(); } - if (int_gen_code) { + if (gen_switch_code) { select.scs->ilt_generate_code_switch(ilt, expr_init, head_expr, tmp_id.c_str()); } else { @@ -10672,24 +10672,40 @@ error: return str; } - char* SelectCase::generate_code_case(char *str, bool&else_branch) { + char* SelectCase::generate_code_case(char *str, bool &else_branch, + vector<const Int>& used_numbers) { + bool already_present_all = true; // to decide if we need to generate the block if (tis != NULL) { for (size_t i = 0; i < tis->get_nof_tis(); i++) { - str = mputprintf(str, "case("); - expression_struct expr; - Code::init_expr(&expr); - tis->get_ti_byIndex(i)->get_specific_value()->generate_code_expr(&expr); - str = mputprintf(str, "%s):\n", expr.expr); - Code::free_expr(&expr); + int_val_t* val = tis->get_ti_byIndex(i)->get_specific_value()->get_val_Int(); + bool already_present = false; // to decide if we need to generate the case + for (size_t j = 0; j < used_numbers.size(); j++) { + if (*(used_numbers[j]) == val->get_val()) { + already_present = true; + break; + } + } + used_numbers.add(&val->get_val()); + if (!already_present) { + already_present_all = false; + str = mputprintf(str, "case("); + expression_struct expr; + Code::init_expr(&expr); + tis->get_ti_byIndex(i)->get_specific_value()->generate_code_expr(&expr); + str = mputprintf(str, "%s):\n", expr.expr); + Code::free_expr(&expr); + } } } else { else_branch = true; + already_present_all = false; str = mputstr(str, "default:\n"); // The else branch } - - str = mputstr(str, "{\n"); - str = block->generate_code(str); - str = mputstr(str, "break;\n}\n"); + if (!already_present_all) { + str = mputstr(str, "{\n"); + str = block->generate_code(str); + str = mputstr(str, "break;\n}\n"); + } return str; } @@ -10824,7 +10840,7 @@ error: return false; } - bool SelectCases::foldable_branches() const { + bool SelectCases::can_generate_switch() const { for(size_t i=0; i<scs.size(); i++) { TemplateInstances* tis = scs[i]->get_tis(); if (tis == NULL) { // the else brach @@ -10832,9 +10848,9 @@ error: } for(size_t j=0; j<tis->get_nof_tis(); j++) { Value * v = tis->get_ti_byIndex(j)->get_specific_value(); - if (v == NULL || v->is_unfoldable()) { - return false; - } + if (v == NULL) return false; + if (v->is_unfoldable()) return false; + if (!v->get_val_Int()->is_native()) return false; } } return true; @@ -10882,12 +10898,14 @@ error: char* SelectCases::generate_code_switch(char *str, const char *expr_name) { bool else_branch=false; + vector<const Int> used_numbers; // store the case values to remove duplicates str=mputprintf(str, "switch(%s.get_long_long_val()) {\n", expr_name); for(size_t i=0; i<scs.size(); i++) { - str=scs[i]->generate_code_case(str, else_branch); + str=scs[i]->generate_code_case(str, else_branch, used_numbers); if(else_branch) break; } str=mputprintf(str, "};"); + used_numbers.clear(); return str; } @@ -10926,12 +10944,14 @@ error: } str=mputstr(str, head_expr); bool else_branch=false; + vector<const Int> used_numbers; // store the case values to remove duplicates str=mputprintf(str, "switch(%s.get_long_long_val()) {\n", expr_name); for(size_t i=0; i<scs.size(); i++) { - str=scs[i]->generate_code_case(str, else_branch); + str=scs[i]->generate_code_case(str, else_branch, used_numbers); if(else_branch) break; } str=mputprintf(str, "};"); + used_numbers.clear(); if (expr_init[0]) str=mputstr(str, "}\n"); } diff --git a/compiler2/ttcn3/Statement.hh b/compiler2/ttcn3/Statement.hh index 72df3a3aae3aa450f1f2571bb60dc905d6f3987e..e5135f9f94598fceac08972469e432c44f444b6f 100644 --- a/compiler2/ttcn3/Statement.hh +++ b/compiler2/ttcn3/Statement.hh @@ -1335,7 +1335,8 @@ namespace Ttcn { void set_code_section(GovernedSimple::code_section_t p_code_section); char* generate_code_if(char *str, const char *tmp_prefix, const char *expr_name, size_t idx, bool& unreach); - char* generate_code_case(char *str, bool& else_branch); + char* generate_code_case(char *str, bool& else_branch, + vector<const Int>& used_numbers); char* generate_code_stmt(char *str, const char *tmp_prefix, size_t idx, bool& unreach); void ilt_generate_code_stmt(ILT *ilt, const char *tmp_prefix, @@ -1370,7 +1371,7 @@ namespace Ttcn { void set_my_laic_stmt(AltGuards *p_ags, Statement *p_loop_stmt); StatementBlock::returnstatus_t has_return() const; bool has_receiving_stmt() const; - bool foldable_branches() const; + bool can_generate_switch() const; /* checking functions */ /** p_gov is the governor type of select expression */ void chk(Type *p_gov); diff --git a/regression_test/basicStatem/TbasicStatem.ttcn b/regression_test/basicStatem/TbasicStatem.ttcn index 32112214e8ac0fa0e5d70524d0a03b7c3b6b1a0d..2af9770ffd55ac65f7255f313e5d23d74fb14d54 100644 --- a/regression_test/basicStatem/TbasicStatem.ttcn +++ b/regression_test/basicStatem/TbasicStatem.ttcn @@ -108,6 +108,24 @@ select (int1 + int2) { case (11,4) { setverdict(pass); } case else { setverdict(inconc); } } +select (int1 + int2) { + case (3,0) { setverdict(fail); } + case (3) { setverdict(fail); } + case (0,3) { setverdict(fail); } + case (0,4) { setverdict(fail); } + case (99999999999999999999999999999999999) { setverdict(fail); } + case (11,4) { setverdict(pass); } + case else { setverdict(inconc); } + case else { setverdict(inconc); } +} +select (int1 + int2) { + case (3,0) { setverdict(fail); } + case (3) { setverdict(fail); } + case (0,3) { setverdict(fail); } + case (0,4) { setverdict(fail); } + case (11,4) { setverdict(pass); } + case else { setverdict(inconc); } +} var octetstring octet1, octet2; octet1:= 'A9'O; octet2:= '1267FD'O;