GDScript: Fix type conversion in assignment with operation
This commit is contained in:
parent
f065b34e96
commit
475d7f0e52
@ -1144,7 +1144,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
|
|||||||
|
|
||||||
GDScriptDataType assign_type = _gdtype_from_datatype(on->arguments[0]->get_datatype());
|
GDScriptDataType assign_type = _gdtype_from_datatype(on->arguments[0]->get_datatype());
|
||||||
|
|
||||||
if (assign_type.has_type && !on->arguments[1]->get_datatype().has_type) {
|
if (assign_type.has_type && !on->datatype.has_type) {
|
||||||
// Typed assignment
|
// Typed assignment
|
||||||
switch (assign_type.kind) {
|
switch (assign_type.kind) {
|
||||||
case GDScriptDataType::BUILTIN: {
|
case GDScriptDataType::BUILTIN: {
|
||||||
|
@ -764,15 +764,17 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|||||||
GET_VARIANT_PTR(dst, 2);
|
GET_VARIANT_PTR(dst, 2);
|
||||||
GET_VARIANT_PTR(src, 3);
|
GET_VARIANT_PTR(src, 3);
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
|
||||||
Variant::Type var_type = (Variant::Type)_code_ptr[ip + 1];
|
Variant::Type var_type = (Variant::Type)_code_ptr[ip + 1];
|
||||||
GD_ERR_BREAK(var_type < 0 || var_type >= Variant::VARIANT_MAX);
|
GD_ERR_BREAK(var_type < 0 || var_type >= Variant::VARIANT_MAX);
|
||||||
|
|
||||||
if (src->get_type() != var_type) {
|
if (src->get_type() != var_type) {
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
if (Variant::can_convert_strict(src->get_type(), var_type)) {
|
if (Variant::can_convert_strict(src->get_type(), var_type)) {
|
||||||
|
#endif // DEBUG_ENABLED
|
||||||
Variant::CallError ce;
|
Variant::CallError ce;
|
||||||
*dst = Variant::construct(var_type, const_cast<const Variant **>(&src), 1, ce);
|
*dst = Variant::construct(var_type, const_cast<const Variant **>(&src), 1, ce);
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
err_text = "Trying to assign value of type '" + Variant::get_type_name(src->get_type()) +
|
err_text = "Trying to assign value of type '" + Variant::get_type_name(src->get_type()) +
|
||||||
"' to a variable of type '" + Variant::get_type_name(var_type) + "'.";
|
"' to a variable of type '" + Variant::get_type_name(var_type) + "'.";
|
||||||
OPCODE_BREAK;
|
OPCODE_BREAK;
|
||||||
@ -780,9 +782,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|||||||
} else {
|
} else {
|
||||||
#endif // DEBUG_ENABLED
|
#endif // DEBUG_ENABLED
|
||||||
*dst = *src;
|
*dst = *src;
|
||||||
#ifdef DEBUG_ENABLED
|
|
||||||
}
|
}
|
||||||
#endif // DEBUG_ENABLED
|
|
||||||
|
|
||||||
ip += 4;
|
ip += 4;
|
||||||
}
|
}
|
||||||
|
@ -8185,7 +8185,9 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
|
|||||||
}
|
}
|
||||||
#endif // DEBUG_ENABLED
|
#endif // DEBUG_ENABLED
|
||||||
|
|
||||||
|
bool type_match = check_types;
|
||||||
if (check_types && !_is_type_compatible(lh_type, rh_type)) {
|
if (check_types && !_is_type_compatible(lh_type, rh_type)) {
|
||||||
|
type_match = false;
|
||||||
// Try supertype test
|
// Try supertype test
|
||||||
if (_is_type_compatible(rh_type, lh_type)) {
|
if (_is_type_compatible(rh_type, lh_type)) {
|
||||||
_mark_line_as_unsafe(op->line);
|
_mark_line_as_unsafe(op->line);
|
||||||
@ -8197,23 +8199,27 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
|
|||||||
op->line);
|
op->line);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Replace assignment with implicit conversion
|
if (op->op == OperatorNode::OP_ASSIGN) {
|
||||||
BuiltInFunctionNode *convert = alloc_node<BuiltInFunctionNode>();
|
// Replace assignment with implicit conversion
|
||||||
convert->line = op->line;
|
BuiltInFunctionNode *convert = alloc_node<BuiltInFunctionNode>();
|
||||||
convert->function = GDScriptFunctions::TYPE_CONVERT;
|
convert->line = op->line;
|
||||||
|
convert->function = GDScriptFunctions::TYPE_CONVERT;
|
||||||
|
|
||||||
ConstantNode *tgt_type = alloc_node<ConstantNode>();
|
ConstantNode *tgt_type = alloc_node<ConstantNode>();
|
||||||
tgt_type->line = op->line;
|
tgt_type->line = op->line;
|
||||||
tgt_type->value = (int)lh_type.builtin_type;
|
tgt_type->value = (int)lh_type.builtin_type;
|
||||||
|
|
||||||
OperatorNode *convert_call = alloc_node<OperatorNode>();
|
OperatorNode *convert_call = alloc_node<OperatorNode>();
|
||||||
convert_call->line = op->line;
|
convert_call->line = op->line;
|
||||||
convert_call->op = OperatorNode::OP_CALL;
|
convert_call->op = OperatorNode::OP_CALL;
|
||||||
convert_call->arguments.push_back(convert);
|
convert_call->arguments.push_back(convert);
|
||||||
convert_call->arguments.push_back(op->arguments[1]);
|
convert_call->arguments.push_back(op->arguments[1]);
|
||||||
convert_call->arguments.push_back(tgt_type);
|
convert_call->arguments.push_back(tgt_type);
|
||||||
|
|
||||||
op->arguments.write[1] = convert_call;
|
op->arguments.write[1] = convert_call;
|
||||||
|
|
||||||
|
type_match = true; // Since we are converting, the type is matching
|
||||||
|
}
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (lh_type.builtin_type == Variant::INT && rh_type.builtin_type == Variant::REAL) {
|
if (lh_type.builtin_type == Variant::INT && rh_type.builtin_type == Variant::REAL) {
|
||||||
_add_warning(GDScriptWarning::NARROWING_CONVERSION, op->line);
|
_add_warning(GDScriptWarning::NARROWING_CONVERSION, op->line);
|
||||||
@ -8226,6 +8232,7 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
|
|||||||
_mark_line_as_unsafe(op->line);
|
_mark_line_as_unsafe(op->line);
|
||||||
}
|
}
|
||||||
#endif // DEBUG_ENABLED
|
#endif // DEBUG_ENABLED
|
||||||
|
op->datatype.has_type = type_match;
|
||||||
} break;
|
} break;
|
||||||
case OperatorNode::OP_CALL:
|
case OperatorNode::OP_CALL:
|
||||||
case OperatorNode::OP_PARENT_CALL: {
|
case OperatorNode::OP_PARENT_CALL: {
|
||||||
|
Loading…
Reference in New Issue
Block a user