normalizeTypeFromSignature: Beware of anonymous struct/union

Do a quick check whether the type name contains an anonymous type. If
so, do not try to use optimized version. The simple check should still
be faster than calling normalizeType unconditionally.

Also only apply the faster version for clang and gcc, instead of all
non-MSVC compilers. Applying it to other compilers would require further
testing to handle anonymous structs.

Moreover, remove space before '(', which is necessary for function
pointers.

Fixes: QTBUG-94213
Change-Id: I795d1964f7a68daa6f9a5f262816d51ee7728788
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
This commit is contained in:
Fabian Kosmale 2021-06-07 13:59:45 +02:00
parent 14b74af060
commit c76a2d7c9c
2 changed files with 26 additions and 2 deletions

View File

@ -1879,12 +1879,21 @@ private:
}
public:
#ifndef Q_CC_MSVC
#if defined(Q_CC_CLANG) || defined (Q_CC_GNU)
// this is much simpler than the full type normalization below
// the reason is that the signature returned by Q_FUNC_INFO is already
// normalized to the largest degree, and we need to do only small adjustments
constexpr int normalizeTypeFromSignature(const char *begin, const char *end)
{
// bail out if there is an anonymous struct
std::string_view name(begin, end-begin);
#if defined (Q_CC_CLANG)
if (name.find("anonymous ") != std::string_view::npos)
return normalizeType(begin, end);
#else
if (name.find("unnamed ") != std::string_view::npos)
return normalizeType(begin, end);
#endif
while (begin < end) {
if (*begin == ' ') {
if (last == ',' || last == '>' || last == '<' || last == '*' || last == '&') {
@ -1893,7 +1902,7 @@ public:
}
}
if (last == ' ') {
if (*begin == '*' || *begin == '&') {
if (*begin == '*' || *begin == '&' || *begin == '(') {
replaceLast(*begin);
++begin;
continue;

View File

@ -385,6 +385,11 @@ struct CharTemplate
{
int a;
} x;
union
{
int a;
} y;
};
void tst_QMetaType::operatorEq_data()
@ -479,6 +484,16 @@ void tst_QMetaType::typeNameNormalization()
// The string based normalization doesn't handle aliases, QMetaType::fromType() does
// CHECK_TYPE_NORMALIZATION("qulonglong", quint64);
QCOMPARE(QMetaType::fromType<quint64>().name(), "qulonglong");
// noramlizedType and metatype name agree
{
auto type = QMetaType::fromType<decltype(CharTemplate<'<'>::x)>();
QCOMPARE(type.name(), QMetaObject::normalizedType(type.name()));
}
{
auto type = QMetaType::fromType<decltype(CharTemplate<'<'>::y)>();
QCOMPARE(type.name(), QMetaObject::normalizedType(type.name()));
}
}
// Compile-time test, it should be possible to register function pointer types