Repository: godotengine/godot
File: modules/gdscript/gdscript_vm.cpp (C++)

Code before:
				if (GDScriptLanguage::get_singleton()->profiling) {
					call_time = OS::get_singleton()->get_ticks_usec();
				}

#endif
				Callable::CallError err;
				if (call_ret) {
					GET_INSTRUCTION_ARG(ret, argc + 1);
#ifdef DEBUG_ENABLED
					Variant::Type base_type = base->get_type();
					Object *base_obj = base->get_validated_object();
					StringName base_class = base_obj ? base_obj->get_class_name() : StringName();
#endif
					base->callp(*methodname, (const Variant **)argptrs, argc, *ret, err);
#ifdef DEBUG_ENABLED
					if (ret->get_type() == Variant::NIL) {
						if (base_type == Variant::OBJECT) {
							if (base_obj) {
								MethodBind *method = ClassDB::get_method(base_class, *methodname);
								if (*methodname == CoreStringNames::get_singleton()->_free || (method && !method->has_return())) {
									err_text = R"(Trying to get a return value of a method that returns "void")";
									OPCODE_BREAK;
								}
							}
						} else if (Variant::has_builtin_method(base_type, *methodname) && !Variant::has_builtin_method_return_value(base_type, *methodname)) {
							err_text = R"(Trying to get a return value of a method that returns "void")";
							OPCODE_BREAK;
						}
					}

					if (!call_async && ret->get_type() == Variant::OBJECT) {
						// Check if getting a function state without await.
						bool was_freed = false;
						Object *obj = ret->get_validated_object_with_check(was_freed);

						if (obj && obj->is_class_ptr(GDScriptFunctionState::get_class_ptr_static())) {
							err_text = R"(Trying to call an async function without "await".)";
							OPCODE_BREAK;
						}
					}
#endif
				} else {
					Variant ret;
					base->callp(*methodname, (const Variant **)argptrs, argc, ret, err);
				}
#ifdef DEBUG_ENABLED
				if (GDScriptLanguage::get_singleton()->profiling) {
					function_call_time += OS::get_singleton()->get_ticks_usec() - call_time;
				}

				if (err.error != Callable::CallError::CALL_OK) {

Review comment (suggestion):
I don't see why this would be the case. They should still have a base Object which will always have a class name (unless they are freed or it's `null`). The only exception are calls on built-in types (Vector2, String, etc.) which don't have a base Object.

Code after:
#ifdef DEBUG_ENABLED
				bool call_async = (_code_ptr[ip]) == OPCODE_CALL_ASYNC;
#endif
				LOAD_INSTRUCTION_ARGS
				CHECK_SPACE(3 + instr_arg_count);

				ip += instr_arg_count;

				int argc = _code_ptr[ip + 1];
				GD_ERR_BREAK(argc < 0);

				int methodname_idx = _code_ptr[ip + 2];
				GD_ERR_BREAK(methodname_idx < 0 || methodname_idx >= _global_names_count);
				const StringName *methodname = &_global_names_ptr[methodname_idx];

				GET_INSTRUCTION_ARG(base, argc);
				Variant **argptrs = instruction_args;

#ifdef DEBUG_ENABLED
				uint64_t call_time = 0;

				if (GDScriptLanguage::get_singleton()->profiling) {
					call_time = OS::get_singleton()->get_ticks_usec();
				}
				Variant::Type base_type = base->get_type();
				Object *base_obj = base->get_validated_object();
				StringName base_class = base_obj ? base_obj->get_class_name() : StringName();
#endif

				Callable::CallError err;
				if (call_ret) {
					GET_INSTRUCTION_ARG(ret, argc + 1);
					base->callp(*methodname, (const Variant **)argptrs, argc, *ret, err);
#ifdef DEBUG_ENABLED
					if (ret->get_type() == Variant::NIL) {
						if (base_type == Variant::OBJECT) {
							if (base_obj) {
								MethodBind *method = ClassDB::get_method(base_class, *methodname);
								if (*methodname == CoreStringNames::get_singleton()->_free || (method && !method->has_return())) {
									err_text = R"(Trying to get a return value of a method that returns "void")";
									OPCODE_BREAK;
								}
							}
						} else if (Variant::has_builtin_method(base_type, *methodname) && !Variant::has_builtin_method_return_value(base_type, *methodname)) {
							err_text = R"(Trying to get a return value of a method that returns "void")";
							OPCODE_BREAK;
						}
					}

					if (!call_async && ret->get_type() == Variant::OBJECT) {
						// Check if getting a function state without await.