summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/gdscript/doc_classes/@GDScript.xml14
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp7
-rw-r--r--modules/gdscript/gdscript_byte_codegen.cpp3
-rw-r--r--modules/gdscript/gdscript_compiler.cpp13
-rw-r--r--modules/gdscript/gdscript_vm.cpp38
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/not_found_type.gd3
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/not_found_type.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/inheritance_signature_check_no_meta.gd10
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/inheritance_signature_check_no_meta.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/script_typed_assign_null.gd18
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/script_typed_assign_null.out7
11 files changed, 91 insertions, 26 deletions
diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml
index 08c8763493..045505b720 100644
--- a/modules/gdscript/doc_classes/@GDScript.xml
+++ b/modules/gdscript/doc_classes/@GDScript.xml
@@ -126,6 +126,20 @@
<param index="0" name="value" type="Variant" />
<param index="1" name="type" type="Variant" />
<description>
+ Returns [code]true[/code] if [param value] is an instance of [param type]. The [param type] value must be one of the following:
+ - A constant from the [enum Variant.Type] enumeration, for example [constant TYPE_INT].
+ - An [Object]-derived class which exists in [ClassDB], for example [Node].
+ - A [Script] (you can use any class, including inner one).
+ Unlike the right operand of the [code]is[/code] operator, [param type] can be a non-constant value. The [code]is[/code] operator supports more features (such as typed arrays) and is more performant. Use the operator instead of this method if you do not need dynamic type checking.
+ Examples:
+ [codeblock]
+ print(is_instance_of(a, TYPE_INT))
+ print(is_instance_of(a, Node))
+ print(is_instance_of(a, MyClass))
+ print(is_instance_of(a, MyClass.InnerClass))
+ [/codeblock]
+ [b]Note:[/b] If [param value] and/or [param type] are freed objects (see [method @GlobalScope.is_instance_valid]), or [param type] is not one of the above options, this method will raise an runtime error.
+ See also [method @GlobalScope.typeof], [method type_exists], [method Array.is_same_typed] (and other [Array] methods).
</description>
</method>
<method name="len">
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index 38f9163f70..5ce01a08bf 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -657,6 +657,10 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type
} else if (ProjectSettings::get_singleton()->has_autoload(first) && ProjectSettings::get_singleton()->get_autoload(first).is_singleton) {
const ProjectSettings::AutoloadInfo &autoload = ProjectSettings::get_singleton()->get_autoload(first);
Ref<GDScriptParserRef> ref = get_parser_for(autoload.path);
+ if (ref.is_null()) {
+ push_error(vformat(R"(The referenced autoload "%s" (from "%s") could not be loaded.)", first, autoload.path), p_type);
+ return bad_type;
+ }
if (ref->raise_status(GDScriptParserRef::INHERITANCE_SOLVED) != OK) {
push_error(vformat(R"(Could not parse singleton "%s" from "%s".)", first, autoload.path), p_type);
return bad_type;
@@ -727,7 +731,7 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type
}
}
if (!result.is_set()) {
- push_error(vformat(R"("%s" was not found in the current scope.)", first), p_type);
+ push_error(vformat(R"(Could not find type "%s" in the current scope.)", first), p_type);
return bad_type;
}
@@ -1534,6 +1538,7 @@ void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode *
// Check if the function signature matches the parent. If not it's an error since it breaks polymorphism.
// Not for the constructor which can vary in signature.
GDScriptParser::DataType base_type = parser->current_class->base_type;
+ base_type.is_meta_type = false;
GDScriptParser::DataType parent_return_type;
List<GDScriptParser::DataType> parameters_types;
int default_par_count = 0;
diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp
index a13bf8009f..5b092e3691 100644
--- a/modules/gdscript/gdscript_byte_codegen.cpp
+++ b/modules/gdscript/gdscript_byte_codegen.cpp
@@ -581,7 +581,8 @@ void GDScriptByteCodeGenerator::write_unary_operator(const Address &p_target, Va
}
void GDScriptByteCodeGenerator::write_binary_operator(const Address &p_target, Variant::Operator p_operator, const Address &p_left_operand, const Address &p_right_operand) {
- if (HAS_BUILTIN_TYPE(p_left_operand) && HAS_BUILTIN_TYPE(p_right_operand)) {
+ // Avoid validated evaluator for modulo and division when operands are int, since there's no check for division by zero.
+ if (HAS_BUILTIN_TYPE(p_left_operand) && HAS_BUILTIN_TYPE(p_right_operand) && ((p_operator != Variant::OP_DIVIDE && p_operator != Variant::OP_MODULE) || p_left_operand.type.builtin_type != Variant::INT || p_right_operand.type.builtin_type != Variant::INT)) {
if (p_target.mode == Address::TEMPORARY) {
Variant::Type result_type = Variant::get_operator_return_type(p_operator, p_left_operand.type.builtin_type, p_right_operand.type.builtin_type);
Variant::Type temp_type = temporaries[p_target.address].type;
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index efa75528fc..35c9946bc1 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -2265,13 +2265,15 @@ Error GDScriptCompiler::_populate_class_members(GDScript *p_script, const GDScri
GDScriptDataType base_type = _gdtype_from_datatype(p_class->base_type, p_script);
+ int native_idx = GDScriptLanguage::get_singleton()->get_global_map()[base_type.native_type];
+ p_script->native = GDScriptLanguage::get_singleton()->get_global_array()[native_idx];
+ ERR_FAIL_COND_V(p_script->native.is_null(), ERR_BUG);
+
// Inheritance
switch (base_type.kind) {
- case GDScriptDataType::NATIVE: {
- int native_idx = GDScriptLanguage::get_singleton()->get_global_map()[base_type.native_type];
- p_script->native = GDScriptLanguage::get_singleton()->get_global_array()[native_idx];
- ERR_FAIL_COND_V(p_script->native.is_null(), ERR_BUG);
- } break;
+ case GDScriptDataType::NATIVE:
+ // Nothing more to do.
+ break;
case GDScriptDataType::GDSCRIPT: {
Ref<GDScript> base = Ref<GDScript>(base_type.script_type);
if (base.is_null()) {
@@ -2303,7 +2305,6 @@ Error GDScriptCompiler::_populate_class_members(GDScript *p_script, const GDScri
p_script->base = base;
p_script->_base = base.ptr();
p_script->member_indices = base->member_indices;
- p_script->native = base->native;
} break;
default: {
_set_error("Parser bug: invalid inheritance.", nullptr);
diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp
index ba400b8e15..83d2ed6010 100644
--- a/modules/gdscript/gdscript_vm.cpp
+++ b/modules/gdscript/gdscript_vm.cpp
@@ -1326,28 +1326,30 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE_BREAK;
}
- ScriptInstance *scr_inst = val_obj->get_script_instance();
- if (!scr_inst) {
- err_text = "Trying to assign value of type '" + val_obj->get_class_name() +
- "' to a variable of type '" + base_type->get_path().get_file() + "'.";
- OPCODE_BREAK;
- }
+ if (val_obj) { // src is not null
+ ScriptInstance *scr_inst = val_obj->get_script_instance();
+ if (!scr_inst) {
+ err_text = "Trying to assign value of type '" + val_obj->get_class_name() +
+ "' to a variable of type '" + base_type->get_path().get_file() + "'.";
+ OPCODE_BREAK;
+ }
- Script *src_type = val_obj->get_script_instance()->get_script().ptr();
- bool valid = false;
+ Script *src_type = scr_inst->get_script().ptr();
+ bool valid = false;
- while (src_type) {
- if (src_type == base_type) {
- valid = true;
- break;
+ while (src_type) {
+ if (src_type == base_type) {
+ valid = true;
+ break;
+ }
+ src_type = src_type->get_base_script().ptr();
}
- src_type = src_type->get_base_script().ptr();
- }
- if (!valid) {
- err_text = "Trying to assign value of type '" + val_obj->get_script_instance()->get_script()->get_path().get_file() +
- "' to a variable of type '" + base_type->get_path().get_file() + "'.";
- OPCODE_BREAK;
+ if (!valid) {
+ err_text = "Trying to assign value of type '" + val_obj->get_script_instance()->get_script()->get_path().get_file() +
+ "' to a variable of type '" + base_type->get_path().get_file() + "'.";
+ OPCODE_BREAK;
+ }
}
}
#endif // DEBUG_ENABLED
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/not_found_type.gd b/modules/gdscript/tests/scripts/analyzer/errors/not_found_type.gd
new file mode 100644
index 0000000000..1644295b38
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/not_found_type.gd
@@ -0,0 +1,3 @@
+func test():
+ var foo: Foo
+ print('not ok')
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/not_found_type.out b/modules/gdscript/tests/scripts/analyzer/errors/not_found_type.out
new file mode 100644
index 0000000000..3f6c2d868d
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/not_found_type.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Could not find type "Foo" in the current scope.
diff --git a/modules/gdscript/tests/scripts/analyzer/features/inheritance_signature_check_no_meta.gd b/modules/gdscript/tests/scripts/analyzer/features/inheritance_signature_check_no_meta.gd
new file mode 100644
index 0000000000..6c056530f6
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/inheritance_signature_check_no_meta.gd
@@ -0,0 +1,10 @@
+func test():
+ print("ok")
+
+# https://github.com/godotengine/godot/issues/71994
+class A:
+ extends RefCounted
+class B:
+ extends A
+ func duplicate():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/features/inheritance_signature_check_no_meta.out b/modules/gdscript/tests/scripts/analyzer/features/inheritance_signature_check_no_meta.out
new file mode 100644
index 0000000000..1b47ed10dc
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/inheritance_signature_check_no_meta.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+ok
diff --git a/modules/gdscript/tests/scripts/analyzer/features/script_typed_assign_null.gd b/modules/gdscript/tests/scripts/analyzer/features/script_typed_assign_null.gd
new file mode 100644
index 0000000000..1b47680a7b
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/script_typed_assign_null.gd
@@ -0,0 +1,18 @@
+extends Node
+
+class LocalClass extends Node:
+ pass
+
+func test():
+ var typed: LocalClass = get_node_or_null("does_not_exist")
+ var untyped = null
+ var node_1: LocalClass = typed
+ var node_2: LocalClass = untyped
+ var node_3 = typed
+ var node_4 = untyped
+ print(typed)
+ print(untyped)
+ print(node_1)
+ print(node_2)
+ print(node_3)
+ print(node_4)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/script_typed_assign_null.out b/modules/gdscript/tests/scripts/analyzer/features/script_typed_assign_null.out
new file mode 100644
index 0000000000..d66b72f5c3
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/script_typed_assign_null.out
@@ -0,0 +1,7 @@
+GDTEST_OK
+<Object#null>
+<null>
+<Object#null>
+<null>
+<Object#null>
+<null>