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

OOP: operator '=>' can now cast to abstract classes (bug 563718)



Change-Id: Ie21f78b761036d014f429b1ec14af1879ea2f934
Signed-off-by: Botond Baranyi's avatarBotond Baranyi <botond.baranyi@ericsson.com>
parent 06342d86
......@@ -8477,22 +8477,16 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
}
erroneous = true;
}
else if (u.expr.v_optype == OPTYPE_CLASS_CASTING) {
else if (u.expr.v_optype == OPTYPE_CLASS_CASTING && !erroneous) {
Ttcn::ClassTypeBody* new_class = type_last->get_class_type_body();
if (new_class->is_abstract()) {
u.expr.type->error("Cannot cast to abstract class type `%s'",
Ttcn::ClassTypeBody* old_class = ref_type_last->get_class_type_body();
if (!new_class->is_parent_class(old_class) &&
!old_class->is_parent_class(new_class)) {
u.expr.type->error("Cannot cast an object of class type `%s' "
"to class type `%s'",
ref_type_last->get_typename().c_str(),
u.expr.type->get_typename().c_str());
}
if (!erroneous) {
Ttcn::ClassTypeBody* old_class = ref_type_last->get_class_type_body();
if (!new_class->is_parent_class(old_class) &&
!old_class->is_parent_class(new_class)) {
u.expr.type->error("Cannot cast an object of class type `%s' "
"to class type `%s'",
ref_type_last->get_typename().c_str(),
u.expr.type->get_typename().c_str());
}
}
}
}
if (erroneous) {
......@@ -14138,6 +14132,8 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
Code::free_expr(&ref_expr);
break; }
case OPTYPE_CLASS_CASTING: {
Ttcn::ClassTypeBody* exp_class = u.expr.type->get_type_refd_last()->
get_class_type_body();
expression_struct_t ref_expr;
Code::init_expr(&ref_expr);
u.expr.r2->generate_code(&ref_expr);
......@@ -14146,7 +14142,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
}
expr->expr = mputprintf(expr->expr,
"%s.cast_to<%s>()",
ref_expr.expr,
ref_expr.expr, exp_class->is_built_in() ? "OBJECT" :
u.expr.type->get_type_refd_last()->get_genname_own(my_scope).c_str());
if (ref_expr.postamble != NULL) {
expr->postamble = mputstr(expr->postamble, ref_expr.postamble);
......
......@@ -10257,6 +10257,13 @@ ClassCastingOp:
$$ = new Value(Value::OPTYPE_CLASS_CASTING, $3, $1);
$$->set_location(infile, @$);
}
| VariableRef ClassCastingSymbol ObjectKeyword
{
Type* type = new Type(Type::T_CLASS);
type->set_location(infile, @3);
$$ = new Value(Value::OPTYPE_CLASS_CASTING, type, $1);
$$->set_location(infile, @$);
}
| VariableRef ClassCastingSymbol '(' VariableRef ')'
{
$$ = new Value(Value::OPTYPE_CLASS_CASTING_REF, $4, $1);
......
......@@ -506,7 +506,7 @@ function f_casting() { //^In function definition//
var C35 x1 := C36.create;
var C36 x2 := x1 => C36;
var C0 x3 := x1 => C0; //^In variable definition// //^In the second operand of operation `=>'// //Cannot cast an object of class type `@oop_SE.C35' to class type `@oop_SE.C0'//
var C35 x4 := x2 => (x1); //^In variable definition// //^In the second operand of operation `=>'// //Cannot cast to abstract class type `@oop_SE.C35'//
var C35 x4 := x2 => (x1);
var C36 x5 := c => C36; //^In variable definition// //^In the first operand of operation `=>'// //Reference to a variable or value parameter was expected instead of constant `@oop_SE.c'//
var Rec x6 := x1 => Rec; //^In variable definition// //^In the second operand of operation `=>'// //Class type was expected//
var integer x7 := x1 => (x6); //^In variable definition// //^In the second operand of operation `=>'// //Class type was expected//
......
......@@ -390,8 +390,8 @@ testcase tc_references() runs on CT {
type class Node {
var integer data;
var Node next;
public var integer data;
public var Node next;
}
function f_test(in Node p1, inout Node p2, out Node p3,
......@@ -435,8 +435,8 @@ testcase tc_function_pars_and_retval() runs on CT {
}
type class Node2 {
var object data;
var Node2 next;
public var object data;
public var Node2 next;
}
type class Something {
......@@ -624,10 +624,10 @@ testcase tc_casting() runs on CT {
var object v_obj := Node.create(3, null);
var BaseClass v_null := null;
var Node v_null2 := null;
var object v_con := ConcreteClass.create;
var BaseClass v_base := v_sub => BaseClass;
var BaseClass v_base2 := v_sub;
if (log2str(v_base) != log2str(v_base2)) {
if (log2str(v_base) != log2str(v_sub)) {
setverdict(fail, "#1: ", v_base);
}
var FinalClass v_final2 := v_final => FinalClass;
......@@ -642,24 +642,36 @@ testcase tc_casting() runs on CT {
if (log2str(v_sub2) != log2str(v_sub)) {
setverdict(fail, "#4: ", v_sub2);
}
var object v_obj2 := v_sub => object;
if (log2str(v_obj2) != log2str(v_sub)) {
setverdict(fail, "#5: ", v_obj2);
}
var AbstractClass v_abs := v_con => AbstractClass;
if (log2str(v_abs) != log2str(v_con)) {
setverdict(fail, "#6: ", v_abs);
}
@try {
var SubClass v_bad := v_null => SubClass;
setverdict(fail, "#5: Error expected");
setverdict(fail, "#7: Error expected");
}
@catch(msg) {
if (not match(msg, pattern "*Casting a null reference")) {
setverdict(fail, "#5: Invalid error: ", msg);
setverdict(fail, "#7: Invalid error: ", msg);
}
}
@try {
var FinalClass v_bad2 := v_sub => FinalClass;
setverdict(fail, "#6: Error expected");
setverdict(fail, "#8: Error expected");
}
@catch(msg) {
if (not match(msg, pattern "*Invalid casting to class type `FinalClass'")) {
setverdict(fail, "#6: Invalid error: ", msg);
setverdict(fail, "#8: Invalid error: ", msg);
}
}
/*var integer v_int := (v_obj => Node).data;
if (v_int != 3) {
setverdict(fail, "#9: ", v_int);
}*/
setverdict(pass);
}
......
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