diff options
author | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2021-08-16 17:04:08 +0200 |
---|---|---|
committer | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2021-08-17 02:55:12 +0200 |
commit | 0f39fc55c93bd0e9d53f42feb845524d2d9dfcd1 (patch) | |
tree | 24bda8f8ea136c610e9ce55dcd4da09dcddc63cd /src/corelib/global | |
parent | de9c03dc6eff8fd54c95d1aa533eabecaad20417 (diff) |
Forward declare Objective-C classes as class, not typedef objc_object
Forward declaring an Objective-C class in Objective-C/C++ mode is done
by using the `@class` syntax, e.g.:
@class NSString;
In C/C++ mode however there's no documented approach, so we chose
to flatten the type down to the opaque objc_object "base class":
typedef struct objc_object NSString;
As it turns out, when Objective-C classes are used as arguments or return
types in C++, the signature they produce is equal to what it would have
been if the type was a normal class. For example:
void foo(NSString *) -> __Z3fooP8NSString
The is due to @class in Objective-C++ just being just sugar, so an NSString
pointer is not treated as `struct objc_object *` but rather a pointer to a
distinct type, which then gets mangled as such by LLVM's Itanium mangler
in CXXNameMangler::mangleType(const ObjCObjectType *T).
With our current forward declaration however, we are expecting:
void foo(NSString *) -> __Z3fooP11objc_object
As a consequence exported helper functions such as QString::fromNSString()
are not possible to use from plain C++ right now, as it will give a linker
error for the missing QString::fromNSString(objc_object*) function.
And even if we did define the extra signature, it would not be possible
to declare overloaded functions taking Objective-C classes, as they would
all produce ambiguous overloads in C++ mode.
To fix this we change the forward declaration to a plain old class,
which matches the signature in both Objective-C++ and plain C++ mode,
and allows overloads. This is a binary compatible change, as no client
were using any of these functions from C++ anyways as they would have
produced linker errors. It does have a slight source compatible break,
for clients that manually forward declared classes using the old style,
but that use-case is deemed fringe enough to accept, and clients can
work around this by defining Q_FORWARD_DECLARE_OBJC_CLASS to their
preferred format, which Qt will respect.
Pick-to: 6.2
Change-Id: I04813c60a7da22379dd9de1be56cc12c53a38232
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/corelib/global')
-rw-r--r-- | src/corelib/global/qglobal.h | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index e2dc919e26..6467ba1984 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -859,7 +859,7 @@ constexpr inline QTypeTraits::Promoted<T, U> qBound(const U &min, const T &val, # ifdef __OBJC__ # define Q_FORWARD_DECLARE_OBJC_CLASS(classname) @class classname # else -# define Q_FORWARD_DECLARE_OBJC_CLASS(classname) typedef struct objc_object classname +# define Q_FORWARD_DECLARE_OBJC_CLASS(classname) class classname # endif #endif #ifndef Q_FORWARD_DECLARE_CF_TYPE |