Merge pull request #31600 from Chaosus/shader_func_return_fix
Fix shader crash when users miss the return statement
This commit is contained in:
commit
96ea1e6fb0
2 changed files with 62 additions and 0 deletions
|
@ -5141,6 +5141,14 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
if (func_node->return_type != DataType::TYPE_VOID) {
|
||||
|
||||
BlockNode *block = func_node->body;
|
||||
if (_find_last_flow_op_in_block(block, FlowOperation::FLOW_OP_RETURN) != OK) {
|
||||
_set_error("Expected at least one return statement in a non-void function.");
|
||||
return ERR_PARSE_ERROR;
|
||||
}
|
||||
}
|
||||
current_function = StringName();
|
||||
}
|
||||
}
|
||||
|
@ -5151,6 +5159,57 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
|
|||
return OK;
|
||||
}
|
||||
|
||||
Error ShaderLanguage::_find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOperation p_op) {
|
||||
|
||||
bool found = false;
|
||||
|
||||
for (int i = p_flow->blocks.size() - 1; i >= 0; i--) {
|
||||
if (p_flow->blocks[i]->type == Node::TYPE_BLOCK) {
|
||||
BlockNode *last_block = (BlockNode *)p_flow->blocks[i];
|
||||
if (_find_last_flow_op_in_block(last_block, p_op) == OK) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
return OK;
|
||||
}
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
Error ShaderLanguage::_find_last_flow_op_in_block(BlockNode *p_block, FlowOperation p_op) {
|
||||
|
||||
bool found = false;
|
||||
|
||||
for (int i = p_block->statements.size() - 1; i >= 0; i--) {
|
||||
|
||||
if (p_block->statements[i]->type == Node::TYPE_CONTROL_FLOW) {
|
||||
ControlFlowNode *flow = (ControlFlowNode *)p_block->statements[i];
|
||||
if (flow->flow_op == p_op) {
|
||||
found = true;
|
||||
break;
|
||||
} else {
|
||||
if (_find_last_flow_op_in_op(flow, p_op) == OK) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (p_block->statements[i]->type == Node::TYPE_BLOCK) {
|
||||
BlockNode *block = (BlockNode *)p_block->statements[i];
|
||||
if (_find_last_flow_op_in_block(block, p_op) == OK) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
return OK;
|
||||
}
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
// skips over whitespace and /* */ and // comments
|
||||
static int _get_first_ident_pos(const String &p_code) {
|
||||
|
||||
|
|
|
@ -750,6 +750,9 @@ private:
|
|||
Error _parse_block(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, bool p_just_one = false, bool p_can_break = false, bool p_can_continue = false);
|
||||
Error _parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types);
|
||||
|
||||
Error _find_last_flow_op_in_block(BlockNode *p_block, FlowOperation p_op);
|
||||
Error _find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOperation p_op);
|
||||
|
||||
public:
|
||||
//static void get_keyword_list(ShaderType p_type,List<String> *p_keywords);
|
||||
|
||||
|
|
Loading…
Reference in a new issue