Browse Source

Merge pull request #55508 from Chaosus/shader_fix_semicolon

Yuri Roubinsky 3 years ago
parent
commit
56f73a7e29

+ 4 - 0
drivers/gles3/shader_compiler_gles3.cpp

@@ -758,6 +758,10 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
 					code += a + " - " + n + " * (" + a + " / " + n + "))";
 					code += a + " - " + n + " * (" + a + " / " + n + "))";
 				} break;
 				} break;
 
 
+				case SL::OP_EMPTY: {
+					// Semicolon (or empty statement) - ignored.
+				} break;
+
 				default: {
 				default: {
 					if (p_use_scope) {
 					if (p_use_scope) {
 						code += "(";
 						code += "(";

+ 3 - 0
servers/rendering/renderer_rd/shader_compiler_rd.cpp

@@ -1318,6 +1318,9 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
 					code += ")";
 					code += ")";
 
 
 				} break;
 				} break;
+				case SL::OP_EMPTY: {
+					// Semicolon (or empty statement) - ignored.
+				} break;
 
 
 				default: {
 				default: {
 					if (p_use_scope) {
 					if (p_use_scope) {

+ 15 - 3
servers/rendering/shader_language.cpp

@@ -5208,9 +5208,21 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
 			expression.push_back(e);
 			expression.push_back(e);
 			continue;
 			continue;
 		} else {
 		} else {
-			_set_error("Expected expression, found: " + get_token_text(tk));
-			return nullptr;
-			//nothing
+			if (tk.type != TK_SEMICOLON) {
+				_set_error("Expected expression, found: " + get_token_text(tk));
+				return nullptr;
+			} else {
+#if DEBUG_ENABLED
+				if (check_warnings && HAS_WARNING(ShaderWarning::FORMATTING_ERROR_FLAG)) {
+					_add_line_warning(ShaderWarning::FORMATTING_ERROR, "Empty statement. Remove ';' to fix this warning.");
+				}
+#endif // DEBUG_ENABLED
+				_set_tkpos(prepos);
+
+				OperatorNode *func = alloc_node<OperatorNode>();
+				func->op = OP_EMPTY;
+				expr = func;
+			}
 		}
 		}
 
 
 		ERR_FAIL_COND_V(!expr, nullptr);
 		ERR_FAIL_COND_V(!expr, nullptr);

+ 1 - 0
servers/rendering/shader_language.h

@@ -287,6 +287,7 @@ public:
 		OP_CONSTRUCT,
 		OP_CONSTRUCT,
 		OP_STRUCT,
 		OP_STRUCT,
 		OP_INDEX,
 		OP_INDEX,
+		OP_EMPTY,
 		OP_MAX
 		OP_MAX
 	};
 	};
 
 

+ 4 - 0
servers/rendering/shader_warnings.cpp

@@ -61,6 +61,8 @@ String ShaderWarning::get_message() const {
 			return vformat("The varying '%s' is declared but never used.", subject);
 			return vformat("The varying '%s' is declared but never used.", subject);
 		case UNUSED_LOCAL_VARIABLE:
 		case UNUSED_LOCAL_VARIABLE:
 			return vformat("The local variable '%s' is declared but never used.", subject);
 			return vformat("The local variable '%s' is declared but never used.", subject);
+		case FORMATTING_ERROR:
+			return subject;
 		default:
 		default:
 			break;
 			break;
 	}
 	}
@@ -82,6 +84,7 @@ String ShaderWarning::get_name_from_code(Code p_code) {
 		"UNUSED_UNIFORM",
 		"UNUSED_UNIFORM",
 		"UNUSED_VARYING",
 		"UNUSED_VARYING",
 		"UNUSED_LOCAL_VARIABLE",
 		"UNUSED_LOCAL_VARIABLE",
+		"FORMATTING_ERROR",
 	};
 	};
 
 
 	static_assert((sizeof(names) / sizeof(*names)) == WARNING_MAX, "Amount of warning types don't match the amount of warning names.");
 	static_assert((sizeof(names) / sizeof(*names)) == WARNING_MAX, "Amount of warning types don't match the amount of warning names.");
@@ -110,6 +113,7 @@ static void init_code_to_flags_map() {
 	code_to_flags_map->insert(ShaderWarning::UNUSED_UNIFORM, ShaderWarning::UNUSED_UNIFORM_FLAG);
 	code_to_flags_map->insert(ShaderWarning::UNUSED_UNIFORM, ShaderWarning::UNUSED_UNIFORM_FLAG);
 	code_to_flags_map->insert(ShaderWarning::UNUSED_VARYING, ShaderWarning::UNUSED_VARYING_FLAG);
 	code_to_flags_map->insert(ShaderWarning::UNUSED_VARYING, ShaderWarning::UNUSED_VARYING_FLAG);
 	code_to_flags_map->insert(ShaderWarning::UNUSED_LOCAL_VARIABLE, ShaderWarning::UNUSED_LOCAL_VARIABLE_FLAG);
 	code_to_flags_map->insert(ShaderWarning::UNUSED_LOCAL_VARIABLE, ShaderWarning::UNUSED_LOCAL_VARIABLE_FLAG);
+	code_to_flags_map->insert(ShaderWarning::FORMATTING_ERROR, ShaderWarning::FORMATTING_ERROR_FLAG);
 }
 }
 
 
 ShaderWarning::CodeFlags ShaderWarning::get_flags_from_codemap(const Map<Code, bool> &p_map) {
 ShaderWarning::CodeFlags ShaderWarning::get_flags_from_codemap(const Map<Code, bool> &p_map) {

+ 2 - 0
servers/rendering/shader_warnings.h

@@ -47,6 +47,7 @@ public:
 		UNUSED_UNIFORM,
 		UNUSED_UNIFORM,
 		UNUSED_VARYING,
 		UNUSED_VARYING,
 		UNUSED_LOCAL_VARIABLE,
 		UNUSED_LOCAL_VARIABLE,
+		FORMATTING_ERROR,
 		WARNING_MAX,
 		WARNING_MAX,
 	};
 	};
 
 
@@ -59,6 +60,7 @@ public:
 		UNUSED_UNIFORM_FLAG = 16U,
 		UNUSED_UNIFORM_FLAG = 16U,
 		UNUSED_VARYING_FLAG = 32U,
 		UNUSED_VARYING_FLAG = 32U,
 		UNUSED_LOCAL_VARIABLE_FLAG = 64U,
 		UNUSED_LOCAL_VARIABLE_FLAG = 64U,
+		FORMATTING_ERROR_FLAG = 128U,
 	};
 	};
 
 
 private:
 private:

+ 2 - 0
tests/servers/test_shader_lang.cpp

@@ -261,6 +261,8 @@ static String dump_node_code(SL::Node *p_node, int p_level) {
 					}
 					}
 					code += ")";
 					code += ")";
 					break;
 					break;
+				case SL::OP_EMPTY:
+					break;
 				default: {
 				default: {
 					code = "(" + dump_node_code(onode->arguments[0], p_level) + _opstr(onode->op) + dump_node_code(onode->arguments[1], p_level) + ")";
 					code = "(" + dump_node_code(onode->arguments[0], p_level) + _opstr(onode->op) + dump_node_code(onode->arguments[1], p_level) + ")";
 					break;
 					break;