Fix shader incorrectly expects `int` on `uint` and vice-versa in cases
This commit is contained in:
parent
97ef3c8372
commit
b2611c198e
|
@ -8071,12 +8071,10 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
|
||||||
if (!n) {
|
if (!n) {
|
||||||
return ERR_PARSE_ERROR;
|
return ERR_PARSE_ERROR;
|
||||||
}
|
}
|
||||||
{
|
const ShaderLanguage::DataType data_type = n->get_datatype();
|
||||||
const ShaderLanguage::DataType switch_type = n->get_datatype();
|
if (data_type != TYPE_INT && data_type != TYPE_UINT) {
|
||||||
if (switch_type != TYPE_INT && switch_type != TYPE_UINT) {
|
_set_error(RTR("Expected an integer or unsigned integer expression."));
|
||||||
_set_error(RTR("Expected an integer expression."));
|
return ERR_PARSE_ERROR;
|
||||||
return ERR_PARSE_ERROR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
tk = _get_token();
|
tk = _get_token();
|
||||||
if (tk.type != TK_PARENTHESIS_CLOSE) {
|
if (tk.type != TK_PARENTHESIS_CLOSE) {
|
||||||
|
@ -8091,11 +8089,22 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
|
||||||
BlockNode *switch_block = alloc_node<BlockNode>();
|
BlockNode *switch_block = alloc_node<BlockNode>();
|
||||||
switch_block->block_type = BlockNode::BLOCK_TYPE_SWITCH;
|
switch_block->block_type = BlockNode::BLOCK_TYPE_SWITCH;
|
||||||
switch_block->parent_block = p_block;
|
switch_block->parent_block = p_block;
|
||||||
|
switch_block->expected_type = data_type;
|
||||||
cf->expressions.push_back(n);
|
cf->expressions.push_back(n);
|
||||||
cf->blocks.push_back(switch_block);
|
cf->blocks.push_back(switch_block);
|
||||||
p_block->statements.push_back(cf);
|
p_block->statements.push_back(cf);
|
||||||
|
|
||||||
int prev_type = TK_CF_CASE;
|
pos = _get_tkpos();
|
||||||
|
tk = _get_token();
|
||||||
|
TokenType prev_type;
|
||||||
|
if (tk.type == TK_CF_CASE || tk.type == TK_CF_DEFAULT) {
|
||||||
|
prev_type = tk.type;
|
||||||
|
_set_tkpos(pos);
|
||||||
|
} else {
|
||||||
|
_set_expected_error("case", "default");
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
while (true) { // Go-through multiple cases.
|
while (true) { // Go-through multiple cases.
|
||||||
|
|
||||||
if (_parse_block(switch_block, p_function_info, true, true, false) != OK) {
|
if (_parse_block(switch_block, p_function_info, true, true, false) != OK) {
|
||||||
|
@ -8117,43 +8126,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
|
||||||
_set_tkpos(pos);
|
_set_tkpos(pos);
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
HashSet<int> constants;
|
|
||||||
for (ShaderLanguage::Node *statement : switch_block->statements) { // Checks for duplicates.
|
|
||||||
ControlFlowNode *flow = static_cast<ControlFlowNode *>(statement);
|
|
||||||
if (flow) {
|
|
||||||
if (flow->flow_op == FLOW_OP_CASE) {
|
|
||||||
if (flow->expressions[0]->type == Node::NODE_TYPE_CONSTANT) {
|
|
||||||
ConstantNode *cn = static_cast<ConstantNode *>(flow->expressions[0]);
|
|
||||||
if (!cn || cn->values.is_empty()) {
|
|
||||||
return ERR_PARSE_ERROR;
|
|
||||||
}
|
|
||||||
if (constants.has(cn->values[0].sint)) {
|
|
||||||
_set_error(vformat(RTR("Duplicated case label: %d."), cn->values[0].sint));
|
|
||||||
return ERR_PARSE_ERROR;
|
|
||||||
}
|
|
||||||
constants.insert(cn->values[0].sint);
|
|
||||||
} else if (flow->expressions[0]->type == Node::NODE_TYPE_VARIABLE) {
|
|
||||||
VariableNode *vn = static_cast<VariableNode *>(flow->expressions[0]);
|
|
||||||
if (!vn) {
|
|
||||||
return ERR_PARSE_ERROR;
|
|
||||||
}
|
|
||||||
Vector<Scalar> v = { Scalar() };
|
|
||||||
_find_identifier(p_block, false, p_function_info, vn->name, nullptr, nullptr, nullptr, nullptr, nullptr, &v);
|
|
||||||
if (constants.has(v[0].sint)) {
|
|
||||||
_set_error(vformat(RTR("Duplicated case label: %d."), v[0].sint));
|
|
||||||
return ERR_PARSE_ERROR;
|
|
||||||
}
|
|
||||||
constants.insert(v[0].sint);
|
|
||||||
}
|
|
||||||
} else if (flow->flow_op == FLOW_OP_DEFAULT) {
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
return ERR_PARSE_ERROR;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return ERR_PARSE_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8184,36 +8156,77 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
|
||||||
|
|
||||||
if (!tk.is_integer_constant()) {
|
if (!tk.is_integer_constant()) {
|
||||||
bool correct_constant_expression = false;
|
bool correct_constant_expression = false;
|
||||||
DataType data_type;
|
|
||||||
|
|
||||||
if (tk.type == TK_IDENTIFIER) {
|
if (tk.type == TK_IDENTIFIER) {
|
||||||
|
DataType data_type;
|
||||||
bool is_const;
|
bool is_const;
|
||||||
|
|
||||||
_find_identifier(p_block, false, p_function_info, tk.text, &data_type, nullptr, &is_const);
|
_find_identifier(p_block, false, p_function_info, tk.text, &data_type, nullptr, &is_const);
|
||||||
if (is_const) {
|
if (is_const && data_type == p_block->expected_type) {
|
||||||
if (data_type == TYPE_INT) {
|
correct_constant_expression = true;
|
||||||
correct_constant_expression = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!correct_constant_expression) {
|
if (!correct_constant_expression) {
|
||||||
_set_error(RTR("Expected an integer constant."));
|
if (p_block->expected_type == TYPE_UINT) {
|
||||||
|
_set_error(RTR("Expected an unsigned integer constant."));
|
||||||
|
} else {
|
||||||
|
_set_error(RTR("Expected an integer constant."));
|
||||||
|
}
|
||||||
return ERR_PARSE_ERROR;
|
return ERR_PARSE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
VariableNode *vn = alloc_node<VariableNode>();
|
VariableNode *vn = alloc_node<VariableNode>();
|
||||||
vn->name = tk.text;
|
vn->name = tk.text;
|
||||||
|
{
|
||||||
|
Vector<Scalar> v;
|
||||||
|
DataType data_type;
|
||||||
|
|
||||||
|
_find_identifier(p_block, false, p_function_info, vn->name, &data_type, nullptr, nullptr, nullptr, nullptr, &v);
|
||||||
|
if (data_type == TYPE_INT) {
|
||||||
|
if (p_block->constants.has(v[0].sint)) {
|
||||||
|
_set_error(vformat(RTR("Duplicated case label: %d."), v[0].sint));
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
p_block->constants.insert(v[0].sint);
|
||||||
|
} else {
|
||||||
|
if (p_block->constants.has(v[0].uint)) {
|
||||||
|
_set_error(vformat(RTR("Duplicated case label: %d."), v[0].uint));
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
p_block->constants.insert(v[0].uint);
|
||||||
|
}
|
||||||
|
}
|
||||||
n = vn;
|
n = vn;
|
||||||
} else {
|
} else {
|
||||||
Scalar v;
|
|
||||||
if (tk.type == TK_UINT_CONSTANT) {
|
|
||||||
v.uint = (uint32_t)tk.constant;
|
|
||||||
} else {
|
|
||||||
v.sint = (int)tk.constant * sign;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConstantNode *cn = alloc_node<ConstantNode>();
|
ConstantNode *cn = alloc_node<ConstantNode>();
|
||||||
|
Scalar v;
|
||||||
|
if (p_block->expected_type == TYPE_UINT) {
|
||||||
|
if (tk.type != TK_UINT_CONSTANT) {
|
||||||
|
_set_error(RTR("Expected an unsigned integer constant."));
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
v.uint = (uint32_t)tk.constant;
|
||||||
|
if (p_block->constants.has(v.uint)) {
|
||||||
|
_set_error(vformat(RTR("Duplicated case label: %d."), v.uint));
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
p_block->constants.insert(v.uint);
|
||||||
|
cn->datatype = TYPE_UINT;
|
||||||
|
} else {
|
||||||
|
if (tk.type != TK_INT_CONSTANT) {
|
||||||
|
_set_error(RTR("Expected an integer constant."));
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
v.sint = (int32_t)tk.constant * sign;
|
||||||
|
if (p_block->constants.has(v.sint)) {
|
||||||
|
_set_error(vformat(RTR("Duplicated case label: %d."), v.sint));
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
p_block->constants.insert(v.sint);
|
||||||
|
cn->datatype = TYPE_INT;
|
||||||
|
}
|
||||||
cn->values.push_back(v);
|
cn->values.push_back(v);
|
||||||
cn->datatype = (tk.type == TK_UINT_CONSTANT ? TYPE_UINT : TYPE_INT);
|
|
||||||
n = cn;
|
n = cn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -544,6 +544,9 @@ public:
|
||||||
bool use_comma_between_statements = false;
|
bool use_comma_between_statements = false;
|
||||||
bool use_op_eval = true;
|
bool use_op_eval = true;
|
||||||
|
|
||||||
|
DataType expected_type = TYPE_VOID;
|
||||||
|
HashSet<int> constants;
|
||||||
|
|
||||||
BlockNode() :
|
BlockNode() :
|
||||||
Node(NODE_TYPE_BLOCK) {}
|
Node(NODE_TYPE_BLOCK) {}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue