diff --git a/src/Expr.cc b/src/Expr.cc index 1a4c42cf95..24d5036994 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -3977,15 +3977,8 @@ RecordCoerceExpr::RecordCoerceExpr(Expr* op, RecordType* r) { int t_i = t_r->FieldOffset(sub_r->FieldName(i)); if ( t_i < 0 ) - { - // Same as in RecordConstructorExpr::InitVal. - char buf[512]; - safe_snprintf(buf, sizeof(buf), - "orphan record field \"%s\"", - sub_r->FieldName(i)); - Error(buf); + // Orphane field in rhs, that's ok. continue; - } BroType* sub_t_i = sub_r->FieldType(i); BroType* sup_t_i = t_r->FieldType(t_i); @@ -4031,8 +4024,19 @@ Val* RecordCoerceExpr::Fold(Val* v) const { if ( map[i] >= 0 ) { - Val* v = rv->Lookup(map[i]); - val->Assign(i, v ? v->Ref() : 0); + Val* rhs = rv->Lookup(map[i]); + if ( ! rhs ) + { + const Attr* def = rv->Type()->AsRecordType()->FieldDecl(map[i])->FindAttr(ATTR_DEFAULT); + if ( def ) + rhs = def->AttrExpr()->Eval(0); + } + + if ( rhs ) + rhs = rhs->Ref(); + + assert(rhs || Type()->AsRecordType()->FieldDecl(i)->FindAttr(ATTR_OPTIONAL)); + val->Assign(i, rhs); } else val->Assign(i, 0); diff --git a/src/Val.cc b/src/Val.cc index a665249539..2b086ccec3 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -2949,8 +2949,16 @@ RecordVal* RecordVal::CoerceTo(const RecordType* t, Val* aggr) const break; } - else - ar->Assign(t_i, Lookup(i)->Ref()); + if ( ar_t->FieldType(t_i)->Tag() == TYPE_RECORD + && ! same_type(ar_t->FieldType(t_i), Lookup(i)->Type()) ) + { + Expr* rhs = new ConstExpr(Lookup(i)->Ref()); + Expr* e = new RecordCoerceExpr(rhs, ar_t->FieldType(t_i)->AsRecordType()); + ar->Assign(t_i, e->Eval(0)); + break; + } + + ar->Assign(t_i, Lookup(i)->Ref()); } for ( i = 0; i < ar_t->NumFields(); ++i )