Val: use IntrusivePtr in check_and_promote()

This commit is contained in:
Max Kellermann 2020-02-26 20:29:53 +01:00
parent 3d999b53fe
commit 96951c1300
3 changed files with 23 additions and 31 deletions

View file

@ -127,7 +127,7 @@ IntrusivePtr<Val> Expr::InitVal(const BroType* t, IntrusivePtr<Val> aggr) const
if ( IsError() )
return 0;
return {AdoptRef{}, check_and_promote(Eval(0).release(), t, 1)};
return check_and_promote(Eval(0), t, 1);
}
int Expr::IsError() const
@ -2279,7 +2279,7 @@ void AssignExpr::EvalIntoAggregate(const BroType* t, Val* aggr, Frame* f) const
TableVal* tv = aggr->AsTableVal();
auto index = op1->Eval(f);
IntrusivePtr<Val> v{AdoptRef{}, check_and_promote(op2->Eval(f).release(), t->YieldType(), 1)};
auto v = check_and_promote(op2->Eval(f), t->YieldType(), 1);
if ( ! index || ! v )
return;
@ -3220,7 +3220,7 @@ IntrusivePtr<Val> SetConstructorExpr::InitVal(const BroType* t, IntrusivePtr<Val
for ( const auto& e : exprs )
{
IntrusivePtr<Val> element = {AdoptRef{}, check_and_promote(e->Eval(0).release(), index_type, 1)};
auto element = check_and_promote(e->Eval(0), index_type, 1);
if ( ! element || ! tval->Assign(element.get(), 0) )
{
@ -3321,7 +3321,7 @@ IntrusivePtr<Val> VectorConstructorExpr::InitVal(const BroType* t, IntrusivePtr<
loop_over_list(exprs, i)
{
Expr* e = exprs[i];
IntrusivePtr<Val> v{AdoptRef{}, check_and_promote(e->Eval(0).release(), t->YieldType(), 1)};
auto v = check_and_promote(e->Eval(0), t->YieldType(), 1);
if ( ! v || ! vec->Assign(i, v.release()) )
{
@ -3640,9 +3640,9 @@ IntrusivePtr<Val> RecordCoerceExpr::Fold(Val* v) const
else if ( BothArithmetic(rhs_type->Tag(), field_type->Tag()) &&
! same_type(rhs_type, field_type) )
{
if ( Val* new_val = check_and_promote(rhs.release(), field_type, false, op->GetLocationInfo()) )
if ( auto new_val = check_and_promote(rhs, field_type, false, op->GetLocationInfo()) )
{
rhs = {AdoptRef{}, new_val};
rhs = std::move(new_val);
}
else
{
@ -4653,9 +4653,9 @@ IntrusivePtr<Val> ListExpr::AddSetInit(const BroType* t, IntrusivePtr<Val> aggr)
}
if ( expr->Type()->Tag() == TYPE_LIST )
element = {AdoptRef{}, check_and_promote(element.release(), it, 1)};
element = check_and_promote(std::move(element), it, 1);
else
element = {AdoptRef{}, check_and_promote(element.release(), (*it->Types())[0], 1)};
element = check_and_promote(std::move(element), (*it->Types())[0], 1);
if ( ! element )
return 0;

View file

@ -3034,7 +3034,7 @@ void VectorVal::ValDescribe(ODesc* d) const
d->Add("]");
}
Val* check_and_promote(Val* v, const BroType* t, int is_init, const Location* expr_location)
IntrusivePtr<Val> check_and_promote(IntrusivePtr<Val> v, const BroType* t, int is_init, const Location* expr_location)
{
if ( ! v )
return nullptr;
@ -3058,8 +3058,7 @@ Val* check_and_promote(Val* v, const BroType* t, int is_init, const Location* ex
if ( same_type(t, vt, is_init) )
return v;
t->Error("type clash", v, 0, expr_location);
Unref(v);
t->Error("type clash", v.get(), 0, expr_location);
return nullptr;
}
@ -3067,10 +3066,9 @@ Val* check_and_promote(Val* v, const BroType* t, int is_init, const Location* ex
(! IsArithmetic(v_tag) || t_tag != TYPE_TIME || ! v->IsZero()) )
{
if ( t_tag == TYPE_LIST || v_tag == TYPE_LIST )
t->Error("list mixed with scalar", v, 0, expr_location);
t->Error("list mixed with scalar", v.get(), 0, expr_location);
else
t->Error("arithmetic mixed with non-arithmetic", v, 0, expr_location);
Unref(v);
t->Error("arithmetic mixed with non-arithmetic", v.get(), 0, expr_location);
return nullptr;
}
@ -3082,8 +3080,7 @@ Val* check_and_promote(Val* v, const BroType* t, int is_init, const Location* ex
TypeTag mt = max_type(t_tag, v_tag);
if ( mt != t_tag )
{
t->Error("over-promotion of arithmetic value", v, 0, expr_location);
Unref(v);
t->Error("over-promotion of arithmetic value", v.get(), 0, expr_location);
return nullptr;
}
}
@ -3096,55 +3093,49 @@ Val* check_and_promote(Val* v, const BroType* t, int is_init, const Location* ex
// Already has the right internal type.
return v;
Val* promoted_v;
IntrusivePtr<Val> promoted_v;
switch ( it ) {
case TYPE_INTERNAL_INT:
if ( ( vit == TYPE_INTERNAL_UNSIGNED || vit == TYPE_INTERNAL_DOUBLE ) && Val::WouldOverflow(vt, t, v) )
if ( ( vit == TYPE_INTERNAL_UNSIGNED || vit == TYPE_INTERNAL_DOUBLE ) && Val::WouldOverflow(vt, t, v.get()) )
{
t->Error("overflow promoting from unsigned/double to signed arithmetic value", v, 0, expr_location);
Unref(v);
t->Error("overflow promoting from unsigned/double to signed arithmetic value", v.get(), 0, expr_location);
return nullptr;
}
else if ( t_tag == TYPE_INT )
promoted_v = val_mgr->GetInt(v->CoerceToInt());
promoted_v = {AdoptRef{}, val_mgr->GetInt(v->CoerceToInt())};
else // enum
{
reporter->InternalError("bad internal type in check_and_promote()");
Unref(v);
return nullptr;
}
break;
case TYPE_INTERNAL_UNSIGNED:
if ( ( vit == TYPE_INTERNAL_DOUBLE || vit == TYPE_INTERNAL_INT) && Val::WouldOverflow(vt, t, v) )
if ( ( vit == TYPE_INTERNAL_DOUBLE || vit == TYPE_INTERNAL_INT) && Val::WouldOverflow(vt, t, v.get()) )
{
t->Error("overflow promoting from signed/double to unsigned arithmetic value", v, 0, expr_location);
Unref(v);
t->Error("overflow promoting from signed/double to unsigned arithmetic value", v.get(), 0, expr_location);
return nullptr;
}
else if ( t_tag == TYPE_COUNT || t_tag == TYPE_COUNTER )
promoted_v = val_mgr->GetCount(v->CoerceToUnsigned());
promoted_v = {AdoptRef{}, val_mgr->GetCount(v->CoerceToUnsigned())};
else // port
{
reporter->InternalError("bad internal type in check_and_promote()");
Unref(v);
return nullptr;
}
break;
case TYPE_INTERNAL_DOUBLE:
promoted_v = new Val(v->CoerceToDouble(), t_tag);
promoted_v = make_intrusive<Val>(v->CoerceToDouble(), t_tag);
break;
default:
reporter->InternalError("bad internal type in check_and_promote()");
Unref(v);
return nullptr;
}
Unref(v);
return promoted_v;
}

View file

@ -29,6 +29,7 @@ using std::string;
template <class T> class IntrusivePtr;
template<typename T> class PDict;
template <class T> class IntrusivePtr;
class IterCookie;
class Val;
@ -1018,7 +1019,7 @@ protected:
// Unref()'ing the original. If not a match, generates an error message
// and returns nil, also Unref()'ing v. If is_init is true, then
// the checking is done in the context of an initialization.
extern Val* check_and_promote(Val* v, const BroType* t, int is_init, const Location* expr_location = nullptr);
extern IntrusivePtr<Val> check_and_promote(IntrusivePtr<Val> v, const BroType* t, int is_init, const Location* expr_location = nullptr);
// Given a pointer to where a Val's core (i.e., its BRO value) resides,
// returns a corresponding newly-created or Ref()'d Val. ptr must already