Browse Source

Merge pull request #69303 from Chaosus/gds_fix_loops

Reset unassigned local variables to null in the loops
Rémi Verschelde 2 years ago
parent
commit
eb555d7559

+ 9 - 0
modules/gdscript/gdscript_compiler.cpp

@@ -1875,6 +1875,7 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
 				GDScriptCodeGenerator::Address local = codegen.locals[lv->identifier->name];
 				GDScriptDataType local_type = _gdtype_from_datatype(lv->get_datatype(), codegen.script);
 
+				bool initialized = false;
 				if (lv->initializer != nullptr) {
 					// For typed arrays we need to make sure this is already initialized correctly so typed assignment work.
 					if (local_type.has_type && local_type.builtin_type == Variant::ARRAY) {
@@ -1896,15 +1897,23 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
 					if (src_address.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
 						codegen.generator->pop_temporary();
 					}
+					initialized = true;
 				} else if (local_type.has_type) {
 					// Initialize with default for type.
 					if (local_type.has_container_element_type()) {
 						codegen.generator->write_construct_typed_array(local, local_type.get_container_element_type(), Vector<GDScriptCodeGenerator::Address>());
+						initialized = true;
 					} else if (local_type.kind == GDScriptDataType::BUILTIN) {
 						codegen.generator->write_construct(local, local_type.builtin_type, Vector<GDScriptCodeGenerator::Address>());
+						initialized = true;
 					}
 					// The `else` branch is for objects, in such case we leave it as `null`.
 				}
+
+				// Assigns a null for the unassigned variables in loops.
+				if (!initialized && p_block->is_loop) {
+					codegen.generator->write_construct(local, Variant::NIL, Vector<GDScriptCodeGenerator::Address>());
+				}
 			} break;
 			case GDScriptParser::Node::CONSTANT: {
 				// Local constants.

+ 2 - 1
modules/gdscript/gdscript_parser.cpp

@@ -1835,9 +1835,9 @@ GDScriptParser::ForNode *GDScriptParser::parse_for() {
 		}
 		suite->add_local(SuiteNode::Local(n_for->variable, current_function));
 	}
-	suite->parent_for = n_for;
 
 	n_for->loop = parse_suite(R"("for" block)", suite);
+	n_for->loop->is_loop = true;
 	complete_extents(n_for);
 
 	// Reset break/continue state.
@@ -2169,6 +2169,7 @@ GDScriptParser::WhileNode *GDScriptParser::parse_while() {
 	is_continue_match = false;
 
 	n_while->loop = parse_suite(R"("while" block)");
+	n_while->loop->is_loop = true;
 	complete_extents(n_while);
 
 	// Reset break/continue state.

+ 1 - 1
modules/gdscript/gdscript_parser.h

@@ -1055,12 +1055,12 @@ public:
 		HashMap<StringName, int> locals_indices;
 
 		FunctionNode *parent_function = nullptr;
-		ForNode *parent_for = nullptr;
 		IfNode *parent_if = nullptr;
 
 		bool has_return = false;
 		bool has_continue = false;
 		bool has_unreachable_code = false; // Just so warnings aren't given more than once per block.
+		bool is_loop = false;
 
 		bool has_local(const StringName &p_name) const;
 		const Local &get_local(const StringName &p_name) const;