diff options
21 files changed, 80 insertions, 58 deletions
diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index 04e1561a0c..2da9559873 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -3499,7 +3499,7 @@ bool Variant::identity_compare(const Variant &p_variant) const { switch (type) { case OBJECT: { - return _get_obj().obj == p_variant._get_obj().obj; + return _get_obj().id == p_variant._get_obj().id; } break; case DICTIONARY: { diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index 042ebe368a..8f3ae65b9c 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -543,6 +543,13 @@ struct VariantUtilityFunctions { Variant base = *p_args[0]; Variant ret; for (int i = 1; i < p_argcount; i++) { + Variant::Type arg_type = p_args[i]->get_type(); + if (arg_type != Variant::INT && arg_type != Variant::FLOAT) { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.expected = Variant::FLOAT; + r_error.argument = i; + return Variant(); + } bool valid; Variant::evaluate(Variant::OP_LESS, base, *p_args[i], ret, valid); if (!valid) { @@ -576,6 +583,13 @@ struct VariantUtilityFunctions { Variant base = *p_args[0]; Variant ret; for (int i = 1; i < p_argcount; i++) { + Variant::Type arg_type = p_args[i]->get_type(); + if (arg_type != Variant::INT && arg_type != Variant::FLOAT) { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.expected = Variant::FLOAT; + r_error.argument = i; + return Variant(); + } bool valid; Variant::evaluate(Variant::OP_GREATER, base, *p_args[i], ret, valid); if (!valid) { diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index ed7bdc07fc..3bda3a3896 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -656,7 +656,7 @@ <method name="max" qualifiers="vararg"> <return type="Variant" /> <description> - Returns the maximum of the given values. This function can take any number of arguments. + Returns the maximum of the given numeric values. This function can take any number of arguments. [codeblock] max(1, 7, 3, -6, 5) # Returns 7 [/codeblock] @@ -689,7 +689,7 @@ <method name="min" qualifiers="vararg"> <return type="Variant" /> <description> - Returns the minimum of the given values. This function can take any number of arguments. + Returns the minimum of the given numeric values. This function can take any number of arguments. [codeblock] min(1, 7, 3, -6, 5) # Returns -6 [/codeblock] diff --git a/doc/classes/VisualInstance3D.xml b/doc/classes/VisualInstance3D.xml index 3781045c02..b2bc6709a0 100644 --- a/doc/classes/VisualInstance3D.xml +++ b/doc/classes/VisualInstance3D.xml @@ -62,7 +62,7 @@ For [Light3D]s, this can be used to control which [VisualInstance3D]s are affected by a specific light. For [GPUParticles3D], this can be used to control which particles are effected by a specific attractor. For [Decal]s, this can be used to control which [VisualInstance3D]s are affected by a specific decal. </member> <member name="sorting_offset" type="float" setter="set_sorting_offset" getter="get_sorting_offset" default="0.0"> - The sorting offset used by this [VisualInstance3D]. Adjusting it to a higher value will make the [VisualInstance3D] reliably draw on top of other [VisualInstance3D]s that are otherwise positioned at the same spot. + The amount by which the depth of this [VisualInstance3D] will be adjusted when sorting by depth. Uses the same units as the engine (which are typically meters). Adjusting it to a higher value will make the [VisualInstance3D] reliably draw on top of other [VisualInstance3D]s that are otherwise positioned at the same spot. To ensure it always draws on top of other objects around it (not positioned at the same spot), set the value to be greater than the distance between this [VisualInstance3D] and the other nearby [VisualInstance3D]s. </member> <member name="sorting_use_aabb_center" type="bool" setter="set_sorting_use_aabb_center" getter="is_sorting_use_aabb_center"> If [code]true[/code], the object is sorted based on the [AABB] center. The object will be sorted based on the global position otherwise. diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 0f9ce89f02..75a444c877 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -896,15 +896,16 @@ void CanvasItemEditor::_snap_changed() { } void CanvasItemEditor::_selection_result_pressed(int p_result) { - if (selection_results.size() <= p_result) { + if (selection_results_menu.size() <= p_result) { return; } - CanvasItem *item = selection_results[p_result].item; + CanvasItem *item = selection_results_menu[p_result].item; if (item) { _select_click_on_item(item, Point2(), selection_menu_additive_selection); } + selection_results_menu.clear(); } void CanvasItemEditor::_selection_menu_hide() { @@ -2247,6 +2248,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { selection_menu->set_item_tooltip(i, String(item->get_name()) + "\nType: " + item->get_class() + "\nPath: " + node_path); } + selection_results_menu = selection_results; selection_menu_additive_selection = b->is_shift_pressed(); selection_menu->set_position(viewport->get_screen_transform().xform(b->get_position())); selection_menu->reset_size(); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index ebe87a56f7..c5b9bf9e0b 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -256,6 +256,7 @@ private: } }; Vector<_SelectResult> selection_results; + Vector<_SelectResult> selection_results_menu; struct _HoverResult { Point2 position; diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 96f5aeedf0..6580340af4 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -1543,6 +1543,7 @@ void Node3DEditorViewport::_list_select(Ref<InputEventMouseButton> b) { selection_menu->set_item_tooltip(i, String(spat->get_name()) + "\nType: " + spat->get_class() + "\nPath: " + node_path); } + selection_results_menu = selection_results; selection_menu->set_position(get_screen_position() + b->get_position()); selection_menu->reset_size(); selection_menu->popup(); @@ -3609,15 +3610,17 @@ void Node3DEditorViewport::_toggle_cinema_preview(bool p_activate) { } void Node3DEditorViewport::_selection_result_pressed(int p_result) { - if (selection_results.size() <= p_result) { + if (selection_results_menu.size() <= p_result) { return; } - clicked = selection_results[p_result].item->get_instance_id(); + clicked = selection_results_menu[p_result].item->get_instance_id(); if (clicked.is_valid()) { _select_clicked(spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT); } + + selection_results_menu.clear(); } void Node3DEditorViewport::_selection_menu_hide() { diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index a1fd9757d0..e5267e5fad 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -290,6 +290,7 @@ private: ObjectID clicked; ObjectID material_target; Vector<_RayResult> selection_results; + Vector<_RayResult> selection_results_menu; bool clicked_wants_append = false; bool selection_in_progress = false; diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp index 3dd0c84ee7..73d2da63b7 100644 --- a/editor/plugins/tiles/tile_data_editors.cpp +++ b/editor/plugins/tiles/tile_data_editors.cpp @@ -784,7 +784,7 @@ void GenericTilePolygonEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("remove_polygon", "index"), &GenericTilePolygonEditor::remove_polygon); ClassDB::bind_method(D_METHOD("clear_polygons"), &GenericTilePolygonEditor::clear_polygons); ClassDB::bind_method(D_METHOD("set_polygon", "index", "polygon"), &GenericTilePolygonEditor::set_polygon); - ClassDB::bind_method(D_METHOD("get_polygon", "index"), &GenericTilePolygonEditor::set_polygon); + ClassDB::bind_method(D_METHOD("get_polygon", "index"), &GenericTilePolygonEditor::get_polygon); ADD_SIGNAL(MethodInfo("polygons_changed")); } diff --git a/editor/project_converter_3_to_4.cpp b/editor/project_converter_3_to_4.cpp index 0e7476d045..b7c01c061f 100644 --- a/editor/project_converter_3_to_4.cpp +++ b/editor/project_converter_3_to_4.cpp @@ -78,11 +78,11 @@ public: RegEx reg_image_unlock = RegEx("([a-zA-Z0-9_\\.]+)\\.unlock\\(\\)"); RegEx reg_instantiate = RegEx("\\.instance\\(([^\\)]*)\\)"); // Simple OS properties with getters/setters. - RegEx reg_os_current_screen = RegEx("\\bOS\\.(set_|get_)?current_screen\\b"); - RegEx reg_os_min_window_size = RegEx("\\bOS\\.(set_|get_)?min_window_size\\b"); - RegEx reg_os_max_window_size = RegEx("\\bOS\\.(set_|get_)?max_window_size\\b"); - RegEx reg_os_window_position = RegEx("\\bOS\\.(set_|get_)?window_position\\b"); - RegEx reg_os_window_size = RegEx("\\bOS\\.(set_|get_)?window_size\\b"); + RegEx reg_os_current_screen = RegEx("\\bOS\\.((set_|get_)?)current_screen\\b"); + RegEx reg_os_min_window_size = RegEx("\\bOS\\.((set_|get_)?)min_window_size\\b"); + RegEx reg_os_max_window_size = RegEx("\\bOS\\.((set_|get_)?)max_window_size\\b"); + RegEx reg_os_window_position = RegEx("\\bOS\\.((set_|get_)?)window_position\\b"); + RegEx reg_os_window_size = RegEx("\\bOS\\.((set_|get_)?)window_size\\b"); RegEx reg_os_getset_screen_orient = RegEx("\\bOS\\.(s|g)et_screen_orientation\\b"); // OS property getters/setters for non trivial replacements. RegEx reg_os_set_window_resizable = RegEx(make_regex_gds_os_property_set("set_window_resizable")); @@ -1055,20 +1055,20 @@ bool ProjectConverter3To4::test_array_names() { // List of excluded functions from builtin types and global namespace, because currently it is not possible to get list of functions from them. // This will be available when https://github.com/godotengine/godot/pull/49053 or similar will be included into Godot. - static const char *builtin_types_excluded_functions[] = { "dict_to_inst", "inst_to_dict", "bytes_to_var", "bytes_to_var_with_objects", "db_to_linear", "deg_to_rad", "linear_to_db", "rad_to_deg", "randf_range", "snapped", "str_to_var", "var_to_str", "var_to_bytes", "var_to_bytes_with_objects", "move_toward", "uri_encode", "uri_decode", "remove_at", "get_rotation_quaternion", "clamp", "grow_side", "is_absolute_path", "is_valid_int", "lerp", "to_ascii_buffer", "to_utf8_buffer", "to_utf32_buffer", "snapped", "remap", "rfind", nullptr }; + static const char *builtin_types_excluded_functions[] = { "dict_to_inst", "inst_to_dict", "bytes_to_var", "bytes_to_var_with_objects", "db_to_linear", "deg_to_rad", "linear_to_db", "rad_to_deg", "randf_range", "snapped", "str_to_var", "var_to_str", "var_to_bytes", "var_to_bytes_with_objects", "move_toward", "uri_encode", "uri_decode", "remove_at", "get_rotation_quaternion", "limit_length", "grow_side", "is_absolute_path", "is_valid_int", "lerp", "to_ascii_buffer", "to_utf8_buffer", "to_utf32_buffer", "snapped", "remap", "rfind", nullptr }; for (int current_index = 0; builtin_types_excluded_functions[current_index]; current_index++) { all_functions.insert(builtin_types_excluded_functions[current_index]); } - // for (int type = Variant::Type::NIL + 1; type < Variant::Type::VARIANT_MAX; type++) { - // List<MethodInfo> method_list; - // Variant::get_method_list_by_type(&method_list, Variant::Type(type)); - // for (MethodInfo &function_data : method_list) { - // if (!all_functions.has(function_data.name)) { - // all_functions.insert(function_data.name); - // } - // } - // } + //for (int type = Variant::Type::NIL + 1; type < Variant::Type::VARIANT_MAX; type++) { + // List<MethodInfo> method_list; + // Variant::get_method_list_by_type(&method_list, Variant::Type(type)); + // for (MethodInfo &function_data : method_list) { + // if (!all_functions.has(function_data.name)) { + // all_functions.insert(function_data.name); + // } + // } + //} List<StringName> classes_list; ClassDB::get_class_list(&classes_list); diff --git a/editor/renames_map_3_to_4.cpp b/editor/renames_map_3_to_4.cpp index d7cac9a2b9..1c212642ce 100644 --- a/editor/renames_map_3_to_4.cpp +++ b/editor/renames_map_3_to_4.cpp @@ -577,9 +577,9 @@ const char *RenamesMap3To4::gdscript_function_renames[][2] = { // Builtin types // Remember to add them to the builtin_types_excluded_functions variable, because for now these functions cannot be listed. - // { "empty", "is_empty" }, // Array -- Used as custom rule. Be careful, this will be used everywhere. - // { "remove", "remove_at" }, // Array -- Breaks Directory and several more. - { "clamped", "clamp" }, // Vector2 -- Be careful, this will be used everywhere. + //{ "empty", "is_empty" }, // Array -- Used as custom rule. Be careful, this will be used everywhere. + //{ "remove", "remove_at" }, // Array -- Breaks Directory and several more. + { "clamped", "limit_length" }, // Vector2 { "get_rotation_quat", "get_rotation_quaternion" }, // Basis { "grow_margin", "grow_side" }, // Rect2 { "invert", "reverse" }, // Array -- Give it a check. Be careful, this will be used everywhere. @@ -1024,9 +1024,9 @@ const char *RenamesMap3To4::csharp_function_renames[][2] = { { "GetUniformName", "GetParameterName" }, // ParameterRef // Builtin types - // { "Empty", "IsEmpty" }, // Array -- Used as custom rule. Be careful, this will be used everywhere. - // { "Remove", "RemoveAt" }, // Array -- Breaks Directory and several more. - { "Clamped", "Clamp" }, // Vector2 -- Be careful, this will be used everywhere. + // { "Empty", "IsEmpty" }, // Array -- Used as custom rule. Be careful, this will be used everywhere. + // { "Remove", "RemoveAt" }, // Array -- Breaks Directory and several more. + { "Clamped", "LimitLength" }, // Vector2 { "GetRotationQuat", "GetRotationQuaternion" }, // Basis { "GrowMargin", "GrowSide" }, // Rect2 { "Invert", "Reverse" }, // Array -- Give it a check. Be careful, this will be used everywhere. diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp index 5b092e3691..d6f21d297a 100644 --- a/modules/gdscript/gdscript_byte_codegen.cpp +++ b/modules/gdscript/gdscript_byte_codegen.cpp @@ -1058,7 +1058,7 @@ void GDScriptByteCodeGenerator::write_call_gdscript_utility(const Address &p_tar void GDScriptByteCodeGenerator::write_call_utility(const Address &p_target, const StringName &p_function, const Vector<Address> &p_arguments) { bool is_validated = true; if (Variant::is_utility_function_vararg(p_function)) { - is_validated = true; // Vararg works fine with any argument, since they can be any type. + is_validated = false; // Vararg needs runtime checks, can't use validated call. } else if (p_arguments.size() == Variant::get_utility_function_argument_count(p_function)) { bool all_types_exact = true; for (int i = 0; i < p_arguments.size(); i++) { @@ -1107,7 +1107,7 @@ void GDScriptByteCodeGenerator::write_call_builtin_type(const Address &p_target, // Check if all types are correct. if (Variant::is_builtin_method_vararg(p_type, p_method)) { - is_validated = true; // Vararg works fine with any argument, since they can be any type. + is_validated = false; // Vararg needs runtime checks, can't use validated call. } else if (p_arguments.size() == Variant::get_builtin_method_argument_count(p_type, p_method)) { bool all_types_exact = true; for (int i = 0; i < p_arguments.size(); i++) { diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 7feb19c8ed..e0f0d3ba9d 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -211,10 +211,6 @@ static bool _can_use_ptrcall(const MethodBind *p_method, const Vector<GDScriptCo return true; } -inline static bool is_category_or_group(const PropertyInfo &p_info) { - return p_info.usage & PROPERTY_USAGE_CATEGORY || p_info.usage & PROPERTY_USAGE_GROUP || p_info.usage & PROPERTY_USAGE_SUBGROUP; -} - GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &codegen, Error &r_error, const GDScriptParser::ExpressionNode *p_expression, bool p_root, bool p_initializer, const GDScriptCodeGenerator::Address &p_index_addr) { if (p_expression->is_constant && !(p_expression->get_datatype().is_meta_type && p_expression->get_datatype().kind == GDScriptParser::DataType::CLASS)) { return codegen.add_constant(p_expression->reduced_value); @@ -250,7 +246,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code // Try members. if (!codegen.function_node || !codegen.function_node->is_static) { // Try member variables. - if (codegen.script->member_indices.has(identifier) && !is_category_or_group(codegen.script->member_info[identifier])) { + if (codegen.script->member_indices.has(identifier)) { if (codegen.script->member_indices[identifier].getter != StringName() && codegen.script->member_indices[identifier].getter != codegen.function_name) { // Perform getter. GDScriptCodeGenerator::Address temp = codegen.add_temporary(codegen.script->member_indices[identifier].data_type); diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/lambda_unused_arg.gd b/modules/gdscript/tests/scripts/analyzer/warnings/lambda_unused_arg.gd index 6fc90ea29c..1e5c10b7d5 100644 --- a/modules/gdscript/tests/scripts/analyzer/warnings/lambda_unused_arg.gd +++ b/modules/gdscript/tests/scripts/analyzer/warnings/lambda_unused_arg.gd @@ -1,4 +1,4 @@ func test(): var lambda := func(unused: Variant) -> void: pass - lambda.call() + lambda.call("something") diff --git a/modules/gdscript/tests/scripts/runtime/features/groups_are_not_properties.gd b/modules/gdscript/tests/scripts/runtime/features/groups_are_not_properties.gd deleted file mode 100644 index a5ad7c0b85..0000000000 --- a/modules/gdscript/tests/scripts/runtime/features/groups_are_not_properties.gd +++ /dev/null @@ -1,11 +0,0 @@ -# https://github.com/godotengine/godot/issues/73843 -extends RefCounted - -@export_group("Resource") -@export_category("RefCounted") - -func test(): - var res = Resource.new() - var ref = RefCounted.new() - prints("Resource class not shadowed:", res is Resource) - prints("RefCounted class not shadowed:", ref is RefCounted) diff --git a/modules/gdscript/tests/scripts/runtime/features/groups_are_not_properties.out b/modules/gdscript/tests/scripts/runtime/features/groups_are_not_properties.out deleted file mode 100644 index 182c6dcd3a..0000000000 --- a/modules/gdscript/tests/scripts/runtime/features/groups_are_not_properties.out +++ /dev/null @@ -1,3 +0,0 @@ -GDTEST_OK -Resource class not shadowed: true -RefCounted class not shadowed: true diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index ad6306bb41..cbe5266f7e 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -2831,7 +2831,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() { TypeInterface itype = TypeInterface::create_object_type(type_cname, pascal_to_pascal_case(type_cname), api_type); itype.base_name = ClassDB::get_parent_class(type_cname); - itype.is_singleton = Engine::get_singleton()->has_singleton(itype.proxy_name); + itype.is_singleton = Engine::get_singleton()->has_singleton(type_cname); itype.is_instantiable = class_info->creation_func && !itype.is_singleton; itype.is_ref_counted = ClassDB::is_parent_class(type_cname, name_cache.type_RefCounted); itype.memory_own = itype.is_ref_counted; diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp index b38f7225a2..6c961813b4 100644 --- a/modules/theora/video_stream_theora.cpp +++ b/modules/theora/video_stream_theora.cpp @@ -251,8 +251,12 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) { /* we're expecting more header packets. */ while ((theora_p && theora_p < 3) || (vorbis_p && vorbis_p < 3)) { + int ret = 0; + /* look for further theora headers */ - int ret = ogg_stream_packetout(&to, &op); + if (theora_p && theora_p < 3) { + ret = ogg_stream_packetout(&to, &op); + } while (theora_p && theora_p < 3 && ret) { if (ret < 0) { fprintf(stderr, "Error parsing Theora stream headers; corrupt stream?\n"); @@ -269,7 +273,9 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) { } /* look for more vorbis header packets */ - ret = ogg_stream_packetout(&vo, &op); + if (vorbis_p && vorbis_p < 3) { + ret = ogg_stream_packetout(&vo, &op); + } while (vorbis_p && vorbis_p < 3 && ret) { if (ret < 0) { fprintf(stderr, "Error parsing Vorbis stream headers; corrupt stream?\n"); diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index cf73729c0a..1a6adca121 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -1715,12 +1715,12 @@ void PopupMenu::activate_item(int p_item) { need_hide = false; } - emit_signal(SNAME("id_pressed"), id); - emit_signal(SNAME("index_pressed"), p_item); - if (need_hide) { hide(); } + + emit_signal(SNAME("id_pressed"), id); + emit_signal(SNAME("index_pressed"), p_item); } void PopupMenu::remove_item(int p_idx) { diff --git a/servers/rendering/shader_preprocessor.cpp b/servers/rendering/shader_preprocessor.cpp index b45a7c0db3..ff1d55f905 100644 --- a/servers/rendering/shader_preprocessor.cpp +++ b/servers/rendering/shader_preprocessor.cpp @@ -679,6 +679,11 @@ void ShaderPreprocessor::process_include(Tokenizer *p_tokenizer) { path = state->current_filename.get_base_dir().path_join(path); } + if (!ResourceLoader::exists(path)) { + set_error(RTR("Shader include file does not exist: ") + path, line); + return; + } + Ref<Resource> res = ResourceLoader::load(path); if (res.is_null()) { set_error(RTR("Shader include load failed. Does the shader include exist? Is there a cyclic dependency?"), line); diff --git a/tests/core/variant/test_variant.h b/tests/core/variant/test_variant.h index dfbaa36af8..024fcf53c4 100644 --- a/tests/core/variant/test_variant.h +++ b/tests/core/variant/test_variant.h @@ -1056,6 +1056,14 @@ TEST_CASE("[Variant] Identity comparison") { Variant obj_null_two_var = Variant((Object *)nullptr); CHECK(obj_null_one_var.identity_compare(obj_null_one_var)); CHECK(obj_null_one_var.identity_compare(obj_null_two_var)); + + Object *freed_one = new Object(); + Variant freed_one_var = freed_one; + delete freed_one; + Object *freed_two = new Object(); + Variant freed_two_var = freed_two; + delete freed_two; + CHECK_FALSE(freed_one_var.identity_compare(freed_two_var)); } TEST_CASE("[Variant] Nested array comparison") { |