QMetaType: fix typenameHelper() for types in the QtPrivate namespace

GCC at some point decided that it wouldn't include the full namespace
expansion in __PRETTY_FUNCTION__ for any type that is in the same
namespace as the template function being expanded (that is, the
QtPrivate) namespace. I don't know how long this behavior has been in
place, but it can be seen with GCC 13, where the expansion of that macro
inside QtPrivate::typenameHelper<QtPrivate::ModelIndex>() is:

 constexpr auto QtPrivate::typenameHelper() [with T = ModelIndex]

This can be easily worked around by using a different namespace.

Fixes: QTBUG-119650
Pick-to: 6.6 6.5 6.2
Change-Id: Ica7a43f6147b49c187ccfffd179df309e43a70cb
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
Thiago Macieira 2023-12-05 05:37:37 -08:00
parent 0d85d0a72f
commit ead408ca1b
3 changed files with 24 additions and 5 deletions

View File

@ -2235,6 +2235,7 @@ struct is_std_pair<std::pair<T1_, T2_>> : std::true_type {
using T2 = T2_;
};
namespace TypeNameHelper {
template<typename T>
constexpr auto typenameHelper()
{
@ -2276,15 +2277,15 @@ constexpr auto typenameHelper()
QT_STRINGIFY(QT_NAMESPACE) "::"
#endif
#if defined(Q_CC_MSVC) && defined(Q_CC_CLANG)
"auto __cdecl QtPrivate::typenameHelper(void) [T = "
"auto __cdecl QtPrivate::TypeNameHelper::typenameHelper(void) [T = "
#elif defined(Q_CC_MSVC)
"auto __cdecl QtPrivate::typenameHelper<"
"auto __cdecl QtPrivate::TypeNameHelper::typenameHelper<"
#elif defined(Q_CC_CLANG)
"auto QtPrivate::typenameHelper() [T = "
"auto QtPrivate::TypeNameHelper::typenameHelper() [T = "
#elif defined(Q_CC_GHS)
"auto QtPrivate::typenameHelper<T>()[with T="
"auto QtPrivate::TypeNameHelper::typenameHelper<T>()[with T="
#else
"constexpr auto QtPrivate::typenameHelper() [with T = "
"constexpr auto QtPrivate::TypeNameHelper::typenameHelper() [with T = "
#endif
) - 1;
#if defined(Q_CC_MSVC) && !defined(Q_CC_CLANG)
@ -2310,6 +2311,8 @@ constexpr auto typenameHelper()
return result;
}
}
} // namespace TypeNameHelper
using TypeNameHelper::typenameHelper;
template<typename T, typename = void>
struct BuiltinMetaType : std::integral_constant<int, 0>

View File

@ -120,6 +120,7 @@ private slots:
void typesWithInaccessibleDTors();
void voidIsNotUnknown();
void typeNameNormalization();
void typeNameInQtPrivate();
// Tests for deprecated APIs
#if QT_DEPRECATED_SINCE(6, 0)

View File

@ -640,6 +640,21 @@ void tst_QMetaType::typeNameNormalization()
}
}
QT_BEGIN_NAMESPACE
namespace QtPrivate { struct tst_QMetaType_TestType {}; }
QT_END_NAMESPACE
void tst_QMetaType::typeNameInQtPrivate()
{
using T = QT_PREPEND_NAMESPACE(QtPrivate::tst_QMetaType_TestType);
// some compilers (GCC) are known to suppress the namespace prefix if the
// type and the function where it is expanded on are on the same namespace
static constexpr char expectedName[] = "QtPrivate::tst_QMetaType_TestType";
QMetaType mt = QMetaType::fromType<T>();
QCOMPARE(mt.name(), expectedName);
}
#if QT_DEPRECATED_SINCE(6, 0)
void tst_QMetaType::testDeprecatedGetters()
{