ソースを参照

[Core] Improve error messages with `vformat`

A Thousand Ships 9 ヶ月 前
コミット
38f9769bc6
49 ファイル変更292 行追加292 行削除
  1. 21 21
      core/config/project_settings.cpp
  2. 13 13
      core/core_bind.cpp
  3. 1 1
      core/crypto/crypto.cpp
  4. 2 2
      core/crypto/crypto_core.cpp
  5. 9 9
      core/debugger/engine_debugger.cpp
  6. 2 2
      core/debugger/remote_debugger.cpp
  7. 1 1
      core/debugger/remote_debugger_peer.cpp
  8. 2 2
      core/extension/extension_api_dump.cpp
  9. 15 15
      core/extension/gdextension.cpp
  10. 1 1
      core/extension/gdextension_interface.cpp
  11. 5 5
      core/extension/gdextension_library_loader.cpp
  12. 1 1
      core/extension/gdextension_manager.cpp
  13. 1 1
      core/input/input_map.cpp
  14. 8 8
      core/io/dir_access.cpp
  15. 2 2
      core/io/dir_access.h
  16. 10 10
      core/io/file_access.cpp
  17. 1 1
      core/io/file_access_compressed.cpp
  18. 1 1
      core/io/file_access_encrypted.cpp
  19. 1 1
      core/io/file_access_memory.cpp
  20. 5 5
      core/io/file_access_pack.cpp
  21. 2 2
      core/io/file_access_zip.cpp
  22. 2 2
      core/io/http_client.cpp
  23. 26 26
      core/io/image.cpp
  24. 2 2
      core/io/image_loader.cpp
  25. 2 2
      core/io/ip.cpp
  26. 1 1
      core/io/json.cpp
  27. 4 4
      core/io/marshalls.cpp
  28. 1 1
      core/io/pck_packer.cpp
  29. 1 1
      core/io/plist.cpp
  30. 7 7
      core/io/remote_filesystem_client.cpp
  31. 1 1
      core/io/resource.cpp
  32. 28 28
      core/io/resource_format_binary.cpp
  33. 2 2
      core/io/resource_importer.cpp
  34. 3 3
      core/io/resource_loader.cpp
  35. 1 1
      core/io/resource_saver.cpp
  36. 15 15
      core/io/translation_loader_po.cpp
  37. 2 2
      core/io/xml_parser.cpp
  38. 1 1
      core/math/expression.cpp
  39. 44 44
      core/object/class_db.cpp
  40. 20 20
      core/object/object.cpp
  41. 3 3
      core/object/script_language.cpp
  42. 1 1
      core/object/undo_redo.cpp
  43. 1 1
      core/os/os.cpp
  44. 1 1
      core/string/node_path.cpp
  45. 5 5
      core/string/translation_po.cpp
  46. 7 7
      core/variant/array.cpp
  47. 5 5
      core/variant/container_type_validate.h
  48. 1 1
      core/variant/variant_construct.cpp
  49. 1 1
      core/variant/variant_utility.cpp

+ 21 - 21
core/config/project_settings.cpp

@@ -214,36 +214,36 @@ String ProjectSettings::localize_path(const String &p_path) const {
 }
 }
 
 
 void ProjectSettings::set_initial_value(const String &p_name, const Variant &p_value) {
 void ProjectSettings::set_initial_value(const String &p_name, const Variant &p_value) {
-	ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + ".");
+	ERR_FAIL_COND_MSG(!props.has(p_name), vformat("Request for nonexistent project setting: '%s'.", p_name));
 
 
 	// Duplicate so that if value is array or dictionary, changing the setting will not change the stored initial value.
 	// Duplicate so that if value is array or dictionary, changing the setting will not change the stored initial value.
 	props[p_name].initial = p_value.duplicate();
 	props[p_name].initial = p_value.duplicate();
 }
 }
 
 
 void ProjectSettings::set_restart_if_changed(const String &p_name, bool p_restart) {
 void ProjectSettings::set_restart_if_changed(const String &p_name, bool p_restart) {
-	ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + ".");
+	ERR_FAIL_COND_MSG(!props.has(p_name), vformat("Request for nonexistent project setting: '%s'.", p_name));
 	props[p_name].restart_if_changed = p_restart;
 	props[p_name].restart_if_changed = p_restart;
 }
 }
 
 
 void ProjectSettings::set_as_basic(const String &p_name, bool p_basic) {
 void ProjectSettings::set_as_basic(const String &p_name, bool p_basic) {
-	ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + ".");
+	ERR_FAIL_COND_MSG(!props.has(p_name), vformat("Request for nonexistent project setting: '%s'.", p_name));
 	props[p_name].basic = p_basic;
 	props[p_name].basic = p_basic;
 }
 }
 
 
 void ProjectSettings::set_as_internal(const String &p_name, bool p_internal) {
 void ProjectSettings::set_as_internal(const String &p_name, bool p_internal) {
-	ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + ".");
+	ERR_FAIL_COND_MSG(!props.has(p_name), vformat("Request for nonexistent project setting: '%s'.", p_name));
 	props[p_name].internal = p_internal;
 	props[p_name].internal = p_internal;
 }
 }
 
 
 void ProjectSettings::set_ignore_value_in_docs(const String &p_name, bool p_ignore) {
 void ProjectSettings::set_ignore_value_in_docs(const String &p_name, bool p_ignore) {
-	ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + ".");
+	ERR_FAIL_COND_MSG(!props.has(p_name), vformat("Request for nonexistent project setting: '%s'.", p_name));
 #ifdef DEBUG_METHODS_ENABLED
 #ifdef DEBUG_METHODS_ENABLED
 	props[p_name].ignore_value_in_docs = p_ignore;
 	props[p_name].ignore_value_in_docs = p_ignore;
 #endif
 #endif
 }
 }
 
 
 bool ProjectSettings::get_ignore_value_in_docs(const String &p_name) const {
 bool ProjectSettings::get_ignore_value_in_docs(const String &p_name) const {
-	ERR_FAIL_COND_V_MSG(!props.has(p_name), false, "Request for nonexistent project setting: " + p_name + ".");
+	ERR_FAIL_COND_V_MSG(!props.has(p_name), false, vformat("Request for nonexistent project setting: '%s'.", p_name));
 #ifdef DEBUG_METHODS_ENABLED
 #ifdef DEBUG_METHODS_ENABLED
 	return props[p_name].ignore_value_in_docs;
 	return props[p_name].ignore_value_in_docs;
 #else
 #else
@@ -371,7 +371,7 @@ Variant ProjectSettings::get_setting_with_override(const StringName &p_name) con
 	}
 	}
 
 
 	if (!props.has(name)) {
 	if (!props.has(name)) {
-		WARN_PRINT("Property not found: " + String(name));
+		WARN_PRINT(vformat("Property not found: '%s'.", String(name)));
 		return Variant();
 		return Variant();
 	}
 	}
 	return props[name].variant;
 	return props[name].variant;
@@ -565,7 +565,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
 
 
 	if (!p_main_pack.is_empty()) {
 	if (!p_main_pack.is_empty()) {
 		bool ok = _load_resource_pack(p_main_pack);
 		bool ok = _load_resource_pack(p_main_pack);
-		ERR_FAIL_COND_V_MSG(!ok, ERR_CANT_OPEN, "Cannot open resource pack '" + p_main_pack + "'.");
+		ERR_FAIL_COND_V_MSG(!ok, ERR_CANT_OPEN, vformat("Cannot open resource pack '%s'.", p_main_pack));
 
 
 		Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
 		Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
 		if (err == OK && !p_ignore_override) {
 		if (err == OK && !p_ignore_override) {
@@ -644,7 +644,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
 	// or, if requested (`p_upwards`) in parent directories.
 	// or, if requested (`p_upwards`) in parent directories.
 
 
 	Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 	Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
-	ERR_FAIL_COND_V_MSG(d.is_null(), ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_path + "'.");
+	ERR_FAIL_COND_V_MSG(d.is_null(), ERR_CANT_CREATE, vformat("Cannot create DirAccess for path '%s'.", p_path));
 	d->change_dir(p_path);
 	d->change_dir(p_path);
 
 
 	String current_dir = d->get_current_dir();
 	String current_dir = d->get_current_dir();
@@ -748,7 +748,7 @@ Error ProjectSettings::_load_settings_binary(const String &p_path) {
 		f->get_buffer(d.ptrw(), vlen);
 		f->get_buffer(d.ptrw(), vlen);
 		Variant value;
 		Variant value;
 		err = decode_variant(value, d.ptr(), d.size(), nullptr, true);
 		err = decode_variant(value, d.ptr(), d.size(), nullptr, true);
-		ERR_CONTINUE_MSG(err != OK, "Error decoding property: " + key + ".");
+		ERR_CONTINUE_MSG(err != OK, vformat("Error decoding property: '%s'.", key));
 		set(key, value);
 		set(key, value);
 	}
 	}
 
 
@@ -790,7 +790,7 @@ Error ProjectSettings::_load_settings_text(const String &p_path) {
 			last_save_time = FileAccess::get_modified_time(get_resource_path().path_join("project.godot"));
 			last_save_time = FileAccess::get_modified_time(get_resource_path().path_join("project.godot"));
 			return OK;
 			return OK;
 		}
 		}
-		ERR_FAIL_COND_V_MSG(err != OK, err, "Error parsing " + p_path + " at line " + itos(lines) + ": " + error_text + " File might be corrupted.");
+		ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Error parsing '%s' at line %d: %s File might be corrupted.", p_path, lines, error_text));
 
 
 		if (!assign.is_empty()) {
 		if (!assign.is_empty()) {
 			if (section.is_empty() && assign == "config_version") {
 			if (section.is_empty() && assign == "config_version") {
@@ -816,7 +816,7 @@ Error ProjectSettings::_load_settings_text_or_binary(const String &p_text_path,
 		return OK;
 		return OK;
 	} else if (err != ERR_FILE_NOT_FOUND) {
 	} else if (err != ERR_FILE_NOT_FOUND) {
 		// If the file exists but can't be loaded, we want to know it.
 		// If the file exists but can't be loaded, we want to know it.
-		ERR_PRINT("Couldn't load file '" + p_bin_path + "', error code " + itos(err) + ".");
+		ERR_PRINT(vformat("Couldn't load file '%s', error code %d.", p_bin_path, err));
 	}
 	}
 
 
 	// Fallback to text-based project.godot file if binary was not found.
 	// Fallback to text-based project.godot file if binary was not found.
@@ -824,7 +824,7 @@ Error ProjectSettings::_load_settings_text_or_binary(const String &p_text_path,
 	if (err == OK) {
 	if (err == OK) {
 		return OK;
 		return OK;
 	} else if (err != ERR_FILE_NOT_FOUND) {
 	} else if (err != ERR_FILE_NOT_FOUND) {
-		ERR_PRINT("Couldn't load file '" + p_text_path + "', error code " + itos(err) + ".");
+		ERR_PRINT(vformat("Couldn't load file '%s', error code %d.", p_text_path, err));
 	}
 	}
 
 
 	return err;
 	return err;
@@ -838,17 +838,17 @@ Error ProjectSettings::load_custom(const String &p_path) {
 }
 }
 
 
 int ProjectSettings::get_order(const String &p_name) const {
 int ProjectSettings::get_order(const String &p_name) const {
-	ERR_FAIL_COND_V_MSG(!props.has(p_name), -1, "Request for nonexistent project setting: " + p_name + ".");
+	ERR_FAIL_COND_V_MSG(!props.has(p_name), -1, vformat("Request for nonexistent project setting: '%s'.", p_name));
 	return props[p_name].order;
 	return props[p_name].order;
 }
 }
 
 
 void ProjectSettings::set_order(const String &p_name, int p_order) {
 void ProjectSettings::set_order(const String &p_name, int p_order) {
-	ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + ".");
+	ERR_FAIL_COND_MSG(!props.has(p_name), vformat("Request for nonexistent project setting: '%s'.", p_name));
 	props[p_name].order = p_order;
 	props[p_name].order = p_order;
 }
 }
 
 
 void ProjectSettings::set_builtin_order(const String &p_name) {
 void ProjectSettings::set_builtin_order(const String &p_name) {
-	ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + ".");
+	ERR_FAIL_COND_MSG(!props.has(p_name), vformat("Request for nonexistent project setting: '%s'.", p_name));
 	if (props[p_name].order >= NO_BUILTIN_ORDER_BASE) {
 	if (props[p_name].order >= NO_BUILTIN_ORDER_BASE) {
 		props[p_name].order = last_builtin_order++;
 		props[p_name].order = last_builtin_order++;
 	}
 	}
@@ -856,12 +856,12 @@ void ProjectSettings::set_builtin_order(const String &p_name) {
 
 
 bool ProjectSettings::is_builtin_setting(const String &p_name) const {
 bool ProjectSettings::is_builtin_setting(const String &p_name) const {
 	// Return true because a false negative is worse than a false positive.
 	// Return true because a false negative is worse than a false positive.
-	ERR_FAIL_COND_V_MSG(!props.has(p_name), true, "Request for nonexistent project setting: " + p_name + ".");
+	ERR_FAIL_COND_V_MSG(!props.has(p_name), true, vformat("Request for nonexistent project setting: '%s'.", p_name));
 	return props[p_name].order < NO_BUILTIN_ORDER_BASE;
 	return props[p_name].order < NO_BUILTIN_ORDER_BASE;
 }
 }
 
 
 void ProjectSettings::clear(const String &p_name) {
 void ProjectSettings::clear(const String &p_name) {
-	ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + ".");
+	ERR_FAIL_COND_MSG(!props.has(p_name), vformat("Request for nonexistent project setting: '%s'.", p_name));
 	props.erase(p_name);
 	props.erase(p_name);
 }
 }
 
 
@@ -876,7 +876,7 @@ Error ProjectSettings::save() {
 Error ProjectSettings::_save_settings_binary(const String &p_file, const RBMap<String, List<String>> &p_props, const CustomMap &p_custom, const String &p_custom_features) {
 Error ProjectSettings::_save_settings_binary(const String &p_file, const RBMap<String, List<String>> &p_props, const CustomMap &p_custom, const String &p_custom_features) {
 	Error err;
 	Error err;
 	Ref<FileAccess> file = FileAccess::open(p_file, FileAccess::WRITE, &err);
 	Ref<FileAccess> file = FileAccess::open(p_file, FileAccess::WRITE, &err);
-	ERR_FAIL_COND_V_MSG(err != OK, err, "Couldn't save project.binary at " + p_file + ".");
+	ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Couldn't save project.binary at '%s'.", p_file));
 
 
 	uint8_t hdr[4] = { 'E', 'C', 'F', 'G' };
 	uint8_t hdr[4] = { 'E', 'C', 'F', 'G' };
 	file->store_buffer(hdr, 4);
 	file->store_buffer(hdr, 4);
@@ -946,7 +946,7 @@ Error ProjectSettings::_save_settings_text(const String &p_file, const RBMap<Str
 	Error err;
 	Error err;
 	Ref<FileAccess> file = FileAccess::open(p_file, FileAccess::WRITE, &err);
 	Ref<FileAccess> file = FileAccess::open(p_file, FileAccess::WRITE, &err);
 
 
-	ERR_FAIL_COND_V_MSG(err != OK, err, "Couldn't save project.godot - " + p_file + ".");
+	ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Couldn't save project.godot - %s.", p_file));
 
 
 	file->store_line("; Engine configuration file.");
 	file->store_line("; Engine configuration file.");
 	file->store_line("; It's best edited using the editor UI and not directly,");
 	file->store_line("; It's best edited using the editor UI and not directly,");
@@ -1119,7 +1119,7 @@ Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_cust
 	} else if (p_path.ends_with(".binary")) {
 	} else if (p_path.ends_with(".binary")) {
 		return _save_settings_binary(p_path, save_props, p_custom, save_features);
 		return _save_settings_binary(p_path, save_props, p_custom, save_features);
 	} else {
 	} else {
-		ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, "Unknown config file format: " + p_path);
+		ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, vformat("Unknown config file format: '%s'.", p_path));
 	}
 	}
 }
 }
 
 

+ 13 - 13
core/core_bind.cpp

@@ -75,7 +75,7 @@ Ref<Resource> ResourceLoader::load(const String &p_path, const String &p_type_hi
 	Error err = OK;
 	Error err = OK;
 	Ref<Resource> ret = ::ResourceLoader::load(p_path, p_type_hint, ResourceFormatLoader::CacheMode(p_cache_mode), &err);
 	Ref<Resource> ret = ::ResourceLoader::load(p_path, p_type_hint, ResourceFormatLoader::CacheMode(p_cache_mode), &err);
 
 
-	ERR_FAIL_COND_V_MSG(err != OK, ret, "Error loading resource: '" + p_path + "'.");
+	ERR_FAIL_COND_V_MSG(err != OK, ret, vformat("Error loading resource: '%s'.", p_path));
 	return ret;
 	return ret;
 }
 }
 
 
@@ -1315,7 +1315,7 @@ void Thread::_start_func(void *ud) {
 	}
 	}
 
 
 	if (ce.error != Callable::CallError::CALL_OK) {
 	if (ce.error != Callable::CallError::CALL_OK) {
-		ERR_FAIL_MSG("Could not call function '" + func_name + "' to start thread " + t->get_id() + ": " + Variant::get_callable_error_text(t->target_callable, nullptr, 0, ce) + ".");
+		ERR_FAIL_MSG(vformat("Could not call function '%s' to start thread %d: %s.", func_name, t->get_id(), Variant::get_callable_error_text(t->target_callable, nullptr, 0, ce)));
 	}
 	}
 }
 }
 
 
@@ -1814,8 +1814,8 @@ Object *Engine::get_singleton_object(const StringName &p_name) const {
 }
 }
 
 
 void Engine::register_singleton(const StringName &p_name, Object *p_object) {
 void Engine::register_singleton(const StringName &p_name, Object *p_object) {
-	ERR_FAIL_COND_MSG(has_singleton(p_name), "Singleton already registered: " + String(p_name));
-	ERR_FAIL_COND_MSG(!String(p_name).is_valid_ascii_identifier(), "Singleton name is not a valid identifier: " + p_name);
+	ERR_FAIL_COND_MSG(has_singleton(p_name), vformat("Singleton already registered: '%s'.", String(p_name)));
+	ERR_FAIL_COND_MSG(!String(p_name).is_valid_ascii_identifier(), vformat("Singleton name is not a valid identifier: '%s'.", p_name));
 	::Engine::Singleton s;
 	::Engine::Singleton s;
 	s.class_name = p_name;
 	s.class_name = p_name;
 	s.name = p_name;
 	s.name = p_name;
@@ -1825,8 +1825,8 @@ void Engine::register_singleton(const StringName &p_name, Object *p_object) {
 }
 }
 
 
 void Engine::unregister_singleton(const StringName &p_name) {
 void Engine::unregister_singleton(const StringName &p_name) {
-	ERR_FAIL_COND_MSG(!has_singleton(p_name), "Attempt to remove unregistered singleton: " + String(p_name));
-	ERR_FAIL_COND_MSG(!::Engine::get_singleton()->is_singleton_user_created(p_name), "Attempt to remove non-user created singleton: " + String(p_name));
+	ERR_FAIL_COND_MSG(!has_singleton(p_name), vformat("Attempt to remove unregistered singleton: '%s'.", String(p_name)));
+	ERR_FAIL_COND_MSG(!::Engine::get_singleton()->is_singleton_user_created(p_name), vformat("Attempt to remove non-user created singleton: '%s'.", String(p_name)));
 	::Engine::get_singleton()->remove_singleton(p_name);
 	::Engine::get_singleton()->remove_singleton(p_name);
 }
 }
 
 
@@ -1970,14 +1970,14 @@ bool EngineDebugger::is_active() {
 void EngineDebugger::register_profiler(const StringName &p_name, Ref<EngineProfiler> p_profiler) {
 void EngineDebugger::register_profiler(const StringName &p_name, Ref<EngineProfiler> p_profiler) {
 	ERR_FAIL_COND(p_profiler.is_null());
 	ERR_FAIL_COND(p_profiler.is_null());
 	ERR_FAIL_COND_MSG(p_profiler->is_bound(), "Profiler already registered.");
 	ERR_FAIL_COND_MSG(p_profiler->is_bound(), "Profiler already registered.");
-	ERR_FAIL_COND_MSG(profilers.has(p_name) || has_profiler(p_name), "Profiler name already in use: " + p_name);
+	ERR_FAIL_COND_MSG(profilers.has(p_name) || has_profiler(p_name), vformat("Profiler name already in use: '%s'.", p_name));
 	Error err = p_profiler->bind(p_name);
 	Error err = p_profiler->bind(p_name);
-	ERR_FAIL_COND_MSG(err != OK, "Profiler failed to register with error: " + itos(err));
+	ERR_FAIL_COND_MSG(err != OK, vformat("Profiler failed to register with error: %d.", err));
 	profilers.insert(p_name, p_profiler);
 	profilers.insert(p_name, p_profiler);
 }
 }
 
 
 void EngineDebugger::unregister_profiler(const StringName &p_name) {
 void EngineDebugger::unregister_profiler(const StringName &p_name) {
-	ERR_FAIL_COND_MSG(!profilers.has(p_name), "Profiler not registered: " + p_name);
+	ERR_FAIL_COND_MSG(!profilers.has(p_name), vformat("Profiler not registered: '%s'.", p_name));
 	profilers[p_name]->unbind();
 	profilers[p_name]->unbind();
 	profilers.erase(p_name);
 	profilers.erase(p_name);
 }
 }
@@ -2001,7 +2001,7 @@ void EngineDebugger::profiler_enable(const StringName &p_name, bool p_enabled, c
 }
 }
 
 
 void EngineDebugger::register_message_capture(const StringName &p_name, const Callable &p_callable) {
 void EngineDebugger::register_message_capture(const StringName &p_name, const Callable &p_callable) {
-	ERR_FAIL_COND_MSG(captures.has(p_name) || has_capture(p_name), "Capture already registered: " + p_name);
+	ERR_FAIL_COND_MSG(captures.has(p_name) || has_capture(p_name), vformat("Capture already registered: '%s'.", p_name));
 	captures.insert(p_name, p_callable);
 	captures.insert(p_name, p_callable);
 	Callable &c = captures[p_name];
 	Callable &c = captures[p_name];
 	::EngineDebugger::Capture capture(&c, &EngineDebugger::call_capture);
 	::EngineDebugger::Capture capture(&c, &EngineDebugger::call_capture);
@@ -2009,7 +2009,7 @@ void EngineDebugger::register_message_capture(const StringName &p_name, const Ca
 }
 }
 
 
 void EngineDebugger::unregister_message_capture(const StringName &p_name) {
 void EngineDebugger::unregister_message_capture(const StringName &p_name) {
-	ERR_FAIL_COND_MSG(!captures.has(p_name), "Capture not registered: " + p_name);
+	ERR_FAIL_COND_MSG(!captures.has(p_name), vformat("Capture not registered: '%s'.", p_name));
 	::EngineDebugger::unregister_message_capture(p_name);
 	::EngineDebugger::unregister_message_capture(p_name);
 	captures.erase(p_name);
 	captures.erase(p_name);
 }
 }
@@ -2043,8 +2043,8 @@ Error EngineDebugger::call_capture(void *p_user, const String &p_cmd, const Arra
 	Variant retval;
 	Variant retval;
 	Callable::CallError err;
 	Callable::CallError err;
 	capture.callp(args, 2, retval, err);
 	capture.callp(args, 2, retval, err);
-	ERR_FAIL_COND_V_MSG(err.error != Callable::CallError::CALL_OK, FAILED, "Error calling 'capture' to callable: " + Variant::get_callable_error_text(capture, args, 2, err));
-	ERR_FAIL_COND_V_MSG(retval.get_type() != Variant::BOOL, FAILED, "Error calling 'capture' to callable: " + String(capture) + ". Return type is not bool.");
+	ERR_FAIL_COND_V_MSG(err.error != Callable::CallError::CALL_OK, FAILED, vformat("Error calling 'capture' to callable: %s.", Variant::get_callable_error_text(capture, args, 2, err)));
+	ERR_FAIL_COND_V_MSG(retval.get_type() != Variant::BOOL, FAILED, vformat("Error calling 'capture' to callable: '%s'. Return type is not bool.", String(capture)));
 	r_captured = retval;
 	r_captured = retval;
 	return OK;
 	return OK;
 }
 }

+ 1 - 1
core/crypto/crypto.cpp

@@ -240,7 +240,7 @@ Error ResourceFormatSaverCrypto::save(const Ref<Resource> &p_resource, const Str
 	} else {
 	} else {
 		ERR_FAIL_V(ERR_INVALID_PARAMETER);
 		ERR_FAIL_V(ERR_INVALID_PARAMETER);
 	}
 	}
-	ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save Crypto resource to file '" + p_path + "'.");
+	ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Cannot save Crypto resource to file '%s'.", p_path));
 	return OK;
 	return OK;
 }
 }
 
 

+ 2 - 2
core/crypto/crypto_core.cpp

