diff --git a/src/Expr.cc b/src/Expr.cc index 24cfde992e..1b2562c2ee 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -3759,8 +3759,7 @@ ValPtr ArithCoerceExpr::Fold(Val* v) const } RecordCoerceExpr::RecordCoerceExpr(ExprPtr arg_op, RecordTypePtr r) - : UnaryExpr(EXPR_RECORD_COERCE, std::move(arg_op)), - map(nullptr), map_size(0) + : UnaryExpr(EXPR_RECORD_COERCE, std::move(arg_op)) { if ( IsError() ) return; @@ -3778,12 +3777,12 @@ RecordCoerceExpr::RecordCoerceExpr(ExprPtr arg_op, RecordTypePtr r) RecordType* t_r = type->AsRecordType(); RecordType* sub_r = op->GetType()->AsRecordType(); - map_size = t_r->NumFields(); - map = new int[map_size]; + int map_size = t_r->NumFields(); + map.reserve(map_size); int i; for ( i = 0; i < map_size; ++i ) - map[i] = -1; // -1 = field is not mapped + map.emplace_back(-1); // -1 = field is not mapped for ( i = 0; i < sub_r->NumFields(); ++i ) { @@ -3865,11 +3864,6 @@ RecordCoerceExpr::RecordCoerceExpr(ExprPtr arg_op, RecordTypePtr r) } } -RecordCoerceExpr::~RecordCoerceExpr() - { - delete [] map; - } - ValPtr RecordCoerceExpr::InitVal(const zeek::Type* t, ValPtr aggr) const { if ( auto v = Eval(nullptr) ) @@ -3892,7 +3886,15 @@ ValPtr RecordCoerceExpr::Fold(Val* v) const if ( same_type(GetType(), Op()->GetType()) ) return IntrusivePtr{NewRef{}, v}; - auto val = make_intrusive(GetType()); + auto rt = cast_intrusive(GetType()); + return coerce_to_record(rt, v, map); + } + +RecordValPtr coerce_to_record(RecordTypePtr rt, Val* v, + const std::vector& map) + { + auto map_size = map.size(); + auto val = make_intrusive(rt); RecordType* val_type = val->GetType()->AsRecordType(); RecordVal* rv = v->AsRecordVal(); @@ -3905,14 +3907,15 @@ ValPtr RecordCoerceExpr::Fold(Val* v) const if ( ! rhs ) { - const auto& def = rv->GetType()->AsRecordType()->FieldDecl( - map[i])->GetAttr(ATTR_DEFAULT); + auto rv_rt = rv->GetType()->AsRecordType(); + const auto& def = rv_rt->FieldDecl(map[i])-> + GetAttr(ATTR_DEFAULT); if ( def ) rhs = def->GetExpr()->Eval(nullptr); } - assert(rhs || GetType()->AsRecordType()->FieldDecl(i)->GetAttr(ATTR_OPTIONAL)); + assert(rhs || rt->FieldDecl(i)->GetAttr(ATTR_OPTIONAL)); if ( ! rhs ) { @@ -3934,21 +3937,19 @@ ValPtr RecordCoerceExpr::Fold(Val* v) const else if ( BothArithmetic(rhs_type->Tag(), field_type->Tag()) && ! same_type(rhs_type, field_type) ) { - if ( auto new_val = check_and_promote(rhs, field_type.get(), false, op->GetLocationInfo()) ) - rhs = std::move(new_val); - else - RuntimeError("Failed type conversion"); + auto new_val = check_and_promote(rhs, field_type.get(), false); + rhs = std::move(new_val); } val->Assign(i, std::move(rhs)); } else { - if ( const auto& def = GetType()->AsRecordType()->FieldDecl(i)->GetAttr(ATTR_DEFAULT) ) + if ( const auto& def = rt->FieldDecl(i)->GetAttr(ATTR_DEFAULT) ) { auto def_val = def->GetExpr()->Eval(nullptr); const auto& def_type = def_val->GetType(); - const auto& field_type = GetType()->AsRecordType()->GetFieldType(i); + const auto& field_type = rt->GetFieldType(i); if ( def_type->Tag() == TYPE_RECORD && field_type->Tag() == TYPE_RECORD && diff --git a/src/Expr.h b/src/Expr.h index 6b99b1572a..33810656e5 100644 --- a/src/Expr.h +++ b/src/Expr.h @@ -1170,21 +1170,24 @@ protected: class RecordCoerceExpr final : public UnaryExpr { public: RecordCoerceExpr(ExprPtr op, RecordTypePtr r); - ~RecordCoerceExpr() override; // Optimization-related: ExprPtr Duplicate() override; + const std::vector& Map() const { return map; } + protected: ValPtr InitVal(const zeek::Type* t, ValPtr aggr) const override; ValPtr Fold(Val* v) const override; // For each super-record slot, gives subrecord slot with which to // fill it. - int* map; - int map_size; // equivalent to Type()->AsRecordType()->NumFields() + std::vector map; }; +extern RecordValPtr coerce_to_record(RecordTypePtr rt, Val* v, + const std::vector& map); + class TableCoerceExpr final : public UnaryExpr { public: TableCoerceExpr(ExprPtr op, TableTypePtr r); diff --git a/testing/btest/Baseline/language.type-coerce-numerics/first_set.out b/testing/btest/Baseline/language.type-coerce-numerics/first_set.out index f053ab7046..7af2ad4a31 100644 --- a/testing/btest/Baseline/language.type-coerce-numerics/first_set.out +++ b/testing/btest/Baseline/language.type-coerce-numerics/first_set.out @@ -1,6 +1,5 @@ ### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. error in int and ./first_set.zeek, line 46: overflow promoting from unsigned/double to signed arithmetic value (int and 9223372036854775808) -expression error in ./first_set.zeek, line 46: Failed type conversion ((coerce [$ii=9223372036854775808] to record { ii:int &optional; cc:count &optional; dd:double &optional; })) 3 int 4