Browse Source

Add and require `GDSOFTCLASS` for `Object` subclasses that want to cast but do not use `GDCLASS`.

Lukas Tenbrink 3 months ago
parent
commit
fa0a3c9c6e

+ 2 - 0
core/extension/gdextension_library_loader.h

@@ -37,6 +37,8 @@
 #include "core/os/shared_object.h"
 
 class GDExtensionLibraryLoader : public GDExtensionLoader {
+	GDSOFTCLASS(GDExtensionLibraryLoader, GDExtensionLoader);
+
 	friend class GDExtensionManager;
 	friend class GDExtension;
 

+ 2 - 0
core/extension/gdextension_loader.h

@@ -35,6 +35,8 @@
 class GDExtension;
 
 class GDExtensionLoader : public RefCounted {
+	GDSOFTCLASS(GDExtensionLoader, GDExtensionLoader);
+
 public:
 	virtual Error open_library(const String &p_path) = 0;
 	virtual Error initialize(GDExtensionInterfaceGetProcAddress p_get_proc_address, const Ref<GDExtension> &p_extension, GDExtensionInitialization *r_initialization) = 0;

+ 2 - 0
core/io/plist.h

@@ -83,6 +83,8 @@ public:
 /*************************************************************************/
 
 class PListNode : public RefCounted {
+	GDSOFTCLASS(PListNode, RefCounted);
+
 	static int _asn1_size_len(uint8_t p_len_octets);
 
 public:

+ 21 - 30
core/object/object.h

@@ -386,13 +386,29 @@ struct ObjectGDExtension {
  * much alone defines the object model.
  */
 
+// This is a barebones version of GDCLASS,
+// only intended for simple classes deriving from Object
+// so that they can support the `Object::cast_to()` method.
+#define GDSOFTCLASS(m_class, m_inherits)                                             \
+public:                                                                              \
+	typedef m_class self_type;                                                       \
+	static _FORCE_INLINE_ void *get_class_ptr_static() {                             \
+		static int ptr;                                                              \
+		return &ptr;                                                                 \
+	}                                                                                \
+	virtual bool is_class_ptr(void *p_ptr) const override {                          \
+		return (p_ptr == get_class_ptr_static()) || m_inherits::is_class_ptr(p_ptr); \
+	}                                                                                \
+                                                                                     \
+private:
+
 #define GDCLASS(m_class, m_inherits)                                                                                                        \
+	GDSOFTCLASS(m_class, m_inherits)                                                                                                        \
 private:                                                                                                                                    \
 	void operator=(const m_class &p_rval) {}                                                                                                \
 	friend class ::ClassDB;                                                                                                                 \
                                                                                                                                             \
 public:                                                                                                                                     \
-	typedef m_class self_type;                                                                                                              \
 	static constexpr bool _class_is_enabled = !bool(GD_IS_DEFINED(ClassDB_Disable_##m_class)) && m_inherits::_class_is_enabled;             \
 	virtual String get_class() const override {                                                                                             \
 		if (_get_extension()) {                                                                                                             \
@@ -407,10 +423,6 @@ public:
 		}                                                                                                                                   \
 		return &_class_name_static;                                                                                                         \
 	}                                                                                                                                       \
-	static _FORCE_INLINE_ void *get_class_ptr_static() {                                                                                    \
-		static int ptr;                                                                                                                     \
-		return &ptr;                                                                                                                        \
-	}                                                                                                                                       \
 	static _FORCE_INLINE_ String get_class_static() {                                                                                       \
 		return String(#m_class);                                                                                                            \
 	}                                                                                                                                       \
@@ -427,10 +439,6 @@ public:
 		}                                                                                                                                   \
 		return (p_class == (#m_class)) ? true : m_inherits::is_class(p_class);                                                              \
 	}                                                                                                                                       \
-	virtual bool is_class_ptr(void *p_ptr) const override {                                                                                 \
-		return (p_ptr == get_class_ptr_static()) ? true : m_inherits::is_class_ptr(p_ptr);                                                  \
-	}                                                                                                                                       \
-                                                                                                                                            \
 	static void get_valid_parents_static(List<String> *p_parents) {                                                                         \
 		if (m_class::_get_valid_parents_static != m_inherits::_get_valid_parents_static) {                                                  \
 			m_class::_get_valid_parents_static(p_parents);                                                                                  \
@@ -440,9 +448,6 @@ public:
 	}                                                                                                                                       \
                                                                                                                                             \
 protected:                                                                                                                                  \
-	virtual bool _derives_from(const std::type_info &p_type_info) const override {                                                          \
-		return typeid(m_class) == p_type_info || m_inherits::_derives_from(p_type_info);                                                    \
-	}                                                                                                                                       \
 	_FORCE_INLINE_ static void (*_get_bind_methods())() {                                                                                   \
 		return &m_class::_bind_methods;                                                                                                     \
 	}                                                                                                                                       \
@@ -771,12 +776,6 @@ protected:
 	mutable VirtualMethodTracker *virtual_method_list = nullptr;
 #endif
 
-	virtual bool _derives_from(const std::type_info &p_type_info) const {
-		// This could just be false because nobody would reasonably ask if an Object subclass derives from Object,
-		// but it would be wrong if somebody actually does ask. It's not too slow to check anyway.
-		return typeid(Object) == p_type_info;
-	}
-
 public: // Should be protected, but bug in clang++.
 	static void initialize_class();
 	_FORCE_INLINE_ static void register_custom_data_to_otdb() {}
@@ -799,23 +798,15 @@ public:
 		// This is like dynamic_cast, but faster.
 		// The reason is that we can assume no virtual and multiple inheritance.
 		static_assert(std::is_base_of_v<Object, T>, "T must be derived from Object");
-		if constexpr (std::is_same_v<std::decay_t<T>, typename T::self_type>) {
-			return p_object && p_object->_derives_from(typeid(T)) ? static_cast<T *>(p_object) : nullptr;
-		} else {
-			// T does not use GDCLASS, must fall back to dynamic_cast.
-			return p_object ? dynamic_cast<T *>(p_object) : nullptr;
-		}
+		static_assert(std::is_same_v<std::decay_t<T>, typename T::self_type>, "T must use GDCLASS or GDSOFTCLASS");
+		return p_object && p_object->is_class_ptr(T::get_class_ptr_static()) ? static_cast<T *>(p_object) : nullptr;
 	}
 
 	template <typename T>
 	static const T *cast_to(const Object *p_object) {
 		static_assert(std::is_base_of_v<Object, T>, "T must be derived from Object");
-		if constexpr (std::is_same_v<std::decay_t<T>, typename T::self_type>) {
-			return p_object && p_object->_derives_from(typeid(T)) ? static_cast<const T *>(p_object) : nullptr;
-		} else {
-			// T does not use GDCLASS, must fall back to dynamic_cast.
-			return p_object ? dynamic_cast<const T *>(p_object) : nullptr;
-		}
+		static_assert(std::is_same_v<std::decay_t<T>, typename T::self_type>, "T must use GDCLASS or GDSOFTCLASS");
+		return p_object && p_object->is_class_ptr(T::get_class_ptr_static()) ? static_cast<const T *>(p_object) : nullptr;
 	}
 
 	enum {

+ 2 - 0
editor/export/codesign.h

@@ -113,6 +113,8 @@ public:
 /*************************************************************************/
 
 class CodeSignBlob : public RefCounted {
+	GDSOFTCLASS(CodeSignBlob, RefCounted);
+
 public:
 	virtual PackedByteArray get_hash_sha1() const = 0;
 	virtual PackedByteArray get_hash_sha256() const = 0;

+ 8 - 6
modules/camera/camera_feed_linux.h

@@ -40,6 +40,8 @@
 struct StreamingBuffer;
 
 class CameraFeedLinux : public CameraFeed {
+	GDSOFTCLASS(CameraFeedLinux, CameraFeed);
+
 private:
 	SafeFlag exit_flag;
 	Thread *thread = nullptr;
@@ -64,12 +66,12 @@ private:
 
 public:
 	String get_device_name() const;
-	bool activate_feed();
-	void deactivate_feed();
-	bool set_format(int p_index, const Dictionary &p_parameters);
-	Array get_formats() const;
-	FeedFormat get_format() const;
+	bool activate_feed() override;
+	void deactivate_feed() override;
+	bool set_format(int p_index, const Dictionary &p_parameters) override;
+	Array get_formats() const override;
+	FeedFormat get_format() const override;
 
 	CameraFeedLinux(const String &p_device_name);
-	virtual ~CameraFeedLinux();
+	~CameraFeedLinux() override;
 };

+ 2 - 0
modules/camera/camera_macos.h

@@ -36,6 +36,8 @@
 #include "servers/camera_server.h"
 
 class CameraMacOS : public CameraServer {
+	GDSOFTCLASS(CameraMacOS, CameraServer);
+
 public:
 	CameraMacOS() = default;
 

+ 4 - 2
modules/camera/camera_macos.mm

@@ -195,6 +195,8 @@
 // CameraFeedMacOS - Subclass for camera feeds in macOS
 
 class CameraFeedMacOS : public CameraFeed {
+	GDSOFTCLASS(CameraFeedMacOS, CameraFeed);
+
 private:
 	AVCaptureDevice *device;
 	MyCaptureSession *capture_session;
@@ -206,8 +208,8 @@ public:
 
 	void set_device(AVCaptureDevice *p_device);
 
-	bool activate_feed();
-	void deactivate_feed();
+	bool activate_feed() override;
+	void deactivate_feed() override;
 };
 
 AVCaptureDevice *CameraFeedMacOS::get_device() const {

+ 2 - 0
modules/gdscript/gdscript_cache.h

@@ -41,6 +41,8 @@ class GDScriptAnalyzer;
 class GDScriptParser;
 
 class GDScriptParserRef : public RefCounted {
+	GDSOFTCLASS(GDScriptParserRef, RefCounted);
+
 public:
 	enum Status {
 		EMPTY,

+ 28 - 24
modules/mbedtls/crypto_mbedtls.h

@@ -39,6 +39,8 @@
 class CryptoMbedTLS;
 class TLSContextMbedTLS;
 class CryptoKeyMbedTLS : public CryptoKey {
+	GDSOFTCLASS(CryptoKeyMbedTLS, CryptoKey);
+
 private:
 	mbedtls_pk_context pkey;
 	int locks = 0;
@@ -51,17 +53,17 @@ public:
 	static void make_default() { CryptoKey::_create = create; }
 	static void finalize() { CryptoKey::_create = nullptr; }
 
-	virtual Error load(const String &p_path, bool p_public_only);
-	virtual Error save(const String &p_path, bool p_public_only);
-	virtual String save_to_string(bool p_public_only);
-	virtual Error load_from_string(const String &p_string_key, bool p_public_only);
-	virtual bool is_public_only() const { return public_only; }
+	Error load(const String &p_path, bool p_public_only) override;
+	Error save(const String &p_path, bool p_public_only) override;
+	String save_to_string(bool p_public_only) override;
+	Error load_from_string(const String &p_string_key, bool p_public_only) override;
+	bool is_public_only() const override { return public_only; }
 
 	CryptoKeyMbedTLS() {
 		mbedtls_pk_init(&pkey);
 		locks = 0;
 	}
-	~CryptoKeyMbedTLS() {
+	~CryptoKeyMbedTLS() override {
 		mbedtls_pk_free(&pkey);
 	}
 
@@ -73,6 +75,8 @@ public:
 };
 
 class X509CertificateMbedTLS : public X509Certificate {
+	GDSOFTCLASS(X509CertificateMbedTLS, X509Certificate);
+
 private:
 	mbedtls_x509_crt cert;
 	int locks;
@@ -82,17 +86,17 @@ public:
 	static void make_default() { X509Certificate::_create = create; }
 	static void finalize() { X509Certificate::_create = nullptr; }
 
-	virtual Error load(const String &p_path);
-	virtual Error load_from_memory(const uint8_t *p_buffer, int p_len);
-	virtual Error save(const String &p_path);
-	virtual String save_to_string();
-	virtual Error load_from_string(const String &p_string_key);
+	Error load(const String &p_path) override;
+	Error load_from_memory(const uint8_t *p_buffer, int p_len) override;
+	Error save(const String &p_path) override;
+	String save_to_string() override;
+	Error load_from_string(const String &p_string_key) override;
 
 	X509CertificateMbedTLS() {
 		mbedtls_x509_crt_init(&cert);
 		locks = 0;
 	}
-	~X509CertificateMbedTLS() {
+	~X509CertificateMbedTLS() override {
 		mbedtls_x509_crt_free(&cert);
 	}
 
@@ -116,12 +120,12 @@ public:
 
 	static bool is_md_type_allowed(mbedtls_md_type_t p_md_type);
 
-	virtual Error start(HashingContext::HashType p_hash_type, const PackedByteArray &p_key);
-	virtual Error update(const PackedByteArray &p_data);
-	virtual PackedByteArray finish();
+	Error start(HashingContext::HashType p_hash_type, const PackedByteArray &p_key) override;
+	Error update(const PackedByteArray &p_data) override;
+	PackedByteArray finish() override;
 
 	HMACContextMbedTLS() {}
-	~HMACContextMbedTLS();
+	~HMACContextMbedTLS() override;
 };
 
 class CryptoMbedTLS : public Crypto {
@@ -138,14 +142,14 @@ public:
 	static void load_default_certificates(const String &p_path);
 	static mbedtls_md_type_t md_type_from_hashtype(HashingContext::HashType p_hash_type, int &r_size);
 
-	virtual PackedByteArray generate_random_bytes(int p_bytes);
-	virtual Ref<CryptoKey> generate_rsa(int p_bytes);
-	virtual Ref<X509Certificate> generate_self_signed_certificate(Ref<CryptoKey> p_key, const String &p_issuer_name, const String &p_not_before, const String &p_not_after);
-	virtual Vector<uint8_t> sign(HashingContext::HashType p_hash_type, const Vector<uint8_t> &p_hash, Ref<CryptoKey> p_key);
-	virtual bool verify(HashingContext::HashType p_hash_type, const Vector<uint8_t> &p_hash, const Vector<uint8_t> &p_signature, Ref<CryptoKey> p_key);
-	virtual Vector<uint8_t> encrypt(Ref<CryptoKey> p_key, const Vector<uint8_t> &p_plaintext);
-	virtual Vector<uint8_t> decrypt(Ref<CryptoKey> p_key, const Vector<uint8_t> &p_ciphertext);
+	PackedByteArray generate_random_bytes(int p_bytes) override;
+	Ref<CryptoKey> generate_rsa(int p_bytes) override;
+	Ref<X509Certificate> generate_self_signed_certificate(Ref<CryptoKey> p_key, const String &p_issuer_name, const String &p_not_before, const String &p_not_after) override;
+	Vector<uint8_t> sign(HashingContext::HashType p_hash_type, const Vector<uint8_t> &p_hash, Ref<CryptoKey> p_key) override;
+	bool verify(HashingContext::HashType p_hash_type, const Vector<uint8_t> &p_hash, const Vector<uint8_t> &p_signature, Ref<CryptoKey> p_key) override;
+	Vector<uint8_t> encrypt(Ref<CryptoKey> p_key, const Vector<uint8_t> &p_plaintext) override;
+	Vector<uint8_t> decrypt(Ref<CryptoKey> p_key, const Vector<uint8_t> &p_ciphertext) override;
 
 	CryptoMbedTLS();
-	~CryptoMbedTLS();
+	~CryptoMbedTLS() override;
 };

+ 4 - 4
modules/mbedtls/dtls_server_mbedtls.h

@@ -44,10 +44,10 @@ public:
 	static void initialize();
 	static void finalize();
 
-	virtual Error setup(Ref<TLSOptions> p_options);
-	virtual void stop();
-	virtual Ref<PacketPeerDTLS> take_connection(Ref<PacketPeerUDP> p_peer);
+	Error setup(Ref<TLSOptions> p_options) override;
+	void stop() override;
+	Ref<PacketPeerDTLS> take_connection(Ref<PacketPeerUDP> p_peer) override;
 
 	DTLSServerMbedTLS();
-	~DTLSServerMbedTLS();
+	~DTLSServerMbedTLS() override;
 };

+ 2 - 2
modules/mbedtls/tls_context_mbedtls.h

@@ -56,7 +56,7 @@ public:
 	void clear();
 
 	CookieContextMbedTLS();
-	~CookieContextMbedTLS();
+	~CookieContextMbedTLS() override;
 };
 
 class TLSContextMbedTLS : public RefCounted {
@@ -83,5 +83,5 @@ public:
 	mbedtls_ssl_context *get_context();
 
 	TLSContextMbedTLS();
-	~TLSContextMbedTLS();
+	~TLSContextMbedTLS() override;
 };

+ 1 - 1
platform/android/display_server_android.h

@@ -38,7 +38,7 @@ class RenderingDevice;
 #endif
 
 class DisplayServerAndroid : public DisplayServer {
-	// No need to register with GDCLASS, it's platform-specific and nothing is added.
+	GDSOFTCLASS(DisplayServerAndroid, DisplayServer);
 
 	String rendering_driver;
 

+ 14 - 0
platform/linuxbsd/wayland/wayland_thread.h

@@ -88,6 +88,8 @@ class WaylandThread {
 public:
 	// Messages used for exchanging information between Godot's and Wayland's thread.
 	class Message : public RefCounted {
+		GDSOFTCLASS(Message, RefCounted);
+
 	public:
 		Message() {}
 		virtual ~Message() = default;
@@ -95,6 +97,8 @@ public:
 
 	// Message data for window rect changes.
 	class WindowRectMessage : public Message {
+		GDSOFTCLASS(WindowRectMessage, Message);
+
 	public:
 		// NOTE: This is in "scaled" terms. For example, if there's a 1920x1080 rect
 		// with a scale factor of 2, the actual value of `rect` will be 3840x2160.
@@ -102,27 +106,37 @@ public:
 	};
 
 	class WindowEventMessage : public Message {
+		GDSOFTCLASS(WindowEventMessage, Message);
+
 	public:
 		DisplayServer::WindowEvent event;
 	};
 
 	class InputEventMessage : public Message {
+		GDSOFTCLASS(InputEventMessage, Message);
+
 	public:
 		Ref<InputEvent> event;
 	};
 
 	class DropFilesEventMessage : public Message {
+		GDSOFTCLASS(DropFilesEventMessage, Message);
+
 	public:
 		Vector<String> files;
 	};
 
 	class IMEUpdateEventMessage : public Message {
+		GDSOFTCLASS(IMEUpdateEventMessage, Message);
+
 	public:
 		String text;
 		Vector2i selection;
 	};
 
 	class IMECommitEventMessage : public Message {
+		GDSOFTCLASS(IMECommitEventMessage, Message);
+
 	public:
 		String text;
 	};

+ 2 - 0
platform/web/javascript_bridge_singleton.cpp

@@ -64,6 +64,8 @@ extern int godot_js_wrapper_object_transfer_buffer(int p_id, void *p_byte_arr, v
 };
 
 class JavaScriptObjectImpl : public JavaScriptObject {
+	GDSOFTCLASS(JavaScriptObjectImpl, JavaScriptObject);
+
 private:
 	friend class JavaScriptBridge;
 

+ 2 - 0
tests/core/object/test_method_bind.h

@@ -55,6 +55,8 @@ public:
 	};
 
 	class ObjectSubclass : public Object {
+		GDSOFTCLASS(ObjectSubclass, Object);
+
 	public:
 		int value = 1;
 	};