diff options
author | Yuri Roubinsky <chaosus89@gmail.com> | 2021-04-27 14:58:32 +0300 |
---|---|---|
committer | Yuri Roubinsky <chaosus89@gmail.com> | 2021-04-27 15:23:01 +0300 |
commit | 3c82f011341de2497c72229a00f13736003e9803 (patch) | |
tree | 9f1428548fcb91ac1891b4dfb95f625f8046f9f1 /servers/rendering | |
parent | b95a82d46a4c463815c199b839d8ac81683706b2 (diff) |
Fix shader handle constant expressions in function call
Diffstat (limited to 'servers/rendering')
-rw-r--r-- | servers/rendering/shader_language.cpp | 48 | ||||
-rw-r--r-- | servers/rendering/shader_language.h | 1 |
2 files changed, 45 insertions, 4 deletions
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 32c38e9138..0d6d3f5e13 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -3168,6 +3168,36 @@ bool ShaderLanguage::_validate_varying_using(ShaderNode::Varying &p_varying, Str return true; } +bool ShaderLanguage::_check_node_constness(const Node *p_node) const { + switch (p_node->type) { + case Node::TYPE_OPERATOR: { + OperatorNode *op_node = (OperatorNode *)p_node; + for (int i = (1 ? op_node->op == OP_CALL : 0); i < op_node->arguments.size(); i++) { + if (!_check_node_constness(op_node->arguments[i])) { + return false; + } + } + } break; + case Node::TYPE_CONSTANT: + break; + case Node::TYPE_VARIABLE: { + VariableNode *varn = (VariableNode *)p_node; + if (!varn->is_const) { + return false; + } + } break; + case Node::TYPE_ARRAY: { + ArrayNode *arrn = (ArrayNode *)p_node; + if (!arrn->is_const) { + return false; + } + } break; + default: + return false; + } + return true; +} + bool ShaderLanguage::_validate_assign(Node *p_node, const FunctionInfo &p_function_info, String *r_message) { if (p_node->type == Node::TYPE_OPERATOR) { OperatorNode *op = static_cast<OperatorNode *>(p_node); @@ -5384,8 +5414,13 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun return ERR_PARSE_ERROR; } if (node->is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) { - _set_error("Expected constant expression after '='"); - return ERR_PARSE_ERROR; + OperatorNode *op = ((OperatorNode *)n); + for (int i = 1; i < op->arguments.size(); i++) { + if (!_check_node_constness(op->arguments[i])) { + _set_error("Expected constant expression for argument '" + itos(i - 1) + "' of function call after '='"); + return ERR_PARSE_ERROR; + } + } } decl.initializer = n; @@ -6964,8 +6999,13 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } if (expr->type == Node::TYPE_OPERATOR && ((OperatorNode *)expr)->op == OP_CALL) { - _set_error("Expected constant expression after '='"); - return ERR_PARSE_ERROR; + OperatorNode *op = ((OperatorNode *)expr); + for (int i = 1; i < op->arguments.size(); i++) { + if (!_check_node_constness(op->arguments[i])) { + _set_error("Expected constant expression for argument '" + itos(i - 1) + "' of function call after '='"); + return ERR_PARSE_ERROR; + } + } } constant.initializer = static_cast<ConstantNode *>(expr); diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index 03327f9677..470f3d38d5 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -891,6 +891,7 @@ private: bool _propagate_function_call_sampler_builtin_reference(StringName p_name, int p_argument, const StringName &p_builtin); bool _validate_varying_assign(ShaderNode::Varying &p_varying, String *r_message); bool _validate_varying_using(ShaderNode::Varying &p_varying, String *r_message); + bool _check_node_constness(const Node *p_node) const; Node *_parse_expression(BlockNode *p_block, const FunctionInfo &p_function_info); Node *_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info, DataType p_type, const StringName &p_struct_name, int p_array_size); |