diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 3358e6838c5f..8204e5a8bcb7 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -561,10 +561,10 @@
When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when defining a local or member variable, signal, or enum that would have the same name as a built-in function or global class name, thus shadowing it.
- When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when defining a local or member variable that would shadow a member variable that the class defines.
+ When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when defining a local or class variable that would shadow a member that the class defines.
- When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when defining a local or subclass member variable that would shadow a variable that is inherited from a parent class.
+ When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when defining a local or subclass variable that would shadow a member that is inherited from a parent class.
When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when calling an expression that may have no effect on the surrounding code, such as writing [code]2 + 2[/code] as a statement.
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index 93d4a512a923..4bcd55534bd1 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -5839,12 +5839,23 @@ void GDScriptAnalyzer::is_shadowing(GDScriptParser::IdentifierNode *p_identifier
}
if (p_in_local_scope) {
- while (base_class != nullptr) {
- if (base_class->has_member(name)) {
- parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_VARIABLE, p_context, p_identifier->name, base_class->get_member(name).get_type_name(), itos(base_class->get_member(name).get_line()));
+ GDScriptParser::ClassNode *current_parent_class = base_class;
+
+ while (current_parent_class != nullptr) {
+ if (current_parent_class->has_member(name)) {
+ if (current_parent_class != base_class) {
+ String current_class_name = current_parent_class->fqcn;
+ if (current_parent_class->identifier != nullptr) {
+ current_class_name = current_parent_class->identifier->name;
+ }
+
+ parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_identifier->name, current_parent_class->get_member(name).get_type_name(), itos(current_parent_class->get_member(name).get_line()), current_class_name);
+ return;
+ }
+ parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_VARIABLE, p_context, p_identifier->name, current_parent_class->get_member(name).get_type_name(), itos(current_parent_class->get_member(name).get_line()));
return;
}
- base_class = base_class->base_type.class_type;
+ current_parent_class = current_parent_class->base_type.class_type;
}
}
diff --git a/modules/gdscript/gdscript_warning.cpp b/modules/gdscript/gdscript_warning.cpp
index 4ffb4bd9d13f..13550709b75b 100644
--- a/modules/gdscript/gdscript_warning.cpp
+++ b/modules/gdscript/gdscript_warning.cpp
@@ -64,7 +64,10 @@ String GDScriptWarning::get_message() const {
return vformat(R"(The local %s "%s" is shadowing an already-declared %s at line %s.)", symbols[0], symbols[1], symbols[2], symbols[3]);
case SHADOWED_VARIABLE_BASE_CLASS:
CHECK_SYMBOLS(4);
- return vformat(R"(The local %s "%s" is shadowing an already-declared %s at the base class "%s".)", symbols[0], symbols[1], symbols[2], symbols[3]);
+ if (symbols.size() < 5) {
+ return vformat(R"(The local %s "%s" is shadowing an already-declared %s at the base class "%s".)", symbols[0], symbols[1], symbols[2], symbols[3]);
+ }
+ return vformat(R"(The local %s "%s" is shadowing an already-declared %s at line %s in the base class "%s".)", symbols[0], symbols[1], symbols[2], symbols[3], symbols[4]);
case SHADOWED_GLOBAL_IDENTIFIER:
CHECK_SYMBOLS(3);
return vformat(R"(The %s "%s" has the same name as a %s.)", symbols[0], symbols[1], symbols[2]);
diff --git a/modules/gdscript/gdscript_warning.h b/modules/gdscript/gdscript_warning.h
index ffcf00a83014..8c0aa16a4705 100644
--- a/modules/gdscript/gdscript_warning.h
+++ b/modules/gdscript/gdscript_warning.h
@@ -53,8 +53,8 @@ class GDScriptWarning {
UNUSED_PRIVATE_CLASS_VARIABLE, // Class variable is declared private ("_" prefix) but never used in the class.
UNUSED_PARAMETER, // Function parameter is never used.
UNUSED_SIGNAL, // Signal is defined but never explicitly used in the class.
- SHADOWED_VARIABLE, // Variable name shadowed by other variable in same class.
- SHADOWED_VARIABLE_BASE_CLASS, // Variable name shadowed by other variable in some base class.
+ SHADOWED_VARIABLE, // Member shadowed by other variable in same class.
+ SHADOWED_VARIABLE_BASE_CLASS, // Variable shadows other member in some base class.
SHADOWED_GLOBAL_IDENTIFIER, // A global class or function has the same name as variable.
UNREACHABLE_CODE, // Code after a return statement.
UNREACHABLE_PATTERN, // Pattern in a match statement after a catch all pattern (wildcard or bind).
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/local_variable_shadows_base_member.gd b/modules/gdscript/tests/scripts/analyzer/warnings/local_variable_shadows_base_member.gd
new file mode 100644
index 000000000000..7895634313d2
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/local_variable_shadows_base_member.gd
@@ -0,0 +1,16 @@
+class A:
+ var foo1
+
+ func foo2():
+ pass
+
+class B extends A:
+ func test1(foo1):
+ return foo1
+
+ func test2():
+ var foo2 = 1
+ return foo2
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/local_variable_shadows_base_member.out b/modules/gdscript/tests/scripts/analyzer/warnings/local_variable_shadows_base_member.out
new file mode 100644
index 000000000000..c69459c4fa75
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/local_variable_shadows_base_member.out
@@ -0,0 +1,9 @@
+GDTEST_OK
+>> WARNING
+>> Line: 8
+>> SHADOWED_VARIABLE_BASE_CLASS
+>> The local function parameter "foo1" is shadowing an already-declared variable at line 2 in the base class "A".
+>> WARNING
+>> Line: 12
+>> SHADOWED_VARIABLE_BASE_CLASS
+>> The local variable "foo2" is shadowing an already-declared function at line 4 in the base class "A".