@@ -70,7 +70,7 @@ int CryptoCore::RandomGenerator::_entropy_poll(void *p_data, unsigned char *r_bu
 Error CryptoCore::RandomGenerator::init() {
 Error CryptoCore::RandomGenerator::init() {
 	int ret = mbedtls_ctr_drbg_seed((mbedtls_ctr_drbg_context *)ctx, mbedtls_entropy_func, (mbedtls_entropy_context *)entropy, nullptr, 0);
 	int ret = mbedtls_ctr_drbg_seed((mbedtls_ctr_drbg_context *)ctx, mbedtls_entropy_func, (mbedtls_entropy_context *)entropy, nullptr, 0);
 	if (ret) {
 	if (ret) {
-		ERR_FAIL_COND_V_MSG(ret, FAILED, " failed\n  ! mbedtls_ctr_drbg_seed returned an error" + itos(ret));
+		ERR_FAIL_COND_V_MSG(ret, FAILED, vformat(" failed\n  ! mbedtls_ctr_drbg_seed returned an error %d.", ret));
 	}
 	}
 	return OK;
 	return OK;
 }
 }
@@ -78,7 +78,7 @@ Error CryptoCore::RandomGenerator::init() {
 Error CryptoCore::RandomGenerator::get_random_bytes(uint8_t *r_buffer, size_t p_bytes) {
 Error CryptoCore::RandomGenerator::get_random_bytes(uint8_t *r_buffer, size_t p_bytes) {
 	ERR_FAIL_NULL_V(ctx, ERR_UNCONFIGURED);
 	ERR_FAIL_NULL_V(ctx, ERR_UNCONFIGURED);
 	int ret = mbedtls_ctr_drbg_random((mbedtls_ctr_drbg_context *)ctx, r_buffer, p_bytes);
 	int ret = mbedtls_ctr_drbg_random((mbedtls_ctr_drbg_context *)ctx, r_buffer, p_bytes);
-	ERR_FAIL_COND_V_MSG(ret, FAILED, " failed\n  ! mbedtls_ctr_drbg_seed returned an error" + itos(ret));
+	ERR_FAIL_COND_V_MSG(ret, FAILED, vformat(" failed\n  ! mbedtls_ctr_drbg_seed returned an error %d.", ret));
 	return OK;
 	return OK;
 }
 }
 
 

+ 9 - 9
core/debugger/engine_debugger.cpp

@@ -46,12 +46,12 @@ HashMap<String, EngineDebugger::CreatePeerFunc> EngineDebugger::protocols;
 void (*EngineDebugger::allow_focus_steal_fn)();
 void (*EngineDebugger::allow_focus_steal_fn)();
 
 
 void EngineDebugger::register_profiler(const StringName &p_name, const Profiler &p_func) {
 void EngineDebugger::register_profiler(const StringName &p_name, const Profiler &p_func) {
-	ERR_FAIL_COND_MSG(profilers.has(p_name), "Profiler already registered: " + p_name);
+	ERR_FAIL_COND_MSG(profilers.has(p_name), vformat("Profiler already registered: '%s'.", p_name));
 	profilers.insert(p_name, p_func);
 	profilers.insert(p_name, p_func);
 }
 }
 
 
 void EngineDebugger::unregister_profiler(const StringName &p_name) {
 void EngineDebugger::unregister_profiler(const StringName &p_name) {
-	ERR_FAIL_COND_MSG(!profilers.has(p_name), "Profiler not registered: " + p_name);
+	ERR_FAIL_COND_MSG(!profilers.has(p_name), vformat("Profiler not registered: '%s'.", p_name));
 	Profiler &p = profilers[p_name];
 	Profiler &p = profilers[p_name];
 	if (p.active && p.toggle) {
 	if (p.active && p.toggle) {
 		p.toggle(p.data, false, Array());
 		p.toggle(p.data, false, Array());
@@ -61,22 +61,22 @@ void EngineDebugger::unregister_profiler(const StringName &p_name) {
 }
 }
 
 
 void EngineDebugger::register_message_capture(const StringName &p_name, Capture p_func) {
 void EngineDebugger::register_message_capture(const StringName &p_name, Capture p_func) {
-	ERR_FAIL_COND_MSG(captures.has(p_name), "Capture already registered: " + p_name);
+	ERR_FAIL_COND_MSG(captures.has(p_name), vformat("Capture already registered: '%s'.", p_name));
 	captures.insert(p_name, p_func);
 	captures.insert(p_name, p_func);
 }
 }
 
 
 void EngineDebugger::unregister_message_capture(const StringName &p_name) {
 void EngineDebugger::unregister_message_capture(const StringName &p_name) {
-	ERR_FAIL_COND_MSG(!captures.has(p_name), "Capture not registered: " + p_name);
+	ERR_FAIL_COND_MSG(!captures.has(p_name), vformat("Capture not registered: '%s'.", p_name));
 	captures.erase(p_name);
 	captures.erase(p_name);
 }
 }
 
 
 void EngineDebugger::register_uri_handler(const String &p_protocol, CreatePeerFunc p_func) {
 void EngineDebugger::register_uri_handler(const String &p_protocol, CreatePeerFunc p_func) {
-	ERR_FAIL_COND_MSG(protocols.has(p_protocol), "Protocol handler already registered: " + p_protocol);
+	ERR_FAIL_COND_MSG(protocols.has(p_protocol), vformat("Protocol handler already registered: '%s'.", p_protocol));
 	protocols.insert(p_protocol, p_func);
 	protocols.insert(p_protocol, p_func);
 }
 }
 
 
 void EngineDebugger::profiler_enable(const StringName &p_name, bool p_enabled, const Array &p_opts) {
 void EngineDebugger::profiler_enable(const StringName &p_name, bool p_enabled, const Array &p_opts) {
-	ERR_FAIL_COND_MSG(!profilers.has(p_name), "Can't change profiler state, no profiler: " + p_name);
+	ERR_FAIL_COND_MSG(!profilers.has(p_name), vformat("Can't change profiler state, no profiler: '%s'.", p_name));
 	Profiler &p = profilers[p_name];
 	Profiler &p = profilers[p_name];
 	if (p.toggle) {
 	if (p.toggle) {
 		p.toggle(p.data, p_enabled, p_opts);
 		p.toggle(p.data, p_enabled, p_opts);
@@ -85,7 +85,7 @@ void EngineDebugger::profiler_enable(const StringName &p_name, bool p_enabled, c
 }
 }
 
 
 void EngineDebugger::profiler_add_frame_data(const StringName &p_name, const Array &p_data) {
 void EngineDebugger::profiler_add_frame_data(const StringName &p_name, const Array &p_data) {
-	ERR_FAIL_COND_MSG(!profilers.has(p_name), "Can't add frame data, no profiler: " + p_name);
+	ERR_FAIL_COND_MSG(!profilers.has(p_name), vformat("Can't add frame data, no profiler: '%s'.", p_name));
 	Profiler &p = profilers[p_name];
 	Profiler &p = profilers[p_name];
 	if (p.add) {
 	if (p.add) {
 		p.add(p.data, p_data);
 		p.add(p.data, p_data);
@@ -106,7 +106,7 @@ bool EngineDebugger::has_capture(const StringName &p_name) {
 
 
 Error EngineDebugger::capture_parse(const StringName &p_name, const String &p_msg, const Array &p_args, bool &r_captured) {
 Error EngineDebugger::capture_parse(const StringName &p_name, const String &p_msg, const Array &p_args, bool &r_captured) {
 	r_captured = false;
 	r_captured = false;
-	ERR_FAIL_COND_V_MSG(!captures.has(p_name), ERR_UNCONFIGURED, "Capture not registered: " + p_name);
+	ERR_FAIL_COND_V_MSG(!captures.has(p_name), ERR_UNCONFIGURED, vformat("Capture not registered: '%s'.", p_name));
 	const Capture &cap = captures[p_name];
 	const Capture &cap = captures[p_name];
 	return cap.capture(cap.data, p_msg, p_args, r_captured);
 	return cap.capture(cap.data, p_msg, p_args, r_captured);
 }
 }
@@ -164,7 +164,7 @@ void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, co
 	for (int i = 0; i < p_breakpoints.size(); i++) {
 	for (int i = 0; i < p_breakpoints.size(); i++) {
 		const String &bp = p_breakpoints[i];
 		const String &bp = p_breakpoints[i];
 		int sp = bp.rfind(":");
 		int sp = bp.rfind(":");
-		ERR_CONTINUE_MSG(sp == -1, "Invalid breakpoint: '" + bp + "', expected file:line format.");
+		ERR_CONTINUE_MSG(sp == -1, vformat("Invalid breakpoint: '%s', expected file:line format.", bp));
 
 
 		singleton_script_debugger->insert_breakpoint(bp.substr(sp + 1, bp.length()).to_int(), bp.substr(0, sp));
 		singleton_script_debugger->insert_breakpoint(bp.substr(sp + 1, bp.length()).to_int(), bp.substr(0, sp));
 	}
 	}

+ 2 - 2
core/debugger/remote_debugger.cpp

@@ -79,7 +79,7 @@ public:
 		for (int i = 0; i < custom_monitor_names.size(); i++) {
 		for (int i = 0; i < custom_monitor_names.size(); i++) {
 			Variant monitor_value = performance->call("get_custom_monitor", custom_monitor_names[i]);
 			Variant monitor_value = performance->call("get_custom_monitor", custom_monitor_names[i]);
 			if (!monitor_value.is_num()) {
 			if (!monitor_value.is_num()) {
-				ERR_PRINT("Value of custom monitor '" + String(custom_monitor_names[i]) + "' is not a number");
+				ERR_PRINT(vformat("Value of custom monitor '%s' is not a number.", String(custom_monitor_names[i])));
 				arr[i + max] = Variant();
 				arr[i + max] = Variant();
 			} else {
 			} else {
 				arr[i + max] = monitor_value;
 				arr[i + max] = monitor_value;
@@ -569,7 +569,7 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
 				bool captured = false;
 				bool captured = false;
 				ERR_CONTINUE(_try_capture(command, data, captured) != OK);
 				ERR_CONTINUE(_try_capture(command, data, captured) != OK);
 				if (!captured) {
 				if (!captured) {
-					WARN_PRINT("Unknown message received from debugger: " + command);
+					WARN_PRINT(vformat("Unknown message received from debugger: %s.", command));
 				}
 				}
 			}
 			}
 		} else {
 		} else {

+ 1 - 1
core/debugger/remote_debugger_peer.cpp

@@ -178,7 +178,7 @@ Error RemoteDebuggerPeerTCP::connect_to_host(const String &p_host, uint16_t p_po
 	}
 	}
 
 
 	if (tcp_client->get_status() != StreamPeerTCP::STATUS_CONNECTED) {
 	if (tcp_client->get_status() != StreamPeerTCP::STATUS_CONNECTED) {
-		ERR_PRINT("Remote Debugger: Unable to connect. Status: " + String::num(tcp_client->get_status()) + ".");
+		ERR_PRINT(vformat("Remote Debugger: Unable to connect. Status: %s.", String::num(tcp_client->get_status())));
 		return FAILED;
 		return FAILED;
 	}
 	}
 	connected = true;
 	connected = true;

+ 2 - 2
core/extension/extension_api_dump.cpp

@@ -1363,7 +1363,7 @@ static bool compare_dict_array(const Dictionary &p_old_api, const Dictionary &p_
 		return true; // May just not have this array and its still good. Probably added recently.
 		return true; // May just not have this array and its still good. Probably added recently.
 	}
 	}
 	bool failed = false;
 	bool failed = false;
-	ERR_FAIL_COND_V_MSG(!p_new_api.has(p_base_array), false, "New API lacks base array: " + p_base_array);
+	ERR_FAIL_COND_V_MSG(!p_new_api.has(p_base_array), false, vformat("New API lacks base array: %s", p_base_array));
 	Array new_api = p_new_api[p_base_array];
 	Array new_api = p_new_api[p_base_array];
 	HashMap<String, Dictionary> new_api_assoc;
 	HashMap<String, Dictionary> new_api_assoc;
 
 
@@ -1515,7 +1515,7 @@ static bool compare_sub_dict_array(HashSet<String> &r_removed_classes_registered
 		return true; // May just not have this array and its still good. Probably added recently or optional.
 		return true; // May just not have this array and its still good. Probably added recently or optional.
 	}
 	}
 	bool failed = false;
 	bool failed = false;
-	ERR_FAIL_COND_V_MSG(!p_new_api.has(p_outer), false, "New API lacks base array: " + p_outer);
+	ERR_FAIL_COND_V_MSG(!p_new_api.has(p_outer), false, vformat("New API lacks base array: %s", p_outer));
 	Array new_api = p_new_api[p_outer];
 	Array new_api = p_new_api[p_outer];
 	HashMap<String, Dictionary> new_api_assoc;
 	HashMap<String, Dictionary> new_api_assoc;
 
 

+ 15 - 15
core/extension/gdextension.cpp

@@ -355,8 +355,8 @@ void GDExtension::_register_extension_class_internal(GDExtensionClassLibraryPtr
 
 
 	StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
 	StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
 	StringName parent_class_name = *reinterpret_cast<const StringName *>(p_parent_class_name);
 	StringName parent_class_name = *reinterpret_cast<const StringName *>(p_parent_class_name);
-	ERR_FAIL_COND_MSG(!String(class_name).is_valid_unicode_identifier(), "Attempt to register extension class '" + class_name + "', which is not a valid class identifier.");
-	ERR_FAIL_COND_MSG(ClassDB::class_exists(class_name), "Attempt to register extension class '" + class_name + "', which appears to be already registered.");
+	ERR_FAIL_COND_MSG(!String(class_name).is_valid_unicode_identifier(), vformat("Attempt to register extension class '%s', which is not a valid class identifier.", class_name));
+	ERR_FAIL_COND_MSG(ClassDB::class_exists(class_name), vformat("Attempt to register extension class '%s', which appears to be already registered.", class_name));
 
 
 	Extension *parent_extension = nullptr;
 	Extension *parent_extension = nullptr;
 
 
@@ -370,7 +370,7 @@ void GDExtension::_register_extension_class_internal(GDExtensionClassLibraryPtr
 			//inheriting from engine class
 			//inheriting from engine class
 		}
 		}
 	} else {
 	} else {
-		ERR_FAIL_MSG("Attempt to register an extension class '" + String(class_name) + "' using non-existing parent class '" + String(parent_class_name) + "'.");
+		ERR_FAIL_MSG(vformat("Attempt to register an extension class '%s' using non-existing parent class '%s'.", String(class_name), String(parent_class_name)));
 	}
 	}
 
 
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
@@ -463,7 +463,7 @@ void GDExtension::_register_extension_class_method(GDExtensionClassLibraryPtr p_
 
 
 	StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
 	StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
 	StringName method_name = *reinterpret_cast<const StringName *>(p_method_info->name);
 	StringName method_name = *reinterpret_cast<const StringName *>(p_method_info->name);
-	ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension method '" + String(method_name) + "' for unexisting class '" + class_name + "'.");
+	ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), vformat("Attempt to register extension method '%s' for unexisting class '%s'.", String(method_name), class_name));
 
 
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
 	Extension *extension = &self->extension_classes[class_name];
 	Extension *extension = &self->extension_classes[class_name];
@@ -513,7 +513,7 @@ void GDExtension::_register_extension_class_integer_constant(GDExtensionClassLib
 	StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
 	StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
 	StringName enum_name = *reinterpret_cast<const StringName *>(p_enum_name);
 	StringName enum_name = *reinterpret_cast<const StringName *>(p_enum_name);
 	StringName constant_name = *reinterpret_cast<const StringName *>(p_constant_name);
 	StringName constant_name = *reinterpret_cast<const StringName *>(p_constant_name);
-	ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension constant '" + constant_name + "' for unexisting class '" + class_name + "'.");
+	ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), vformat("Attempt to register extension constant '%s' for unexisting class '%s'.", constant_name, class_name));
 
 
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
 	// If the extension is still marked as reloading, that means it failed to register again.
 	// If the extension is still marked as reloading, that means it failed to register again.
@@ -537,7 +537,7 @@ void GDExtension::_register_extension_class_property_indexed(GDExtensionClassLib
 	StringName setter = *reinterpret_cast<const StringName *>(p_setter);
 	StringName setter = *reinterpret_cast<const StringName *>(p_setter);
 	StringName getter = *reinterpret_cast<const StringName *>(p_getter);
 	StringName getter = *reinterpret_cast<const StringName *>(p_getter);
 	String property_name = *reinterpret_cast<const StringName *>(p_info->name);
 	String property_name = *reinterpret_cast<const StringName *>(p_info->name);
-	ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property '" + property_name + "' for unexisting class '" + class_name + "'.");
+	ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), vformat("Attempt to register extension class property '%s' for unexisting class '%s'.", property_name, class_name));
 
 
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
 	// If the extension is still marked as reloading, that means it failed to register again.
 	// If the extension is still marked as reloading, that means it failed to register again.
@@ -558,7 +558,7 @@ void GDExtension::_register_extension_class_property_group(GDExtensionClassLibra
 	StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
 	StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
 	String group_name = *reinterpret_cast<const String *>(p_group_name);
 	String group_name = *reinterpret_cast<const String *>(p_group_name);
 	String prefix = *reinterpret_cast<const String *>(p_prefix);
 	String prefix = *reinterpret_cast<const String *>(p_prefix);
-	ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property group '" + group_name + "' for unexisting class '" + class_name + "'.");
+	ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), vformat("Attempt to register extension class property group '%s' for unexisting class '%s'.", group_name, class_name));
 
 
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
 	// If the extension is still marked as reloading, that means it failed to register again.
 	// If the extension is still marked as reloading, that means it failed to register again.
@@ -577,7 +577,7 @@ void GDExtension::_register_extension_class_property_subgroup(GDExtensionClassLi
 	StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
 	StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
 	String subgroup_name = *reinterpret_cast<const String *>(p_subgroup_name);
 	String subgroup_name = *reinterpret_cast<const String *>(p_subgroup_name);
 	String prefix = *reinterpret_cast<const String *>(p_prefix);
 	String prefix = *reinterpret_cast<const String *>(p_prefix);
-	ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property subgroup '" + subgroup_name + "' for unexisting class '" + class_name + "'.");
+	ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), vformat("Attempt to register extension class property subgroup '%s' for unexisting class '%s'.", subgroup_name, class_name));
 
 
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
 	// If the extension is still marked as reloading, that means it failed to register again.
 	// If the extension is still marked as reloading, that means it failed to register again.
@@ -595,7 +595,7 @@ void GDExtension::_register_extension_class_signal(GDExtensionClassLibraryPtr p_
 
 
 	StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
 	StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
 	StringName signal_name = *reinterpret_cast<const StringName *>(p_signal_name);
 	StringName signal_name = *reinterpret_cast<const StringName *>(p_signal_name);
-	ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class signal '" + signal_name + "' for unexisting class '" + class_name + "'.");
+	ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), vformat("Attempt to register extension class signal '%s' for unexisting class '%s'.", signal_name, class_name));
 
 
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
 	// If the extension is still marked as reloading, that means it failed to register again.
 	// If the extension is still marked as reloading, that means it failed to register again.
@@ -618,7 +618,7 @@ void GDExtension::_unregister_extension_class(GDExtensionClassLibraryPtr p_libra
 	GDExtension *self = reinterpret_cast<GDExtension *>(p_library);
 	GDExtension *self = reinterpret_cast<GDExtension *>(p_library);
 
 
 	StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
 	StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
-	ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to unregister unexisting extension class '" + class_name + "'.");
+	ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), vformat("Attempt to unregister unexisting extension class '%s'.", class_name));
 
 
 	Extension *ext = &self->extension_classes[class_name];
 	Extension *ext = &self->extension_classes[class_name];
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
@@ -626,7 +626,7 @@ void GDExtension::_unregister_extension_class(GDExtensionClassLibraryPtr p_libra
 		self->_clear_extension(ext);
 		self->_clear_extension(ext);
 	}
 	}
 #endif
 #endif
-	ERR_FAIL_COND_MSG(ext->gdextension.children.size(), "Attempt to unregister class '" + class_name + "' while other extension classes inherit from it.");
+	ERR_FAIL_COND_MSG(ext->gdextension.children.size(), vformat("Attempt to unregister class '%s' while other extension classes inherit from it.", class_name));
 
 
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
 	ClassDB::unregister_extension_class(class_name, !ext->is_reloading);
 	ClassDB::unregister_extension_class(class_name, !ext->is_reloading);
@@ -664,13 +664,13 @@ void GDExtension::_get_library_path(GDExtensionClassLibraryPtr p_library, GDExte
 HashMap<StringName, GDExtensionInterfaceFunctionPtr> GDExtension::gdextension_interface_functions;
 HashMap<StringName, GDExtensionInterfaceFunctionPtr> GDExtension::gdextension_interface_functions;
 
 
 void GDExtension::register_interface_function(const StringName &p_function_name, GDExtensionInterfaceFunctionPtr p_function_pointer) {
 void GDExtension::register_interface_function(const StringName &p_function_name, GDExtensionInterfaceFunctionPtr p_function_pointer) {
-	ERR_FAIL_COND_MSG(gdextension_interface_functions.has(p_function_name), "Attempt to register interface function '" + p_function_name + "', which appears to be already registered.");
+	ERR_FAIL_COND_MSG(gdextension_interface_functions.has(p_function_name), vformat("Attempt to register interface function '%s', which appears to be already registered.", p_function_name));
 	gdextension_interface_functions.insert(p_function_name, p_function_pointer);
 	gdextension_interface_functions.insert(p_function_name, p_function_pointer);
 }
 }
 
 
 GDExtensionInterfaceFunctionPtr GDExtension::get_interface_function(const StringName &p_function_name) {
 GDExtensionInterfaceFunctionPtr GDExtension::get_interface_function(const StringName &p_function_name) {
 	GDExtensionInterfaceFunctionPtr *function = gdextension_interface_functions.getptr(p_function_name);
 	GDExtensionInterfaceFunctionPtr *function = gdextension_interface_functions.getptr(p_function_name);
-	ERR_FAIL_NULL_V_MSG(function, nullptr, "Attempt to get non-existent interface function: " + String(p_function_name) + ".");
+	ERR_FAIL_NULL_V_MSG(function, nullptr, vformat("Attempt to get non-existent interface function: '%s'.", String(p_function_name)));
 	return *function;
 	return *function;
 }
 }
 
 
@@ -680,8 +680,8 @@ Error GDExtension::open_library(const String &p_path, const Ref<GDExtensionLoade
 
 
 	Error err = loader->open_library(p_path);
 	Error err = loader->open_library(p_path);
 
 
-	ERR_FAIL_COND_V_MSG(err == ERR_FILE_NOT_FOUND, err, "GDExtension dynamic library not found: " + p_path);
-	ERR_FAIL_COND_V_MSG(err != OK, err, "Can't open GDExtension dynamic library: " + p_path);
+	ERR_FAIL_COND_V_MSG(err == ERR_FILE_NOT_FOUND, err, vformat("GDExtension dynamic library not found: '%s'.", p_path));
+	ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Can't open GDExtension dynamic library: '%s'.", p_path));
 
 
 	err = loader->initialize(&gdextension_get_proc_address, this, &initialization);
 	err = loader->initialize(&gdextension_get_proc_address, this, &initialization);
 
 

+ 1 - 1
core/extension/gdextension_interface.cpp

@@ -1526,7 +1526,7 @@ static GDExtensionMethodBindPtr gdextension_classdb_get_method_bind(GDExtensionC
 #endif
 #endif
 
 
 	if (!mb && exists) {
 	if (!mb && exists) {
-		ERR_PRINT("Method '" + classname + "." + methodname + "' has changed and no compatibility fallback has been provided. Please open an issue.");
+		ERR_PRINT(vformat("Method '%s.%s' has changed and no compatibility fallback has been provided. Please open an issue.", classname, methodname));
 		return nullptr;
 		return nullptr;
 	}
 	}
 	ERR_FAIL_NULL_V(mb, nullptr);
 	ERR_FAIL_NULL_V(mb, nullptr);

+ 5 - 5
core/extension/gdextension_library_loader.cpp

@@ -219,7 +219,7 @@ Error GDExtensionLibraryLoader::initialize(GDExtensionInterfaceGetProcAddress p_
 	Error err = OS::get_singleton()->get_dynamic_library_symbol_handle(library, entry_symbol, entry_funcptr, false);
 	Error err = OS::get_singleton()->get_dynamic_library_symbol_handle(library, entry_symbol, entry_funcptr, false);
 
 
 	if (err != OK) {
 	if (err != OK) {
-		ERR_PRINT("GDExtension entry point '" + entry_symbol + "' not found in library " + library_path);
+		ERR_PRINT(vformat("GDExtension entry point '%s' not found in library %s.", entry_symbol, library_path));
 		return err;
 		return err;
 	}
 	}
 
 
@@ -230,7 +230,7 @@ Error GDExtensionLibraryLoader::initialize(GDExtensionInterfaceGetProcAddress p_
 	if (ret) {
 	if (ret) {
 		return OK;
 		return OK;
 	} else {
 	} else {
-		ERR_PRINT("GDExtension initialization function '" + entry_symbol + "' returned an error.");
+		ERR_PRINT(vformat("GDExtension initialization function '%s' returned an error.", entry_symbol));
 		return FAILED;
 		return FAILED;
 	}
 	}
 }
 }
@@ -272,12 +272,12 @@ Error GDExtensionLibraryLoader::parse_gdextension_file(const String &p_path) {
 	Error err = config->load(p_path);
 	Error err = config->load(p_path);
 
 
 	if (err != OK) {
 	if (err != OK) {
-		ERR_PRINT("Error loading GDExtension configuration file: " + p_path);
+		ERR_PRINT(vformat("Error loading GDExtension configuration file: '%s'.", p_path));
 		return err;
 		return err;
 	}
 	}
 
 
 	if (!config->has_section_key("configuration", "entry_symbol")) {
 	if (!config->has_section_key("configuration", "entry_symbol")) {
-		ERR_PRINT("GDExtension configuration file must contain a \"configuration/entry_symbol\" key: " + p_path);
+		ERR_PRINT(vformat("GDExtension configuration file must contain a \"configuration/entry_symbol\" key: '%s'.", p_path));
 		return ERR_INVALID_DATA;
 		return ERR_INVALID_DATA;
 	}
 	}
 
 
@@ -296,7 +296,7 @@ Error GDExtensionLibraryLoader::parse_gdextension_file(const String &p_path) {
 			}
 			}
 		}
 		}
 	} else {
 	} else {
-		ERR_PRINT("GDExtension configuration file must contain a \"configuration/compatibility_minimum\" key: " + p_path);
+		ERR_PRINT(vformat("GDExtension configuration file must contain a \"configuration/compatibility_minimum\" key: '%s'.", p_path));
 		return ERR_INVALID_DATA;
 		return ERR_INVALID_DATA;
 	}
 	}
 
 

+ 1 - 1
core/extension/gdextension_manager.cpp

@@ -258,7 +258,7 @@ void GDExtensionManager::load_extensions() {
 		String s = f->get_line().strip_edges();
 		String s = f->get_line().strip_edges();
 		if (!s.is_empty()) {
 		if (!s.is_empty()) {
 			LoadStatus err = load_extension(s);
 			LoadStatus err = load_extension(s);
-			ERR_CONTINUE_MSG(err == LOAD_STATUS_FAILED, "Error loading extension: " + s);
+			ERR_CONTINUE_MSG(err == LOAD_STATUS_FAILED, vformat("Error loading extension: '%s'.", s));
 		}
 		}
 	}
 	}
 
 

+ 1 - 1
core/input/input_map.cpp

@@ -114,7 +114,7 @@ void InputMap::get_argument_options(const StringName &p_function, int p_idx, Lis
 #endif
 #endif
 
 
 void InputMap::add_action(const StringName &p_action, float p_deadzone) {
 void InputMap::add_action(const StringName &p_action, float p_deadzone) {
-	ERR_FAIL_COND_MSG(input_map.has(p_action), "InputMap already has action \"" + String(p_action) + "\".");
+	ERR_FAIL_COND_MSG(input_map.has(p_action), vformat("InputMap already has action \"%s\".", String(p_action)));
 	input_map[p_action] = Action();
 	input_map[p_action] = Action();
 	static int last_id = 1;
 	static int last_id = 1;
 	input_map[p_action].id = last_id;
 	input_map[p_action].id = last_id;

+ 8 - 8
core/io/dir_access.cpp

@@ -177,7 +177,7 @@ Error DirAccess::make_dir_recursive(const String &p_dir) {
 		curpath = curpath.path_join(subdirs[i]);
 		curpath = curpath.path_join(subdirs[i]);
 		Error err = make_dir(curpath);
 		Error err = make_dir(curpath);
 		if (err != OK && err != ERR_ALREADY_EXISTS) {
 		if (err != OK && err != ERR_ALREADY_EXISTS) {
-			ERR_FAIL_V_MSG(err, "Could not create directory: " + curpath);
+			ERR_FAIL_V_MSG(err, vformat("Could not create directory: '%s'.", curpath));
 		}
 		}
 	}
 	}
 
 
@@ -239,7 +239,7 @@ Ref<DirAccess> DirAccess::create_for_path(const String &p_path) {
 
 
 Ref<DirAccess> DirAccess::open(const String &p_path, Error *r_error) {
 Ref<DirAccess> DirAccess::open(const String &p_path, Error *r_error) {
 	Ref<DirAccess> da = create_for_path(p_path);
 	Ref<DirAccess> da = create_for_path(p_path);
-	ERR_FAIL_COND_V_MSG(da.is_null(), nullptr, "Cannot create DirAccess for path '" + p_path + "'.");
+	ERR_FAIL_COND_V_MSG(da.is_null(), nullptr, vformat("Cannot create DirAccess for path '%s'.", p_path));
 	Error err = da->change_dir(p_path);
 	Error err = da->change_dir(p_path);
 	if (r_error) {
 	if (r_error) {
 		*r_error = err;
 		*r_error = err;
@@ -345,10 +345,10 @@ Error DirAccess::copy(const String &p_from, const String &p_to, int p_chmod_flag
 	Error err;
 	Error err;
 	{
 	{
 		Ref<FileAccess> fsrc = FileAccess::open(p_from, FileAccess::READ, &err);
 		Ref<FileAccess> fsrc = FileAccess::open(p_from, FileAccess::READ, &err);
-		ERR_FAIL_COND_V_MSG(err != OK, err, "Failed to open " + p_from);
+		ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Failed to open '%s'.", p_from));
 
 
 		Ref<FileAccess> fdst = FileAccess::open(p_to, FileAccess::WRITE, &err);
 		Ref<FileAccess> fdst = FileAccess::open(p_to, FileAccess::WRITE, &err);
-		ERR_FAIL_COND_V_MSG(err != OK, err, "Failed to open " + p_to);
+		ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Failed to open '%s'.", p_to));
 
 
 		const size_t copy_buffer_limit = 65536; // 64 KB
 		const size_t copy_buffer_limit = 65536; // 64 KB
 
 
@@ -444,11 +444,11 @@ Error DirAccess::_copy_dir(Ref<DirAccess> &p_target_da, const String &p_to, int
 		String target_dir = p_to + rel_path;
 		String target_dir = p_to + rel_path;
 		if (!p_target_da->dir_exists(target_dir)) {
 		if (!p_target_da->dir_exists(target_dir)) {
 			Error err = p_target_da->make_dir(target_dir);
 			Error err = p_target_da->make_dir(target_dir);
-			ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot create directory '" + target_dir + "'.");
+			ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Cannot create directory '%s'.", target_dir));
 		}
 		}
 
 
 		Error err = change_dir(rel_path);
 		Error err = change_dir(rel_path);
-		ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot change current directory to '" + rel_path + "'.");
+		ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Cannot change current directory to '%s'.", rel_path));
 
 
 		err = _copy_dir(p_target_da, p_to + rel_path + "/", p_chmod_flags, p_copy_links);
 		err = _copy_dir(p_target_da, p_to + rel_path + "/", p_chmod_flags, p_copy_links);
 		if (err) {
 		if (err) {
@@ -466,11 +466,11 @@ Error DirAccess::copy_dir(const String &p_from, String p_to, int p_chmod_flags,
 	ERR_FAIL_COND_V_MSG(!dir_exists(p_from), ERR_FILE_NOT_FOUND, "Source directory doesn't exist.");
 	ERR_FAIL_COND_V_MSG(!dir_exists(p_from), ERR_FILE_NOT_FOUND, "Source directory doesn't exist.");
 
 
 	Ref<DirAccess> target_da = DirAccess::create_for_path(p_to);
 	Ref<DirAccess> target_da = DirAccess::create_for_path(p_to);
-	ERR_FAIL_COND_V_MSG(target_da.is_null(), ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_to + "'.");
+	ERR_FAIL_COND_V_MSG(target_da.is_null(), ERR_CANT_CREATE, vformat("Cannot create DirAccess for path '%s'.", p_to));
 
 
 	if (!target_da->dir_exists(p_to)) {
 	if (!target_da->dir_exists(p_to)) {
 		Error err = target_da->make_dir_recursive(p_to);
 		Error err = target_da->make_dir_recursive(p_to);
-		ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot create directory '" + p_to + "'.");
+		ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Cannot create directory '%s'.", p_to));
 	}
 	}
 
 
 	if (!p_to.ends_with("/")) {
 	if (!p_to.ends_with("/")) {

+ 2 - 2
core/io/dir_access.h

@@ -116,10 +116,10 @@ public:
 		Ref<DirAccess> da = create(ACCESS_FILESYSTEM);
 		Ref<DirAccess> da = create(ACCESS_FILESYSTEM);
 		if (da->file_exists(p_path)) {
 		if (da->file_exists(p_path)) {
 			if (da->remove(p_path) != OK) {
 			if (da->remove(p_path) != OK) {
-				ERR_FAIL_MSG("Cannot remove file or directory: " + p_path);
+				ERR_FAIL_MSG(vformat("Cannot remove file or directory: '%s'.", p_path));
 			}
 			}
 		} else {
 		} else {
-			ERR_FAIL_MSG("Cannot remove non-existent file or directory: " + p_path);
+			ERR_FAIL_MSG(vformat("Cannot remove non-existent file or directory: '%s'.", p_path));
 		}
 		}
 	}
 	}
 
 

+ 10 - 10
core/io/file_access.cpp

@@ -459,7 +459,7 @@ Vector<uint8_t> FileAccess::get_buffer(int64_t p_length) const {
 	}
 	}
 
 
 	Error err = data.resize(p_length);
 	Error err = data.resize(p_length);
-	ERR_FAIL_COND_V_MSG(err != OK, data, "Can't resize data to " + itos(p_length) + " elements.");
+	ERR_FAIL_COND_V_MSG(err != OK, data, vformat("Can't resize data to %d elements.", p_length));
 
 
 	uint8_t *w = data.ptrw();
 	uint8_t *w = data.ptrw();
 	int64_t len = get_buffer(w, p_length);
 	int64_t len = get_buffer(w, p_length);
@@ -540,7 +540,7 @@ uint64_t FileAccess::get_modified_time(const String &p_file) {
 	}
 	}
 
 
 	Ref<FileAccess> fa = create_for_path(p_file);
 	Ref<FileAccess> fa = create_for_path(p_file);
-	ERR_FAIL_COND_V_MSG(fa.is_null(), 0, "Cannot create FileAccess for path '" + p_file + "'.");
+	ERR_FAIL_COND_V_MSG(fa.is_null(), 0, vformat("Cannot create FileAccess for path '%s'.", p_file));
 
 
 	uint64_t mt = fa->_get_modified_time(p_file);
 	uint64_t mt = fa->_get_modified_time(p_file);
 	return mt;
 	return mt;
@@ -552,7 +552,7 @@ BitField<FileAccess::UnixPermissionFlags> FileAccess::get_unix_permissions(const
 	}
 	}
 
 
 	Ref<FileAccess> fa = create_for_path(p_file);
 	Ref<FileAccess> fa = create_for_path(p_file);
-	ERR_FAIL_COND_V_MSG(fa.is_null(), 0, "Cannot create FileAccess for path '" + p_file + "'.");
+	ERR_FAIL_COND_V_MSG(fa.is_null(), 0, vformat("Cannot create FileAccess for path '%s'.", p_file));
 
 
 	return fa->_get_unix_permissions(p_file);
 	return fa->_get_unix_permissions(p_file);
 }
 }
@@ -563,7 +563,7 @@ Error FileAccess::set_unix_permissions(const String &p_file, BitField<FileAccess
 	}
 	}
 
 
 	Ref<FileAccess> fa = create_for_path(p_file);
 	Ref<FileAccess> fa = create_for_path(p_file);
-	ERR_FAIL_COND_V_MSG(fa.is_null(), ERR_CANT_CREATE, "Cannot create FileAccess for path '" + p_file + "'.");
+	ERR_FAIL_COND_V_MSG(fa.is_null(), ERR_CANT_CREATE, vformat("Cannot create FileAccess for path '%s'.", p_file));
 
 
 	Error err = fa->_set_unix_permissions(p_file, p_permissions);
 	Error err = fa->_set_unix_permissions(p_file, p_permissions);
 	return err;
 	return err;
@@ -575,7 +575,7 @@ bool FileAccess::get_hidden_attribute(const String &p_file) {
 	}
 	}
 
 
 	Ref<FileAccess> fa = create_for_path(p_file);
 	Ref<FileAccess> fa = create_for_path(p_file);
-	ERR_FAIL_COND_V_MSG(fa.is_null(), false, "Cannot create FileAccess for path '" + p_file + "'.");
+	ERR_FAIL_COND_V_MSG(fa.is_null(), false, vformat("Cannot create FileAccess for path '%s'.", p_file));
 
 
 	return fa->_get_hidden_attribute(p_file);
 	return fa->_get_hidden_attribute(p_file);
 }
 }
@@ -586,7 +586,7 @@ Error FileAccess::set_hidden_attribute(const String &p_file, bool p_hidden) {
 	}
 	}
 
 
 	Ref<FileAccess> fa = create_for_path(p_file);
 	Ref<FileAccess> fa = create_for_path(p_file);
-	ERR_FAIL_COND_V_MSG(fa.is_null(), ERR_CANT_CREATE, "Cannot create FileAccess for path '" + p_file + "'.");
+	ERR_FAIL_COND_V_MSG(fa.is_null(), ERR_CANT_CREATE, vformat("Cannot create FileAccess for path '%s'.", p_file));
 
 
 	Error err = fa->_set_hidden_attribute(p_file, p_hidden);
 	Error err = fa->_set_hidden_attribute(p_file, p_hidden);
 	return err;
 	return err;
@@ -598,7 +598,7 @@ bool FileAccess::get_read_only_attribute(const String &p_file) {
 	}
 	}
 
 
 	Ref<FileAccess> fa = create_for_path(p_file);
 	Ref<FileAccess> fa = create_for_path(p_file);
-	ERR_FAIL_COND_V_MSG(fa.is_null(), false, "Cannot create FileAccess for path '" + p_file + "'.");
+	ERR_FAIL_COND_V_MSG(fa.is_null(), false, vformat("Cannot create FileAccess for path '%s'.", p_file));
 
 
 	return fa->_get_read_only_attribute(p_file);
 	return fa->_get_read_only_attribute(p_file);
 }
 }
@@ -609,7 +609,7 @@ Error FileAccess::set_read_only_attribute(const String &p_file, bool p_ro) {
 	}
 	}
 
 
 	Ref<FileAccess> fa = create_for_path(p_file);
 	Ref<FileAccess> fa = create_for_path(p_file);
-	ERR_FAIL_COND_V_MSG(fa.is_null(), ERR_CANT_CREATE, "Cannot create FileAccess for path '" + p_file + "'.");
+	ERR_FAIL_COND_V_MSG(fa.is_null(), ERR_CANT_CREATE, vformat("Cannot create FileAccess for path '%s'.", p_file));
 
 
 	Error err = fa->_set_read_only_attribute(p_file, p_ro);
 	Error err = fa->_set_read_only_attribute(p_file, p_ro);
 	return err;
 	return err;
@@ -697,7 +697,7 @@ Vector<uint8_t> FileAccess::get_file_as_bytes(const String &p_path, Error *r_err
 		if (r_error) { // if error requested, do not throw error
 		if (r_error) { // if error requested, do not throw error
 			return Vector<uint8_t>();
 			return Vector<uint8_t>();
 		}
 		}
-		ERR_FAIL_V_MSG(Vector<uint8_t>(), "Can't open file from path '" + String(p_path) + "'.");
+		ERR_FAIL_V_MSG(Vector<uint8_t>(), vformat("Can't open file from path '%s'.", String(p_path)));
 	}
 	}
 	Vector<uint8_t> data;
 	Vector<uint8_t> data;
 	data.resize(f->get_length());
 	data.resize(f->get_length());
@@ -715,7 +715,7 @@ String FileAccess::get_file_as_string(const String &p_path, Error *r_error) {
 		if (r_error) {
 		if (r_error) {
 			return String();
 			return String();
 		}
 		}
-		ERR_FAIL_V_MSG(String(), "Can't get file as string from path '" + String(p_path) + "'.");
+		ERR_FAIL_V_MSG(String(), vformat("Can't get file as string from path '%s'.", String(p_path)));
 	}
 	}
 
 
 	String ret;
 	String ret;

+ 1 - 1
core/io/file_access_compressed.cpp

@@ -58,7 +58,7 @@ Error FileAccessCompressed::open_after_magic(Ref<FileAccess> p_base) {
 	block_size = f->get_32();
 	block_size = f->get_32();
 	if (block_size == 0) {
 	if (block_size == 0) {
 		f.unref();
 		f.unref();
-		ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Can't open compressed file '" + p_base->get_path() + "' with block size 0, it is corrupted.");
+		ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, vformat("Can't open compressed file '%s' with block size 0, it is corrupted.", p_base->get_path()));
 	}
 	}
 	read_total = f->get_32();
 	read_total = f->get_32();
 	uint32_t bc = (read_total / block_size) + 1;
 	uint32_t bc = (read_total / block_size) + 1;

+ 1 - 1
core/io/file_access_encrypted.cpp

@@ -37,7 +37,7 @@
 #include <stdio.h>
 #include <stdio.h>
 
 
 Error FileAccessEncrypted::open_and_parse(Ref<FileAccess> p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic) {
 Error FileAccessEncrypted::open_and_parse(Ref<FileAccess> p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic) {
-	ERR_FAIL_COND_V_MSG(file.is_valid(), ERR_ALREADY_IN_USE, "Can't open file while another file from path '" + file->get_path_absolute() + "' is open.");
+	ERR_FAIL_COND_V_MSG(file.is_valid(), ERR_ALREADY_IN_USE, vformat("Can't open file while another file from path '%s' is open.", file->get_path_absolute()));
 	ERR_FAIL_COND_V(p_key.size() != 32, ERR_INVALID_PARAMETER);
 	ERR_FAIL_COND_V(p_key.size() != 32, ERR_INVALID_PARAMETER);
 
 
 	pos = 0;
 	pos = 0;

+ 1 - 1
core/io/file_access_memory.cpp

@@ -85,7 +85,7 @@ Error FileAccessMemory::open_internal(const String &p_path, int p_mode_flags) {
 	//name = DirAccess::normalize_path(name);
 	//name = DirAccess::normalize_path(name);
 
 
 	HashMap<String, Vector<uint8_t>>::Iterator E = files->find(name);
 	HashMap<String, Vector<uint8_t>>::Iterator E = files->find(name);
-	ERR_FAIL_COND_V_MSG(!E, ERR_FILE_NOT_FOUND, "Can't find file '" + p_path + "'.");
+	ERR_FAIL_COND_V_MSG(!E, ERR_FILE_NOT_FOUND, vformat("Can't find file '%s'.", p_path));
 
 
 	data = E->value.ptrw();
 	data = E->value.ptrw();
 	length = E->value.size();
 	length = E->value.size();

+ 5 - 5
core/io/file_access_pack.cpp

@@ -223,8 +223,8 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
 	uint32_t ver_minor = f->get_32();
 	uint32_t ver_minor = f->get_32();
 	f->get_32(); // patch number, not used for validation.
 	f->get_32(); // patch number, not used for validation.
 
 
-	ERR_FAIL_COND_V_MSG(version != PACK_FORMAT_VERSION, false, "Pack version unsupported: " + itos(version) + ".");
-	ERR_FAIL_COND_V_MSG(ver_major > VERSION_MAJOR || (ver_major == VERSION_MAJOR && ver_minor > VERSION_MINOR), false, "Pack created with a newer version of the engine: " + itos(ver_major) + "." + itos(ver_minor) + ".");
+	ERR_FAIL_COND_V_MSG(version != PACK_FORMAT_VERSION, false, vformat("Pack version unsupported: %d.", version));
+	ERR_FAIL_COND_V_MSG(ver_major > VERSION_MAJOR || (ver_major == VERSION_MAJOR && ver_minor > VERSION_MINOR), false, vformat("Pack created with a newer version of the engine: %d.%d.", ver_major, ver_minor));
 
 
 	uint32_t pack_flags = f->get_32();
 	uint32_t pack_flags = f->get_32();
 	uint64_t file_base = f->get_64();
 	uint64_t file_base = f->get_64();
@@ -386,7 +386,7 @@ void FileAccessPack::close() {
 FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file) :
 FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file) :
 		pf(p_file),
 		pf(p_file),
 		f(FileAccess::open(pf.pack, FileAccess::READ)) {
 		f(FileAccess::open(pf.pack, FileAccess::READ)) {
-	ERR_FAIL_COND_MSG(f.is_null(), "Can't open pack-referenced file '" + String(pf.pack) + "'.");
+	ERR_FAIL_COND_MSG(f.is_null(), vformat("Can't open pack-referenced file '%s'.", String(pf.pack)));
 
 
 	f->seek(pf.offset);
 	f->seek(pf.offset);
 	off = pf.offset;
 	off = pf.offset;
@@ -394,7 +394,7 @@ FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFil
 	if (pf.encrypted) {
 	if (pf.encrypted) {
 		Ref<FileAccessEncrypted> fae;
 		Ref<FileAccessEncrypted> fae;
 		fae.instantiate();
 		fae.instantiate();
-		ERR_FAIL_COND_MSG(fae.is_null(), "Can't open encrypted pack-referenced file '" + String(pf.pack) + "'.");
+		ERR_FAIL_COND_MSG(fae.is_null(), vformat("Can't open encrypted pack-referenced file '%s'.", String(pf.pack)));
 
 
 		Vector<uint8_t> key;
 		Vector<uint8_t> key;
 		key.resize(32);
 		key.resize(32);
@@ -403,7 +403,7 @@ FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFil
 		}
 		}
 
 
 		Error err = fae->open_and_parse(f, key, FileAccessEncrypted::MODE_READ, false);
 		Error err = fae->open_and_parse(f, key, FileAccessEncrypted::MODE_READ, false);
-		ERR_FAIL_COND_MSG(err, "Can't open encrypted pack-referenced file '" + String(pf.pack) + "'.");
+		ERR_FAIL_COND_MSG(err, vformat("Can't open encrypted pack-referenced file '%s'.", String(pf.pack)));
 		f = fae;
 		f = fae;
 		off = 0;
 		off = 0;
 	}
 	}

+ 2 - 2
core/io/file_access_zip.cpp

@@ -116,7 +116,7 @@ void ZipArchive::close_handle(unzFile p_file) const {
 }
 }
 
 
 unzFile ZipArchive::get_file_handle(const String &p_file) const {
 unzFile ZipArchive::get_file_handle(const String &p_file) const {
-	ERR_FAIL_COND_V_MSG(!file_exists(p_file), nullptr, "File '" + p_file + " doesn't exist.");
+	ERR_FAIL_COND_V_MSG(!file_exists(p_file), nullptr, vformat("File '%s' doesn't exist.", p_file));
 	File file = files[p_file];
 	File file = files[p_file];
 
 
 	zlib_filefunc_def io;
 	zlib_filefunc_def io;
@@ -136,7 +136,7 @@ unzFile ZipArchive::get_file_handle(const String &p_file) const {
 	io.free_mem = godot_free;
 	io.free_mem = godot_free;
 
 
 	unzFile pkg = unzOpen2(packages[file.package].filename.utf8().get_data(), &io);
 	unzFile pkg = unzOpen2(packages[file.package].filename.utf8().get_data(), &io);
-	ERR_FAIL_NULL_V_MSG(pkg, nullptr, "Cannot open file '" + packages[file.package].filename + "'.");
+	ERR_FAIL_NULL_V_MSG(pkg, nullptr, vformat("Cannot open file '%s'.", packages[file.package].filename));
 	int unz_err = unzGoToFilePos(pkg, &file.file_pos);
 	int unz_err = unzGoToFilePos(pkg, &file.file_pos);
 	if (unz_err != UNZ_OK || unzOpenCurrentFile(pkg) != UNZ_OK) {
 	if (unz_err != UNZ_OK || unzOpenCurrentFile(pkg) != UNZ_OK) {
 		unzClose(pkg);
 		unzClose(pkg);

+ 2 - 2
core/io/http_client.cpp

@@ -100,9 +100,9 @@ String HTTPClient::query_string_from_dict(const Dictionary &p_dict) {
 Error HTTPClient::verify_headers(const Vector<String> &p_headers) {
 Error HTTPClient::verify_headers(const Vector<String> &p_headers) {
 	for (int i = 0; i < p_headers.size(); i++) {
 	for (int i = 0; i < p_headers.size(); i++) {
 		String sanitized = p_headers[i].strip_edges();
 		String sanitized = p_headers[i].strip_edges();
-		ERR_FAIL_COND_V_MSG(sanitized.is_empty(), ERR_INVALID_PARAMETER, "Invalid HTTP header at index " + itos(i) + ": empty.");
+		ERR_FAIL_COND_V_MSG(sanitized.is_empty(), ERR_INVALID_PARAMETER, vformat("Invalid HTTP header at index %d: empty.", i));
 		ERR_FAIL_COND_V_MSG(sanitized.find(":") < 1, ERR_INVALID_PARAMETER,
 		ERR_FAIL_COND_V_MSG(sanitized.find(":") < 1, ERR_INVALID_PARAMETER,
-				"Invalid HTTP header at index " + itos(i) + ": String must contain header-value pair, delimited by ':', but was: " + p_headers[i]);
+				vformat("Invalid HTTP header at index %d: String must contain header-value pair, delimited by ':', but was: '%s'.", i, p_headers[i]));
 	}
 	}
 
 
 	return OK;
 	return OK;

+ 26 - 26
core/io/image.cpp

@@ -535,7 +535,7 @@ static bool _are_formats_compatible(Image::Format p_format0, Image::Format p_for
 }
 }
 
 
 void Image::convert(Format p_new_format) {
 void Image::convert(Format p_new_format) {
-	ERR_FAIL_INDEX_MSG(p_new_format, FORMAT_MAX, "The Image format specified (" + itos(p_new_format) + ") is out of range. See Image's Format enum.");
+	ERR_FAIL_INDEX_MSG(p_new_format, FORMAT_MAX, vformat("The Image format specified (%d) is out of range. See Image's Format enum.", p_new_format));
 	if (data.size() == 0) {
 	if (data.size() == 0) {
 		return;
 		return;
 	}
 	}
@@ -1132,9 +1132,9 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
 
 
 	ERR_FAIL_COND_MSG(p_width <= 0, "Image width must be greater than 0.");
 	ERR_FAIL_COND_MSG(p_width <= 0, "Image width must be greater than 0.");
 	ERR_FAIL_COND_MSG(p_height <= 0, "Image height must be greater than 0.");
 	ERR_FAIL_COND_MSG(p_height <= 0, "Image height must be greater than 0.");
-	ERR_FAIL_COND_MSG(p_width > MAX_WIDTH, "Image width cannot be greater than " + itos(MAX_WIDTH) + ".");
-	ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT, "Image height cannot be greater than " + itos(MAX_HEIGHT) + ".");
-	ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS, "Too many pixels for image, maximum is " + itos(MAX_PIXELS));
+	ERR_FAIL_COND_MSG(p_width > MAX_WIDTH, vformat("Image width cannot be greater than %d pixels.", MAX_WIDTH));
+	ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT, vformat("Image height cannot be greater than %d pixels.", MAX_HEIGHT));
+	ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS, vformat("Too many pixels for image, maximum is %d pixels.", MAX_PIXELS));
 
 
 	if (p_width == width && p_height == height) {
 	if (p_width == width && p_height == height) {
 		return;
 		return;
@@ -1435,8 +1435,8 @@ void Image::crop_from_point(int p_x, int p_y, int p_width, int p_height) {
 	ERR_FAIL_COND_MSG(p_y < 0, "Start y position cannot be smaller than 0.");
 	ERR_FAIL_COND_MSG(p_y < 0, "Start y position cannot be smaller than 0.");
 	ERR_FAIL_COND_MSG(p_width <= 0, "Width of image must be greater than 0.");
 	ERR_FAIL_COND_MSG(p_width <= 0, "Width of image must be greater than 0.");
 	ERR_FAIL_COND_MSG(p_height <= 0, "Height of image must be greater than 0.");
 	ERR_FAIL_COND_MSG(p_height <= 0, "Height of image must be greater than 0.");
-	ERR_FAIL_COND_MSG(p_x + p_width > MAX_WIDTH, "End x position cannot be greater than " + itos(MAX_WIDTH) + ".");
-	ERR_FAIL_COND_MSG(p_y + p_height > MAX_HEIGHT, "End y position cannot be greater than " + itos(MAX_HEIGHT) + ".");
+	ERR_FAIL_COND_MSG(p_x + p_width > MAX_WIDTH, vformat("End x position cannot be greater than %d.", MAX_WIDTH));
+	ERR_FAIL_COND_MSG(p_y + p_height > MAX_HEIGHT, vformat("End y position cannot be greater than %d.", MAX_HEIGHT));
 
 
 	/* to save memory, cropping should be done in-place, however, since this function
 	/* to save memory, cropping should be done in-place, however, since this function
 	   will most likely either not be used much, or in critical areas, for now it won't, because
 	   will most likely either not be used much, or in critical areas, for now it won't, because
@@ -1484,8 +1484,8 @@ void Image::crop(int p_width, int p_height) {
 
 
 void Image::rotate_90(ClockDirection p_direction) {
 void Image::rotate_90(ClockDirection p_direction) {
 	ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot rotate in compressed or custom image formats.");
 	ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot rotate in compressed or custom image formats.");
-	ERR_FAIL_COND_MSG(width <= 0, "The Image width specified (" + itos(width) + " pixels) must be greater than 0 pixels.");
-	ERR_FAIL_COND_MSG(height <= 0, "The Image height specified (" + itos(height) + " pixels) must be greater than 0 pixels.");
+	ERR_FAIL_COND_MSG(width <= 0, vformat("The Image width specified (%d pixels) must be greater than 0 pixels.", width));
+	ERR_FAIL_COND_MSG(height <= 0, vformat("The Image height specified (%d pixels) must be greater than 0 pixels.", height));
 
 
 	bool used_mipmaps = has_mipmaps();
 	bool used_mipmaps = has_mipmaps();
 	if (used_mipmaps) {
 	if (used_mipmaps) {
@@ -1602,8 +1602,8 @@ void Image::rotate_90(ClockDirection p_direction) {
 
 
 void Image::rotate_180() {
 void Image::rotate_180() {
 	ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot rotate in compressed or custom image formats.");
 	ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot rotate in compressed or custom image formats.");
-	ERR_FAIL_COND_MSG(width <= 0, "The Image width specified (" + itos(width) + " pixels) must be greater than 0 pixels.");
-	ERR_FAIL_COND_MSG(height <= 0, "The Image height specified (" + itos(height) + " pixels) must be greater than 0 pixels.");
+	ERR_FAIL_COND_MSG(width <= 0, vformat("The Image width specified (%d pixels) must be greater than 0 pixels.", width));
+	ERR_FAIL_COND_MSG(height <= 0, vformat("The Image height specified (%d pixels) must be greater than 0 pixels.", height));
 
 
 	bool used_mipmaps = has_mipmaps();
 	bool used_mipmaps = has_mipmaps();
 	if (used_mipmaps) {
 	if (used_mipmaps) {
@@ -2249,15 +2249,15 @@ void Image::set_data(int p_width, int p_height, bool p_use_mipmaps, Format p_for
 }
 }
 
 
 void Image::initialize_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format) {
 void Image::initialize_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format) {
-	ERR_FAIL_COND_MSG(p_width <= 0, "The Image width specified (" + itos(p_width) + " pixels) must be greater than 0 pixels.");
-	ERR_FAIL_COND_MSG(p_height <= 0, "The Image height specified (" + itos(p_height) + " pixels) must be greater than 0 pixels.");
+	ERR_FAIL_COND_MSG(p_width <= 0, vformat("The Image width specified (%d pixels) must be greater than 0 pixels.", p_width));
+	ERR_FAIL_COND_MSG(p_height <= 0, vformat("The Image height specified (%d pixels) must be greater than 0 pixels.", p_height));
 	ERR_FAIL_COND_MSG(p_width > MAX_WIDTH,
 	ERR_FAIL_COND_MSG(p_width > MAX_WIDTH,
-			"The Image width specified (" + itos(p_width) + " pixels) cannot be greater than " + itos(MAX_WIDTH) + "pixels.");
+			vformat("The Image width specified (%d pixels) cannot be greater than %d pixels.", p_width, MAX_WIDTH));
 	ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT,
 	ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT,
-			"The Image height specified (" + itos(p_height) + " pixels) cannot be greater than " + itos(MAX_HEIGHT) + "pixels.");
+			vformat("The Image height specified (%d pixels) cannot be greater than %d pixels.", p_height, MAX_HEIGHT));
 	ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS,
 	ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS,
-			"Too many pixels for Image. Maximum is " + itos(MAX_WIDTH) + "x" + itos(MAX_HEIGHT) + " = " + itos(MAX_PIXELS) + "pixels.");
-	ERR_FAIL_INDEX_MSG(p_format, FORMAT_MAX, "The Image format specified (" + itos(p_format) + ") is out of range. See Image's Format enum.");
+			vformat("Too many pixels for Image. Maximum is %dx%d = %d pixels.", MAX_WIDTH, MAX_HEIGHT, MAX_PIXELS));
+	ERR_FAIL_INDEX_MSG(p_format, FORMAT_MAX, vformat("The Image format specified (%d) is out of range. See Image's Format enum.", p_format));
 
 
 	int mm = 0;
 	int mm = 0;
 	int64_t size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0);
 	int64_t size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0);
@@ -2275,15 +2275,15 @@ void Image::initialize_data(int p_width, int p_height, bool p_use_mipmaps, Forma
 }
 }
 
 
 void Image::initialize_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data) {
 void Image::initialize_data(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data) {
-	ERR_FAIL_COND_MSG(p_width <= 0, "The Image width specified (" + itos(p_width) + " pixels) must be greater than 0 pixels.");
-	ERR_FAIL_COND_MSG(p_height <= 0, "The Image height specified (" + itos(p_height) + " pixels) must be greater than 0 pixels.");
+	ERR_FAIL_COND_MSG(p_width <= 0, vformat("The Image width specified (%d pixels) must be greater than 0 pixels.", p_width));
+	ERR_FAIL_COND_MSG(p_height <= 0, vformat("The Image height specified (%d pixels) must be greater than 0 pixels.", p_height));
 	ERR_FAIL_COND_MSG(p_width > MAX_WIDTH,
 	ERR_FAIL_COND_MSG(p_width > MAX_WIDTH,
-			"The Image width specified (" + itos(p_width) + " pixels) cannot be greater than " + itos(MAX_WIDTH) + " pixels.");
+			vformat("The Image width specified (%d pixels) cannot be greater than %d pixels.", p_width, MAX_WIDTH));
 	ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT,
 	ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT,
-			"The Image height specified (" + itos(p_height) + " pixels) cannot be greater than " + itos(MAX_HEIGHT) + " pixels.");
+			vformat("The Image height specified (%d pixels) cannot be greater than %d pixels.", p_height, MAX_HEIGHT));
 	ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS,
 	ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS,
-			"Too many pixels for Image. Maximum is " + itos(MAX_WIDTH) + "x" + itos(MAX_HEIGHT) + " = " + itos(MAX_PIXELS) + "pixels .");
-	ERR_FAIL_INDEX_MSG(p_format, FORMAT_MAX, "The Image format specified (" + itos(p_format) + ") is out of range. See Image's Format enum.");
+			vformat("Too many pixels for Image. Maximum is %dx%d = %d pixels.", MAX_WIDTH, MAX_HEIGHT, MAX_PIXELS));
+	ERR_FAIL_INDEX_MSG(p_format, FORMAT_MAX, vformat("The Image format specified (%d) is out of range. See Image's Format enum.", p_format));
 
 
 	int mm;
 	int mm;
 	int64_t size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0);
 	int64_t size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0);
@@ -2577,7 +2577,7 @@ Image::AlphaMode Image::detect_alpha() const {
 Error Image::load(const String &p_path) {
 Error Image::load(const String &p_path) {
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 	if (p_path.begins_with("res://") && ResourceLoader::exists(p_path)) {
 	if (p_path.begins_with("res://") && ResourceLoader::exists(p_path)) {
-		WARN_PRINT("Loaded resource as image file, this will not work on export: '" + p_path + "'. Instead, import the image file as an Image resource and load it normally as a resource.");
+		WARN_PRINT(vformat("Loaded resource as image file, this will not work on export: '%s'. Instead, import the image file as an Image resource and load it normally as a resource.", p_path));
 	}
 	}
 #endif
 #endif
 	return ImageLoader::load_image(p_path, this);
 	return ImageLoader::load_image(p_path, this);
@@ -2586,7 +2586,7 @@ Error Image::load(const String &p_path) {
 Ref<Image> Image::load_from_file(const String &p_path) {
 Ref<Image> Image::load_from_file(const String &p_path) {
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 	if (p_path.begins_with("res://") && ResourceLoader::exists(p_path)) {
 	if (p_path.begins_with("res://") && ResourceLoader::exists(p_path)) {
-		WARN_PRINT("Loaded resource as image file, this will not work on export: '" + p_path + "'. Instead, import the image file as an Image resource and load it normally as a resource.");
+		WARN_PRINT(vformat("Loaded resource as image file, this will not work on export: '%s'. Instead, import the image file as an Image resource and load it normally as a resource.", p_path));
 	}
 	}
 #endif
 #endif
 	Ref<Image> image;
 	Ref<Image> image;
@@ -2649,7 +2649,7 @@ Error Image::save_webp(const String &p_path, const bool p_lossy, const float p_q
 	if (save_webp_func == nullptr) {
 	if (save_webp_func == nullptr) {
 		return ERR_UNAVAILABLE;
 		return ERR_UNAVAILABLE;
 	}
 	}
-	ERR_FAIL_COND_V_MSG(p_lossy && !(0.0f <= p_quality && p_quality <= 1.0f), ERR_INVALID_PARAMETER, "The WebP lossy quality was set to " + rtos(p_quality) + ", which is not valid. WebP lossy quality must be between 0.0 and 1.0 (inclusive).");
+	ERR_FAIL_COND_V_MSG(p_lossy && !(0.0f <= p_quality && p_quality <= 1.0f), ERR_INVALID_PARAMETER, vformat("The WebP lossy quality was set to %f, which is not valid. WebP lossy quality must be between 0.0 and 1.0 (inclusive).", p_quality));
 
 
 	return save_webp_func(p_path, Ref<Image>((Image *)this), p_lossy, p_quality);
 	return save_webp_func(p_path, Ref<Image>((Image *)this), p_lossy, p_quality);
 }
 }
@@ -2658,7 +2658,7 @@ Vector<uint8_t> Image::save_webp_to_buffer(const bool p_lossy, const float p_qua
 	if (save_webp_buffer_func == nullptr) {
 	if (save_webp_buffer_func == nullptr) {
 		return Vector<uint8_t>();
 		return Vector<uint8_t>();
 	}
 	}
-	ERR_FAIL_COND_V_MSG(p_lossy && !(0.0f <= p_quality && p_quality <= 1.0f), Vector<uint8_t>(), "The WebP lossy quality was set to " + rtos(p_quality) + ", which is not valid. WebP lossy quality must be between 0.0 and 1.0 (inclusive).");
+	ERR_FAIL_COND_V_MSG(p_lossy && !(0.0f <= p_quality && p_quality <= 1.0f), Vector<uint8_t>(), vformat("The WebP lossy quality was set to %f, which is not valid. WebP lossy quality must be between 0.0 and 1.0 (inclusive).", p_quality));
 
 
 	return save_webp_buffer_func(Ref<Image>((Image *)this), p_lossy, p_quality);
 	return save_webp_buffer_func(Ref<Image>((Image *)this), p_lossy, p_quality);
 }
 }

+ 2 - 2
core/io/image_loader.cpp

@@ -87,7 +87,7 @@ Error ImageLoader::load_image(const String &p_file, Ref<Image> p_image, Ref<File
 	if (f.is_null()) {
 	if (f.is_null()) {
 		Error err;
 		Error err;
 		f = FileAccess::open(p_file, FileAccess::READ, &err);
 		f = FileAccess::open(p_file, FileAccess::READ, &err);
-		ERR_FAIL_COND_V_MSG(f.is_null(), err, "Error opening file '" + p_file + "'.");
+		ERR_FAIL_COND_V_MSG(f.is_null(), err, vformat("Error opening file '%s'.", p_file));
 	}
 	}
 
 
 	String extension = p_file.get_extension();
 	String extension = p_file.get_extension();
@@ -98,7 +98,7 @@ Error ImageLoader::load_image(const String &p_file, Ref<Image> p_image, Ref<File
 		}
 		}
 		Error err = loader.write[i]->load_image(p_image, f, p_flags, p_scale);
 		Error err = loader.write[i]->load_image(p_image, f, p_flags, p_scale);
 		if (err != OK) {
 		if (err != OK) {
-			ERR_PRINT("Error loading image: " + p_file);
+			ERR_PRINT(vformat("Error loading image: '%s'.", p_file));
 		}
 		}
 
 
 		if (err != ERR_FILE_UNRECOGNIZED) {
 		if (err != ERR_FILE_UNRECOGNIZED) {

+ 2 - 2
core/io/ip.cpp

@@ -201,7 +201,7 @@ IPAddress IP::get_resolve_item_address(ResolverID p_id) const {
 	MutexLock lock(resolver->mutex);
 	MutexLock lock(resolver->mutex);
 
 
 	if (resolver->queue[p_id].status.get() != IP::RESOLVER_STATUS_DONE) {
 	if (resolver->queue[p_id].status.get() != IP::RESOLVER_STATUS_DONE) {
-		ERR_PRINT("Resolve of '" + resolver->queue[p_id].hostname + "'' didn't complete yet.");
+		ERR_PRINT(vformat("Resolve of '%s' didn't complete yet.", resolver->queue[p_id].hostname));
 		return IPAddress();
 		return IPAddress();
 	}
 	}
 
 
@@ -220,7 +220,7 @@ Array IP::get_resolve_item_addresses(ResolverID p_id) const {
 	MutexLock lock(resolver->mutex);
 	MutexLock lock(resolver->mutex);
 
 
 	if (resolver->queue[p_id].status.get() != IP::RESOLVER_STATUS_DONE) {
 	if (resolver->queue[p_id].status.get() != IP::RESOLVER_STATUS_DONE) {
-		ERR_PRINT("Resolve of '" + resolver->queue[p_id].hostname + "'' didn't complete yet.");
+		ERR_PRINT(vformat("Resolve of '%s' didn't complete yet.", resolver->queue[p_id].hostname));
 		return Array();
 		return Array();
 	}
 	}
 
 

+ 1 - 1
core/io/json.cpp

@@ -1402,7 +1402,7 @@ Error ResourceFormatSaverJSON::save(const Ref<Resource> &p_resource, const Strin
 	Error err;
 	Error err;
 	Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err);
 	Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err);
 
 
-	ERR_FAIL_COND_V_MSG(err, err, "Cannot save json '" + p_path + "'.");
+	ERR_FAIL_COND_V_MSG(err, err, vformat("Cannot save json '%s'.", p_path));
 
 
 	file->store_string(source);
 	file->store_string(source);
 	if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
 	if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {

+ 4 - 4
core/io/marshalls.cpp

@@ -698,9 +698,9 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
 						if (str == "script" && value.get_type() != Variant::NIL) {
 						if (str == "script" && value.get_type() != Variant::NIL) {
 							ERR_FAIL_COND_V_MSG(value.get_type() != Variant::STRING, ERR_INVALID_DATA, "Invalid value for \"script\" property, expected script path as String.");
 							ERR_FAIL_COND_V_MSG(value.get_type() != Variant::STRING, ERR_INVALID_DATA, "Invalid value for \"script\" property, expected script path as String.");
 							String path = value;
 							String path = value;
-							ERR_FAIL_COND_V_MSG(path.is_empty() || !path.begins_with("res://") || !ResourceLoader::exists(path, "Script"), ERR_INVALID_DATA, "Invalid script path: '" + path + "'.");
+							ERR_FAIL_COND_V_MSG(path.is_empty() || !path.begins_with("res://") || !ResourceLoader::exists(path, "Script"), ERR_INVALID_DATA, vformat("Invalid script path: '%s'.", path));
 							Ref<Script> script = ResourceLoader::load(path, "Script");
 							Ref<Script> script = ResourceLoader::load(path, "Script");
-							ERR_FAIL_COND_V_MSG(script.is_null(), ERR_INVALID_DATA, "Can't load script at path: '" + path + "'.");
+							ERR_FAIL_COND_V_MSG(script.is_null(), ERR_INVALID_DATA, vformat("Can't load script at path: '%s'.", path));
 							obj->set_script(script);
 							obj->set_script(script);
 						} else {
 						} else {
 							obj->set(str, value);
 							obj->set(str, value);
@@ -820,9 +820,9 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
 
 
 					builtin_type = Variant::OBJECT;
 					builtin_type = Variant::OBJECT;
 					if (p_allow_objects) {
 					if (p_allow_objects) {
-						ERR_FAIL_COND_V_MSG(path.is_empty() || !path.begins_with("res://") || !ResourceLoader::exists(path, "Script"), ERR_INVALID_DATA, "Invalid script path: '" + path + "'.");
+						ERR_FAIL_COND_V_MSG(path.is_empty() || !path.begins_with("res://") || !ResourceLoader::exists(path, "Script"), ERR_INVALID_DATA, vformat("Invalid script path: '%s'.", path));
 						script = ResourceLoader::load(path, "Script");
 						script = ResourceLoader::load(path, "Script");
-						ERR_FAIL_COND_V_MSG(script.is_null(), ERR_INVALID_DATA, "Can't load script at path: '" + path + "'.");
+						ERR_FAIL_COND_V_MSG(script.is_null(), ERR_INVALID_DATA, vformat("Can't load script at path: '%s'.", path));
 						class_name = script->get_instance_base_type();
 						class_name = script->get_instance_base_type();
 					} else {
 					} else {
 						class_name = EncodedObjectAsID::get_class_static();
 						class_name = EncodedObjectAsID::get_class_static();

+ 1 - 1
core/io/pck_packer.cpp

@@ -84,7 +84,7 @@ Error PCKPacker::pck_start(const String &p_pck_path, int p_alignment, const Stri
 	enc_dir = p_encrypt_directory;
 	enc_dir = p_encrypt_directory;
 
 
 	file = FileAccess::open(p_pck_path, FileAccess::WRITE);
 	file = FileAccess::open(p_pck_path, FileAccess::WRITE);
-	ERR_FAIL_COND_V_MSG(file.is_null(), ERR_CANT_CREATE, "Can't open file to write: " + String(p_pck_path) + ".");
+	ERR_FAIL_COND_V_MSG(file.is_null(), ERR_CANT_CREATE, vformat("Can't open file to write: '%s'.", String(p_pck_path)));
 
 
 	alignment = p_alignment;
 	alignment = p_alignment;
 
 

+ 1 - 1
core/io/plist.cpp

@@ -450,7 +450,7 @@ PList::PList() {
 PList::PList(const String &p_string) {
 PList::PList(const String &p_string) {
 	String err_str;
 	String err_str;
 	bool ok = load_string(p_string, err_str);
 	bool ok = load_string(p_string, err_str);
-	ERR_FAIL_COND_MSG(!ok, "PList: " + err_str);
+	ERR_FAIL_COND_MSG(!ok, vformat("PList: %s.", err_str));
 }
 }
 
 
 uint64_t PList::read_bplist_var_size_int(Ref<FileAccess> p_file, uint8_t p_size) {
 uint64_t PList::read_bplist_var_size_int(Ref<FileAccess> p_file, uint8_t p_size) {

+ 7 - 7
core/io/remote_filesystem_client.cpp

@@ -96,7 +96,7 @@ Error RemoteFilesystemClient::_store_file(const String &p_path, const LocalVecto
 	}
 	}
 
 
 	Ref<FileAccess> f = FileAccess::open(full_path, FileAccess::WRITE);
 	Ref<FileAccess> f = FileAccess::open(full_path, FileAccess::WRITE);
-	ERR_FAIL_COND_V_MSG(f.is_null(), ERR_FILE_CANT_OPEN, "Unable to open file for writing to remote filesystem cache: " + p_path);
+	ERR_FAIL_COND_V_MSG(f.is_null(), ERR_FILE_CANT_OPEN, vformat("Unable to open file for writing to remote filesystem cache: '%s'.", p_path));
 	f->store_buffer(p_file.ptr(), p_file.size());
 	f->store_buffer(p_file.ptr(), p_file.size());
 	Error err = f->get_error();
 	Error err = f->get_error();
 	if (err) {
 	if (err) {
@@ -115,10 +115,10 @@ Error RemoteFilesystemClient::_store_cache_file(const Vector<FileCache> &p_cache
 	String full_path = cache_path.path_join(FILES_CACHE_FILE);
 	String full_path = cache_path.path_join(FILES_CACHE_FILE);
 	String base_file_dir = full_path.get_base_dir();
 	String base_file_dir = full_path.get_base_dir();
 	Error err = DirAccess::make_dir_recursive_absolute(base_file_dir);
 	Error err = DirAccess::make_dir_recursive_absolute(base_file_dir);
-	ERR_FAIL_COND_V_MSG(err != OK && err != ERR_ALREADY_EXISTS, err, "Unable to create base directory to store cache file: " + base_file_dir);
+	ERR_FAIL_COND_V_MSG(err != OK && err != ERR_ALREADY_EXISTS, err, vformat("Unable to create base directory to store cache file: '%s'.", base_file_dir));
 
 
 	Ref<FileAccess> f = FileAccess::open(full_path, FileAccess::WRITE);
 	Ref<FileAccess> f = FileAccess::open(full_path, FileAccess::WRITE);
-	ERR_FAIL_COND_V_MSG(f.is_null(), ERR_FILE_CANT_OPEN, "Unable to open the remote cache file for writing: " + full_path);
+	ERR_FAIL_COND_V_MSG(f.is_null(), ERR_FILE_CANT_OPEN, vformat("Unable to open the remote cache file for writing: '%s'.", full_path));
 	f->store_line(itos(FILESYSTEM_CACHE_VERSION));
 	f->store_line(itos(FILESYSTEM_CACHE_VERSION));
 	for (int i = 0; i < p_cache.size(); i++) {
 	for (int i = 0; i < p_cache.size(); i++) {
 		String l = p_cache[i].path + "::" + itos(p_cache[i].server_modified_time) + "::" + itos(p_cache[i].modified_time);
 		String l = p_cache[i].path + "::" + itos(p_cache[i].server_modified_time) + "::" + itos(p_cache[i].modified_time);
@@ -151,10 +151,10 @@ Error RemoteFilesystemClient::_synchronize_with_server(const String &p_host, int
 	tcp_client.instantiate();
 	tcp_client.instantiate();
 
 
 	IPAddress ip = p_host.is_valid_ip_address() ? IPAddress(p_host) : IP::get_singleton()->resolve_hostname(p_host);
 	IPAddress ip = p_host.is_valid_ip_address() ? IPAddress(p_host) : IP::get_singleton()->resolve_hostname(p_host);
-	ERR_FAIL_COND_V_MSG(!ip.is_valid(), ERR_INVALID_PARAMETER, "Unable to resolve remote filesystem server hostname: " + p_host);
+	ERR_FAIL_COND_V_MSG(!ip.is_valid(), ERR_INVALID_PARAMETER, vformat("Unable to resolve remote filesystem server hostname: '%s'.", p_host));
 	print_verbose(vformat("Remote Filesystem: Connecting to host %s, port %d.", ip, p_port));
 	print_verbose(vformat("Remote Filesystem: Connecting to host %s, port %d.", ip, p_port));
 	Error err = tcp_client->connect_to_host(ip, p_port);
 	Error err = tcp_client->connect_to_host(ip, p_port);
-	ERR_FAIL_COND_V_MSG(err != OK, err, "Unable to open connection to remote file server (" + String(p_host) + ", port " + itos(p_port) + ") failed.");
+	ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Unable to open connection to remote file server (%s, port %d) failed.", String(p_host), p_port));
 
 
 	while (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTING) {
 	while (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTING) {
 		tcp_client->poll();
 		tcp_client->poll();
@@ -162,7 +162,7 @@ Error RemoteFilesystemClient::_synchronize_with_server(const String &p_host, int
 	}
 	}
 
 
 	if (tcp_client->get_status() != StreamPeerTCP::STATUS_CONNECTED) {
 	if (tcp_client->get_status() != StreamPeerTCP::STATUS_CONNECTED) {
-		ERR_FAIL_V_MSG(ERR_CANT_CONNECT, "Connection to remote file server (" + String(p_host) + ", port " + itos(p_port) + ") failed.");
+		ERR_FAIL_V_MSG(ERR_CANT_CONNECT, vformat("Connection to remote file server (%s, port %d) failed.", String(p_host), p_port));
 	}
 	}
 
 
 	// Connection OK, now send the current file state.
 	// Connection OK, now send the current file state.
@@ -280,7 +280,7 @@ Error RemoteFilesystemClient::_synchronize_with_server(const String &p_host, int
 
 
 		err = tcp_client->get_data(file_buffer.ptr(), file_size);
 		err = tcp_client->get_data(file_buffer.ptr(), file_size);
 		if (err != OK) {
 		if (err != OK) {
-			ERR_PRINT("Error retrieving file from remote filesystem: " + file);
+			ERR_PRINT(vformat("Error retrieving file from remote filesystem: '%s'.", file));
 			server_disconnected = true;
 			server_disconnected = true;
 		}
 		}
 
 

+ 1 - 1
core/io/resource.cpp

@@ -76,7 +76,7 @@ void Resource::set_path(const String &p_path, bool p_take_over) {
 				existing->path_cache = String();
 				existing->path_cache = String();
 				ResourceCache::resources.erase(p_path);
 				ResourceCache::resources.erase(p_path);
 			} else {
 			} else {
-				ERR_FAIL_MSG("Another resource is loaded from path '" + p_path + "' (possible cyclic resource inclusion).");
+				ERR_FAIL_MSG(vformat("Another resource is loaded from path '%s' (possible cyclic resource inclusion).", p_path));
 			}
 			}
 		}
 		}
 
 

+ 28 - 28
core/io/resource_format_binary.cpp

@@ -411,7 +411,7 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
 
 
 					//always use internal cache for loading internal resources
 					//always use internal cache for loading internal resources
 					if (!internal_index_cache.has(path)) {
 					if (!internal_index_cache.has(path)) {
-						WARN_PRINT(String("Couldn't load resource (no cache): " + path).utf8().get_data());
+						WARN_PRINT(vformat("Couldn't load resource (no cache): %s.", path));
 						r_v = Variant();
 						r_v = Variant();
 					} else {
 					} else {
 						r_v = internal_index_cache[path];
 						r_v = internal_index_cache[path];
@@ -435,7 +435,7 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
 					Ref<Resource> res = ResourceLoader::load(path, exttype, cache_mode_for_external);
 					Ref<Resource> res = ResourceLoader::load(path, exttype, cache_mode_for_external);
 
 
 					if (res.is_null()) {
 					if (res.is_null()) {
-						WARN_PRINT(String("Couldn't load resource: " + path).utf8().get_data());
+						WARN_PRINT(vformat("Couldn't load resource: %s.", path));
 					}
 					}
 					r_v = res;
 					r_v = res;
 
 
@@ -458,7 +458,7 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
 										ResourceLoader::notify_dependency_error(local_path, external_resources[erindex].path, external_resources[erindex].type);
 										ResourceLoader::notify_dependency_error(local_path, external_resources[erindex].path, external_resources[erindex].type);
 									} else {
 									} else {
 										error = ERR_FILE_MISSING_DEPENDENCIES;
 										error = ERR_FILE_MISSING_DEPENDENCIES;
-										ERR_FAIL_V_MSG(error, "Can't load dependency: " + external_resources[erindex].path + ".");
+										ERR_FAIL_V_MSG(error, vformat("Can't load dependency: '%s'.", external_resources[erindex].path));
 									}
 									}
 								}
 								}
 							} else {
 							} else {
@@ -704,7 +704,7 @@ Error ResourceLoaderBinary::load() {
 				ResourceLoader::notify_dependency_error(local_path, path, external_resources[i].type);
 				ResourceLoader::notify_dependency_error(local_path, path, external_resources[i].type);
 			} else {
 			} else {
 				error = ERR_FILE_MISSING_DEPENDENCIES;
 				error = ERR_FILE_MISSING_DEPENDENCIES;
-				ERR_FAIL_V_MSG(error, "Can't load dependency: " + path + ".");
+				ERR_FAIL_V_MSG(error, vformat("Can't load dependency: '%s'.", path));
 			}
 			}
 		}
 		}
 	}
 	}
@@ -780,7 +780,7 @@ Error ResourceLoaderBinary::load() {
 						obj = missing_resource;
 						obj = missing_resource;
 					} else {
 					} else {
 						error = ERR_FILE_CORRUPT;
 						error = ERR_FILE_CORRUPT;
-						ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, local_path + ":Resource of unrecognized type in file: " + t + ".");
+						ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, vformat("'%s': Resource of unrecognized type in file: '%s'.", local_path, t));
 					}
 					}
 				}
 				}
 
 
@@ -789,7 +789,7 @@ Error ResourceLoaderBinary::load() {
 					String obj_class = obj->get_class();
 					String obj_class = obj->get_class();
 					error = ERR_FILE_CORRUPT;
 					error = ERR_FILE_CORRUPT;
 					memdelete(obj); //bye
 					memdelete(obj); //bye
-					ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, local_path + ":Resource type in resource field not a resource, type is: " + obj_class + ".");
+					ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, vformat("'%s': Resource type in resource field not a resource, type is: %s.", local_path, obj_class));
 				}
 				}
 
 
 				res = Ref<Resource>(r);
 				res = Ref<Resource>(r);
@@ -999,7 +999,7 @@ void ResourceLoaderBinary::open(Ref<FileAccess> p_f, bool p_no_resources, bool p
 		error = fac->open_after_magic(f);
 		error = fac->open_after_magic(f);
 		if (error != OK) {
 		if (error != OK) {
 			f.unref();
 			f.unref();
-			ERR_FAIL_MSG("Failed to open binary resource file: " + local_path + ".");
+			ERR_FAIL_MSG(vformat("Failed to open binary resource file: '%s'.", local_path));
 		}
 		}
 		f = fac;
 		f = fac;
 
 
@@ -1007,7 +1007,7 @@ void ResourceLoaderBinary::open(Ref<FileAccess> p_f, bool p_no_resources, bool p
 		// Not normal.
 		// Not normal.
 		error = ERR_FILE_UNRECOGNIZED;
 		error = ERR_FILE_UNRECOGNIZED;
 		f.unref();
 		f.unref();
-		ERR_FAIL_MSG("Unrecognized binary resource file: " + local_path + ".");
+		ERR_FAIL_MSG(vformat("Unrecognized binary resource file: '%s'.", local_path));
 	}
 	}
 
 
 	bool big_endian = f->get_32();
 	bool big_endian = f->get_32();
@@ -1093,10 +1093,10 @@ void ResourceLoaderBinary::open(Ref<FileAccess> p_f, bool p_no_resources, bool p
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
 					// Silence a warning that can happen during the initial filesystem scan due to cache being regenerated.
 					// Silence a warning that can happen during the initial filesystem scan due to cache being regenerated.
 					if (ResourceLoader::get_resource_uid(res_path) != er.uid) {
 					if (ResourceLoader::get_resource_uid(res_path) != er.uid) {
-						WARN_PRINT(String(res_path + ": In external resource #" + itos(i) + ", invalid UID: " + ResourceUID::get_singleton()->id_to_text(er.uid) + " - using text path instead: " + er.path).utf8().get_data());
+						WARN_PRINT(vformat("'%s': In external resource #%d, invalid UID: '%s' - using text path instead: '%s'.", res_path, i, ResourceUID::get_singleton()->id_to_text(er.uid), er.path));
 					}
 					}
 #else
 #else
-					WARN_PRINT(String(res_path + ": In external resource #" + itos(i) + ", invalid UID: " + ResourceUID::get_singleton()->id_to_text(er.uid) + " - using text path instead: " + er.path).utf8().get_data());
+					WARN_PRINT(vformat("'%s': In external resource #%d, invalid UID: '%s' - using text path instead: '%s'.", res_path, i, ResourceUID::get_singleton()->id_to_text(er.uid), er.path));
 #endif
 #endif
 				}
 				}
 			}
 			}
@@ -1120,7 +1120,7 @@ void ResourceLoaderBinary::open(Ref<FileAccess> p_f, bool p_no_resources, bool p
 	if (f->eof_reached()) {
 	if (f->eof_reached()) {
 		error = ERR_FILE_CORRUPT;
 		error = ERR_FILE_CORRUPT;
 		f.unref();
 		f.unref();
-		ERR_FAIL_MSG("Premature end of file (EOF): " + local_path + ".");
+		ERR_FAIL_MSG(vformat("Premature end of file (EOF): '%s'.", local_path));
 	}
 	}
 }
 }
 
 
@@ -1224,7 +1224,7 @@ Ref<Resource> ResourceFormatLoaderBinary::load(const String &p_path, const Strin
 	Error err;
 	Error err;
 	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
 	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
 
 
-	ERR_FAIL_COND_V_MSG(err != OK, Ref<Resource>(), "Cannot open file '" + p_path + "'.");
+	ERR_FAIL_COND_V_MSG(err != OK, Ref<Resource>(), vformat("Cannot open file '%s'.", p_path));
 
 
 	ResourceLoaderBinary loader;
 	ResourceLoaderBinary loader;
 	switch (p_cache_mode) {
 	switch (p_cache_mode) {
@@ -1301,7 +1301,7 @@ bool ResourceFormatLoaderBinary::handles_type(const String &p_type) const {
 
 
 void ResourceFormatLoaderBinary::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
 void ResourceFormatLoaderBinary::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
 	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
 	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
-	ERR_FAIL_COND_MSG(f.is_null(), "Cannot open file '" + p_path + "'.");
+	ERR_FAIL_COND_MSG(f.is_null(), vformat("Cannot open file '%s'.", p_path));
 
 
 	ResourceLoaderBinary loader;
 	ResourceLoaderBinary loader;
 	loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
 	loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
@@ -1311,7 +1311,7 @@ void ResourceFormatLoaderBinary::get_dependencies(const String &p_path, List<Str
 
 
 Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, const HashMap<String, String> &p_map) {
 Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, const HashMap<String, String> &p_map) {
 	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
 	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
-	ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, "Cannot open file '" + p_path + "'.");
+	ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, vformat("Cannot open file '%s'.", p_path));
 
 
 	Ref<FileAccess> fw;
 	Ref<FileAccess> fw;
 
 
@@ -1324,23 +1324,23 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
 		Ref<FileAccessCompressed> fac;
 		Ref<FileAccessCompressed> fac;
 		fac.instantiate();
 		fac.instantiate();
 		Error err = fac->open_after_magic(f);
 		Error err = fac->open_after_magic(f);
-		ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot open file '" + p_path + "'.");
+		ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Cannot open file '%s'.", p_path));
 		f = fac;
 		f = fac;
 
 
 		Ref<FileAccessCompressed> facw;
 		Ref<FileAccessCompressed> facw;
 		facw.instantiate();
 		facw.instantiate();
 		facw->configure("RSCC");
 		facw->configure("RSCC");
 		err = facw->open_internal(p_path + ".depren", FileAccess::WRITE);
 		err = facw->open_internal(p_path + ".depren", FileAccess::WRITE);
-		ERR_FAIL_COND_V_MSG(err, ERR_FILE_CORRUPT, "Cannot create file '" + p_path + ".depren'.");
+		ERR_FAIL_COND_V_MSG(err, ERR_FILE_CORRUPT, vformat("Cannot create file '%s.depren'.", p_path));
 
 
 		fw = facw;
 		fw = facw;
 
 
 	} else if (header[0] != 'R' || header[1] != 'S' || header[2] != 'R' || header[3] != 'C') {
 	} else if (header[0] != 'R' || header[1] != 'S' || header[2] != 'R' || header[3] != 'C') {
 		// Not normal.
 		// Not normal.
-		ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, "Unrecognized binary resource file '" + local_path + "'.");
+		ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, vformat("Unrecognized binary resource file '%s'.", local_path));
 	} else {
 	} else {
 		fw = FileAccess::open(p_path + ".depren", FileAccess::WRITE);
 		fw = FileAccess::open(p_path + ".depren", FileAccess::WRITE);
-		ERR_FAIL_COND_V_MSG(fw.is_null(), ERR_CANT_CREATE, "Cannot create file '" + p_path + ".depren'.");
+		ERR_FAIL_COND_V_MSG(fw.is_null(), ERR_CANT_CREATE, vformat("Cannot create file '%s.depren'.", p_path));
 
 
 		uint8_t magic[4] = { 'R', 'S', 'R', 'C' };
 		uint8_t magic[4] = { 'R', 'S', 'R', 'C' };
 		fw->store_buffer(magic, 4);
 		fw->store_buffer(magic, 4);
@@ -1372,12 +1372,12 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
 
 
 		// Use the old approach.
 		// Use the old approach.
 
 
-		WARN_PRINT("This file is old, so it can't refactor dependencies, opening and resaving '" + p_path + "'.");
+		WARN_PRINT(vformat("This file is old, so it can't refactor dependencies, opening and resaving '%s'.", p_path));
 
 
 		Error err;
 		Error err;
 		f = FileAccess::open(p_path, FileAccess::READ, &err);
 		f = FileAccess::open(p_path, FileAccess::READ, &err);
 
 
-		ERR_FAIL_COND_V_MSG(err != OK, ERR_FILE_CANT_OPEN, "Cannot open file '" + p_path + "'.");
+		ERR_FAIL_COND_V_MSG(err != OK, ERR_FILE_CANT_OPEN, vformat("Cannot open file '%s'.", p_path));
 
 
 		ResourceLoaderBinary loader;
 		ResourceLoaderBinary loader;
 		loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
 		loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
@@ -1523,7 +1523,7 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
 
 
 void ResourceFormatLoaderBinary::get_classes_used(const String &p_path, HashSet<StringName> *r_classes) {
 void ResourceFormatLoaderBinary::get_classes_used(const String &p_path, HashSet<StringName> *r_classes) {
 	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
 	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
-	ERR_FAIL_COND_MSG(f.is_null(), "Cannot open file '" + p_path + "'.");
+	ERR_FAIL_COND_MSG(f.is_null(), vformat("Cannot open file '%s'.", p_path));
 
 
 	ResourceLoaderBinary loader;
 	ResourceLoaderBinary loader;
 	loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
 	loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
@@ -2027,7 +2027,7 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant
 
 
 			if (!p_main && (!bundle_resources) && !res->is_built_in()) {
 			if (!p_main && (!bundle_resources) && !res->is_built_in()) {
 				if (res->get_path() == path) {
 				if (res->get_path() == path) {
-					ERR_PRINT("Circular reference to resource being saved found: '" + local_path + "' will be null next time it's loaded.");
+					ERR_PRINT(vformat("Circular reference to resource being saved found: '%s' will be null next time it's loaded.", local_path));
 					return;
 					return;
 				}
 				}
 				int idx = external_resources.size();
 				int idx = external_resources.size();
@@ -2153,7 +2153,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const Ref<Re
 		f = FileAccess::open(p_path, FileAccess::WRITE, &err);
 		f = FileAccess::open(p_path, FileAccess::WRITE, &err);
 	}
 	}
 
 
-	ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot create file '" + p_path + "'.");
+	ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Cannot create file '%s'.", p_path));
 
 
 	relative_paths = p_flags & ResourceSaver::FLAG_RELATIVE_PATHS;
 	relative_paths = p_flags & ResourceSaver::FLAG_RELATIVE_PATHS;
 	skip_editor = p_flags & ResourceSaver::FLAG_OMIT_EDITOR_PROPERTIES;
 	skip_editor = p_flags & ResourceSaver::FLAG_OMIT_EDITOR_PROPERTIES;
@@ -2384,7 +2384,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const Ref<Re
 
 
 Error ResourceFormatSaverBinaryInstance::set_uid(const String &p_path, ResourceUID::ID p_uid) {
 Error ResourceFormatSaverBinaryInstance::set_uid(const String &p_path, ResourceUID::ID p_uid) {
 	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
 	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
-	ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, "Cannot open file '" + p_path + "'.");
+	ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, vformat("Cannot open file '%s'.", p_path));
 
 
 	Ref<FileAccess> fw;
 	Ref<FileAccess> fw;
 
 
@@ -2397,14 +2397,14 @@ Error ResourceFormatSaverBinaryInstance::set_uid(const String &p_path, ResourceU
 		Ref<FileAccessCompressed> fac;
 		Ref<FileAccessCompressed> fac;
 		fac.instantiate();
 		fac.instantiate();
 		Error err = fac->open_after_magic(f);
 		Error err = fac->open_after_magic(f);
-		ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot open file '" + p_path + "'.");
+		ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Cannot open file '%s'.", p_path));
 		f = fac;
 		f = fac;
 
 
 		Ref<FileAccessCompressed> facw;
 		Ref<FileAccessCompressed> facw;
 		facw.instantiate();
 		facw.instantiate();
 		facw->configure("RSCC");
 		facw->configure("RSCC");
 		err = facw->open_internal(p_path + ".uidren", FileAccess::WRITE);
 		err = facw->open_internal(p_path + ".uidren", FileAccess::WRITE);
-		ERR_FAIL_COND_V_MSG(err, ERR_FILE_CORRUPT, "Cannot create file '" + p_path + ".uidren'.");
+		ERR_FAIL_COND_V_MSG(err, ERR_FILE_CORRUPT, vformat("Cannot create file '%s.uidren'.", p_path));
 
 
 		fw = facw;
 		fw = facw;
 
 
@@ -2413,7 +2413,7 @@ Error ResourceFormatSaverBinaryInstance::set_uid(const String &p_path, ResourceU
 		return ERR_FILE_UNRECOGNIZED;
 		return ERR_FILE_UNRECOGNIZED;
 	} else {
 	} else {
 		fw = FileAccess::open(p_path + ".uidren", FileAccess::WRITE);
 		fw = FileAccess::open(p_path + ".uidren", FileAccess::WRITE);
-		ERR_FAIL_COND_V_MSG(fw.is_null(), ERR_CANT_CREATE, "Cannot create file '" + p_path + ".uidren'.");
+		ERR_FAIL_COND_V_MSG(fw.is_null(), ERR_CANT_CREATE, vformat("Cannot create file '%s.uidren'.", p_path));
 
 
 		uint8_t magich[4] = { 'R', 'S', 'R', 'C' };
 		uint8_t magich[4] = { 'R', 'S', 'R', 'C' };
 		fw->store_buffer(magich, 4);
 		fw->store_buffer(magich, 4);
@@ -2444,7 +2444,7 @@ Error ResourceFormatSaverBinaryInstance::set_uid(const String &p_path, ResourceU
 
 
 		// Use the old approach.
 		// Use the old approach.
 
 
-		WARN_PRINT("This file is old, so it does not support UIDs, opening and resaving '" + p_path + "'.");
+		WARN_PRINT(vformat("This file is old, so it does not support UIDs, opening and resaving '%s'.", p_path));
 		return ERR_UNAVAILABLE;
 		return ERR_UNAVAILABLE;
 	}
 	}
 
 

+ 2 - 2
core/io/resource_importer.cpp

@@ -75,7 +75,7 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy
 		if (err == ERR_FILE_EOF) {
 		if (err == ERR_FILE_EOF) {
 			return OK;
 			return OK;
 		} else if (err != OK) {
 		} else if (err != OK) {
-			ERR_PRINT("ResourceFormatImporter::load - " + p_path + ".import:" + itos(lines) + " error: " + error_text);
+			ERR_PRINT(vformat("ResourceFormatImporter::load - %s.import:%d error: %s.", p_path, lines, error_text));
 			return err;
 			return err;
 		}
 		}
 
 
@@ -335,7 +335,7 @@ void ResourceFormatImporter::get_internal_resource_path_list(const String &p_pat
 		if (err == ERR_FILE_EOF) {
 		if (err == ERR_FILE_EOF) {
 			return;
 			return;
 		} else if (err != OK) {
 		} else if (err != OK) {
-			ERR_PRINT("ResourceFormatImporter::get_internal_resource_path_list - " + p_path + ".import:" + itos(lines) + " error: " + error_text);
+			ERR_PRINT(vformat("ResourceFormatImporter::get_internal_resource_path_list - %s.import:%d error: %s.", p_path, lines, error_text));
 			return;
 			return;
 		}
 		}
 
 

+ 3 - 3
core/io/resource_loader.cpp

@@ -162,7 +162,7 @@ Ref<Resource> ResourceFormatLoader::load(const String &p_path, const String &p_o
 		}
 		}
 	}
 	}
 
 
-	ERR_FAIL_V_MSG(Ref<Resource>(), "Failed to load resource '" + p_path + "'. ResourceFormatLoader::load was not implemented for this resource type.");
+	ERR_FAIL_V_MSG(Ref<Resource>(), vformat("Failed to load resource '%s'. ResourceFormatLoader::load was not implemented for this resource type.", p_path));
 }
 }
 
 
 void ResourceFormatLoader::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
 void ResourceFormatLoader::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
@@ -1163,7 +1163,7 @@ String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_rem
 		// An extra remap may still be necessary afterwards due to the text -> binary converter on export.
 		// An extra remap may still be necessary afterwards due to the text -> binary converter on export.
 
 
 		String locale = TranslationServer::get_singleton()->get_locale();
 		String locale = TranslationServer::get_singleton()->get_locale();
-		ERR_FAIL_COND_V_MSG(locale.length() < 2, p_path, "Could not remap path '" + p_path + "' for translation as configured locale '" + locale + "' is invalid.");
+		ERR_FAIL_COND_V_MSG(locale.length() < 2, p_path, vformat("Could not remap path '%s' for translation as configured locale '%s' is invalid.", p_path, locale));
 
 
 		Vector<String> &res_remaps = *translation_remaps.getptr(new_path);
 		Vector<String> &res_remaps = *translation_remaps.getptr(new_path);
 
 
@@ -1222,7 +1222,7 @@ String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_rem
 					if (err == ERR_FILE_EOF) {
 					if (err == ERR_FILE_EOF) {
 						break;
 						break;
 					} else if (err != OK) {
 					} else if (err != OK) {
-						ERR_PRINT("Parse error: " + p_path + ".remap:" + itos(lines) + " error: " + error_text + ".");
+						ERR_PRINT(vformat("Parse error: %s.remap:%d error: %s.", p_path, lines, error_text));
 						break;
 						break;
 					}
 					}
 
 

+ 1 - 1
core/io/resource_saver.cpp

@@ -98,7 +98,7 @@ void ResourceFormatSaver::_bind_methods() {
 }
 }
 
 
 Error ResourceSaver::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) {
 Error ResourceSaver::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) {
-	ERR_FAIL_COND_V_MSG(p_resource.is_null(), ERR_INVALID_PARAMETER, "Can't save empty resource to path '" + p_path + "'.");
+	ERR_FAIL_COND_V_MSG(p_resource.is_null(), ERR_INVALID_PARAMETER, vformat("Can't save empty resource to path '%s'.", p_path));
 	String path = p_path;
 	String path = p_path;
 	if (path.is_empty()) {
 	if (path.is_empty()) {
 		path = p_resource->get_path();
 		path = p_resource->get_path();

+ 15 - 15
core/io/translation_loader_po.cpp

@@ -169,14 +169,14 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_
 			// If we reached last line and it's not a content line, break, otherwise let processing that last loop
 			// If we reached last line and it's not a content line, break, otherwise let processing that last loop
 			if (is_eof && l.is_empty()) {
 			if (is_eof && l.is_empty()) {
 				if (status == STATUS_READING_ID || status == STATUS_READING_CONTEXT || (status == STATUS_READING_PLURAL && plural_index != plural_forms - 1)) {
 				if (status == STATUS_READING_ID || status == STATUS_READING_CONTEXT || (status == STATUS_READING_PLURAL && plural_index != plural_forms - 1)) {
-					ERR_FAIL_V_MSG(Ref<Resource>(), "Unexpected EOF while reading PO file at: " + path + ":" + itos(line));
+					ERR_FAIL_V_MSG(Ref<Resource>(), vformat("Unexpected EOF while reading PO file at: %s:%d.", path, line));
 				} else {
 				} else {
 					break;
 					break;
 				}
 				}
 			}
 			}
 
 
 			if (l.begins_with("msgctxt")) {
 			if (l.begins_with("msgctxt")) {
-				ERR_FAIL_COND_V_MSG(status != STATUS_READING_STRING && status != STATUS_READING_PLURAL, Ref<Resource>(), "Unexpected 'msgctxt', was expecting 'msgid_plural' or 'msgstr' before 'msgctxt' while parsing: " + path + ":" + itos(line));
+				ERR_FAIL_COND_V_MSG(status != STATUS_READING_STRING && status != STATUS_READING_PLURAL, Ref<Resource>(), vformat("Unexpected 'msgctxt', was expecting 'msgid_plural' or 'msgstr' before 'msgctxt' while parsing: %s:%d.", path, line));
 
 
 				// In PO file, "msgctxt" appears before "msgid". If we encounter a "msgctxt", we add what we have read
 				// In PO file, "msgctxt" appears before "msgid". If we encounter a "msgctxt", we add what we have read
 				// and set "entered_context" to true to prevent adding twice.
 				// and set "entered_context" to true to prevent adding twice.
@@ -184,7 +184,7 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_
 					if (status == STATUS_READING_STRING) {
 					if (status == STATUS_READING_STRING) {
 						translation->add_message(msg_id, msg_str, msg_context);
 						translation->add_message(msg_id, msg_str, msg_context);
 					} else if (status == STATUS_READING_PLURAL) {
 					} else if (status == STATUS_READING_PLURAL) {
-						ERR_FAIL_COND_V_MSG(plural_index != plural_forms - 1, Ref<Resource>(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line));
+						ERR_FAIL_COND_V_MSG(plural_index != plural_forms - 1, Ref<Resource>(), vformat("Number of 'msgstr[]' doesn't match with number of plural forms: %s:%d.", path, line));
 						translation->add_plural_message(msg_id, msgs_plural, msg_context);
 						translation->add_plural_message(msg_id, msgs_plural, msg_context);
 					}
 					}
 				}
 				}
@@ -196,9 +196,9 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_
 
 
 			if (l.begins_with("msgid_plural")) {
 			if (l.begins_with("msgid_plural")) {
 				if (plural_forms == 0) {
 				if (plural_forms == 0) {
-					ERR_FAIL_V_MSG(Ref<Resource>(), "PO file uses 'msgid_plural' but 'Plural-Forms' is invalid or missing in header: " + path + ":" + itos(line));
+					ERR_FAIL_V_MSG(Ref<Resource>(), vformat("PO file uses 'msgid_plural' but 'Plural-Forms' is invalid or missing in header: %s:%d.", path, line));
 				} else if (status != STATUS_READING_ID) {
 				} else if (status != STATUS_READING_ID) {
-					ERR_FAIL_V_MSG(Ref<Resource>(), "Unexpected 'msgid_plural', was expecting 'msgid' before 'msgid_plural' while parsing: " + path + ":" + itos(line));
+					ERR_FAIL_V_MSG(Ref<Resource>(), vformat("Unexpected 'msgid_plural', was expecting 'msgid' before 'msgid_plural' while parsing: %s:%d.", path, line));
 				}
 				}
 				// We don't record the message in "msgid_plural" itself as tr_n(), TTRN(), RTRN() interfaces provide the plural string already.
 				// We don't record the message in "msgid_plural" itself as tr_n(), TTRN(), RTRN() interfaces provide the plural string already.
 				// We just have to reset variables related to plurals for "msgstr[]" later on.
 				// We just have to reset variables related to plurals for "msgstr[]" later on.
@@ -208,14 +208,14 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_
 				msgs_plural.resize(plural_forms);
 				msgs_plural.resize(plural_forms);
 				status = STATUS_READING_PLURAL;
 				status = STATUS_READING_PLURAL;
 			} else if (l.begins_with("msgid")) {
 			} else if (l.begins_with("msgid")) {
-				ERR_FAIL_COND_V_MSG(status == STATUS_READING_ID, Ref<Resource>(), "Unexpected 'msgid', was expecting 'msgstr' while parsing: " + path + ":" + itos(line));
+				ERR_FAIL_COND_V_MSG(status == STATUS_READING_ID, Ref<Resource>(), vformat("Unexpected 'msgid', was expecting 'msgstr' while parsing: %s:%d.", path, line));
 
 
 				if (!msg_id.is_empty()) {
 				if (!msg_id.is_empty()) {
 					if (!skip_this && !entered_context) {
 					if (!skip_this && !entered_context) {
 						if (status == STATUS_READING_STRING) {
 						if (status == STATUS_READING_STRING) {
 							translation->add_message(msg_id, msg_str, msg_context);
 							translation->add_message(msg_id, msg_str, msg_context);
 						} else if (status == STATUS_READING_PLURAL) {
 						} else if (status == STATUS_READING_PLURAL) {
-							ERR_FAIL_COND_V_MSG(plural_index != plural_forms - 1, Ref<Resource>(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line));
+							ERR_FAIL_COND_V_MSG(plural_index != plural_forms - 1, Ref<Resource>(), vformat("Number of 'msgstr[]' doesn't match with number of plural forms: %s:%d.", path, line));
 							translation->add_plural_message(msg_id, msgs_plural, msg_context);
 							translation->add_plural_message(msg_id, msgs_plural, msg_context);
 						}
 						}
 					}
 					}
@@ -244,11 +244,11 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_
 			}
 			}
 
 
 			if (l.begins_with("msgstr[")) {
 			if (l.begins_with("msgstr[")) {
-				ERR_FAIL_COND_V_MSG(status != STATUS_READING_PLURAL, Ref<Resource>(), "Unexpected 'msgstr[]', was expecting 'msgid_plural' before 'msgstr[]' while parsing: " + path + ":" + itos(line));
+				ERR_FAIL_COND_V_MSG(status != STATUS_READING_PLURAL, Ref<Resource>(), vformat("Unexpected 'msgstr[]', was expecting 'msgid_plural' before 'msgstr[]' while parsing: %s:%d.", path, line));
 				plural_index++; // Increment to add to the next slot in vector msgs_plural.
 				plural_index++; // Increment to add to the next slot in vector msgs_plural.
 				l = l.substr(9, l.length()).strip_edges();
 				l = l.substr(9, l.length()).strip_edges();
 			} else if (l.begins_with("msgstr")) {
 			} else if (l.begins_with("msgstr")) {
-				ERR_FAIL_COND_V_MSG(status != STATUS_READING_ID, Ref<Resource>(), "Unexpected 'msgstr', was expecting 'msgid' before 'msgstr' while parsing: " + path + ":" + itos(line));
+				ERR_FAIL_COND_V_MSG(status != STATUS_READING_ID, Ref<Resource>(), vformat("Unexpected 'msgstr', was expecting 'msgid' before 'msgstr' while parsing: %s:%d.", path, line));
 				l = l.substr(6, l.length()).strip_edges();
 				l = l.substr(6, l.length()).strip_edges();
 				status = STATUS_READING_STRING;
 				status = STATUS_READING_STRING;
 			}
 			}
@@ -261,7 +261,7 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_
 				continue; // Nothing to read or comment.
 				continue; // Nothing to read or comment.
 			}
 			}
 
 
-			ERR_FAIL_COND_V_MSG(!l.begins_with("\"") || status == STATUS_NONE, Ref<Resource>(), "Invalid line '" + l + "' while parsing: " + path + ":" + itos(line));
+			ERR_FAIL_COND_V_MSG(!l.begins_with("\"") || status == STATUS_NONE, Ref<Resource>(), vformat("Invalid line '%s' while parsing: %s:%d.", l, path, line));
 
 
 			l = l.substr(1, l.length());
 			l = l.substr(1, l.length());
 			// Find final quote, ignoring escaped ones (\").
 			// Find final quote, ignoring escaped ones (\").
@@ -283,7 +283,7 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_
 				escape_next = false;
 				escape_next = false;
 			}
 			}
 
 
-			ERR_FAIL_COND_V_MSG(end_pos == -1, Ref<Resource>(), "Expected '\"' at end of message while parsing: " + path + ":" + itos(line));
+			ERR_FAIL_COND_V_MSG(end_pos == -1, Ref<Resource>(), vformat("Expected '\"' at end of message while parsing: %s:%d.", path, line));
 
 
 			l = l.substr(0, end_pos);
 			l = l.substr(0, end_pos);
 			l = l.c_unescape();
 			l = l.c_unescape();
@@ -295,7 +295,7 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_
 			} else if (status == STATUS_READING_CONTEXT) {
 			} else if (status == STATUS_READING_CONTEXT) {
 				msg_context += l;
 				msg_context += l;
 			} else if (status == STATUS_READING_PLURAL && plural_index >= 0) {
 			} else if (status == STATUS_READING_PLURAL && plural_index >= 0) {
-				ERR_FAIL_COND_V_MSG(plural_index >= plural_forms, Ref<Resource>(), "Unexpected plural form while parsing: " + path + ":" + itos(line));
+				ERR_FAIL_COND_V_MSG(plural_index >= plural_forms, Ref<Resource>(), vformat("Unexpected plural form while parsing: %s:%d.", path, line));
 				msgs_plural.write[plural_index] = msgs_plural[plural_index] + l;
 				msgs_plural.write[plural_index] = msgs_plural[plural_index] + l;
 			}
 			}
 
 
@@ -313,13 +313,13 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_
 			}
 			}
 		} else if (status == STATUS_READING_PLURAL) {
 		} else if (status == STATUS_READING_PLURAL) {
 			if (!skip_this && !msg_id.is_empty()) {
 			if (!skip_this && !msg_id.is_empty()) {
-				ERR_FAIL_COND_V_MSG(plural_index != plural_forms - 1, Ref<Resource>(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line));
+				ERR_FAIL_COND_V_MSG(plural_index != plural_forms - 1, Ref<Resource>(), vformat("Number of 'msgstr[]' doesn't match with number of plural forms: %s:%d.", path, line));
 				translation->add_plural_message(msg_id, msgs_plural, msg_context);
 				translation->add_plural_message(msg_id, msgs_plural, msg_context);
 			}
 			}
 		}
 		}
 	}
 	}
 
 
-	ERR_FAIL_COND_V_MSG(config.is_empty(), Ref<Resource>(), "No config found in file: " + path + ".");
+	ERR_FAIL_COND_V_MSG(config.is_empty(), Ref<Resource>(), vformat("No config found in file: '%s'.", path));
 
 
 	Vector<String> configs = config.split("\n");
 	Vector<String> configs = config.split("\n");
 	for (int i = 0; i < configs.size(); i++) {
 	for (int i = 0; i < configs.size(); i++) {
@@ -349,7 +349,7 @@ Ref<Resource> TranslationLoaderPO::load(const String &p_path, const String &p_or
 	}
 	}
 
 
 	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
 	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
-	ERR_FAIL_COND_V_MSG(f.is_null(), Ref<Resource>(), "Cannot open file '" + p_path + "'.");
+	ERR_FAIL_COND_V_MSG(f.is_null(), Ref<Resource>(), vformat("Cannot open file '%s'.", p_path));
 
 
 	return load_translation(f, r_error);
 	return load_translation(f, r_error);
 }
 }

+ 2 - 2
core/io/xml_parser.cpp

@@ -429,7 +429,7 @@ String XMLParser::get_named_attribute_value(const String &p_name) const {
 		}
 		}
 	}
 	}
 
 
-	ERR_FAIL_COND_V_MSG(idx < 0, "", "Attribute not found: " + p_name + ".");
+	ERR_FAIL_COND_V_MSG(idx < 0, "", vformat("Attribute not found: '%s'.", p_name));
 
 
 	return attributes[idx].value;
 	return attributes[idx].value;
 }
 }
@@ -493,7 +493,7 @@ Error XMLParser::open(const String &p_path) {
 	Error err;
 	Error err;
 	Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::READ, &err);
 	Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::READ, &err);
 
 
-	ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot open file '" + p_path + "'.");
+	ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Cannot open file '%s'.", p_path));
 
 
 	length = file->get_length();
 	length = file->get_length();
 	ERR_FAIL_COND_V(length < 1, ERR_FILE_CORRUPT);
 	ERR_FAIL_COND_V(length < 1, ERR_FILE_CORRUPT);

+ 1 - 1
core/math/expression.cpp

@@ -1491,7 +1491,7 @@ Error Expression::parse(const String &p_expression, const Vector<String> &p_inpu
 }
 }
 
 
 Variant Expression::execute(const Array &p_inputs, Object *p_base, bool p_show_error, bool p_const_calls_only) {
 Variant Expression::execute(const Array &p_inputs, Object *p_base, bool p_show_error, bool p_const_calls_only) {
-	ERR_FAIL_COND_V_MSG(error_set, Variant(), "There was previously a parse error: " + error_str + ".");
+	ERR_FAIL_COND_V_MSG(error_set, Variant(), vformat("There was previously a parse error: %s.", error_str));
 
 
 	execution_error = false;
 	execution_error = false;
 	Variant output;
 	Variant output;

+ 44 - 44
core/object/class_db.cpp

@@ -352,7 +352,7 @@ StringName ClassDB::get_compatibility_remapped_class(const StringName &p_class)
 
 
 StringName ClassDB::_get_parent_class(const StringName &p_class) {
 StringName ClassDB::_get_parent_class(const StringName &p_class) {
 	ClassInfo *ti = classes.getptr(p_class);
 	ClassInfo *ti = classes.getptr(p_class);
-	ERR_FAIL_NULL_V_MSG(ti, StringName(), "Cannot get class '" + String(p_class) + "'.");
+	ERR_FAIL_NULL_V_MSG(ti, StringName(), vformat("Cannot get class '%s'.", String(p_class)));
 	return ti->inherits;
 	return ti->inherits;
 }
 }
 
 
@@ -367,7 +367,7 @@ ClassDB::APIType ClassDB::get_api_type(const StringName &p_class) {
 
 
 	ClassInfo *ti = classes.getptr(p_class);
 	ClassInfo *ti = classes.getptr(p_class);
 
 
-	ERR_FAIL_NULL_V_MSG(ti, API_NONE, "Cannot get class '" + String(p_class) + "'.");
+	ERR_FAIL_NULL_V_MSG(ti, API_NONE, vformat("Cannot get class '%s'.", String(p_class)));
 	return ti->api;
 	return ti->api;
 }
 }
 
 
@@ -390,7 +390,7 @@ uint32_t ClassDB::get_api_hash(APIType p_api) {
 
 
 	for (const StringName &E : class_list) {
 	for (const StringName &E : class_list) {
 		ClassInfo *t = classes.getptr(E);
 		ClassInfo *t = classes.getptr(E);
-		ERR_FAIL_NULL_V_MSG(t, 0, "Cannot get class '" + String(E) + "'.");
+		ERR_FAIL_NULL_V_MSG(t, 0, vformat("Cannot get class '%s'.", String(E)));
 		if (t->api != p_api || !t->exposed) {
 		if (t->api != p_api || !t->exposed) {
 			continue;
 			continue;
 		}
 		}
@@ -547,14 +547,14 @@ Object *ClassDB::_instantiate_internal(const StringName &p_class, bool p_require
 				ti = classes.getptr(compat_classes[p_class]);
 				ti = classes.getptr(compat_classes[p_class]);
 			}
 			}
 		}
 		}
-		ERR_FAIL_NULL_V_MSG(ti, nullptr, "Cannot get class '" + String(p_class) + "'.");
-		ERR_FAIL_COND_V_MSG(ti->disabled, nullptr, "Class '" + String(p_class) + "' is disabled.");
-		ERR_FAIL_NULL_V_MSG(ti->creation_func, nullptr, "Class '" + String(p_class) + "' or its base class cannot be instantiated.");
+		ERR_FAIL_NULL_V_MSG(ti, nullptr, vformat("Cannot get class '%s'.", String(p_class)));
+		ERR_FAIL_COND_V_MSG(ti->disabled, nullptr, vformat("Class '%s' is disabled.", String(p_class)));
+		ERR_FAIL_NULL_V_MSG(ti->creation_func, nullptr, vformat("Class '%s' or its base class cannot be instantiated.", String(p_class)));
 	}
 	}
 
 
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
 	if ((ti->api == API_EDITOR || ti->api == API_EDITOR_EXTENSION) && !Engine::get_singleton()->is_editor_hint()) {
 	if ((ti->api == API_EDITOR || ti->api == API_EDITOR_EXTENSION) && !Engine::get_singleton()->is_editor_hint()) {
-		ERR_PRINT("Class '" + String(p_class) + "' can only be instantiated by editor.");
+		ERR_PRINT(vformat("Class '%s' can only be instantiated by editor.", String(p_class)));
 		return nullptr;
 		return nullptr;
 	}
 	}
 #endif
 #endif
@@ -653,8 +653,8 @@ ObjectGDExtension *ClassDB::get_placeholder_extension(const StringName &p_class)
 				ti = classes.getptr(compat_classes[p_class]);
 				ti = classes.getptr(compat_classes[p_class]);
 			}
 			}
 		}
 		}
-		ERR_FAIL_NULL_V_MSG(ti, nullptr, "Cannot get class '" + String(p_class) + "'.");
-		ERR_FAIL_COND_V_MSG(ti->disabled, nullptr, "Class '" + String(p_class) + "' is disabled.");
+		ERR_FAIL_NULL_V_MSG(ti, nullptr, vformat("Cannot get class '%s'.", String(p_class)));
+		ERR_FAIL_COND_V_MSG(ti->disabled, nullptr, vformat("Class '%s' is disabled.", String(p_class)));
 	}
 	}
 
 
 	// Make a "fake" extension to act as a placeholder.
 	// Make a "fake" extension to act as a placeholder.
@@ -734,9 +734,9 @@ void ClassDB::set_object_extension_instance(Object *p_object, const StringName &
 				ti = classes.getptr(compat_classes[p_class]);
 				ti = classes.getptr(compat_classes[p_class]);
 			}
 			}
 		}
 		}
-		ERR_FAIL_NULL_MSG(ti, "Cannot get class '" + String(p_class) + "'.");
-		ERR_FAIL_COND_MSG(ti->disabled, "Class '" + String(p_class) + "' is disabled.");
-		ERR_FAIL_NULL_MSG(ti->gdextension, "Class '" + String(p_class) + "' has no native extension.");
+		ERR_FAIL_NULL_MSG(ti, vformat("Cannot get class '%s'.", String(p_class)));
+		ERR_FAIL_COND_MSG(ti->disabled, vformat("Class '%s' is disabled.", String(p_class)));
+		ERR_FAIL_NULL_MSG(ti->gdextension, vformat("Class '%s' has no native extension.", String(p_class)));
 	}
 	}
 
 
 	p_object->_extension = ti->gdextension;
 	p_object->_extension = ti->gdextension;
@@ -755,7 +755,7 @@ bool ClassDB::can_instantiate(const StringName &p_class) {
 	ClassInfo *ti = classes.getptr(p_class);
 	ClassInfo *ti = classes.getptr(p_class);
 	if (!ti) {
 	if (!ti) {
 		if (!ScriptServer::is_global_class(p_class)) {
 		if (!ScriptServer::is_global_class(p_class)) {
-			ERR_FAIL_V_MSG(false, "Cannot get class '" + String(p_class) + "'.");
+			ERR_FAIL_V_MSG(false, vformat("Cannot get class '%s'.", String(p_class)));
 		}
 		}
 		String path = ScriptServer::get_global_class_path(p_class);
 		String path = ScriptServer::get_global_class_path(p_class);
 		Ref<Script> scr = ResourceLoader::load(path);
 		Ref<Script> scr = ResourceLoader::load(path);
@@ -775,7 +775,7 @@ bool ClassDB::is_abstract(const StringName &p_class) {
 	ClassInfo *ti = classes.getptr(p_class);
 	ClassInfo *ti = classes.getptr(p_class);
 	if (!ti) {
 	if (!ti) {
 		if (!ScriptServer::is_global_class(p_class)) {
 		if (!ScriptServer::is_global_class(p_class)) {
-			ERR_FAIL_V_MSG(false, "Cannot get class '" + String(p_class) + "'.");
+			ERR_FAIL_V_MSG(false, vformat("Cannot get class '%s'.", String(p_class)));
 		}
 		}
 		String path = ScriptServer::get_global_class_path(p_class);
 		String path = ScriptServer::get_global_class_path(p_class);
 		Ref<Script> scr = ResourceLoader::load(path);
 		Ref<Script> scr = ResourceLoader::load(path);
@@ -801,7 +801,7 @@ bool ClassDB::is_virtual(const StringName &p_class) {
 	ClassInfo *ti = classes.getptr(p_class);
 	ClassInfo *ti = classes.getptr(p_class);
 	if (!ti) {
 	if (!ti) {
 		if (!ScriptServer::is_global_class(p_class)) {
 		if (!ScriptServer::is_global_class(p_class)) {
-			ERR_FAIL_V_MSG(false, "Cannot get class '" + String(p_class) + "'.");
+			ERR_FAIL_V_MSG(false, vformat("Cannot get class '%s'.", String(p_class)));
 		}
 		}
 		String path = ScriptServer::get_global_class_path(p_class);
 		String path = ScriptServer::get_global_class_path(p_class);
 		Ref<Script> scr = ResourceLoader::load(path);
 		Ref<Script> scr = ResourceLoader::load(path);
@@ -820,7 +820,7 @@ void ClassDB::_add_class2(const StringName &p_class, const StringName &p_inherit
 
 
 	const StringName &name = p_class;
 	const StringName &name = p_class;
 
 
-	ERR_FAIL_COND_MSG(classes.has(name), "Class '" + String(p_class) + "' already exists.");
+	ERR_FAIL_COND_MSG(classes.has(name), vformat("Class '%s' already exists.", String(p_class)));
 
 
 	classes[name] = ClassInfo();
 	classes[name] = ClassInfo();
 	ClassInfo &ti = classes[name];
 	ClassInfo &ti = classes[name];
@@ -1328,7 +1328,7 @@ void ClassDB::add_signal(const StringName &p_class, const MethodInfo &p_signal)
 #ifdef DEBUG_METHODS_ENABLED
 #ifdef DEBUG_METHODS_ENABLED
 	ClassInfo *check = type;
 	ClassInfo *check = type;
 	while (check) {
 	while (check) {
-		ERR_FAIL_COND_MSG(check->signal_map.has(sname), "Class '" + String(p_class) + "' already has signal '" + String(sname) + "'.");
+		ERR_FAIL_COND_MSG(check->signal_map.has(sname), vformat("Class '%s' already has signal '%s'.", String(p_class), String(sname)));
 		check = check->inherits_ptr;
 		check = check->inherits_ptr;
 	}
 	}
 #endif
 #endif
@@ -1442,10 +1442,10 @@ void ClassDB::add_property(const StringName &p_class, const PropertyInfo &p_pinf
 		mb_set = get_method(p_class, p_setter);
 		mb_set = get_method(p_class, p_setter);
 #ifdef DEBUG_METHODS_ENABLED
 #ifdef DEBUG_METHODS_ENABLED
 
 
-		ERR_FAIL_NULL_MSG(mb_set, "Invalid setter '" + p_class + "::" + p_setter + "' for property '" + p_pinfo.name + "'.");
+		ERR_FAIL_NULL_MSG(mb_set, vformat("Invalid setter '%s::%s' for property '%s'.", p_class, p_setter, p_pinfo.name));
 
 
 		int exp_args = 1 + (p_index >= 0 ? 1 : 0);
 		int exp_args = 1 + (p_index >= 0 ? 1 : 0);
-		ERR_FAIL_COND_MSG(mb_set->get_argument_count() != exp_args, "Invalid function for setter '" + p_class + "::" + p_setter + " for property '" + p_pinfo.name + "'.");
+		ERR_FAIL_COND_MSG(mb_set->get_argument_count() != exp_args, vformat("Invalid function for setter '%s::%s' for property '%s'.", p_class, p_setter, p_pinfo.name));
 #endif
 #endif
 	}
 	}
 
 
@@ -1454,15 +1454,15 @@ void ClassDB::add_property(const StringName &p_class, const PropertyInfo &p_pinf
 		mb_get = get_method(p_class, p_getter);
 		mb_get = get_method(p_class, p_getter);
 #ifdef DEBUG_METHODS_ENABLED
 #ifdef DEBUG_METHODS_ENABLED
 
 
-		ERR_FAIL_NULL_MSG(mb_get, "Invalid getter '" + p_class + "::" + p_getter + "' for property '" + p_pinfo.name + "'.");
+		ERR_FAIL_NULL_MSG(mb_get, vformat("Invalid getter '%s::%s' for property '%s'.", p_class, p_getter, p_pinfo.name));
 
 
 		int exp_args = 0 + (p_index >= 0 ? 1 : 0);
 		int exp_args = 0 + (p_index >= 0 ? 1 : 0);
-		ERR_FAIL_COND_MSG(mb_get->get_argument_count() != exp_args, "Invalid function for getter '" + p_class + "::" + p_getter + "' for property: '" + p_pinfo.name + "'.");
+		ERR_FAIL_COND_MSG(mb_get->get_argument_count() != exp_args, vformat("Invalid function for getter '%s::%s' for property '%s'.", p_class, p_getter, p_pinfo.name));
 #endif
 #endif
 	}
 	}
 
 
 #ifdef DEBUG_METHODS_ENABLED
 #ifdef DEBUG_METHODS_ENABLED
-	ERR_FAIL_COND_MSG(type->property_setget.has(p_pinfo.name), "Object '" + p_class + "' already has property '" + p_pinfo.name + "'.");
+	ERR_FAIL_COND_MSG(type->property_setget.has(p_pinfo.name), vformat("Object '%s' already has property '%s'.", p_class, p_pinfo.name));
 #endif
 #endif
 
 
 	OBJTYPE_WLOCK
 	OBJTYPE_WLOCK
@@ -1847,7 +1847,7 @@ void ClassDB::_bind_method_custom(const StringName &p_class, MethodBind *p_metho
 
 
 	ClassInfo *type = classes.getptr(p_class);
 	ClassInfo *type = classes.getptr(p_class);
 	if (!type) {
 	if (!type) {
-		ERR_FAIL_MSG("Couldn't bind custom method '" + p_method->get_name() + "' for instance '" + p_class + "'.");
+		ERR_FAIL_MSG(vformat("Couldn't bind custom method '%s' for instance '%s'.", p_method->get_name(), p_class));
 	}
 	}
 
 
 	if (p_compatibility) {
 	if (p_compatibility) {
@@ -1857,7 +1857,7 @@ void ClassDB::_bind_method_custom(const StringName &p_class, MethodBind *p_metho
 
 
 	if (type->method_map.has(p_method->get_name())) {
 	if (type->method_map.has(p_method->get_name())) {
 		// overloading not supported
 		// overloading not supported
-		ERR_FAIL_MSG("Method already bound '" + p_class + "::" + p_method->get_name() + "'.");
+		ERR_FAIL_MSG(vformat("Method already bound '%s::%s'.", p_class, p_method->get_name()));
 	}
 	}
 
 
 #ifdef DEBUG_METHODS_ENABLED
 #ifdef DEBUG_METHODS_ENABLED
@@ -1888,7 +1888,7 @@ MethodBind *ClassDB::_bind_vararg_method(MethodBind *p_bind, const StringName &p
 	if (type->method_map.has(p_name)) {
 	if (type->method_map.has(p_name)) {
 		memdelete(bind);
 		memdelete(bind);
 		// Overloading not supported
 		// Overloading not supported
-		ERR_FAIL_V_MSG(nullptr, "Method already bound: " + instance_type + "::" + p_name + ".");
+		ERR_FAIL_V_MSG(nullptr, vformat("Method already bound: '%s::%s'.", instance_type, p_name));
 	}
 	}
 	type->method_map[p_name] = bind;
 	type->method_map[p_name] = bind;
 #ifdef DEBUG_METHODS_ENABLED
 #ifdef DEBUG_METHODS_ENABLED
@@ -1916,26 +1916,26 @@ MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, bool p_
 
 
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 
 
-	ERR_FAIL_COND_V_MSG(!p_compatibility && has_method(instance_type, mdname), nullptr, "Class " + String(instance_type) + " already has a method " + String(mdname) + ".");
+	ERR_FAIL_COND_V_MSG(!p_compatibility && has_method(instance_type, mdname), nullptr, vformat("Class '%s' already has a method '%s'.", String(instance_type), String(mdname)));
 #endif
 #endif
 
 
 	ClassInfo *type = classes.getptr(instance_type);
 	ClassInfo *type = classes.getptr(instance_type);
 	if (!type) {
 	if (!type) {
 		memdelete(p_bind);
 		memdelete(p_bind);
-		ERR_FAIL_V_MSG(nullptr, "Couldn't bind method '" + mdname + "' for instance '" + instance_type + "'.");
+		ERR_FAIL_V_MSG(nullptr, vformat("Couldn't bind method '%s' for instance '%s'.", mdname, instance_type));
 	}
 	}
 
 
 	if (!p_compatibility && type->method_map.has(mdname)) {
 	if (!p_compatibility && type->method_map.has(mdname)) {
 		memdelete(p_bind);
 		memdelete(p_bind);
 		// overloading not supported
 		// overloading not supported
-		ERR_FAIL_V_MSG(nullptr, "Method already bound '" + instance_type + "::" + mdname + "'.");
+		ERR_FAIL_V_MSG(nullptr, vformat("Method already bound '%s::%s'.", instance_type, mdname));
 	}
 	}
 
 
 #ifdef DEBUG_METHODS_ENABLED
 #ifdef DEBUG_METHODS_ENABLED
 
 
 	if (method_name.args.size() > p_bind->get_argument_count()) {
 	if (method_name.args.size() > p_bind->get_argument_count()) {
 		memdelete(p_bind);
 		memdelete(p_bind);
-		ERR_FAIL_V_MSG(nullptr, "Method definition provides more arguments than the method actually has '" + instance_type + "::" + mdname + "'.");
+		ERR_FAIL_V_MSG(nullptr, vformat("Method definition provides more arguments than the method actually has '%s::%s'.", instance_type, mdname));
 	}
 	}
 
 
 	p_bind->set_argument_names(method_name.args);
 	p_bind->set_argument_names(method_name.args);
@@ -1964,7 +1964,7 @@ MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, bool p_
 }
 }
 
 
 void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_method, bool p_virtual, const Vector<String> &p_arg_names, bool p_object_core) {
 void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_method, bool p_virtual, const Vector<String> &p_arg_names, bool p_object_core) {
-	ERR_FAIL_COND_MSG(!classes.has(p_class), "Request for nonexistent class '" + p_class + "'.");
+	ERR_FAIL_COND_MSG(!classes.has(p_class), vformat("Request for nonexistent class '%s'.", p_class));
 
 
 	OBJTYPE_WLOCK;
 	OBJTYPE_WLOCK;
 
 
@@ -1979,7 +1979,7 @@ void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_
 
 
 	if (!p_object_core) {
 	if (!p_object_core) {
 		if (p_arg_names.size() != mi.arguments.size()) {
 		if (p_arg_names.size() != mi.arguments.size()) {
-			WARN_PRINT("Mismatch argument name count for virtual method: " + String(p_class) + "::" + p_method.name);
+			WARN_PRINT(vformat("Mismatch argument name count for virtual method: '%s::%s'.", String(p_class), p_method.name));
 		} else {
 		} else {
 			List<PropertyInfo>::Iterator itr = mi.arguments.begin();
 			List<PropertyInfo>::Iterator itr = mi.arguments.begin();
 			for (int i = 0; i < p_arg_names.size(); ++itr, ++i) {
 			for (int i = 0; i < p_arg_names.size(); ++itr, ++i) {
@@ -1990,7 +1990,7 @@ void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_
 
 
 	if (classes[p_class].virtual_methods_map.has(p_method.name)) {
 	if (classes[p_class].virtual_methods_map.has(p_method.name)) {
 		// overloading not supported
 		// overloading not supported
-		ERR_FAIL_MSG("Virtual method already bound '" + String(p_class) + "::" + p_method.name + "'.");
+		ERR_FAIL_MSG(vformat("Virtual method already bound '%s::%s'.", String(p_class), p_method.name));
 	}
 	}
 	classes[p_class].virtual_methods.push_back(mi);
 	classes[p_class].virtual_methods.push_back(mi);
 	classes[p_class].virtual_methods_map[p_method.name] = mi;
 	classes[p_class].virtual_methods_map[p_method.name] = mi;
@@ -1999,7 +1999,7 @@ void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_
 }
 }
 
 
 void ClassDB::get_virtual_methods(const StringName &p_class, List<MethodInfo> *p_methods, bool p_no_inheritance) {
 void ClassDB::get_virtual_methods(const StringName &p_class, List<MethodInfo> *p_methods, bool p_no_inheritance) {
-	ERR_FAIL_COND_MSG(!classes.has(p_class), "Request for nonexistent class '" + p_class + "'.");
+	ERR_FAIL_COND_MSG(!classes.has(p_class), vformat("Request for nonexistent class '%s'.", p_class));
 
 
 #ifdef DEBUG_METHODS_ENABLED
 #ifdef DEBUG_METHODS_ENABLED
 
 
@@ -2020,7 +2020,7 @@ void ClassDB::get_virtual_methods(const StringName &p_class, List<MethodInfo> *p
 }
 }
 
 
 void ClassDB::add_extension_class_virtual_method(const StringName &p_class, const GDExtensionClassVirtualMethodInfo *p_method_info) {
 void ClassDB::add_extension_class_virtual_method(const StringName &p_class, const GDExtensionClassVirtualMethodInfo *p_method_info) {
-	ERR_FAIL_COND_MSG(!classes.has(p_class), "Request for nonexistent class '" + p_class + "'.");
+	ERR_FAIL_COND_MSG(!classes.has(p_class), vformat("Request for nonexistent class '%s'.", p_class));
 
 
 #ifdef DEBUG_METHODS_ENABLED
 #ifdef DEBUG_METHODS_ENABLED
 	PackedStringArray arg_names;
 	PackedStringArray arg_names;
@@ -2044,7 +2044,7 @@ void ClassDB::add_extension_class_virtual_method(const StringName &p_class, cons
 void ClassDB::set_class_enabled(const StringName &p_class, bool p_enable) {
 void ClassDB::set_class_enabled(const StringName &p_class, bool p_enable) {
 	OBJTYPE_WLOCK;
 	OBJTYPE_WLOCK;
 
 
-	ERR_FAIL_COND_MSG(!classes.has(p_class), "Request for nonexistent class '" + p_class + "'.");
+	ERR_FAIL_COND_MSG(!classes.has(p_class), vformat("Request for nonexistent class '%s'.", p_class));
 	classes[p_class].disabled = !p_enable;
 	classes[p_class].disabled = !p_enable;
 }
 }
 
 
@@ -2058,7 +2058,7 @@ bool ClassDB::is_class_enabled(const StringName &p_class) {
 		}
 		}
 	}
 	}
 
 
-	ERR_FAIL_NULL_V_MSG(ti, false, "Cannot get class '" + String(p_class) + "'.");
+	ERR_FAIL_NULL_V_MSG(ti, false, vformat("Cannot get class '%s'.", String(p_class)));
 	return !ti->disabled;
 	return !ti->disabled;
 }
 }
 
 
@@ -2066,7 +2066,7 @@ bool ClassDB::is_class_exposed(const StringName &p_class) {
 	OBJTYPE_RLOCK;
 	OBJTYPE_RLOCK;
 
 
 	ClassInfo *ti = classes.getptr(p_class);
 	ClassInfo *ti = classes.getptr(p_class);
-	ERR_FAIL_NULL_V_MSG(ti, false, "Cannot get class '" + String(p_class) + "'.");
+	ERR_FAIL_NULL_V_MSG(ti, false, vformat("Cannot get class '%s'.", String(p_class)));
 	return ti->exposed;
 	return ti->exposed;
 }
 }
 
 
@@ -2074,7 +2074,7 @@ bool ClassDB::is_class_reloadable(const StringName &p_class) {
 	OBJTYPE_RLOCK;
 	OBJTYPE_RLOCK;
 
 
 	ClassInfo *ti = classes.getptr(p_class);
 	ClassInfo *ti = classes.getptr(p_class);
-	ERR_FAIL_NULL_V_MSG(ti, false, "Cannot get class '" + String(p_class) + "'.");
+	ERR_FAIL_NULL_V_MSG(ti, false, vformat("Cannot get class '%s'.", String(p_class)));
 	return ti->reloadable;
 	return ti->reloadable;
 }
 }
 
 
@@ -2082,7 +2082,7 @@ bool ClassDB::is_class_runtime(const StringName &p_class) {
 	OBJTYPE_RLOCK;
 	OBJTYPE_RLOCK;
 
 
 	ClassInfo *ti = classes.getptr(p_class);
 	ClassInfo *ti = classes.getptr(p_class);
-	ERR_FAIL_NULL_V_MSG(ti, false, "Cannot get class '" + String(p_class) + "'.");
+	ERR_FAIL_NULL_V_MSG(ti, false, vformat("Cannot get class '%s'.", String(p_class)));
 	return ti->is_runtime;
 	return ti->is_runtime;
 }
 }
 
 
@@ -2192,14 +2192,14 @@ Variant ClassDB::class_get_default_property_value(const StringName &p_class, con
 void ClassDB::register_extension_class(ObjectGDExtension *p_extension) {
 void ClassDB::register_extension_class(ObjectGDExtension *p_extension) {
 	GLOBAL_LOCK_FUNCTION;
 	GLOBAL_LOCK_FUNCTION;
 
 
-	ERR_FAIL_COND_MSG(classes.has(p_extension->class_name), "Class already registered: " + String(p_extension->class_name));
-	ERR_FAIL_COND_MSG(!classes.has(p_extension->parent_class_name), "Parent class name for extension class not found: " + String(p_extension->parent_class_name));
+	ERR_FAIL_COND_MSG(classes.has(p_extension->class_name), vformat("Class already registered: '%s'.", String(p_extension->class_name)));
+	ERR_FAIL_COND_MSG(!classes.has(p_extension->parent_class_name), vformat("Parent class name for extension class not found: '%s'.", String(p_extension->parent_class_name)));
 
 
 	ClassInfo *parent = classes.getptr(p_extension->parent_class_name);
 	ClassInfo *parent = classes.getptr(p_extension->parent_class_name);
 
 
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
 	// @todo This is a limitation of the current implementation, but it should be possible to remove.
 	// @todo This is a limitation of the current implementation, but it should be possible to remove.
-	ERR_FAIL_COND_MSG(p_extension->is_runtime && parent->gdextension && !parent->is_runtime, "Extension runtime class " + String(p_extension->class_name) + " cannot descend from " + parent->name + " which isn't also a runtime class");
+	ERR_FAIL_COND_MSG(p_extension->is_runtime && parent->gdextension && !parent->is_runtime, vformat("Extension runtime class '%s' cannot descend from '%s' which isn't also a runtime class.", String(p_extension->class_name), parent->name));
 #endif
 #endif
 
 
 	ClassInfo c;
 	ClassInfo c;
@@ -2215,7 +2215,7 @@ void ClassDB::register_extension_class(ObjectGDExtension *p_extension) {
 				concrete_ancestor->gdextension != nullptr) {
 				concrete_ancestor->gdextension != nullptr) {
 			concrete_ancestor = concrete_ancestor->inherits_ptr;
 			concrete_ancestor = concrete_ancestor->inherits_ptr;
 		}
 		}
-		ERR_FAIL_NULL_MSG(concrete_ancestor->creation_func, "Extension class " + String(p_extension->class_name) + " cannot extend native abstract class " + String(concrete_ancestor->name));
+		ERR_FAIL_NULL_MSG(concrete_ancestor->creation_func, vformat("Extension class '%s' cannot extend native abstract class '%s'.", String(p_extension->class_name), String(concrete_ancestor->name)));
 		c.creation_func = concrete_ancestor->creation_func;
 		c.creation_func = concrete_ancestor->creation_func;
 	}
 	}
 	c.inherits = parent->name;
 	c.inherits = parent->name;
@@ -2239,7 +2239,7 @@ void ClassDB::register_extension_class(ObjectGDExtension *p_extension) {
 
 
 void ClassDB::unregister_extension_class(const StringName &p_class, bool p_free_method_binds) {
 void ClassDB::unregister_extension_class(const StringName &p_class, bool p_free_method_binds) {
 	ClassInfo *c = classes.getptr(p_class);
 	ClassInfo *c = classes.getptr(p_class);
-	ERR_FAIL_NULL_MSG(c, "Class '" + String(p_class) + "' does not exist.");
+	ERR_FAIL_NULL_MSG(c, vformat("Class '%s' does not exist.", String(p_class)));
 	if (p_free_method_binds) {
 	if (p_free_method_binds) {
 		for (KeyValue<StringName, MethodBind *> &F : c->method_map) {
 		for (KeyValue<StringName, MethodBind *> &F : c->method_map) {
 			memdelete(F.value);
 			memdelete(F.value);

+ 20 - 20
core/object/object.cpp

@@ -750,7 +750,7 @@ Variant Object::callv(const StringName &p_method, const Array &p_args) {
 	Callable::CallError ce;
 	Callable::CallError ce;
 	const Variant ret = callp(p_method, argptrs, p_args.size(), ce);
 	const Variant ret = callp(p_method, argptrs, p_args.size(), ce);
 	if (ce.error != Callable::CallError::CALL_OK) {
 	if (ce.error != Callable::CallError::CALL_OK) {
-		ERR_FAIL_V_MSG(Variant(), "Error calling method from 'callv': " + Variant::get_call_error_text(this, p_method, argptrs, p_args.size(), ce) + ".");
+		ERR_FAIL_V_MSG(Variant(), vformat("Error calling method from 'callv': %s.", Variant::get_call_error_text(this, p_method, argptrs, p_args.size(), ce)));
 	}
 	}
 	return ret;
 	return ret;
 }
 }
@@ -999,7 +999,7 @@ void Object::set_meta(const StringName &p_name, const Variant &p_value) {
 	if (E) {
 	if (E) {
 		E->value = p_value;
 		E->value = p_value;
 	} else {
 	} else {
-		ERR_FAIL_COND_MSG(!p_name.operator String().is_valid_ascii_identifier(), "Invalid metadata identifier: '" + p_name + "'.");
+		ERR_FAIL_COND_MSG(!p_name.operator String().is_valid_ascii_identifier(), vformat("Invalid metadata identifier: '%s'.", p_name));
 		Variant *V = &metadata.insert(p_name, p_value)->value;
 		Variant *V = &metadata.insert(p_name, p_value)->value;
 
 
 		const String &sname = p_name;
 		const String &sname = p_name;
@@ -1015,7 +1015,7 @@ Variant Object::get_meta(const StringName &p_name, const Variant &p_default) con
 		if (p_default != Variant()) {
 		if (p_default != Variant()) {
 			return p_default;
 			return p_default;
 		} else {
 		} else {
-			ERR_FAIL_V_MSG(Variant(), "The object does not have any 'meta' values with the key '" + p_name + "'.");
+			ERR_FAIL_V_MSG(Variant(), vformat("The object does not have any 'meta' values with the key '%s'.", p_name));
 		}
 		}
 	}
 	}
 	return metadata[p_name];
 	return metadata[p_name];
@@ -1071,8 +1071,8 @@ void Object::get_meta_list(List<StringName> *p_list) const {
 
 
 void Object::add_user_signal(const MethodInfo &p_signal) {
 void Object::add_user_signal(const MethodInfo &p_signal) {
 	ERR_FAIL_COND_MSG(p_signal.name.is_empty(), "Signal name cannot be empty.");
 	ERR_FAIL_COND_MSG(p_signal.name.is_empty(), "Signal name cannot be empty.");
-	ERR_FAIL_COND_MSG(ClassDB::has_signal(get_class_name(), p_signal.name), "User signal's name conflicts with a built-in signal of '" + get_class_name() + "'.");
-	ERR_FAIL_COND_MSG(signal_map.has(p_signal.name), "Trying to add already existing signal '" + p_signal.name + "'.");
+	ERR_FAIL_COND_MSG(ClassDB::has_signal(get_class_name(), p_signal.name), vformat("User signal's name conflicts with a built-in signal of '%s'.", get_class_name()));
+	ERR_FAIL_COND_MSG(signal_map.has(p_signal.name), vformat("Trying to add already existing signal '%s'.", p_signal.name));
 	SignalData s;
 	SignalData s;
 	s.user = p_signal;
 	s.user = p_signal;
 	signal_map[p_signal.name] = s;
 	signal_map[p_signal.name] = s;
@@ -1137,7 +1137,7 @@ Error Object::emit_signalp(const StringName &p_name, const Variant **p_args, int
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 		bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_name);
 		bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_name);
 		//check in script
 		//check in script
-		ERR_FAIL_COND_V_MSG(!signal_is_valid && !script.is_null() && !Ref<Script>(script)->has_script_signal(p_name), ERR_UNAVAILABLE, "Can't emit non-existing signal " + String("\"") + p_name + "\".");
+		ERR_FAIL_COND_V_MSG(!signal_is_valid && !script.is_null() && !Ref<Script>(script)->has_script_signal(p_name), ERR_UNAVAILABLE, vformat("Can't emit non-existing signal \"%s\".", p_name));
 #endif
 #endif
 		//not connected? just return
 		//not connected? just return
 		return ERR_UNAVAILABLE;
 		return ERR_UNAVAILABLE;
@@ -1210,7 +1210,7 @@ Error Object::emit_signalp(const StringName &p_name, const Variant **p_args, int
 				if (ce.error == Callable::CallError::CALL_ERROR_INVALID_METHOD && target && !ClassDB::class_exists(target->get_class_name())) {
 				if (ce.error == Callable::CallError::CALL_ERROR_INVALID_METHOD && target && !ClassDB::class_exists(target->get_class_name())) {
 					//most likely object is not initialized yet, do not throw error.
 					//most likely object is not initialized yet, do not throw error.
 				} else {
 				} else {
-					ERR_PRINT("Error calling from signal '" + String(p_name) + "' to callable: " + Variant::get_callable_error_text(callable, args, argc, ce) + ".");
+					ERR_PRINT(vformat("Error calling from signal '%s' to callable: %s.", String(p_name), Variant::get_callable_error_text(callable, args, argc, ce)));
 					err = ERR_METHOD_NOT_FOUND;
 					err = ERR_METHOD_NOT_FOUND;
 				}
 				}
 			}
 			}
@@ -1371,15 +1371,15 @@ void Object::get_signals_connected_to_this(List<Connection> *p_connections) cons
 }
 }
 
 
 Error Object::connect(const StringName &p_signal, const Callable &p_callable, uint32_t p_flags) {
 Error Object::connect(const StringName &p_signal, const Callable &p_callable, uint32_t p_flags) {
-	ERR_FAIL_COND_V_MSG(p_callable.is_null(), ERR_INVALID_PARAMETER, "Cannot connect to '" + p_signal + "': the provided callable is null.");
+	ERR_FAIL_COND_V_MSG(p_callable.is_null(), ERR_INVALID_PARAMETER, vformat("Cannot connect to '%s': the provided callable is null.", p_signal));
 
 
 	if (p_callable.is_standard()) {
 	if (p_callable.is_standard()) {
 		// FIXME: This branch should probably removed in favor of the `is_valid()` branch, but there exist some classes
 		// FIXME: This branch should probably removed in favor of the `is_valid()` branch, but there exist some classes
 		// that call `connect()` before they are fully registered with ClassDB. Until all such classes can be found
 		// that call `connect()` before they are fully registered with ClassDB. Until all such classes can be found
 		// and registered soon enough this branch is needed to allow `connect()` to succeed.
 		// and registered soon enough this branch is needed to allow `connect()` to succeed.
-		ERR_FAIL_NULL_V_MSG(p_callable.get_object(), ERR_INVALID_PARAMETER, "Cannot connect to '" + p_signal + "' to callable '" + p_callable + "': the callable object is null.");
+		ERR_FAIL_NULL_V_MSG(p_callable.get_object(), ERR_INVALID_PARAMETER, vformat("Cannot connect to '%s' to callable '%s': the callable object is null.", p_signal, p_callable));
 	} else {
 	} else {
-		ERR_FAIL_COND_V_MSG(!p_callable.is_valid(), ERR_INVALID_PARAMETER, "Cannot connect to '" + p_signal + "': the provided callable is not valid: " + p_callable);
+		ERR_FAIL_COND_V_MSG(!p_callable.is_valid(), ERR_INVALID_PARAMETER, vformat("Cannot connect to '%s': the provided callable is not valid: '%s'.", p_signal, p_callable));
 	}
 	}
 
 
 	SignalData *s = signal_map.getptr(p_signal);
 	SignalData *s = signal_map.getptr(p_signal);
@@ -1400,7 +1400,7 @@ Error Object::connect(const StringName &p_signal, const Callable &p_callable, ui
 #endif
 #endif
 		}
 		}
 
 
-		ERR_FAIL_COND_V_MSG(!signal_is_valid, ERR_INVALID_PARAMETER, "In Object of type '" + String(get_class()) + "': Attempt to connect nonexistent signal '" + p_signal + "' to callable '" + p_callable + "'.");
+		ERR_FAIL_COND_V_MSG(!signal_is_valid, ERR_INVALID_PARAMETER, vformat("In Object of type '%s': Attempt to connect nonexistent signal '%s' to callable '%s'.", String(get_class()), p_signal, p_callable));
 
 
 		signal_map[p_signal] = SignalData();
 		signal_map[p_signal] = SignalData();
 		s = &signal_map[p_signal];
 		s = &signal_map[p_signal];
@@ -1412,7 +1412,7 @@ Error Object::connect(const StringName &p_signal, const Callable &p_callable, ui
 			s->slot_map[*p_callable.get_base_comparator()].reference_count++;
 			s->slot_map[*p_callable.get_base_comparator()].reference_count++;
 			return OK;
 			return OK;
 		} else {
 		} else {
-			ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, "Signal '" + p_signal + "' is already connected to given callable '" + p_callable + "' in that object.");
+			ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, vformat("Signal '%s' is already connected to given callable '%s' in that object.", p_signal, p_callable));
 		}
 		}
 	}
 	}
 
 
@@ -1439,7 +1439,7 @@ Error Object::connect(const StringName &p_signal, const Callable &p_callable, ui
 }
 }
 
 
 bool Object::is_connected(const StringName &p_signal, const Callable &p_callable) const {
 bool Object::is_connected(const StringName &p_signal, const Callable &p_callable) const {
-	ERR_FAIL_COND_V_MSG(p_callable.is_null(), false, "Cannot determine if connected to '" + p_signal + "': the provided callable is null."); // Should use `is_null`, see note in `connect` about the use of `is_valid`.
+	ERR_FAIL_COND_V_MSG(p_callable.is_null(), false, vformat("Cannot determine if connected to '%s': the provided callable is null.", p_signal)); // Should use `is_null`, see note in `connect` about the use of `is_valid`.
 	const SignalData *s = signal_map.getptr(p_signal);
 	const SignalData *s = signal_map.getptr(p_signal);
 	if (!s) {
 	if (!s) {
 		bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_signal);
 		bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_signal);
@@ -1451,7 +1451,7 @@ bool Object::is_connected(const StringName &p_signal, const Callable &p_callable
 			return false;
 			return false;
 		}
 		}
 
 
-		ERR_FAIL_V_MSG(false, "Nonexistent signal: " + p_signal + ".");
+		ERR_FAIL_V_MSG(false, vformat("Nonexistent signal: '%s'.", p_signal));
 	}
 	}
 
 
 	return s->slot_map.has(*p_callable.get_base_comparator());
 	return s->slot_map.has(*p_callable.get_base_comparator());
@@ -1469,7 +1469,7 @@ bool Object::has_connections(const StringName &p_signal) const {
 			return false;
 			return false;
 		}
 		}
 
 
-		ERR_FAIL_V_MSG(false, "Nonexistent signal: " + p_signal + ".");
+		ERR_FAIL_V_MSG(false, vformat("Nonexistent signal: '%s'.", p_signal));
 	}
 	}
 
 
 	return !s->slot_map.is_empty();
 	return !s->slot_map.is_empty();
@@ -1480,17 +1480,17 @@ void Object::disconnect(const StringName &p_signal, const Callable &p_callable)
 }
 }
 
 
 bool Object::_disconnect(const StringName &p_signal, const Callable &p_callable, bool p_force) {
 bool Object::_disconnect(const StringName &p_signal, const Callable &p_callable, bool p_force) {
-	ERR_FAIL_COND_V_MSG(p_callable.is_null(), false, "Cannot disconnect from '" + p_signal + "': the provided callable is null."); // Should use `is_null`, see note in `connect` about the use of `is_valid`.
+	ERR_FAIL_COND_V_MSG(p_callable.is_null(), false, vformat("Cannot disconnect from '%s': the provided callable is null.", p_signal)); // Should use `is_null`, see note in `connect` about the use of `is_valid`.
 
 
 	SignalData *s = signal_map.getptr(p_signal);
 	SignalData *s = signal_map.getptr(p_signal);
 	if (!s) {
 	if (!s) {
 		bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_signal) ||
 		bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_signal) ||
 				(!script.is_null() && Ref<Script>(script)->has_script_signal(p_signal));
 				(!script.is_null() && Ref<Script>(script)->has_script_signal(p_signal));
-		ERR_FAIL_COND_V_MSG(signal_is_valid, false, "Attempt to disconnect a nonexistent connection from '" + to_string() + "'. Signal: '" + p_signal + "', callable: '" + p_callable + "'.");
+		ERR_FAIL_COND_V_MSG(signal_is_valid, false, vformat("Attempt to disconnect a nonexistent connection from '%s'. Signal: '%s', callable: '%s'.", to_string(), p_signal, p_callable));
 	}
 	}
-	ERR_FAIL_NULL_V_MSG(s, false, vformat("Disconnecting nonexistent signal '%s' in %s.", p_signal, to_string()));
+	ERR_FAIL_NULL_V_MSG(s, false, vformat("Disconnecting nonexistent signal '%s' in '%s'.", p_signal, to_string()));
 
 
-	ERR_FAIL_COND_V_MSG(!s->slot_map.has(*p_callable.get_base_comparator()), false, "Attempt to disconnect a nonexistent connection from '" + to_string() + "'. Signal: '" + p_signal + "', callable: '" + p_callable + "'.");
+	ERR_FAIL_COND_V_MSG(!s->slot_map.has(*p_callable.get_base_comparator()), false, vformat("Attempt to disconnect a nonexistent connection from '%s'. Signal: '%s', callable: '%s'.", to_string(), p_signal, p_callable));
 
 
 	SignalData::Slot *slot = &s->slot_map[*p_callable.get_base_comparator()];
 	SignalData::Slot *slot = &s->slot_map[*p_callable.get_base_comparator()];
 
 
@@ -2128,7 +2128,7 @@ Object::~Object() {
 
 
 	if (_emitting) {
 	if (_emitting) {
 		//@todo this may need to actually reach the debugger prioritarily somehow because it may crash before
 		//@todo this may need to actually reach the debugger prioritarily somehow because it may crash before
-		ERR_PRINT("Object " + to_string() + " was freed or unreferenced while a signal is being emitted from it. Try connecting to the signal using 'CONNECT_DEFERRED' flag, or use queue_free() to free the object (if this object is a Node) to avoid this error and potential crashes.");
+		ERR_PRINT(vformat("Object '%s' was freed or unreferenced while a signal is being emitted from it. Try connecting to the signal using 'CONNECT_DEFERRED' flag, or use queue_free() to free the object (if this object is a Node) to avoid this error and potential crashes.", to_string()));
 	}
 	}
 
 
 	// Drop all connections to the signals of this object.
 	// Drop all connections to the signals of this object.

+ 3 - 3
core/object/script_language.cpp

@@ -239,9 +239,9 @@ Error ScriptServer::register_language(ScriptLanguage *p_language) {
 	ERR_FAIL_COND_V_MSG(_language_count >= MAX_LANGUAGES, ERR_UNAVAILABLE, "Script languages limit has been reach, cannot register more.");
 	ERR_FAIL_COND_V_MSG(_language_count >= MAX_LANGUAGES, ERR_UNAVAILABLE, "Script languages limit has been reach, cannot register more.");
 	for (int i = 0; i < _language_count; i++) {
 	for (int i = 0; i < _language_count; i++) {
 		const ScriptLanguage *other_language = _languages[i];
 		const ScriptLanguage *other_language = _languages[i];
-		ERR_FAIL_COND_V_MSG(other_language->get_extension() == p_language->get_extension(), ERR_ALREADY_EXISTS, "A script language with extension '" + p_language->get_extension() + "' is already registered.");
-		ERR_FAIL_COND_V_MSG(other_language->get_name() == p_language->get_name(), ERR_ALREADY_EXISTS, "A script language with name '" + p_language->get_name() + "' is already registered.");
-		ERR_FAIL_COND_V_MSG(other_language->get_type() == p_language->get_type(), ERR_ALREADY_EXISTS, "A script language with type '" + p_language->get_type() + "' is already registered.");
+		ERR_FAIL_COND_V_MSG(other_language->get_extension() == p_language->get_extension(), ERR_ALREADY_EXISTS, vformat("A script language with extension '%s' is already registered.", p_language->get_extension()));
+		ERR_FAIL_COND_V_MSG(other_language->get_name() == p_language->get_name(), ERR_ALREADY_EXISTS, vformat("A script language with name '%s' is already registered.", p_language->get_name()));
+		ERR_FAIL_COND_V_MSG(other_language->get_type() == p_language->get_type(), ERR_ALREADY_EXISTS, vformat("A script language with type '%s' is already registered.", p_language->get_type()));
 	}
 	}
 	_languages[_language_count++] = p_language;
 	_languages[_language_count++] = p_language;
 	return OK;
 	return OK;

+ 1 - 1
core/object/undo_redo.cpp

@@ -364,7 +364,7 @@ void UndoRedo::_process_operation_list(List<Operation>::Element *E, bool p_execu
 					Variant ret;
 					Variant ret;
 					op.callable.callp(nullptr, 0, ret, ce);
 					op.callable.callp(nullptr, 0, ret, ce);
 					if (ce.error != Callable::CallError::CALL_OK) {
 					if (ce.error != Callable::CallError::CALL_OK) {
-						ERR_PRINT("Error calling UndoRedo method operation '" + String(op.name) + "': " + Variant::get_call_error_text(obj, op.name, nullptr, 0, ce));
+						ERR_PRINT(vformat("Error calling UndoRedo method operation '%s': %s.", String(op.name), Variant::get_call_error_text(obj, op.name, nullptr, 0, ce)));
 					}
 					}
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
 					Resource *res = Object::cast_to<Resource>(obj);
 					Resource *res = Object::cast_to<Resource>(obj);

+ 1 - 1
core/os/os.cpp

@@ -352,7 +352,7 @@ void OS::ensure_user_data_dir() {
 
 
 	Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 	Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 	Error err = da->make_dir_recursive(dd);
 	Error err = da->make_dir_recursive(dd);
-	ERR_FAIL_COND_MSG(err != OK, "Error attempting to create data dir: " + dd + ".");
+	ERR_FAIL_COND_MSG(err != OK, vformat("Error attempting to create data dir: %s.", dd));
 }
 }
 
 
 String OS::get_model_name() const {
 String OS::get_model_name() const {

+ 1 - 1
core/string/node_path.cpp

@@ -420,7 +420,7 @@ NodePath::NodePath(const String &p_path) {
 						continue; // Allow end-of-path :
 						continue; // Allow end-of-path :
 					}
 					}
 
 
-					ERR_FAIL_MSG("Invalid NodePath '" + p_path + "'.");
+					ERR_FAIL_MSG(vformat("Invalid NodePath '%s'.", p_path));
 				}
 				}
 				subpath.push_back(str);
 				subpath.push_back(str);
 
 

+ 5 - 5
core/string/translation_po.cpp

@@ -246,7 +246,7 @@ void TranslationPO::add_message(const StringName &p_src_text, const StringName &
 	HashMap<StringName, Vector<StringName>> &map_id_str = translation_map[p_context];
 	HashMap<StringName, Vector<StringName>> &map_id_str = translation_map[p_context];
 
 
 	if (map_id_str.has(p_src_text)) {
 	if (map_id_str.has(p_src_text)) {
-		WARN_PRINT("Double translations for \"" + String(p_src_text) + "\" under the same context \"" + String(p_context) + "\" for locale \"" + get_locale() + "\".\nThere should only be one unique translation for a given string under the same context.");
+		WARN_PRINT(vformat("Double translations for \"%s\" under the same context \"%s\" for locale \"%s\".\nThere should only be one unique translation for a given string under the same context.", String(p_src_text), String(p_context), get_locale()));
 		map_id_str[p_src_text].set(0, p_xlated_text);
 		map_id_str[p_src_text].set(0, p_xlated_text);
 	} else {
 	} else {
 		map_id_str[p_src_text].push_back(p_xlated_text);
 		map_id_str[p_src_text].push_back(p_xlated_text);
@@ -254,12 +254,12 @@ void TranslationPO::add_message(const StringName &p_src_text, const StringName &
 }
 }
 
 
 void TranslationPO::add_plural_message(const StringName &p_src_text, const Vector<String> &p_plural_xlated_texts, const StringName &p_context) {
 void TranslationPO::add_plural_message(const StringName &p_src_text, const Vector<String> &p_plural_xlated_texts, const StringName &p_context) {
-	ERR_FAIL_COND_MSG(p_plural_xlated_texts.size() != plural_forms, "Trying to add plural texts that don't match the required number of plural forms for locale \"" + get_locale() + "\"");
+	ERR_FAIL_COND_MSG(p_plural_xlated_texts.size() != plural_forms, vformat("Trying to add plural texts that don't match the required number of plural forms for locale \"%s\".", get_locale()));
 
 
 	HashMap<StringName, Vector<StringName>> &map_id_str = translation_map[p_context];
 	HashMap<StringName, Vector<StringName>> &map_id_str = translation_map[p_context];
 
 
 	if (map_id_str.has(p_src_text)) {
 	if (map_id_str.has(p_src_text)) {
-		WARN_PRINT("Double translations for \"" + p_src_text + "\" under the same context \"" + p_context + "\" for locale " + get_locale() + ".\nThere should only be one unique translation for a given string under the same context.");
+		WARN_PRINT(vformat("Double translations for \"%s\" under the same context \"%s\" for locale %s.\nThere should only be one unique translation for a given string under the same context.", p_src_text, p_context, get_locale()));
 		map_id_str[p_src_text].clear();
 		map_id_str[p_src_text].clear();
 	}
 	}
 
 
@@ -280,7 +280,7 @@ StringName TranslationPO::get_message(const StringName &p_src_text, const String
 	if (!translation_map.has(p_context) || !translation_map[p_context].has(p_src_text)) {
 	if (!translation_map.has(p_context) || !translation_map[p_context].has(p_src_text)) {
 		return StringName();
 		return StringName();
 	}
 	}
-	ERR_FAIL_COND_V_MSG(translation_map[p_context][p_src_text].is_empty(), StringName(), "Source text \"" + String(p_src_text) + "\" is registered but doesn't have a translation. Please report this bug.");
+	ERR_FAIL_COND_V_MSG(translation_map[p_context][p_src_text].is_empty(), StringName(), vformat("Source text \"%s\" is registered but doesn't have a translation. Please report this bug.", String(p_src_text)));
 
 
 	return translation_map[p_context][p_src_text][0];
 	return translation_map[p_context][p_src_text][0];
 }
 }
@@ -296,7 +296,7 @@ StringName TranslationPO::get_plural_message(const StringName &p_src_text, const
 	if (!translation_map.has(p_context) || !translation_map[p_context].has(p_src_text)) {
 	if (!translation_map.has(p_context) || !translation_map[p_context].has(p_src_text)) {
 		return StringName();
 		return StringName();
 	}
 	}
-	ERR_FAIL_COND_V_MSG(translation_map[p_context][p_src_text].is_empty(), StringName(), "Source text \"" + String(p_src_text) + "\" is registered but doesn't have a translation. Please report this bug.");
+	ERR_FAIL_COND_V_MSG(translation_map[p_context][p_src_text].is_empty(), StringName(), vformat("Source text \"%s\" is registered but doesn't have a translation. Please report this bug.", String(p_src_text)));
 
 
 	int plural_index = _get_plural_index(p_n);
 	int plural_index = _get_plural_index(p_n);
 	ERR_FAIL_COND_V_MSG(plural_index < 0 || translation_map[p_context][p_src_text].size() < plural_index + 1, StringName(), "Plural index returned or number of plural translations is not valid. Please report this bug.");
 	ERR_FAIL_COND_V_MSG(plural_index < 0 || translation_map[p_context][p_src_text].size() < plural_index + 1, StringName(), "Plural index returned or number of plural translations is not valid. Please report this bug.");

+ 7 - 7
core/variant/array.cpp

@@ -385,7 +385,7 @@ int Array::find_custom(const Callable &p_callable, int p_from) const {
 		Callable::CallError ce;
 		Callable::CallError ce;
 		p_callable.callp(argptrs, 1, res, ce);
 		p_callable.callp(argptrs, 1, res, ce);
 		if (unlikely(ce.error != Callable::CallError::CALL_OK)) {
 		if (unlikely(ce.error != Callable::CallError::CALL_OK)) {
-			ERR_FAIL_V_MSG(ret, "Error calling method from 'find_custom': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce));
+			ERR_FAIL_V_MSG(ret, vformat("Error calling method from 'find_custom': %s.", Variant::get_callable_error_text(p_callable, argptrs, 1, ce)));
 		}
 		}
 
 
 		ERR_FAIL_COND_V_MSG(res.get_type() != Variant::Type::BOOL, ret, "Error on method from 'find_custom': Return type of callable must be boolean.");
 		ERR_FAIL_COND_V_MSG(res.get_type() != Variant::Type::BOOL, ret, "Error on method from 'find_custom': Return type of callable must be boolean.");
@@ -445,7 +445,7 @@ int Array::rfind_custom(const Callable &p_callable, int p_from) const {
 		Callable::CallError ce;
 		Callable::CallError ce;
 		p_callable.callp(argptrs, 1, res, ce);
 		p_callable.callp(argptrs, 1, res, ce);
 		if (unlikely(ce.error != Callable::CallError::CALL_OK)) {
 		if (unlikely(ce.error != Callable::CallError::CALL_OK)) {
-			ERR_FAIL_V_MSG(-1, "Error calling method from 'rfind_custom': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce));
+			ERR_FAIL_V_MSG(-1, vformat("Error calling method from 'rfind_custom': %s.", Variant::get_callable_error_text(p_callable, argptrs, 1, ce)));
 		}
 		}
 
 
 		ERR_FAIL_COND_V_MSG(res.get_type() != Variant::Type::BOOL, -1, "Error on method from 'rfind_custom': Return type of callable must be boolean.");
 		ERR_FAIL_COND_V_MSG(res.get_type() != Variant::Type::BOOL, -1, "Error on method from 'rfind_custom': Return type of callable must be boolean.");
@@ -574,7 +574,7 @@ Array Array::filter(const Callable &p_callable) const {
 		Callable::CallError ce;
 		Callable::CallError ce;
 		p_callable.callp(argptrs, 1, result, ce);
 		p_callable.callp(argptrs, 1, result, ce);
 		if (ce.error != Callable::CallError::CALL_OK) {
 		if (ce.error != Callable::CallError::CALL_OK) {
-			ERR_FAIL_V_MSG(Array(), "Error calling method from 'filter': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce));
+			ERR_FAIL_V_MSG(Array(), vformat("Error calling method from 'filter': %s.", Variant::get_callable_error_text(p_callable, argptrs, 1, ce)));
 		}
 		}
 
 
 		if (result.operator bool()) {
 		if (result.operator bool()) {
@@ -600,7 +600,7 @@ Array Array::map(const Callable &p_callable) const {
 		Callable::CallError ce;
 		Callable::CallError ce;
 		p_callable.callp(argptrs, 1, result, ce);
 		p_callable.callp(argptrs, 1, result, ce);
 		if (ce.error != Callable::CallError::CALL_OK) {
 		if (ce.error != Callable::CallError::CALL_OK) {
-			ERR_FAIL_V_MSG(Array(), "Error calling method from 'map': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce));
+			ERR_FAIL_V_MSG(Array(), vformat("Error calling method from 'map': %s.", Variant::get_callable_error_text(p_callable, argptrs, 1, ce)));
 		}
 		}
 
 
 		new_arr[i] = result;
 		new_arr[i] = result;
@@ -626,7 +626,7 @@ Variant Array::reduce(const Callable &p_callable, const Variant &p_accum) const
 		Callable::CallError ce;
 		Callable::CallError ce;
 		p_callable.callp(argptrs, 2, result, ce);
 		p_callable.callp(argptrs, 2, result, ce);
 		if (ce.error != Callable::CallError::CALL_OK) {
 		if (ce.error != Callable::CallError::CALL_OK) {
-			ERR_FAIL_V_MSG(Variant(), "Error calling method from 'reduce': " + Variant::get_callable_error_text(p_callable, argptrs, 2, ce));
+			ERR_FAIL_V_MSG(Variant(), vformat("Error calling method from 'reduce': %s.", Variant::get_callable_error_text(p_callable, argptrs, 2, ce)));
 		}
 		}
 		ret = result;
 		ret = result;
 	}
 	}
@@ -643,7 +643,7 @@ bool Array::any(const Callable &p_callable) const {
 		Callable::CallError ce;
 		Callable::CallError ce;
 		p_callable.callp(argptrs, 1, result, ce);
 		p_callable.callp(argptrs, 1, result, ce);
 		if (ce.error != Callable::CallError::CALL_OK) {
 		if (ce.error != Callable::CallError::CALL_OK) {
-			ERR_FAIL_V_MSG(false, "Error calling method from 'any': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce));
+			ERR_FAIL_V_MSG(false, vformat("Error calling method from 'any': %s.", Variant::get_callable_error_text(p_callable, argptrs, 1, ce)));
 		}
 		}
 
 
 		if (result.operator bool()) {
 		if (result.operator bool()) {
@@ -665,7 +665,7 @@ bool Array::all(const Callable &p_callable) const {
 		Callable::CallError ce;
 		Callable::CallError ce;
 		p_callable.callp(argptrs, 1, result, ce);
 		p_callable.callp(argptrs, 1, result, ce);
 		if (ce.error != Callable::CallError::CALL_OK) {
 		if (ce.error != Callable::CallError::CALL_OK) {
-			ERR_FAIL_V_MSG(false, "Error calling method from 'all': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce));
+			ERR_FAIL_V_MSG(false, vformat("Error calling method from 'all': %s.", Variant::get_callable_error_text(p_callable, argptrs, 1, ce)));
 		}
 		}
 
 
 		if (!(result.operator bool())) {
 		if (!(result.operator bool())) {

+ 5 - 5
core/variant/container_type_validate.h

@@ -94,7 +94,7 @@ struct ContainerTypeValidate {
 				return true;
 				return true;
 			}
 			}
 
 
-			ERR_FAIL_V_MSG(false, "Attempted to " + String(p_operation) + " a variable of type '" + Variant::get_type_name(inout_variant.get_type()) + "' into a " + where + " of type '" + Variant::get_type_name(type) + "'.");
+			ERR_FAIL_V_MSG(false, vformat("Attempted to %s a variable of type '%s' into a %s of type '%s'.", String(p_operation), Variant::get_type_name(inout_variant.get_type()), where, Variant::get_type_name(type)));
 		}
 		}
 
 
 		if (type != Variant::OBJECT) {
 		if (type != Variant::OBJECT) {
@@ -113,7 +113,7 @@ struct ContainerTypeValidate {
 			return true; // This is fine, it's null.
 			return true; // This is fine, it's null.
 		}
 		}
 		Object *object = ObjectDB::get_instance(object_id);
 		Object *object = ObjectDB::get_instance(object_id);
-		ERR_FAIL_NULL_V_MSG(object, false, "Attempted to " + String(p_operation) + " an invalid (previously freed?) object instance into a '" + String(where) + ".");
+		ERR_FAIL_NULL_V_MSG(object, false, vformat("Attempted to %s an invalid (previously freed?) object instance into a '%s'.", String(p_operation), String(where)));
 #else
 #else
 		Object *object = p_variant;
 		Object *object = p_variant;
 		if (object == nullptr) {
 		if (object == nullptr) {
@@ -126,7 +126,7 @@ struct ContainerTypeValidate {
 
 
 		StringName obj_class = object->get_class_name();
 		StringName obj_class = object->get_class_name();
 		if (obj_class != class_name) {
 		if (obj_class != class_name) {
-			ERR_FAIL_COND_V_MSG(!ClassDB::is_parent_class(object->get_class_name(), class_name), false, "Attempted to " + String(p_operation) + " an object of type '" + object->get_class() + "' into a " + where + ", which does not inherit from '" + String(class_name) + "'.");
+			ERR_FAIL_COND_V_MSG(!ClassDB::is_parent_class(object->get_class_name(), class_name), false, vformat("Attempted to %s an object of type '%s' into a %s, which does not inherit from '%s'.", String(p_operation), object->get_class(), where, String(class_name)));
 		}
 		}
 
 
 		if (script.is_null()) {
 		if (script.is_null()) {
@@ -136,8 +136,8 @@ struct ContainerTypeValidate {
 		Ref<Script> other_script = object->get_script();
 		Ref<Script> other_script = object->get_script();
 
 
 		// Check base script..
 		// Check base script..
-		ERR_FAIL_COND_V_MSG(other_script.is_null(), false, "Attempted to " + String(p_operation) + " an object into a " + String(where) + ", that does not inherit from '" + String(script->get_class_name()) + "'.");
-		ERR_FAIL_COND_V_MSG(!other_script->inherits_script(script), false, "Attempted to " + String(p_operation) + " an object into a " + String(where) + ", that does not inherit from '" + String(script->get_class_name()) + "'.");
+		ERR_FAIL_COND_V_MSG(other_script.is_null(), false, vformat("Attempted to %s an object into a %s, that does not inherit from '%s'.", String(p_operation), String(where), String(script->get_class_name())));
+		ERR_FAIL_COND_V_MSG(!other_script->inherits_script(script), false, vformat("Attempted to %s an object into a %s, that does not inherit from '%s'.", String(p_operation), String(where), String(script->get_class_name())));
 
 
 		return true;
 		return true;
 	}
 	}

+ 1 - 1
core/variant/variant_construct.cpp

@@ -43,7 +43,7 @@ static LocalVector<VariantConstructData> construct_data[Variant::VARIANT_MAX];
 
 
 template <typename T>
 template <typename T>
 static void add_constructor(const Vector<String> &arg_names) {
 static void add_constructor(const Vector<String> &arg_names) {
-	ERR_FAIL_COND_MSG(arg_names.size() != T::get_argument_count(), "Argument names size mismatch for " + Variant::get_type_name(T::get_base_type()) + ".");
+	ERR_FAIL_COND_MSG(arg_names.size() != T::get_argument_count(), vformat("Argument names size mismatch for '%s'.", Variant::get_type_name(T::get_base_type())));
 
 
 	VariantConstructData cd;
 	VariantConstructData cd;
 	cd.construct = T::construct;
 	cd.construct = T::construct;

+ 1 - 1
core/variant/variant_utility.cpp

@@ -1671,7 +1671,7 @@ static void register_utility_function(const String &p_name, const Vector<String>
 	bfi.argnames = argnames;
 	bfi.argnames = argnames;
 	bfi.argcount = T::get_argument_count();
 	bfi.argcount = T::get_argument_count();
 	if (!bfi.is_vararg) {
 	if (!bfi.is_vararg) {
-		ERR_FAIL_COND_MSG(argnames.size() != bfi.argcount, "wrong number of arguments binding utility function: " + name);
+		ERR_FAIL_COND_MSG(argnames.size() != bfi.argcount, vformat("Wrong number of arguments binding utility function: '%s'.", name));
 	}
 	}
 	bfi.get_arg_type = T::get_argument_type;
 	bfi.get_arg_type = T::get_argument_type;
 	bfi.return_type = T::get_return_type();
 	bfi.return_type = T::get_return_type();