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)
|
if (err)
|
||||||
return 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();
|
current_function = StringName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5151,6 +5159,57 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
|
||||||
return OK;
|
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
|
// skips over whitespace and /* */ and // comments
|
||||||
static int _get_first_ident_pos(const String &p_code) {
|
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_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 _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:
|
public:
|
||||||
//static void get_keyword_list(ShaderType p_type,List<String> *p_keywords);
|
//static void get_keyword_list(ShaderType p_type,List<String> *p_keywords);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue