Commit cb064d16 authored by Adam Knapp's avatar Adam Knapp Committed by Gerrit Code Review
Browse files

Merge "OOP: reorganized non-C++11 code for finally blocks and fixed code...

Merge "OOP: reorganized non-C++11 code for finally blocks and fixed code generated for shadowed parameters (bug 568899)"
parents 6575ad18 e732de9d
......@@ -588,11 +588,71 @@ namespace Ttcn {
str = mputstr(str, "TTCN_TryBlock try_block;\n");
}
if (finally_block != NULL) {
string tmp_id = get_scope_mod_gen()->get_temporary_id();
#if __cplusplus < 201103L
str = finally_block->generate_code_finally(str, def_glob_vars, src_glob_vars);
#else
// C++11 version:
string tmp_id = get_scope_mod_gen()->get_temporary_id();
str = mputprintf(str,
"FINALLY %s([&] {\n", tmp_id.c_str());
str = finally_block->generate_code(str, def_glob_vars, src_glob_vars);
str = mputstr(str, "});\n");
#endif
}
if (catch_blocks.size() > 0) {
str = mputstr(str, "try {\n");
}
if (stmts.size()>0) {
Statement* first_stmt = stmts[0];
str = first_stmt->generate_code(str, def_glob_vars, src_glob_vars);
if (exception_handling==EH_CATCH) {
if (first_stmt->get_statementtype()!=Statement::S_DEF) FATAL_ERROR("StatementBlock::generate_code()");
Definition* error_msg_def = first_stmt->get_def();
string error_msg_name = error_msg_def->get_id().get_name();
str = mputprintf(str, "%s = ttcn_error.get_message();\n", error_msg_name.c_str());
}
}
for(size_t i=1; i<stmts.size(); i++) {
str = stmts[i]->generate_code(str, def_glob_vars, src_glob_vars);
}
if (alt_guards != NULL && exception_handling == EH_NONE) {
str = alt_guards->generate_code_altstep(str, def_glob_vars, src_glob_vars);
}
if (exception_handling == EH_OOP_CATCH && alt_guards != NULL) {
// we are in an altstep's statement block
// indicate that an alt branch has been chosen (since exceptions can only be raised from
// the statement blocks of the alt branches)
str = mputstr(str, "return ALT_YES;\n");
}
if (catch_blocks.size() > 0) {
str = mputstr(str,
"}\n" // end of the 'try' block
"catch (EXCEPTION_BASE& exc_base) {\n");
for (size_t i = 0; i < catch_blocks.size(); ++i) {
Type* exc_type = catch_blocks[i]->get_stmt_byIndex(0)->get_def()->get_Type();
str = mputprintf(str,
"%sif (exc_base.has_type(\"%s\")) {\n",
i > 0 ? "else " : "", exc_type->get_exception_name().c_str());
str = catch_blocks[i]->generate_code(str, def_glob_vars, src_glob_vars, alt_guards);
str = mputstr(str, "}\n");
}
// if none of the exception types matched, then just re-throw the exception as if nothing happened
str = mputstr(str,
"else { throw exc_base; }\n"
"}\n"); // end of the catch block
}
return str;
}
char* StatementBlock::generate_code_finally(char* str, char*& def_glob_vars, char*& src_glob_vars)
{
// the finally block's code is generated into the destructor of a newly created class;
// all local definitions, parameters and the TTCN_Location object are added to the class as members,
// so the destructor can reach them
if (exception_handling != EH_OOP_FINALLY) {
FATAL_ERROR("StatementBlock::generate_code_finally");
}
string tmp_id = get_scope_mod_gen()->get_temporary_id();
str = mputprintf(str,
"class %s_finally {\n"
"public:\n", tmp_id.c_str());
......@@ -600,80 +660,82 @@ namespace Ttcn {
if (include_location_info) {
str = mputstr(str, "TTCN_Location& current_location;\n");
}
for (size_t i = 0; i < finally_block->refd_local_defs.size(); ++i) {
bool is_const = false;
bool is_template = false;
Common::Assignment* def = finally_block->refd_local_defs.get_nth_key(i);
bool* is_const = NULL;
bool* is_template = NULL;
bool* is_shadowed = NULL;
if (refd_local_defs.size() > 0) {
is_const = new bool[refd_local_defs.size()];
is_template = new bool[refd_local_defs.size()];
is_shadowed = new bool[refd_local_defs.size()];
}
for (size_t i = 0; i < refd_local_defs.size(); ++i) {
is_const[i] = false;
is_template[i] = false;
is_shadowed[i] = false;
Common::Assignment* def = refd_local_defs.get_nth_key(i);
switch (def->get_asstype()) {
case Common::Assignment::A_PAR_TEMPL_IN:
case Common::Assignment::A_TEMPLATE:
is_template = true;
is_template[i] = true;
// fall through
case Common::Assignment::A_PAR_VAL:
case Common::Assignment::A_PAR_VAL_IN:
case Common::Assignment::A_PAR_VAL_IN: {
FormalPar* fpar = dynamic_cast<FormalPar*>(def);
if (fpar == NULL) {
FATAL_ERROR("StatementBlock::generate_code");
}
if (fpar->get_used_as_lvalue()) {
is_shadowed[i] = true;
}
else {
is_const[i] = true;
}
break; }
case Common::Assignment::A_CONST:
is_const = true;
is_const[i] = true;
break;
case Common::Assignment::A_TEMPLATE:
is_const[i] = true;
// fall through
case Common::Assignment::A_VAR_TEMPLATE:
case Common::Assignment::A_PAR_TEMPL_INOUT:
case Common::Assignment::A_PAR_TEMPL_OUT:
is_template = true;
is_template[i] = true;
break;
default:
break;
}
str = mputprintf(str, "%s%s& %s;\n",
is_const ? "const " : "",
is_template ? def->get_Type()->get_genname_template(my_sb).c_str() : def->get_Type()->get_genname_value(my_sb).c_str(),
def->get_id().get_name().c_str());
str = mputprintf(str, "%s%s& %s%s;\n",
is_const[i] ? "const " : "",
is_template[i] ? def->get_Type()->get_genname_template(my_sb).c_str() : def->get_Type()->get_genname_value(my_sb).c_str(),
def->get_id().get_name().c_str(), is_shadowed[i] ? "_shadow" : "");
}
if (include_location_info || finally_block->refd_local_defs.size() > 0) {
if (include_location_info || refd_local_defs.size() > 0) {
str = mputprintf(str, "%s_finally(", tmp_id.c_str());
if (include_location_info) {
str = mputstr(str, "TTCN_Location& p_loc");
}
for (size_t i = 0; i < finally_block->refd_local_defs.size(); ++i) {
bool is_const = false;
bool is_template = false;
Common::Assignment* def = finally_block->refd_local_defs.get_nth_key(i);
switch (def->get_asstype()) {
case Common::Assignment::A_PAR_TEMPL_IN:
case Common::Assignment::A_TEMPLATE:
is_template = true;
// fall through
case Common::Assignment::A_PAR_VAL:
case Common::Assignment::A_PAR_VAL_IN:
case Common::Assignment::A_CONST:
is_const = true;
break;
case Common::Assignment::A_VAR_TEMPLATE:
case Common::Assignment::A_PAR_TEMPL_INOUT:
case Common::Assignment::A_PAR_TEMPL_OUT:
is_template = true;
break;
default:
break;
}
for (size_t i = 0; i < refd_local_defs.size(); ++i) {
Common::Assignment* def = refd_local_defs.get_nth_key(i);
str = mputprintf(str, "%s%s%s& p_%s",
include_location_info || i > 0 ? ", " : "", is_const ? "const " : "",
is_template ? def->get_Type()->get_genname_template(my_sb).c_str() : def->get_Type()->get_genname_value(my_sb).c_str(),
include_location_info || i > 0 ? ", " : "", is_const[i] ? "const " : "",
is_template[i] ? def->get_Type()->get_genname_template(my_sb).c_str() : def->get_Type()->get_genname_value(my_sb).c_str(),
def->get_id().get_name().c_str());
}
str = mputstr(str, "): ");
if (include_location_info) {
str = mputstr(str, "current_location(p_loc)");
}
for (size_t i = 0; i < finally_block->refd_local_defs.size(); ++i) {
Common::Assignment* def = finally_block->refd_local_defs.get_nth_key(i);
str = mputprintf(str, "%s%s(p_%s)", include_location_info || i > 0 ? ", " : "",
def->get_id().get_name().c_str(), def->get_id().get_name().c_str());
for (size_t i = 0; i < refd_local_defs.size(); ++i) {
Common::Assignment* def = refd_local_defs.get_nth_key(i);
str = mputprintf(str, "%s%s%s(p_%s)", include_location_info || i > 0 ? ", " : "",
def->get_id().get_name().c_str(), is_shadowed[i] ? "_shadow" : "", def->get_id().get_name().c_str());
}
str = mputstr(str, " { }\n");
}
str = mputprintf(str,
"~%s_finally() {\n"
"try {\n", tmp_id.c_str());
str = finally_block->generate_code(str, def_glob_vars, src_glob_vars);
str = generate_code(str, def_glob_vars, src_glob_vars);
str = mputprintf(str,
"} catch (...) {\n"
"fprintf(stderr, \"Unhandled exception or dynamic test case error in a finally block. Terminating application.\\n\");\n"
......@@ -683,69 +745,22 @@ namespace Ttcn {
"};\n"
"%s_finally %s",
tmp_id.c_str(), tmp_id.c_str());
if (include_location_info || finally_block->refd_local_defs.size() > 0) {
if (include_location_info || refd_local_defs.size() > 0) {
str = mputc(str, '(');
if (include_location_info) {
str = mputstr(str, "current_location");
}
for (size_t i = 0; i < finally_block->refd_local_defs.size(); ++i) {
str = mputprintf(str, "%s%s", include_location_info || i > 0 ? ", " : "",
finally_block->refd_local_defs.get_nth_key(i)->get_id().get_name().c_str());
for (size_t i = 0; i < refd_local_defs.size(); ++i) {
Common::Assignment* def = refd_local_defs.get_nth_key(i);
str = mputprintf(str, "%s%s%s", include_location_info || i > 0 ? ", " : "",
def->get_id().get_name().c_str(), is_shadowed[i] ? "_shadow" : "");
}
str = mputc(str, ')');
}
str = mputstr(str, ";\n");
#else
// C++11 version:
str = mputprintf(str,
"FINALLY %s([&] {\n", tmp_id.c_str());
str = finally_block->generate_code(str, def_glob_vars, src_glob_vars);
str = mputstr(str, "});\n");
#endif
}
if (catch_blocks.size() > 0) {
str = mputstr(str, "try {\n");
}
if (stmts.size()>0) {
Statement* first_stmt = stmts[0];
str = first_stmt->generate_code(str, def_glob_vars, src_glob_vars);
if (exception_handling==EH_CATCH) {
if (first_stmt->get_statementtype()!=Statement::S_DEF) FATAL_ERROR("StatementBlock::generate_code()");
Definition* error_msg_def = first_stmt->get_def();
string error_msg_name = error_msg_def->get_id().get_name();
str = mputprintf(str, "%s = ttcn_error.get_message();\n", error_msg_name.c_str());
}
}
for(size_t i=1; i<stmts.size(); i++) {
str = stmts[i]->generate_code(str, def_glob_vars, src_glob_vars);
}
if (alt_guards != NULL && exception_handling == EH_NONE) {
str = alt_guards->generate_code_altstep(str, def_glob_vars, src_glob_vars);
}
if (exception_handling == EH_OOP_CATCH && alt_guards != NULL) {
// we are in an altstep's statement block
// indicate that an alt branch has been chosen (since exceptions can only be raised from
// the statement blocks of the alt branches)
str = mputstr(str, "return ALT_YES;\n");
}
if (catch_blocks.size() > 0) {
str = mputstr(str,
"}\n" // end of the 'try' block
"catch (EXCEPTION_BASE& exc_base) {\n");
for (size_t i = 0; i < catch_blocks.size(); ++i) {
Type* exc_type = catch_blocks[i]->get_stmt_byIndex(0)->get_def()->get_Type();
str = mputprintf(str,
"%sif (exc_base.has_type(\"%s\")) {\n",
i > 0 ? "else " : "", exc_type->get_exception_name().c_str());
str = catch_blocks[i]->generate_code(str, def_glob_vars, src_glob_vars, alt_guards);
str = mputstr(str, "}\n");
}
// if none of the exception types matched, then just re-throw the exception as if nothing happened
str = mputstr(str,
"else { throw exc_base; }\n"
"}\n"); // end of the catch block
}
return str;
delete[] is_const;
delete[] is_template;
delete[] is_shadowed;
return mputstr(str, ";\n");
}
void StatementBlock::ilt_generate_code(ILT *ilt)
......
......@@ -182,6 +182,7 @@ namespace Ttcn {
* '@update' statement.
* Also generates code for the alt-guards if this is the statement block of an altstep. */
char* generate_code(char *str, char*& def_glob_vars, char*& src_glob_vars, AltGuards* alt_guards = NULL);
char* generate_code_finally(char* str, char*& def_glob_vars, char*& src_glob_vars);
void ilt_generate_code(ILT *ilt);
virtual void set_parent_path(WithAttribPath* p_path);
......
......@@ -45,8 +45,9 @@ type component CT {
type integer SmallNumber (-100..100);
function test_block(in integer p_exception_type) runs on CT {
function test_block(in integer p_exception_type, in charstring p_dummy := "a") runs on CT {
var integer v_finally_increment := 1;
p_dummy := "abc";
{
select (p_exception_type) {
case (1) {
......@@ -119,6 +120,7 @@ function test_block(in integer p_exception_type) runs on CT {
}
finally {
cv_finally_counter := cv_finally_counter + v_finally_increment; // test referencing a local variable (in the main block)
log(p_dummy); // test referencing a shadowed function parameter (in the main block)
if (cv_finally_counter > 0) {
log(p_exception_type); // test referencing a function parameter (in a sub-block)
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment