Commit e6c2fb02 authored by Botond Baranyi's avatar Botond Baranyi
Browse files

Implemented object-oriented features - stage 6.1 (bug 552011)



Change-Id: Ief2350ee8c8a5d979e8c1efc7e564d691a91fba7
Signed-off-by: Botond Baranyi's avatarBotond Baranyi <botond.baranyi@ericsson.com>
parent e2b8383c
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include "ttcn3/profiler.h" #include "ttcn3/profiler.h"
#include "ttcn3/Attributes.hh" #include "ttcn3/Attributes.hh"
#include "ttcn3/Ttcnstuff.hh" #include "ttcn3/Ttcnstuff.hh"
#include "ttcn3/Statement.hh"
namespace Common { namespace Common {
...@@ -676,6 +677,9 @@ namespace Common { ...@@ -676,6 +677,9 @@ namespace Common {
case Type::T_ALTSTEP: case Type::T_ALTSTEP:
typetype_name = "altstep"; typetype_name = "altstep";
break; break;
case Type::T_CLASS:
typetype_name = "class";
break;
default: default:
FATAL_ERROR("Scope::chk_runs_on_clause()"); FATAL_ERROR("Scope::chk_runs_on_clause()");
typetype_name = 0; typetype_name = 0;
...@@ -727,6 +731,33 @@ namespace Common { ...@@ -727,6 +731,33 @@ namespace Common {
} }
} }
void Scope::chk_mtc_clause(Type* p_type, const Location& p_loc)
{
// component type of the referred definition
Type* refd_comptype = p_type->get_class_type_body()->get_MtcType();
// definitions without 'mtc' can be called from anywhere
if (refd_comptype == NULL) {
return;
}
if (get_statementblock_scope()->get_my_def() == NULL) { // in control part
p_loc.error("Cannot create value of class type `%s', which has an `mtc' "
"clause, in the control part.", p_type->get_typename().c_str());
return;
}
Type* t_comptype = get_mtc_system_comptype(false);
if (t_comptype != NULL) {
if (!refd_comptype->is_compatible_component_by_port(t_comptype)) {
// the 'mtc' clause of the referred definition is not compatible
// with that of the current scope (i.e. the referring definition)
p_loc.error("Mtc clause mismatch: A definition that runs on component "
"type `%s' cannot create a value of class type `%s', which has `mtc' "
"component type `%s'",
t_comptype->get_typename().c_str(), p_type->get_typename().c_str(),
refd_comptype->get_typename().c_str());
}
}
}
void Scope::chk_system_clause(Assignment *p_ass, const Location& p_loc, void Scope::chk_system_clause(Assignment *p_ass, const Location& p_loc,
const char *p_what, bool in_control_part) const char *p_what, bool in_control_part)
{ {
...@@ -751,6 +782,33 @@ namespace Common { ...@@ -751,6 +782,33 @@ namespace Common {
} }
} }
} }
void Scope::chk_system_clause(Type* p_type, const Location& p_loc)
{
// component type of the referred definition
Type* refd_comptype = p_type->get_class_type_body()->get_SystemType();
// definitions without 'system' can be called from anywhere
if (refd_comptype == NULL) {
return;
}
if (get_statementblock_scope()->get_my_def() == NULL) { // in control part
p_loc.error("Cannot create value of class type `%s', which has a `system' "
"clause, in the control part.", p_type->get_typename().c_str());
return;
}
Type* t_comptype = get_mtc_system_comptype(true);
if (t_comptype != NULL) {
if (!refd_comptype->is_compatible_component_by_port(t_comptype)) {
// the 'system' clause of the referred definition is not compatible
// with that of the current scope (i.e. the referring definition)
p_loc.error("System clause mismatch: A definition that runs on component "
"type `%s' cannot create a value of class type `%s', which has `system' "
"component type `%s'",
t_comptype->get_typename().c_str(), p_type->get_typename().c_str(),
refd_comptype->get_typename().c_str());
}
}
}
// ================================= // =================================
// ===== Reference // ===== Reference
......
...@@ -634,10 +634,11 @@ public: ...@@ -634,10 +634,11 @@ public:
* "activate". */ * "activate". */
void chk_runs_on_clause(Assignment *p_ass, const Location& p_loc, void chk_runs_on_clause(Assignment *p_ass, const Location& p_loc,
const char *p_what); const char *p_what);
/** Checks the 'runs on' clause of type \a p_fat that the values of it can /** Checks the 'runs on' clause of type \a p_fat that values of it can
* be called from this scope unit. Type \a p_fat shall be of type function * be called/created from this scope unit.
* or altstep. Parameters \a p_loc and \a p_what are used in error messages. * Type \a p_fat shall be of function, altstep or class type.
* \a p_what contains "call" or "activate". */ * Parameters \a p_loc and \a p_what are used in error messages.
* \a p_what contains "call", "activate" or "create". */
void chk_runs_on_clause(Type *p_fat, const Location& p_loc, void chk_runs_on_clause(Type *p_fat, const Location& p_loc,
const char *p_what); const char *p_what);
/** Checks the 'mtc' clause of definition \a p_ass that it can /** Checks the 'mtc' clause of definition \a p_ass that it can
...@@ -646,12 +647,20 @@ public: ...@@ -646,12 +647,20 @@ public:
* "activate". */ * "activate". */
void chk_mtc_clause(Assignment *p_ass, const Location& p_loc, void chk_mtc_clause(Assignment *p_ass, const Location& p_loc,
const char *p_what, bool in_control_part); const char *p_what, bool in_control_part);
/** Checks the 'mtc' clause of type \a p_type that values of it can
* be created from this scope unit. Type \a p_type shall be of class type.
* Parameters \a p_loc is used in error messages. */
void chk_mtc_clause(Type* p_type, const Location& p_loc);
/** Checks the 'system' clause of definition \a p_ass that it can /** Checks the 'system' clause of definition \a p_ass that it can
* be called from this scope unit. Parameters \a p_loc and \a * be called from this scope unit. Parameters \a p_loc and \a
* p_what are used in error messages. \a p_what contains "call" or * p_what are used in error messages. \a p_what contains "call" or
* "activate". */ * "activate". */
void chk_system_clause(Assignment *p_ass, const Location& p_loc, void chk_system_clause(Assignment *p_ass, const Location& p_loc,
const char *p_what, bool in_control_part); const char *p_what, bool in_control_part);
/** Checks the 'system' clause of type \a p_type that values of it can
* be created from this scope unit. Type \a p_type shall be of class type.
* Parameters \a p_loc is used in error messages. */
void chk_system_clause(Type* p_type, const Location& p_loc);
}; };
/** /**
......
...@@ -53,6 +53,7 @@ ...@@ -53,6 +53,7 @@
#include "ttcn3/Templatestuff.hh" #include "ttcn3/Templatestuff.hh"
#include "ttcn3/RawAST.hh" #include "ttcn3/RawAST.hh"
#include "ttcn3/JsonAST.hh" #include "ttcn3/JsonAST.hh"
#include "ttcn3/Statement.hh"
#include "../common/static_check.h" #include "../common/static_check.h"
#include "PredefFunc.hh" #include "PredefFunc.hh"
...@@ -227,6 +228,7 @@ namespace Common { ...@@ -227,6 +228,7 @@ namespace Common {
case T_VERDICT: case T_VERDICT:
case T_COMPONENT: case T_COMPONENT:
case T_DEFAULT: case T_DEFAULT:
case T_CLASS: // for the built-in class 'object'
break; // we have a pool type break; // we have a pool type
default: default:
return 0; // no pool type for you! return 0; // no pool type for you!
...@@ -867,6 +869,9 @@ namespace Common { ...@@ -867,6 +869,9 @@ namespace Common {
case T_ADDRESS: case T_ADDRESS:
u.address = 0; u.address = 0;
break; break;
case T_CLASS:
u.class_ = new Ttcn::ClassTypeBody();
break;
default: default:
FATAL_ERROR("Type::Type()"); FATAL_ERROR("Type::Type()");
} // switch } // switch
...@@ -1776,66 +1781,91 @@ namespace Common { ...@@ -1776,66 +1781,91 @@ namespace Common {
return 0; return 0;
} }
Ttcn::ClassTypeBody* class_ = t->get_class_type_body(); Ttcn::ClassTypeBody* class_ = t->get_class_type_body();
bool base_toString = false;
if (!class_->has_local_ass_withId(id)) { if (!class_->has_local_ass_withId(id)) {
ref->error("Reference to non-existent method `%s' in class type `%s'", if (id.get_name() == string("toString")) {
id.get_dispname().c_str(), t->get_typename().c_str()); // the 'toString' method is not in the AST, but it is inherited by
return 0; // every class from the 'object' class
} base_toString = true;
Assignment* ass = class_->get_local_ass_byId(id); if (!ref->parameters_checked()) {
if (!class_->chk_visibility(ass, ref, subrefs->get_my_scope())) { Ttcn::FormalParList fp_list; // empty formal parameter list
// the method is not visible (the error has already been reported) Ttcn::ParsedActualParameters* parsed_pars = ref->get_parsed_pars();
return 0; Ttcn::ActualParList* ap_list = new Ttcn::ActualParList;
} bool is_erroneous = fp_list.fold_named_and_chk(parsed_pars, ap_list);
switch (ass->get_asstype()) { if (is_erroneous) {
case Assignment::A_VAR: delete ap_list;
case Assignment::A_VAR_TEMPLATE: return 0;
case Assignment::A_CONST: }
case Assignment::A_TEMPLATE: ap_list->set_fullname(parsed_pars->get_fullname());
ref->error("Invalid reference to member `%s' in class type `%s', " ap_list->set_my_scope(parsed_pars->get_my_scope());
"reference to a method was expected instead", ref->set_actual_par_list(ap_list);
id.get_dispname().c_str(), t->get_typename().c_str()); }
return 0; t = get_pooltype(T_USTR);
case Assignment::A_FUNCTION: // todo: set *last_method
case Assignment::A_EXT_FUNCTION: }
if (i != nof_refs - 1 || last_method == NULL) { else {
ref->error("Invalid reference to method `%s' with no return type in " ref->error("Reference to non-existent method `%s' in class type `%s'",
"class type `%s'",
id.get_dispname().c_str(), t->get_typename().c_str()); id.get_dispname().c_str(), t->get_typename().c_str());
return 0; return 0;
} }
// a method with no return value can still be valid (e.g. if it's }
// in a statement) if (!base_toString) {
// proceed as normal and return null at the end Assignment* ass = class_->get_local_ass_byId(id);
case Assignment::A_FUNCTION_RVAL: if (!class_->chk_visibility(ass, ref, subrefs->get_my_scope())) {
case Assignment::A_FUNCTION_RTEMP: // the method is not visible (the error has already been reported)
case Assignment::A_EXT_FUNCTION_RVAL: return 0;
case Assignment::A_EXT_FUNCTION_RTEMP: {
Ttcn::Def_Function_Base* def_func =
dynamic_cast<Ttcn::Def_Function_Base*>(ass);
if (def_func == NULL) {
FATAL_ERROR("Type::get_field_type");
} }
t = def_func->get_return_type(); switch (ass->get_asstype()) {
if (!ref->parameters_checked()) { case Assignment::A_VAR:
Ttcn::FormalParList* fp_list = ass->get_FormalParList(); case Assignment::A_VAR_TEMPLATE:
Ttcn::ParsedActualParameters* parsed_pars = ref->get_parsed_pars(); case Assignment::A_CONST:
Ttcn::ActualParList* ap_list = new Ttcn::ActualParList; case Assignment::A_TEMPLATE:
bool is_erroneous = fp_list->fold_named_and_chk(parsed_pars, ap_list); ref->error("Invalid reference to member `%s' in class type `%s', "
if (is_erroneous) { "reference to a method was expected instead",
delete ap_list; id.get_dispname().c_str(), t->get_typename().c_str());
return 0;
case Assignment::A_FUNCTION:
case Assignment::A_EXT_FUNCTION:
if (i != nof_refs - 1 || last_method == NULL) {
ref->error("Invalid reference to method `%s' with no return type in "
"class type `%s'",
id.get_dispname().c_str(), t->get_typename().c_str());
return 0; return 0;
} }
ap_list->set_fullname(parsed_pars->get_fullname()); // a method with no return value can still be valid (e.g. if it's
ap_list->set_my_scope(parsed_pars->get_my_scope()); // in a statement)
ref->set_actual_par_list(ap_list); // proceed as normal and return null at the end
} case Assignment::A_FUNCTION_RVAL:
if (last_method != NULL) { case Assignment::A_FUNCTION_RTEMP:
*last_method = ass; case Assignment::A_EXT_FUNCTION_RVAL:
case Assignment::A_EXT_FUNCTION_RTEMP: {
Ttcn::Def_Function_Base* def_func =
dynamic_cast<Ttcn::Def_Function_Base*>(ass);
if (def_func == NULL) {
FATAL_ERROR("Type::get_field_type");
}
t = def_func->get_return_type();
if (!ref->parameters_checked()) {
Ttcn::FormalParList* fp_list = ass->get_FormalParList();
Ttcn::ParsedActualParameters* parsed_pars = ref->get_parsed_pars();
Ttcn::ActualParList* ap_list = new Ttcn::ActualParList;
bool is_erroneous = fp_list->fold_named_and_chk(parsed_pars, ap_list);
if (is_erroneous) {
delete ap_list;
return 0;
}
ap_list->set_fullname(parsed_pars->get_fullname());
ap_list->set_my_scope(parsed_pars->get_my_scope());
ref->set_actual_par_list(ap_list);
}
if (last_method != NULL) {
*last_method = ass;
}
break; }
default:
FATAL_ERROR("Type::get_field_type - %s shouldn't be in a class",
ass->get_assname());
} }
break; }
default:
FATAL_ERROR("Type::get_field_type - %s shouldn't be in a class",
ass->get_assname());
} }
break; } break; }
case Ttcn::FieldOrArrayRef::ARRAY_REF: { case Ttcn::FieldOrArrayRef::ARRAY_REF: {
...@@ -6224,6 +6254,8 @@ namespace Common { ...@@ -6224,6 +6254,8 @@ namespace Common {
case T_ALTSTEP: case T_ALTSTEP:
case T_TESTCASE: case T_TESTCASE:
return u.fatref.runs_on.type; return u.fatref.runs_on.type;
case T_CLASS:
return u.class_->get_RunsOnType();
default: default:
FATAL_ERROR("Type::get_fat_runs_on_type()"); FATAL_ERROR("Type::get_fat_runs_on_type()");
return 0; return 0;
...@@ -7542,6 +7574,9 @@ namespace Common { ...@@ -7542,6 +7574,9 @@ namespace Common {
return string("COMPONENT"); return string("COMPONENT");
case T_DEFAULT: case T_DEFAULT:
return string("DEFAULT"); return string("DEFAULT");
case T_CLASS:
return t->u.class_->is_built_in() ? string("OBJECT_REF<OBJECT>") :
string("OBJECT_REF<") + t->get_genname_own(p_scope) + string(">");
case T_ARRAY: case T_ARRAY:
if (!t->u.array.in_typedef) if (!t->u.array.in_typedef)
return t->u.array.dimension->get_value_type(t->u.array.element_type, return t->u.array.dimension->get_value_type(t->u.array.element_type,
...@@ -7634,6 +7669,11 @@ namespace Common { ...@@ -7634,6 +7669,11 @@ namespace Common {
const char* tn = get_typename_builtin(t->typetype); const char* tn = get_typename_builtin(t->typetype);
if (tn != 0) return string(tn); if (tn != 0) return string(tn);
switch (t->typetype) { switch (t->typetype) {
case T_CLASS:
if (t->u.class_->is_built_in()) {
return string("object");
}
// else fall through
case T_COMPONENT: case T_COMPONENT:
case T_SIGNATURE: case T_SIGNATURE:
case T_CHOICE_A: case T_CHOICE_A:
...@@ -7651,7 +7691,6 @@ namespace Common { ...@@ -7651,7 +7691,6 @@ namespace Common {
case T_FUNCTION: case T_FUNCTION:
case T_ALTSTEP: case T_ALTSTEP:
case T_TESTCASE: case T_TESTCASE:
case T_CLASS:
return t->get_fullname(); return t->get_fullname();
case T_ARRAY: { case T_ARRAY: {
string dimensions(t->u.array.dimension->get_stringRepr()); string dimensions(t->u.array.dimension->get_stringRepr());
......
...@@ -257,6 +257,7 @@ void Type::generate_code_typedescriptor(output_struct *target) ...@@ -257,6 +257,7 @@ void Type::generate_code_typedescriptor(output_struct *target)
switch (get_type_refd_last()->typetype) { switch (get_type_refd_last()->typetype) {
case T_PORT: case T_PORT:
case T_SIGNATURE: case T_SIGNATURE:
case T_CLASS:
// do not generate any type descriptor for these non-data types // do not generate any type descriptor for these non-data types
return; return;
case T_ARRAY: case T_ARRAY:
......
...@@ -2200,6 +2200,7 @@ namespace Common { ...@@ -2200,6 +2200,7 @@ namespace Common {
if(u.expr.v3) u.expr.v3->set_fullname(p_fullname+".<operand3>"); if(u.expr.v3) u.expr.v3->set_fullname(p_fullname+".<operand3>");
break; break;
case OPTYPE_UNDEF_CREATE: // r1 t_list2 b4 case OPTYPE_UNDEF_CREATE: // r1 t_list2 b4
case OPTYPE_CLASS_CREATE: // r1 t_list2 b4
u.expr.r1->set_fullname(p_fullname+".<operand1>"); u.expr.r1->set_fullname(p_fullname+".<operand1>");
u.expr.t_list2->set_fullname(p_fullname+".<parameterlist>"); u.expr.t_list2->set_fullname(p_fullname+".<parameterlist>");
break; break;
...@@ -8216,6 +8217,9 @@ void Value::chk_expr_operand_execute_refd(Value *v1, ...@@ -8216,6 +8217,9 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
u.expr.ap_list2 = parlist; u.expr.ap_list2 = parlist;
} }
chk_expr_dynamic_part(exp_val, true); chk_expr_dynamic_part(exp_val, true);
my_scope->chk_runs_on_clause(t, *this, "create");
my_scope->chk_mtc_clause(t, *this);
my_scope->chk_system_clause(t, *this);
} }
if (u.expr.v_optype != OPTYPE_COMP_CREATE) { if (u.expr.v_optype != OPTYPE_COMP_CREATE) {
break; break;
...@@ -13029,6 +13033,9 @@ void Value::chk_expr_operand_execute_refd(Value *v1, ...@@ -13029,6 +13033,9 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
FATAL_ERROR("Value::generate_code_init()"); FATAL_ERROR("Value::generate_code_init()");
} }
break; break;
case V_TTCN3_NULL:
str = mputprintf(str, "%s = NULL_VALUE;\n", name);
break;
case V_NOTUSED: case V_NOTUSED:
// unbound value, don't generate anything // unbound value, don't generate anything
break; break;
......
...@@ -482,12 +482,19 @@ namespace Ttcn { ...@@ -482,12 +482,19 @@ namespace Ttcn {
Free(prev_expr); Free(prev_expr);
} }
const Identifier& id = *ref->get_id(); const Identifier& id = *ref->get_id();
Common::Assignment* ass = class_->get_local_ass_byId(id); // 'ass' is null if the 'toString' method from the 'object' class is called
Common::Assignment* ass = class_->has_local_ass_withId(id) ?
class_->get_local_ass_byId(id) : NULL;
expr->expr = mputprintf(expr->expr, "->%s(", id.get_name().c_str()); expr->expr = mputprintf(expr->expr, "->%s(", id.get_name().c_str());
ref->get_actual_par_list()->generate_code_noalias(expr, ass->get_FormalParList()); FormalParList* fp_list = ass != NULL ? ass->get_FormalParList() :
new FormalParList; // the formal parameter list of 'toString' is empty
ref->get_actual_par_list()->generate_code_noalias(expr, fp_list);
if (ass == NULL) {
delete fp_list;
}
expr->expr = mputc(expr->expr, ')'); expr->expr = mputc(expr->expr, ')');
Def_Function_Base* def_func = dynamic_cast<Def_Function_Base*>(ass); type = ass != NULL ? ass->get_Type() :
type = def_func->get_return_type(); Common::Type::get_pooltype(Common::Type::T_USTR);
if (const_ref && i < n_refs - 1 && if (const_ref && i < n_refs - 1 &&
refs[i + 1]->get_type() != FieldOrArrayRef::FUNCTION_REF) { refs[i + 1]->get_type() != FieldOrArrayRef::FUNCTION_REF) {
// the next subreference is a field name or array index, have to // the next subreference is a field name or array index, have to
...@@ -1055,15 +1062,17 @@ namespace Ttcn { ...@@ -1055,15 +1062,17 @@ namespace Ttcn {
expr->expr = mputstr(expr->expr, "this->"); expr->expr = mputstr(expr->expr, "this->");
} }
else { // no 'id' means it's just a 'this' reference else { // no 'id' means it's just a 'this' reference
expr->expr = mputprintf(expr->expr, "OBJECT_REF<%s>(this)", expr->expr = mputprintf(expr->expr, "%s(this)",
ass->get_Type()->get_genname_value(my_scope).c_str()); ass->get_Type()->get_genname_value(my_scope).c_str());
return; return;
} }
} }
else if (reftype == REF_SUPER) { else if (reftype == REF_SUPER) {
Common::Type* base_type = my_scope->get_scope_class()->get_base_type()->
get_type_refd_last();
expr->expr = mputprintf(expr->expr, "%s::", expr->expr = mputprintf(expr->expr, "%s::",
my_scope->get_scope_class()->get_base_type()-> base_type->get_class_type_body()->is_built_in() ? "OBJECT" :
get_genname_value(my_scope).c_str()); base_type->get_genname_own(my_scope).c_str());
} }
string const_prefix; // empty by default string const_prefix; // empty by default
if (gen_const_prefix) { if (gen_const_prefix) {
...@@ -1146,12 +1155,8 @@ namespace Ttcn { ...@@ -1146,12 +1155,8 @@ namespace Ttcn {
} else { } else {
// don't convert to const object if the first subreference is a method call // don't convert to const object if the first subreference is a method call
if (t_subrefs->get_ref(0)->get_type() != FieldOrArrayRef::FUNCTION_REF) { if (t_subrefs->get_ref(0)->get_type() != FieldOrArrayRef::FUNCTION_REF) {
string type_str = refd_gov->get_genname_value(get_my_scope());
if (refd_gov->get_type_refd_last()->get_typetype() == Common::Type::T_CLASS) {
type_str = string("OBJECT_REF<") + type_str + string(">");
}
this_expr.expr = mputprintf(this_expr.expr, "const_cast< const %s&>(", this_expr.expr = mputprintf(this_expr.expr, "const_cast< const %s&>(",
type_str.c_str()); refd_gov->get_genname_value(get_my_scope()).c_str());
} }
} }
if (parlist != NULL) { if (parlist != NULL) {
...@@ -3688,6 +3693,11 @@ namespace Ttcn { ...@@ -3688,6 +3693,11 @@ namespace Ttcn {
continue; continue;
} }
field_name = tref->get_id()->get_ttcnname(); field_name = tref->get_id()->get_ttcnname();
if (oop_features && field_name == string("object")) {
ea.error("Class type `object' cannot be added to the anytype");
delete t;
continue;
}
} }
else { else {
// Can't happen here // Can't happen here
...@@ -3888,7 +3898,7 @@ namespace Ttcn { ...@@ -3888,7 +3898,7 @@ namespace Ttcn {
break; break;
case Type::T_CLASS: case Type::T_CLASS:
error("Constant cannot be defined for class type `%s'", error("Constant cannot be defined for class type `%s'",
t->get_fullname().c_str()); t->get_typename().c_str());
break; break;
default: default:
value_under_check = true; value_under_check = true;
...@@ -4078,7 +4088,7 @@ namespace Ttcn { ...@@ -4078,7 +4088,7 @@ namespace Ttcn {
break; break;
case Type::T_CLASS: case Type::T_CLASS:
error("External constant cannot be defined for class type `%s'", error("External constant cannot be defined for class type `%s'",
t->get_fullname().c_str()); t->get_typename().c_str());
break; break;
default: default:
break; break;
...@@ -4204,7 +4214,7 @@ namespace Ttcn { ...@@ -4204,7 +4214,7 @@ namespace Ttcn {
break; break;
case Type::T_CLASS: case Type::T_CLASS:
error("Type of module parameter cannot be or embed class type `%s'", error("Type of module parameter cannot be or embed class type `%s'",
t->get_fullname().c_str()); t->get_typename().c_str());
break; break;
case Type::T_FUNCTION: case Type::T_FUNCTION:
case Type::T_ALTSTEP: case Type::T_ALTSTEP:
...@@ -4384,7 +4394,7 @@ namespace Ttcn { ...@@ -4384,7 +4394,7 @@ namespace Ttcn {
break; break;
case Type::T_CLASS: case Type::T_CLASS:
error("Type of template module parameter cannot be class type `%s'", error("Type of template module parameter cannot be class type `%s'",
t->get_fullname().c_str()); t->get_typename().c_str());
break; break;
default: default:
if (IMPLICIT_OMIT == has_implicit_omit_attr()) { if (IMPLICIT_OMIT == has_implicit_omit_attr()) {
...@@ -4605,7 +4615,7 @@ namespace Ttcn { ...@@ -4605,7 +4615,7 @@ namespace Ttcn {
} }
else if (t->get_typetype() == Type::T_CLASS) { else if (t->get_typetype() == Type::T_CLASS) {
error("Template cannot be defined for class type `%s'", error("Template cannot be defined for class type `%s'",
t->get_fullname().c_str()); t->get_typename().c_str());
} }