Repository: godotengine/godot (language: cpp)

Issue:
False positive UNUSED_VARYING
### Tested versions

- Reproducible in: v4.4.rc3.official [15ff45068], v4.4.dev7.official [46c8f8c5c]
- Not reproducible in: v4.4.dev6.official [1f47e4c4e]

### System information

Godot v4.4.rc3 - Windows 10 (build 19045) - Multi-window, 1 monitor - OpenGL 3 (Compatibility) - NVIDIA GeForce GTX 1050 Ti (NVIDIA; 32.0.15.7260) - Intel(R) Core(TM) i3-10105 CPU @ 3.70GHz (8 threads)

### Issue description

Godot reports a varying is not being used, while it is being used.

### Steps to reproduce

Create or open a shader with a varying and look for warning in the bottom of the shader editor.

Found and reproduced with this shader (included in the MRP below):

```
shader_type canvas_item;

uniform float level;

varying vec4 vertex_color;

void vertex() {
	vertex_color = COLOR;
}

void fragment()
{
	COLOR = vertex_color;
	COLOR.a *= level;
}
```

Here Godot claims `vertex_color` is not being used: `Line 5 (UNUSED_VARYING):The varying 'vertex_color' is declared but never used.`

Note: The shader is based on an example from the documentation at [COLOR and TEXTURE](https://docs.godotengine.org/en/stable/tutorials/shaders/shader_reference/canvas_item_shader.html#color-and-texture):

```
varying vec4 vertex_color;
void vertex() {
  vertex_color = COLOR;
}
void fragment() {
  COLOR = vertex_color;
}
```


### Minimal reproduction project (MRP)

[svwt.zip](https://github.com/user-attachments/files/19036041/svwt.zip)


Discussion / hints:
I haven't bisected but I suspect #95737, cc @Chaosus.

I put this in 4.4 milestone but it will most likely need to wait for 4.4.1 to be fixed as the 4.4 release is imminent - unless the regression fix is really trivial and done quickly.

Fix patch:
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 59adb53b7866..66a43684a52a 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -1342,7 +1342,7 @@ void ShaderLanguage::_parse_used_identifier(const StringName &p_identifier, Iden
 			break;
 		case IdentifierType::IDENTIFIER_VARYING:
 			if (HAS_WARNING(ShaderWarning::UNUSED_VARYING_FLAG) && used_varyings.has(p_identifier)) {
-				if (shader->varyings[p_identifier].stage != ShaderNode::Varying::STAGE_VERTEX && shader->varyings[p_identifier].stage != ShaderNode::Varying::STAGE_FRAGMENT) {
+				if (shader->varyings[p_identifier].stage == ShaderNode::Varying::STAGE_UNKNOWN) {
 					used_varyings[p_identifier].used = true;
 				}
 			}
@@ -6510,6 +6510,27 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
 						_set_error(RTR("Expected constant expression."));
 						return nullptr;
 					}
+					if (ident_type == IDENTIFIER_FUNCTION) {
+						_set_error(vformat(RTR("Can't use function as identifier: '%s'."), String(identifier)));
+						return nullptr;
+					}
+#ifdef DEBUG_ENABLED
+					if (check_warnings) {
+						StringName func_name;
+						BlockNode *b = p_block;
+
+						while (b) {
+							if (b->parent_function) {
+								func_name = b->parent_function->name;
+								break;
+							} else {
+								b = b->parent_block;
+							}
+						}
+
+						_parse_used_identifier(identifier, ident_type, func_name);
+					}
+#endif // DEBUG_ENABLED
 					if (ident_type == IDENTIFIER_VARYING) {
 						TkPos prev_pos = _get_tkpos();
 						Token next_token = _get_token();
@@ -6542,11 +6563,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
 							}
 						}
 					}
-
-					if (ident_type == IDENTIFIER_FUNCTION) {
-						_set_error(vformat(RTR("Can't use function as identifier: '%s'."), String(identifier)));
-						return nullptr;
-					}
 #ifdef DEBUG_ENABLED
 					if (check_position_write && ident_type == IDENTIFIER_BUILTIN_VAR) {
 						if (String(identifier) == "POSITION") {
@@ -6564,7 +6580,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
 							_set_tkpos(prev_pos);
 						}
 					}
-#endif
+#endif // DEBUG_ENABLED
 					if (is_const) {
 						last_type = IDENTIFIER_CONSTANT;
 					} else {
@@ -6656,23 +6672,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
 					varname->is_local = is_local;
 					expr = varname;
 				}
-#ifdef DEBUG_ENABLED
-				if (check_warnings) {
-					StringName func_name;
-					BlockNode *b = p_block;
-
-					while (b) {
-						if (b->parent_function) {
-							func_name = b->parent_function->name;
-							break;
-						} else {
-							b = b->parent_block;
-						}
-					}
-
-					_parse_used_identifier(identifier, ident_type, func_name);
-				}
-#endif // DEBUG_ENABLED
 			}
 		} else if (tk.type == TK_OP_ADD) {
 			continue; //this one does nothing


Test patch: