mirror of
https://github.com/zeek/zeek.git
synced 2025-10-14 04:28:20 +00:00
GH-926: Improve type-checking for ternary conditional operator
This commit is contained in:
parent
9f802b2a4d
commit
3bc5309e9e
8 changed files with 146 additions and 39 deletions
59
src/Expr.cc
59
src/Expr.cc
|
@ -1897,19 +1897,18 @@ CondExpr::CondExpr(ExprPtr arg_op1, ExprPtr arg_op2, ExprPtr arg_op3)
|
|||
else
|
||||
{
|
||||
TypeTag bt2 = op2->GetType()->Tag();
|
||||
|
||||
if ( is_vector(op2) )
|
||||
bt2 = op2->GetType()->AsVectorType()->Yield()->Tag();
|
||||
|
||||
TypeTag bt3 = op3->GetType()->Tag();
|
||||
|
||||
if ( IsVector(bt3) )
|
||||
bt3 = op3->GetType()->AsVectorType()->Yield()->Tag();
|
||||
|
||||
if ( is_vector(op1) && ! (is_vector(op2) && is_vector(op3)) )
|
||||
if ( is_vector(op1) )
|
||||
{
|
||||
ExprError("vector conditional requires vector alternatives");
|
||||
return;
|
||||
if ( ! (is_vector(op2) && is_vector(op3)) )
|
||||
{
|
||||
ExprError("vector conditional requires vector alternatives");
|
||||
return;
|
||||
}
|
||||
|
||||
bt2 = op2->GetType()->AsVectorType()->Yield()->Tag();
|
||||
bt3 = op3->GetType()->AsVectorType()->Yield()->Tag();
|
||||
}
|
||||
|
||||
if ( BothArithmetic(bt2, bt3) )
|
||||
|
@ -1920,7 +1919,7 @@ CondExpr::CondExpr(ExprPtr arg_op1, ExprPtr arg_op2, ExprPtr arg_op3)
|
|||
if ( bt3 != t )
|
||||
op3 = zeek::make_intrusive<ArithCoerceExpr>(std::move(op3), t);
|
||||
|
||||
if ( is_vector(op2) )
|
||||
if ( is_vector(op1) )
|
||||
SetType(zeek::make_intrusive<zeek::VectorType>(base_type(t)));
|
||||
else
|
||||
SetType(base_type(t));
|
||||
|
@ -1931,10 +1930,42 @@ CondExpr::CondExpr(ExprPtr arg_op1, ExprPtr arg_op2, ExprPtr arg_op3)
|
|||
|
||||
else
|
||||
{
|
||||
if ( IsRecord(bt2) && IsRecord(bt3) &&
|
||||
! same_type(op2->GetType(), op3->GetType()) )
|
||||
if ( is_vector(op1) )
|
||||
{
|
||||
ExprError("vector conditional type clash between alternatives");
|
||||
return;
|
||||
}
|
||||
|
||||
if ( bt2 == zeek::TYPE_TABLE )
|
||||
{
|
||||
auto tt2 = op2->GetType<TableType>();
|
||||
auto tt3 = op3->GetType<TableType>();
|
||||
|
||||
if ( tt2->IsUnspecifiedTable() )
|
||||
op2 = make_intrusive<TableCoerceExpr>(std::move(op2), std::move(tt3));
|
||||
else if( tt3->IsUnspecifiedTable() )
|
||||
op3 = make_intrusive<TableCoerceExpr>(std::move(op3), std::move(tt2));
|
||||
else if ( ! same_type(op2->GetType(), op3->GetType()) )
|
||||
ExprError("operands must be of the same type");
|
||||
}
|
||||
else if ( bt2 == zeek::TYPE_VECTOR )
|
||||
{
|
||||
auto vt2 = op2->GetType<VectorType>();
|
||||
auto vt3 = op3->GetType<VectorType>();
|
||||
|
||||
if ( vt2->IsUnspecifiedVector() )
|
||||
op2 = make_intrusive<VectorCoerceExpr>(std::move(op2), std::move(vt3));
|
||||
else if( vt3->IsUnspecifiedVector() )
|
||||
op3 = make_intrusive<VectorCoerceExpr>(std::move(op3), std::move(vt2));
|
||||
else if ( ! same_type(op2->GetType(), op3->GetType()) )
|
||||
ExprError("operands must be of the same type");
|
||||
}
|
||||
else if ( ! same_type(op2->GetType(), op3->GetType()) )
|
||||
// Records could potentially also coerce, but may have some cases
|
||||
// where the coercion direction is ambiguous.
|
||||
ExprError("operands must be of the same type");
|
||||
else
|
||||
|
||||
if ( ! IsError() )
|
||||
SetType(op2->GetType());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue