Browse Source

Merge pull request #51671 from RandomShaper/fix_gdscript_crash

Fix some GDScript bugs
George Marques 3 years ago
parent
commit
b8fdeb6467

+ 21 - 6
modules/gdscript/gdscript_analyzer.cpp

@@ -1187,12 +1187,28 @@ void GDScriptAnalyzer::resolve_for(GDScriptParser::ForNode *p_for) {
 		}
 	}
 
-	if (!list_resolved) {
+	GDScriptParser::DataType variable_type;
+	if (list_resolved) {
+		variable_type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
+		variable_type.kind = GDScriptParser::DataType::BUILTIN;
+		variable_type.builtin_type = Variant::INT; // Can this ever be a float or something else?
+		p_for->variable->set_datatype(variable_type);
+	} else {
 		resolve_node(p_for->list);
+		if (p_for->list->datatype.has_container_element_type()) {
+			variable_type = p_for->list->datatype.get_container_element_type();
+			variable_type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
+		} else if (p_for->list->datatype.is_typed_container_type()) {
+			variable_type = p_for->list->datatype.get_typed_container_type();
+			variable_type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
+		} else {
+			// Last resort
+			// TODO: Must other cases be handled? Must we mark as unsafe?
+			variable_type.type_source = GDScriptParser::DataType::UNDETECTED;
+			variable_type.kind = GDScriptParser::DataType::VARIANT;
+		}
 	}
-
-	// TODO: If list is a typed array, the variable should be an element.
-	// Also applicable for constant range() (so variable is int or float).
+	p_for->variable->set_datatype(variable_type);
 
 	resolve_suite(p_for->loop);
 	p_for->set_datatype(p_for->loop->get_datatype());
@@ -1480,8 +1496,7 @@ void GDScriptAnalyzer::resolve_parameter(GDScriptParser::ParameterNode *p_parame
 	}
 
 	if (p_parameter->datatype_specifier != nullptr) {
-		resolve_datatype(p_parameter->datatype_specifier);
-		result = p_parameter->datatype_specifier->get_datatype();
+		result = resolve_datatype(p_parameter->datatype_specifier);
 		result.is_meta_type = false;
 
 		if (p_parameter->default_value != nullptr) {

+ 3 - 9
modules/gdscript/gdscript_cache.cpp

@@ -51,7 +51,9 @@ GDScriptParser *GDScriptParserRef::get_parser() const {
 Error GDScriptParserRef::raise_status(Status p_new_status) {
 	ERR_FAIL_COND_V(parser == nullptr, ERR_INVALID_DATA);
 
-	Error result = OK;
+	if (result != OK) {
+		return result;
+	}
 
 	while (p_new_status > status) {
 		switch (status) {
@@ -86,14 +88,6 @@ Error GDScriptParserRef::raise_status(Status p_new_status) {
 			}
 		}
 		if (result != OK) {
-			if (parser != nullptr) {
-				memdelete(parser);
-				parser = nullptr;
-			}
-			if (analyzer != nullptr) {
-				memdelete(analyzer);
-				analyzer = nullptr;
-			}
 			return result;
 		}
 	}

+ 1 - 0
modules/gdscript/gdscript_cache.h

@@ -54,6 +54,7 @@ private:
 	GDScriptParser *parser = nullptr;
 	GDScriptAnalyzer *analyzer = nullptr;
 	Status status = EMPTY;
+	Error result = OK;
 	String path;
 
 	friend class GDScriptCache;

+ 33 - 0
modules/gdscript/gdscript_parser.cpp

@@ -3587,6 +3587,39 @@ String GDScriptParser::DataType::to_string() const {
 	ERR_FAIL_V_MSG("<unresolved type", "Kind set outside the enum range.");
 }
 
+static Variant::Type _variant_type_to_typed_array_element_type(Variant::Type p_type) {
+	switch (p_type) {
+		case Variant::PACKED_BYTE_ARRAY:
+		case Variant::PACKED_INT32_ARRAY:
+		case Variant::PACKED_INT64_ARRAY:
+			return Variant::INT;
+		case Variant::PACKED_FLOAT32_ARRAY:
+		case Variant::PACKED_FLOAT64_ARRAY:
+			return Variant::FLOAT;
+		case Variant::PACKED_STRING_ARRAY:
+			return Variant::STRING;
+		case Variant::PACKED_VECTOR2_ARRAY:
+			return Variant::VECTOR2;
+		case Variant::PACKED_VECTOR3_ARRAY:
+			return Variant::VECTOR3;
+		case Variant::PACKED_COLOR_ARRAY:
+			return Variant::COLOR;
+		default:
+			return Variant::NIL;
+	}
+}
+
+bool GDScriptParser::DataType::is_typed_container_type() const {
+	return kind == GDScriptParser::DataType::BUILTIN && _variant_type_to_typed_array_element_type(builtin_type) != Variant::NIL;
+}
+
+GDScriptParser::DataType GDScriptParser::DataType::get_typed_container_type() const {
+	GDScriptParser::DataType type;
+	type.kind = GDScriptParser::DataType::BUILTIN;
+	type.builtin_type = _variant_type_to_typed_array_element_type(builtin_type);
+	return type;
+}
+
 /*---------- PRETTY PRINT FOR DEBUG ----------*/
 
 #ifdef DEBUG_ENABLED

+ 4 - 0
modules/gdscript/gdscript_parser.h

@@ -161,6 +161,10 @@ public:
 			container_element_type = nullptr;
 		}
 
+		bool is_typed_container_type() const;
+
+		GDScriptParser::DataType get_typed_container_type() const;
+
 		bool operator==(const DataType &p_other) const {
 			if (type_source == UNDETECTED || p_other.type_source == UNDETECTED) {
 				return true; // Can be consireded equal for parsing purposes.