Browse Source

Merge pull request #31921 from bojidar-bg/28978-uninitialized-array-value

Fix uninitialized arrays and dictionaries retaining value
Rémi Verschelde 6 years ago
parent
commit
c3d5c96494
2 changed files with 45 additions and 33 deletions
  1. 44 33
      modules/gdscript/gdscript_parser.cpp
  2. 1 0
      modules/gdscript/gdscript_parser.h

+ 44 - 33
modules/gdscript/gdscript_parser.cpp

@@ -2846,15 +2846,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
 					assigned = subexpr;
 				} else {
 
-					ConstantNode *c = alloc_node<ConstantNode>();
-					if (lv->datatype.has_type && lv->datatype.kind == DataType::BUILTIN) {
-						Variant::CallError err;
-						c->value = Variant::construct(lv->datatype.builtin_type, NULL, 0, err);
-					} else {
-						c->value = Variant();
-					}
-					c->line = var_line;
-					assigned = c;
+					assigned = _get_default_value_for_type(lv->datatype, var_line);
 				}
 				lv->assign = assigned;
 				//must be added later, to avoid self-referencing.
@@ -4869,35 +4861,29 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
 						return;
 					}
 
-					Variant::Type initial_type = member.data_type.has_type ? member.data_type.builtin_type : member._export.type;
-
-					if (initial_type != Variant::NIL && initial_type != Variant::OBJECT) {
-						IdentifierNode *id = alloc_node<IdentifierNode>();
-						id->name = member.identifier;
+					Node *expr;
 
-						Node *expr;
+					if (member.data_type.has_type) {
+						expr = _get_default_value_for_type(member.data_type);
+					} else {
+						DataType exported_type;
+						exported_type.has_type = true;
+						exported_type.kind = DataType::BUILTIN;
+						exported_type.builtin_type = member._export.type;
+						expr = _get_default_value_for_type(exported_type);
+					}
 
-						// Make sure arrays and dictionaries are not shared
-						if (initial_type == Variant::ARRAY) {
-							expr = alloc_node<ArrayNode>();
-						} else if (initial_type == Variant::DICTIONARY) {
-							expr = alloc_node<DictionaryNode>();
-						} else {
-							ConstantNode *cn = alloc_node<ConstantNode>();
-							Variant::CallError ce2;
-							cn->value = Variant::construct(initial_type, NULL, 0, ce2);
-							expr = cn;
-						}
+					IdentifierNode *id = alloc_node<IdentifierNode>();
+					id->name = member.identifier;
 
-						OperatorNode *op = alloc_node<OperatorNode>();
-						op->op = OperatorNode::OP_INIT_ASSIGN;
-						op->arguments.push_back(id);
-						op->arguments.push_back(expr);
+					OperatorNode *op = alloc_node<OperatorNode>();
+					op->op = OperatorNode::OP_INIT_ASSIGN;
+					op->arguments.push_back(id);
+					op->arguments.push_back(expr);
 
-						p_class->initializer->statements.push_back(op);
+					p_class->initializer->statements.push_back(op);
 
-						member.initial_assignment = op;
-					}
+					member.initial_assignment = op;
 				}
 
 				if (autoexport && member.data_type.has_type) {
@@ -6177,6 +6163,31 @@ bool GDScriptParser::_is_type_compatible(const DataType &p_container, const Data
 	return false;
 }
 
+GDScriptParser::Node *GDScriptParser::_get_default_value_for_type(const DataType &p_type, int p_line) {
+	Node *result;
+
+	if (p_type.has_type && p_type.kind == DataType::BUILTIN && p_type.builtin_type != Variant::NIL && p_type.builtin_type != Variant::OBJECT) {
+		if (p_type.builtin_type == Variant::ARRAY) {
+			result = alloc_node<ArrayNode>();
+		} else if (p_type.builtin_type == Variant::DICTIONARY) {
+			result = alloc_node<DictionaryNode>();
+		} else {
+			ConstantNode *c = alloc_node<ConstantNode>();
+			Variant::CallError err;
+			c->value = Variant::construct(p_type.builtin_type, NULL, 0, err);
+			result = c;
+		}
+	} else {
+		ConstantNode *c = alloc_node<ConstantNode>();
+		c->value = Variant();
+		result = c;
+	}
+
+	result->line = p_line;
+
+	return result;
+}
+
 GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
 #ifdef DEBUG_ENABLED
 	if (p_node->get_datatype().has_type && p_node->type != Node::TYPE_ARRAY && p_node->type != Node::TYPE_DICTIONARY) {

+ 1 - 0
modules/gdscript/gdscript_parser.h

@@ -615,6 +615,7 @@ private:
 	bool _get_function_signature(DataType &p_base_type, const StringName &p_function, DataType &r_return_type, List<DataType> &r_arg_types, int &r_default_arg_count, bool &r_static, bool &r_vararg) const;
 	bool _get_member_type(const DataType &p_base_type, const StringName &p_member, DataType &r_member_type) const;
 	bool _is_type_compatible(const DataType &p_container, const DataType &p_expression, bool p_allow_implicit_conversion = false) const;
+	Node *_get_default_value_for_type(const DataType &p_type, int p_line = -1);
 
 	DataType _reduce_node_type(Node *p_node);
 	DataType _reduce_function_call_type(const OperatorNode *p_call);