Commit 083dc876 authored by Botond Baranyi's avatar Botond Baranyi
Browse files

OOP: implemented the 'raise' statement and 'catch'/'finally' blocks (Bug 568899)


Signed-off-by: Botond Baranyi's avatarBotond Baranyi <botond.baranyi@ericsson.com>
Change-Id: Id98b9cd7eb7f0a1cd842405f07f8feb75a42d277
Signed-off-by: Botond Baranyi's avatarBotond Baranyi <botond.baranyi@ericsson.com>
parent 4a191f2c
......@@ -1828,6 +1828,8 @@ namespace Common {
return "template";
case A_VAR:
return "variable";
case A_EXCEPTION:
return "exception";
case A_VAR_TEMPLATE:
return "template variable";
case A_TIMER:
......@@ -1884,6 +1886,7 @@ namespace Common {
case A_PAR_TEMPL_INOUT:
case A_PAR_TIMER:
case A_PAR_PORT:
case A_EXCEPTION:
// parameter is identified using its id
ret_val += id->get_dispname();
break;
......
......@@ -515,6 +515,7 @@ namespace Common {
A_MODULEPAR_TEMP, /**< template module parameter */
A_TEMPLATE, /**< template (TTCN-3) */
A_VAR, /**< variable (TTCN-3) */
A_EXCEPTION, /**< exception (at the beginning of a catch block) (TTCN-3) */
A_VAR_TEMPLATE, /**< template variable, dynamic template (TTCN-3) */
A_TIMER, /**< timer (TTCN-3) */
A_PORT, /**< port (TTCN-3) */
......
......@@ -7965,6 +7965,25 @@ namespace Common {
}
}
}
string Type::get_exception_name()
{
switch (ownertype) {
case OT_TYPE_ASS:
case OT_TYPE_DEF:
case OT_ARRAY:
case OT_COMP_FIELD:
case OT_RECORD_OF:
return get_genname_own();
default:
if (is_ref()) {
return get_type_refd()->get_exception_name();
}
else {
return get_typename();
}
}
}
string Type::get_genname_typename(Scope *p_scope)
{
......
......@@ -1368,6 +1368,7 @@ namespace Common {
string get_genname_typedescriptor(Scope *p_scope);
string get_genname_coder(Scope* p_scope);
string get_genname_default_coding(Scope* p_scope);
string get_exception_name();
private:
/** Returns the name prefix of type descriptors, etc. that belong to the
* equivalent C++ class referenced from the module of scope \a p_scope.
......
......@@ -4233,6 +4233,7 @@ bool Type::chk_this_refd_value(Value *value, Common::Assignment *lhs, expected_v
}
// else fall through
case Assignment::A_VAR:
case Assignment::A_EXCEPTION:
case Assignment::A_PAR_VAL:
case Assignment::A_PAR_VAL_IN:
case Assignment::A_PAR_VAL_OUT:
......@@ -6515,6 +6516,7 @@ bool Type::chk_this_template_generic(Template *t, namedbool incomplete_allowed,
switch (ass->get_asstype()) {
case Assignment::A_VAR:
case Assignment::A_EXCEPTION:
case Assignment::A_PAR_VAL_IN:
case Assignment::A_PAR_VAL_INOUT:
case Assignment::A_MODULEPAR:
......
......@@ -4168,6 +4168,7 @@ namespace Common {
case Assignment::A_MODULEPAR_TEMP:
case Assignment::A_TEMPLATE:
case Assignment::A_VAR:
case Assignment::A_EXCEPTION:
case Assignment::A_VAR_TEMPLATE:
case Assignment::A_FUNCTION_RVAL:
case Assignment::A_FUNCTION_RTEMP:
......@@ -4570,6 +4571,7 @@ namespace Common {
case Assignment::A_EXT_CONST:
case Assignment::A_MODULEPAR:
case Assignment::A_VAR:
case Assignment::A_EXCEPTION:
case Assignment::A_PAR_VAL_IN:
case Assignment::A_PAR_VAL_OUT:
case Assignment::A_PAR_VAL_INOUT:
......@@ -5069,6 +5071,7 @@ namespace Common {
case Assignment::A_EXT_CONST:
case Assignment::A_MODULEPAR:
case Assignment::A_VAR:
case Assignment::A_EXCEPTION:
case Assignment::A_FUNCTION_RVAL:
case Assignment::A_EXT_FUNCTION_RVAL:
case Assignment::A_PAR_VAL_IN:
......@@ -5276,6 +5279,7 @@ namespace Common {
case Assignment::A_EXT_CONST:
case Assignment::A_MODULEPAR:
case Assignment::A_VAR:
case Assignment::A_EXCEPTION:
case Assignment::A_FUNCTION_RVAL:
case Assignment::A_EXT_FUNCTION_RVAL:
case Assignment::A_PAR_VAL_IN:
......@@ -6683,6 +6687,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
goto error;
break;
case Assignment::A_VAR:
case Assignment::A_EXCEPTION:
case Assignment::A_PAR_VAL_OUT:
case Assignment::A_PAR_VAL_INOUT:
break;
......@@ -6752,6 +6757,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
// Extra check for HM59355.
switch (t_ass->get_asstype()) {
case Assignment::A_VAR:
case Assignment::A_EXCEPTION:
case Assignment::A_PAR_VAL_IN:
case Assignment::A_PAR_VAL_OUT:
case Assignment::A_PAR_VAL_INOUT:
......@@ -7043,6 +7049,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
}
break;
case Assignment::A_VAR:
case Assignment::A_EXCEPTION:
case Assignment::A_PAR_VAL_IN:
case Assignment::A_PAR_VAL_OUT:
case Assignment::A_PAR_VAL_INOUT:
......@@ -10322,6 +10329,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
case Assignment::A_EXT_CONST:
case Assignment::A_MODULEPAR:
case Assignment::A_VAR:
case Assignment::A_EXCEPTION:
case Assignment::A_FUNCTION_RVAL:
case Assignment::A_EXT_FUNCTION_RVAL:
case Assignment::A_PAR_VAL_IN:
......@@ -12007,6 +12015,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
case Assignment::A_EXT_CONST:
case Assignment::A_MODULEPAR:
case Assignment::A_VAR:
case Assignment::A_EXCEPTION:
case Assignment::A_PAR_VAL_IN:
case Assignment::A_PAR_VAL_OUT:
case Assignment::A_PAR_VAL_INOUT: {
......@@ -15177,6 +15186,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
case Assignment::A_EXT_CONST:
case Assignment::A_MODULEPAR:
case Assignment::A_VAR:
case Assignment::A_EXCEPTION:
case Assignment::A_FUNCTION_RVAL:
case Assignment::A_EXT_FUNCTION_RVAL:
case Assignment::A_PAR_VAL_IN:
......@@ -16778,6 +16788,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
case Assignment::A_EXT_CONST:
case Assignment::A_MODULEPAR:
case Assignment::A_VAR:
case Assignment::A_EXCEPTION:
case Assignment::A_PAR_VAL_IN:
case Assignment::A_PAR_VAL_OUT:
case Assignment::A_PAR_VAL_INOUT:
......
......@@ -398,6 +398,7 @@ namespace Ttcn {
case Common::Assignment::A_EXT_CONST: // a Def_ExtConst
case Common::Assignment::A_MODULEPAR: // a Def_Modulepar
case Common::Assignment::A_VAR: // a Def_Var
case Common::Assignment::A_EXCEPTION: // a Def_Exception
case Common::Assignment::A_FUNCTION_RVAL: // a Def_Function
case Common::Assignment::A_EXT_FUNCTION_RVAL: // a Def_ExtFunction
case Common::Assignment::A_PAR_VAL_IN: // a FormalPar
......@@ -673,6 +674,7 @@ namespace Ttcn {
case Common::Assignment::A_MODULEPAR: /**< module parameter (TTCN-3) */
case Common::Assignment::A_MODULEPAR_TEMP: /**< template module parameter */
case Common::Assignment::A_VAR: /**< variable (TTCN-3) */
case Common::Assignment::A_EXCEPTION: /**< exception (TTCN-3) */
case Common::Assignment::A_VAR_TEMPLATE: /**< template variable: dynamic template (TTCN-3) */
case Common::Assignment::A_TIMER: /**< timer (TTCN-3) */
case Common::Assignment::A_PORT: /**< port (TTCN-3) */
......@@ -914,6 +916,7 @@ namespace Ttcn {
if (ass != NULL && subrefs.get_nof_refs() != 0) {
switch (ass->get_asstype()) {
case Common::Assignment::A_VAR:
case Common::Assignment::A_EXCEPTION:
case Common::Assignment::A_PAR_VAL:
case Common::Assignment::A_PAR_VAL_IN:
case Common::Assignment::A_PAR_VAL_INOUT:
......@@ -981,6 +984,7 @@ namespace Ttcn {
t_ass->use_as_lvalue(*this);
// no break
case Common::Assignment::A_VAR:
case Common::Assignment::A_EXCEPTION:
case Common::Assignment::A_PAR_VAL_OUT:
case Common::Assignment::A_PAR_VAL_INOUT:
if (has_parameters()) {
......@@ -1186,6 +1190,7 @@ namespace Ttcn {
base_type->get_genname_own(my_scope).c_str());
}
string const_prefix; // empty by default
string exception_postfix; // also empty by default
if (gen_const_prefix) {
if (ass->get_asstype() == Common::Assignment::A_CONST) {
const_prefix = "const_";
......@@ -1194,6 +1199,9 @@ namespace Ttcn {
const_prefix = "template_";
}
}
if (ass->get_asstype() == Common::Assignment::A_EXCEPTION) {
exception_postfix = "()";
}
if (parlist != NULL) {
expr->expr = mputprintf(expr->expr, "%s(",
ass->get_genname_from_scope(my_scope).c_str());
......@@ -1204,7 +1212,7 @@ namespace Ttcn {
expr->expr = mputstr(expr->expr,
LazyFuzzyParamData::in_lazy_or_fuzzy() ?
LazyFuzzyParamData::add_ref_genname(ass, my_scope).c_str() :
(const_prefix + ass->get_genname_from_scope(my_scope)).c_str());
(const_prefix + ass->get_genname_from_scope(my_scope) + exception_postfix).c_str());
}
if (subrefs.get_nof_refs() > 0) subrefs.generate_code(expr, ass, my_scope);
}
......@@ -1225,6 +1233,7 @@ namespace Ttcn {
switch (ass->get_asstype()) {
case Common::Assignment::A_MODULEPAR:
case Common::Assignment::A_VAR:
case Common::Assignment::A_EXCEPTION:
case Common::Assignment::A_PAR_VAL:
case Common::Assignment::A_PAR_VAL_IN:
case Common::Assignment::A_PAR_VAL_OUT:
......@@ -1270,6 +1279,10 @@ namespace Ttcn {
refd_gov->get_genname_value(get_my_scope()).c_str());
}
}
string exception_postfix;
if (ass->get_asstype() == Common::Assignment::A_EXCEPTION) {
exception_postfix = "()";
}
if (parlist != NULL) {
// reference without parameters to a template that has only default formal parameters.
// if @lazy: nothing to do, it's a C++ function call just like in case of Ref_pard::generate_code()
......@@ -1282,7 +1295,7 @@ namespace Ttcn {
this_expr.expr = mputstr(this_expr.expr,
LazyFuzzyParamData::in_lazy_or_fuzzy() ?
LazyFuzzyParamData::add_ref_genname(ass, my_scope).c_str() :
ass->get_genname_from_scope(my_scope).c_str());
(ass->get_genname_from_scope(my_scope) + exception_postfix).c_str());
}
if (refd_gov->get_type_refd_last()->get_typetype() != Common::Type::T_CLASS) {
this_expr.expr = mputstr(this_expr.expr, ")");
......@@ -5490,6 +5503,21 @@ namespace Ttcn {
if (initial_value) initial_value->dump(level + 1);
}
// =================================
// ===== Def_Exception
// =================================
Def_Exception::Def_Exception(Identifier* p_id, Type* p_type): Def_Var(p_id, p_type, NULL)
{
asstype = Common::Assignment::A_EXCEPTION;
}
char* Def_Exception::generate_code_str(char *str)
{
return mputprintf(str, "EXCEPTION<%s>& %s = static_cast<EXCEPTION<%s>&>(exc_base);\n",
type->get_genname_value(my_scope).c_str(), id->get_name().c_str(), type->get_genname_value(my_scope).c_str());
}
// =================================
// ===== Def_Var_Template
// =================================
......@@ -8425,9 +8453,7 @@ namespace Ttcn {
body = generate_code_debugger_function_init(body, this);
}
body = sb->generate_code(body, target->header.global_vars,
target->source.global_vars);
body = ags->generate_code_altstep(body, target->header.global_vars,
target->source.global_vars);
target->source.global_vars, ags);
// generate a smart formal parameter list (omits unused parameter names)
char *formal_par_list = fp_list->generate_code(memptystr());
fp_list->generate_code_defval(target);
......@@ -8708,7 +8734,9 @@ namespace Ttcn {
body = generate_code_debugger_function_init(body, this);
}
body = mputprintf(body, "try {\n"
"%s"
"TTCN_Runtime::begin_testcase(\"%s\", \"%s\", ",
oop_features ? "try {\n" : "",
my_scope->get_scope_mod()->get_modid().get_dispname().c_str(),
dispname_str);
ComponentTypeBody *runs_on_body = runs_on_type->get_CompBody();
......@@ -8721,10 +8749,14 @@ namespace Ttcn {
body = block->generate_code(body, target->header.global_vars,
target->source.global_vars);
body = mputprintf(body,
"%s"
"} catch (const TC_Error& tc_error) {\n"
"} catch (const TC_End& tc_end) {\n"
"TTCN_Logger::log_str(TTCN_FUNCTION, \"Test case %s was stopped.\");\n"
"}\n", dispname_str);
"}\n",
oop_features ? "} catch (const EXCEPTION_BASE& exc) {\n"
"TTCN_error(\"Unhandled exception: %s\", (const char*) exc.get_log());\n"
"}\n" : "", dispname_str);
body = mputstr(body, "return TTCN_Runtime::end_testcase();\n");
// smart formal parameter list (names of unused parameters are omitted)
......@@ -9595,6 +9627,7 @@ namespace Ttcn {
}
// no break
case A_VAR:
case A_EXCEPTION:
case A_PAR_VAL_OUT:
case A_PAR_VAL_INOUT:
if (!is_template) asstype_correct = true;
......@@ -10709,6 +10742,7 @@ namespace Ttcn {
if(!t_par_ass) FATAL_ERROR("FormalParList::chk_activate_argument()");
switch (t_par_ass->get_asstype()) {
case Common::Assignment::A_VAR:
case Common::Assignment::A_EXCEPTION: // TODO: can exceptions be of 'default' type?
case Common::Assignment::A_VAR_TEMPLATE:
case Common::Assignment::A_TIMER:
// it is not allowed to pass references of local variables or timers
......@@ -11562,6 +11596,7 @@ namespace Ttcn {
Common::Assignment *ass = par->get_Ref()->get_refd_assignment();
switch (ass->get_asstype()) {
case Common::Assignment::A_VAR:
case Common::Assignment::A_EXCEPTION:
case Common::Assignment::A_PAR_VAL_IN:
case Common::Assignment::A_PAR_VAL_OUT:
case Common::Assignment::A_PAR_VAL_INOUT:
......
......@@ -1166,11 +1166,13 @@ namespace Ttcn {
* Def_Var class represents a variable definition.
*/
class Def_Var : public Definition {
private:
protected:
Type *type;
private:
/** the initial value: optional and maybe incomplete */
Value *initial_value;
/// Copy constructor disabled
Def_Var(const Def_Var& p);
/// %Assignment disabled
......@@ -1191,6 +1193,18 @@ namespace Ttcn {
virtual char *generate_code_init_comp(char *str, Definition *base_defn);
virtual void dump_internal(unsigned level) const;
};
class Def_Exception : public Def_Var {
private:
/// Copy constructor disabled
Def_Exception(const Def_Exception& p);
/// %Assignment disabled
Def_Exception& operator=(const Def_Exception& p);
public:
Def_Exception(Identifier* p_id, Type* p_type);
virtual char* generate_code_str(char *str);
};
/**
* Def_Var_Template class represents a template variable (dynamic template)
......
......@@ -675,6 +675,7 @@ namespace Ttcn {
}
} else if ((assign->get_asstype() == Common::Assignment::A_MODULEPAR
|| assign->get_asstype() == Common::Assignment::A_VAR
|| assign->get_asstype() == Common::Assignment::A_EXCEPTION
|| assign->get_asstype() == Common::Assignment::A_PAR_VAL
|| assign->get_asstype() == Common::Assignment::A_PAR_VAL_IN
|| assign->get_asstype() == Common::Assignment::A_PAR_VAL_OUT
......
......@@ -43,7 +43,8 @@ namespace Ttcn {
// =================================
StatementBlock::StatementBlock()
: Scope(), checked(false), labels_checked(false), my_sb(0), my_def(0), exception_handling(EH_NONE)
: Scope(), checked(false), labels_checked(false), my_sb(0), my_def(0), exception_handling(EH_NONE),
finally_block(NULL)
{
}
......@@ -54,6 +55,11 @@ namespace Ttcn {
stmts.clear();
defs.clear();
labels.clear();
for (size_t i = 0; i < catch_blocks.size(); ++i) {
delete catch_blocks[i];
}
catch_blocks.clear();
delete finally_block;
}
StatementBlock *StatementBlock::clone() const
......@@ -89,6 +95,12 @@ namespace Ttcn {
set_parent_scope(p_scope);
for(size_t i=0; i<stmts.size(); i++)
stmts[i]->set_my_scope(this);
for (size_t i = 0; i < catch_blocks.size(); ++i) {
catch_blocks[i]->set_parent_scope(p_scope);
}
if (finally_block != NULL) {
finally_block->set_parent_scope(p_scope);
}
}
void StatementBlock::set_fullname(const string& p_fullname)
......@@ -96,6 +108,12 @@ namespace Ttcn {
Node::set_fullname(p_fullname);
for(size_t i=0; i<stmts.size(); i++)
stmts[i]->set_fullname(p_fullname+".stmt_"+Int2string(i+1));
for (size_t i = 0; i < catch_blocks.size(); ++i) {
catch_blocks[i]->set_fullname(p_fullname + ".catch_block_" + Int2string(i + 1));
}
if (finally_block != NULL) {
finally_block->set_fullname(p_fullname + ".finally_block");
}
}
/** \todo handle loops and conditional statements */
......@@ -227,6 +245,12 @@ namespace Ttcn {
my_def=p_def;
for(size_t i=0; i<stmts.size(); i++)
stmts[i]->set_my_def(p_def);
for (size_t i = 0; i < catch_blocks.size(); ++i) {
catch_blocks[i]->set_my_def(p_def);
}
if (finally_block != NULL) {
finally_block->set_my_def(p_def);
}
}
void StatementBlock::set_my_ags(AltGuards *p_ags)
......@@ -241,6 +265,24 @@ namespace Ttcn {
for(size_t i=0; i<stmts.size(); i++)
stmts[i]->set_my_laic_stmt(p_ags, p_loop_stmt);
}
void StatementBlock::add_catch_block(StatementBlock* p_catch)
{
if (p_catch == NULL) {
FATAL_ERROR("StatementBlock::add_catch_block");
}
p_catch->exception_handling = EH_OOP_CATCH;
catch_blocks.add(p_catch);
}
void StatementBlock::set_finally_block(StatementBlock* p_finally)
{
if (finally_block != NULL || p_finally == NULL) {
FATAL_ERROR("StatementBlock::set_finally_block");
}
p_finally->exception_handling = EH_OOP_FINALLY;
finally_block = p_finally;
}
StatementBlock::returnstatus_t StatementBlock::has_return() const
{
......@@ -376,6 +418,12 @@ namespace Ttcn {
}
chk_trycatch_blocks(prev_stmt, 0);
chk_unused_labels();
for (size_t i = 0; i < catch_blocks.size(); ++i) {
catch_blocks[i]->chk();
}
if (finally_block != NULL) {
finally_block->chk();
}
checked = true;
}
......@@ -384,6 +432,12 @@ namespace Ttcn {
size_t nof_stmts = stmts.size();
for (size_t i = 0; i < nof_stmts; i++)
stmts[i]->chk_allowed_interleave();
for (size_t i = 0; i < catch_blocks.size(); ++i) {
catch_blocks[i]->chk_allowed_interleave();
}
if (finally_block != NULL) {
finally_block->chk_allowed_interleave();
}
}
void StatementBlock::chk_labels()
......@@ -401,6 +455,12 @@ namespace Ttcn {
}
else labels.add(labelid, st);
}
for (size_t i = 0; i < catch_blocks.size(); ++i) {
catch_blocks[i]->chk_labels();
}
if (finally_block != NULL) {
finally_block->chk_labels();
}
labels_checked=true;
}
......@@ -414,6 +474,12 @@ namespace Ttcn {
stmt->warning("Label `%s' is defined, but not used",
stmt->get_labelid().get_dispname().c_str());
}
for (size_t i = 0; i < catch_blocks.size(); ++i) {
catch_blocks[i]->chk_unused_labels();
}
if (finally_block != NULL) {
finally_block->chk_unused_labels();
}
}
bool StatementBlock::has_label(const Identifier& p_id) const
......@@ -436,13 +502,52 @@ namespace Ttcn {
{
for(size_t i = 0; i < stmts.size(); i++)
stmts[i]->set_code_section(p_code_section);
for (size_t i = 0; i < catch_blocks.size(); ++i) {
catch_blocks[i]->set_code_section(p_code_section);
}
if (finally_block != NULL) {
finally_block->set_code_section(p_code_section);
}
}
char* StatementBlock::generate_code(char *str, char*& def_glob_vars, char*& src_glob_vars)
char* StatementBlock::generate_code(char *str, char*& def_glob_vars, char*& src_glob_vars,
AltGuards* alt_guards /* = NULL */)
{
if (exception_handling==EH_TRY) {
str = mputstr(str, "TTCN_TryBlock try_block;\n");
}
if (finally_block != NULL) {
string tmp_id = get_scope_mod_gen()->get_temporary_id();
/*str = mputprintf(str,
"class %s_finally {\n"
"public:\n", tmp_id.c_str());
// TODO: all local declarations (or those referenced in the 'finally' block) need to
// be added as members of this class, so the destructor can reach them
// or the C++11 code could be used...
if (include_location_info) {
str = mputprintf(str,
"TTCN_Location& current_location;\n"
"%s_finally(TTCN_Location& p_loc):current_location(p_loc) { }\n",
tmp_id.c_str());
}
str = mputprintf(str,
"~%s_finally() {\n", tmp_id.c_str());
str = finally_block->generate_code(str, def_glob_vars, src_glob_vars);
str = mputprintf(str,
"}\n"
"};\n"
"%s_finally %s%s;\n",
tmp_id.c_str(), tmp_id.c_str(),
include_location_info ? "(current_location)" : "");*/
// 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");
}
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);
......@@ -456,6 +561,32 @@ namespace Ttcn {
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;
}
......@@ -491,6 +622,12 @@ namespace Ttcn {
{
for (size_t i = 0; i < stmts.size(); i++)
stmts[i]->set_parent_path(p_path);
for (size_t i = 0; i < catch_blocks.size(); ++i) {
catch_blocks[i]->set_parent_path(p_path);
}
if (finally_block != NULL) {
finally_block->set_parent_path(p_path);
}
}
// =================================
......@@ -758,6 +895,14 @@ namespace Ttcn {
delete setencode_op.type;
delete setencode_op.encoding;
break;
case S_RAISE_OOP:
if (raise_op.checked) {
delete raise_op.v;
}
else {
delete raise_op.ti;
}
break;
default:
FATAL_ERROR("Statement::clean_up()");
} // switch statementtype
......@@ -1550,6 +1695,22 @@ namespace Ttcn {
FATAL_ERROR("Statement::Statement()");
}
}
Statement::Statement(statementtype_t p_st, TemplateInstance* p_ti)
: statementtype(p_st), my_sb(0)
{
switch (statementtype) {
case S_RAISE_OOP:
if (p_ti == NULL) {
FATAL_ERROR("Statement::Statement()");
}
raise_op.checked = false;
raise_op.ti = p_ti;
break;
default:
FATAL_ERROR("Statement::Statement()");
}
}
Statement::~Statement()
{
......@@ -2056,6 +2217,12 @@ namespace Ttcn {
setencode_op.type->set_my_scope(p_scope);
setencode_op.encoding->set_my_scope(p_scope);
break;
case S_RAISE_OOP:
if (raise_op.checked) {
FATAL_ERROR("Statement::set_my_scope()");
}
raise_op.ti->set_my_scope(p_scope);
break;
default:
FATAL_ERROR("Statement::set_my_scope()");
} // switch statementtype
......@@ -2384,6 +2551,12 @@ namespace Ttcn {
setencode_op.type->set_fullname(p_fullname + ".type");
setencode_op.encoding->set_fullname(p_fullname + ".encoding");
break;
case S_RAISE_OOP:
if (raise_op.checked) {
FATAL_ERROR("Statement::set_fullname()");
}
raise_op.ti->set_fullname(p_fullname + ".exception");
break;