Don't declare type 'id' in the global namespace in a public header

It's not necessary, and it breaks the qttools build (where we have a
global variable named 'id'), and thus will most certainly build a lot
of existing user code.

Amends e47c22480fe84c100019cd92d0296f0dd2a7f3f1.

Change-Id: I97a91c2cb23fdae65143cf14c81570cf88d529d5
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
Tor Arne Vestbø 2022-04-26 10:56:54 +02:00
parent c164b75c17
commit aa0a53fc19
3 changed files with 82 additions and 2 deletions

View File

@ -530,7 +530,7 @@ inline QDebug operator<<(QDebug debug, QKeyCombination combination)
QT_END_NAMESPACE
Q_FORWARD_DECLARE_CF_TYPE(CFString);
typedef struct objc_object *id;
struct objc_object;
Q_FORWARD_DECLARE_OBJC_CLASS(NSObject);
QT_FOR_EACH_CORE_FOUNDATION_TYPE(QT_FORWARD_DECLARE_CF_TYPE)
QT_FOR_EACH_MUTABLE_CORE_FOUNDATION_TYPE(QT_FORWARD_DECLARE_MUTABLE_CF_TYPE)
@ -555,7 +555,10 @@ QT_BEGIN_NAMESPACE
}
// Defined in qcore_mac_objc.mm
Q_CORE_EXPORT QDebug operator<<(QDebug, id obj);
#if defined(__OBJC__)
Q_CORE_EXPORT QDebug operator<<(QDebug, id);
#endif
Q_CORE_EXPORT QDebug operator<<(QDebug, objc_object *);
Q_CORE_EXPORT QDebug operator<<(QDebug, const NSObject *);
Q_CORE_EXPORT QDebug operator<<(QDebug, CFStringRef);

View File

@ -10,3 +10,7 @@ qt_internal_add_test(tst_qdebug
PUBLIC_LIBRARIES
Qt::Concurrent
)
if (APPLE)
target_compile_options(tst_qdebug PRIVATE -x objective-c++)
endif()

View File

@ -52,6 +52,10 @@ struct ConvertsToQVariant {
};
static_assert(!QTypeTraits::has_ostream_operator_v<QDebug, ConvertsToQVariant>);
#if defined(Q_OS_DARWIN)
#include <objc/runtime.h>
#include <Foundation/Foundation.h>
#endif
class tst_QDebug: public QObject
{
@ -88,6 +92,12 @@ private slots:
void threadSafety() const;
void toString() const;
void noQVariantEndlessRecursion() const;
#if defined(Q_OS_DARWIN)
void objcInCppMode_data() const;
void objcInCppMode() const;
void objcInObjcMode_data() const;
void objcInObjcMode() const;
#endif
};
void tst_QDebug::assignment() const
@ -873,6 +883,69 @@ void tst_QDebug::noQVariantEndlessRecursion() const
qDebug() << var;
}
#if defined(Q_OS_DARWIN)
@interface MyObjcClass : NSObject
@end
@implementation MyObjcClass : NSObject
- (NSString *)description
{
return @"MyObjcClass is the best";
}
@end
void tst_QDebug::objcInCppMode_data() const
{
QTest::addColumn<objc_object *>("object");
QTest::addColumn<QString>("message");
QTest::newRow("nil") << static_cast<objc_object*>(nullptr) << QString::fromLatin1("(null)");
// Not an NSObject subclass
auto *nsproxy = reinterpret_cast<objc_object *>(class_createInstance(objc_getClass("NSProxy"), 0));
QTest::newRow("NSProxy") << nsproxy << QString::fromLatin1("<NSProxy: 0x%1>").arg(uintptr_t(nsproxy), 1, 16);
// Plain NSObject
auto *nsobject = reinterpret_cast<objc_object *>(class_createInstance(objc_getClass("NSObject"), 0));
QTest::newRow("NSObject") << nsobject << QString::fromLatin1("<NSObject: 0x%1>").arg(uintptr_t(nsobject), 1, 16);
auto str = QString::fromLatin1("foo");
QTest::newRow("NSString") << reinterpret_cast<objc_object*>(str.toNSString()) << str;
// Custom debug description
QTest::newRow("MyObjcClass") << reinterpret_cast<objc_object*>([[MyObjcClass alloc] init])
<< QString::fromLatin1("MyObjcClass is the best");
}
void tst_QDebug::objcInCppMode() const
{
QFETCH(objc_object *, object);
QFETCH(QString, message);
MessageHandlerSetter mhs(myMessageHandler);
{ qDebug() << object; }
QCOMPARE(s_msg, message);
}
void tst_QDebug::objcInObjcMode_data() const
{
objcInCppMode_data();
}
void tst_QDebug::objcInObjcMode() const
{
QFETCH(objc_object *, object);
QFETCH(QString, message);
MessageHandlerSetter mhs(myMessageHandler);
{ qDebug() << static_cast<id>(object); }
QCOMPARE(s_msg, message);
}
#endif
// Should compile: instentiation of unrelated operator<< should not cause cause compilation
// error in QDebug operators (QTBUG-47375)
class TestClassA {};