summaryrefslogtreecommitdiff
path: root/servers/visual/shader_language.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'servers/visual/shader_language.cpp')
-rw-r--r--servers/visual/shader_language.cpp79
1 files changed, 68 insertions, 11 deletions
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index e10a57c571..c69bbb9343 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -755,12 +755,12 @@ void ShaderLanguage::clear() {
}
}
-bool ShaderLanguage::_find_identifier(const BlockNode *p_block, const Map<StringName, DataType> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type, IdentifierType *r_type) {
+bool ShaderLanguage::_find_identifier(const BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type, IdentifierType *r_type) {
if (p_builtin_types.has(p_identifier)) {
if (r_data_type) {
- *r_data_type = p_builtin_types[p_identifier];
+ *r_data_type = p_builtin_types[p_identifier].type;
}
if (r_type) {
*r_type = IDENTIFIER_BUILTIN_VAR;
@@ -2008,7 +2008,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p
return false;
}
-bool ShaderLanguage::_parse_function_arguments(BlockNode *p_block, const Map<StringName, DataType> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg) {
+bool ShaderLanguage::_parse_function_arguments(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg) {
TkPos pos = _get_tkpos();
Token tk = _get_token();
@@ -2261,7 +2261,48 @@ bool ShaderLanguage::_get_completable_identifier(BlockNode *p_block, CompletionT
return false;
}
-ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, const Map<StringName, DataType> &p_builtin_types) {
+bool ShaderLanguage::_is_operator_assign(Operator p_op) const {
+ switch (p_op) {
+ case OP_ASSIGN:
+ case OP_ASSIGN_ADD:
+ case OP_ASSIGN_SUB:
+ case OP_ASSIGN_MUL:
+ case OP_ASSIGN_DIV:
+ case OP_ASSIGN_MOD:
+ case OP_ASSIGN_SHIFT_LEFT:
+ case OP_ASSIGN_SHIFT_RIGHT:
+ case OP_ASSIGN_BIT_AND:
+ case OP_ASSIGN_BIT_OR:
+ case OP_ASSIGN_BIT_XOR:
+ return true;
+ default:
+ return false;
+ }
+
+ return false;
+}
+
+bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types) {
+
+ if (p_node->type == Node::TYPE_OPERATOR) {
+
+ OperatorNode *op = static_cast<OperatorNode *>(p_node);
+ if (op->type == OP_INDEX) {
+ return _validate_assign(op->arguments[0], p_builtin_types);
+ }
+ }
+
+ if (p_node->type == Node::TYPE_VARIABLE) {
+
+ VariableNode *var = static_cast<VariableNode *>(p_node);
+ if (p_builtin_types.has(var->name) && p_builtin_types[var->name].constant) {
+ return false; //ops not valid
+ }
+ }
+ return true;
+}
+
+ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types) {
Vector<Expression> expression;
//Vector<TokenType> operators;
@@ -2765,6 +2806,11 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
_set_error("Invalid base type for increment/decrement operator");
return NULL;
}
+
+ if (!_validate_assign(expr, p_builtin_types)) {
+ _set_error("Invalid use of increment/decrement operator in constant expression.");
+ return NULL;
+ }
expr = op;
} else {
@@ -2948,6 +2994,11 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
OperatorNode *op = alloc_node<OperatorNode>();
op->op = expression[i].op;
+ if ((op->op == OP_INCREMENT || op->op == OP_DECREMENT) && !_validate_assign(expression[i + 1].node, p_builtin_types)) {
+
+ _set_error("Can't use increment/decrement operator in constant expression.");
+ return NULL;
+ }
op->arguments.push_back(expression[i + 1].node);
expression[i].is_op = false;
@@ -3019,6 +3070,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
ERR_FAIL_V(NULL);
}
+ if (_is_operator_assign(op->op) && !_validate_assign(expression[next_op - 1].node, p_builtin_types)) {
+
+ _set_error("Assignment to constant expression.");
+ return NULL;
+ }
+
if (expression[next_op + 1].is_op) {
// this is not invalid and can really appear
// but it becomes invalid anyway because no binary op
@@ -3142,7 +3199,7 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha
return p_node;
}
-ShaderLanguage::Node *ShaderLanguage::_parse_and_reduce_expression(BlockNode *p_block, const Map<StringName, DataType> &p_builtin_types) {
+ShaderLanguage::Node *ShaderLanguage::_parse_and_reduce_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types) {
ShaderLanguage::Node *expr = _parse_expression(p_block, p_builtin_types);
if (!expr) //errored
@@ -3153,7 +3210,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_and_reduce_expression(BlockNode *p_
return expr;
}
-Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, DataType> &p_builtin_types, bool p_just_one, bool p_can_break, bool p_can_continue) {
+Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, bool p_just_one, bool p_can_break, bool p_can_continue) {
while (true) {
@@ -3636,7 +3693,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
name = tk.text;
- if (_find_identifier(NULL, Map<StringName, DataType>(), name)) {
+ if (_find_identifier(NULL, Map<StringName, BuiltInInfo>(), name)) {
_set_error("Redefinition of '" + String(name) + "'");
return ERR_PARSE_ERROR;
}
@@ -3660,7 +3717,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_OP_ASSIGN) {
- Node *expr = _parse_and_reduce_expression(NULL, Map<StringName, DataType>());
+ Node *expr = _parse_and_reduce_expression(NULL, Map<StringName, BuiltInInfo>());
if (!expr)
return ERR_PARSE_ERROR;
if (expr->type != Node::TYPE_CONSTANT) {
@@ -3841,7 +3898,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- if (_find_identifier(NULL, Map<StringName, DataType>(), name)) {
+ if (_find_identifier(NULL, Map<StringName, BuiltInInfo>(), name)) {
_set_error("Redefinition of '" + String(name) + "'");
return ERR_PARSE_ERROR;
}
@@ -3852,7 +3909,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- Map<StringName, DataType> builtin_types;
+ Map<StringName, BuiltInInfo> builtin_types;
if (p_functions.has(name)) {
builtin_types = p_functions[name].built_ins;
}
@@ -4109,7 +4166,7 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
if (comp_ident && skip_function != StringName() && p_functions.has(skip_function)) {
- for (Map<StringName, DataType>::Element *E = p_functions[skip_function].built_ins.front(); E; E = E->next()) {
+ for (Map<StringName, BuiltInInfo>::Element *E = p_functions[skip_function].built_ins.front(); E; E = E->next()) {
matches.insert(E->key());
}
}