moc: change the mangling of class names to closer to the IA-64 ABI

Commit e816f915411a0f517021769abd8919a423f635c3 ("Moc: avoid double
underscores in a generated identifier") added the CLASS..SCOPE..ENDCLASS
mangling to avoid creating double underscores, which are reserved to the
compiler and thus undefined behavior for us to use.

This commit changes that mangling to something similar to the IA-64 C++
ABI because a) that creates shorter identifier names that are often
easier to read if you have to open the moc result and b) will not
collide with a class name by the user that used SCOPE in the name, such
as:

 namespace Outer { class Inner { Q_GADGET }; }
 class OuterSCOPEInner : public QObject { Q_OBJECT } };

Before:
 Q_CONSTINIT static const uint qt_meta_data_CLASSOuterSCOPEInnerENDCLASS[] = {
 Q_CONSTINIT static const uint qt_meta_data_CLASSOuterSCOPEInnerENDCLASS[] = {

Now:
 Q_CONSTINIT static const uint qt_meta_data_ZN5Outer5InnerE[] =
 Q_CONSTINIT static const uint qt_meta_data_ZN15OuterSCOPEInnerE[] =

While I make no promises that this matches the mangling scheme, it can
actually be decoded by the c++filt(1) tool. The main difference (AFAICT)
is that we use the N..E production even for types in the global
namespace (e.g., "QObject" mangling should be "7QObject" but is
"N7QObjectE").

 $ c++filt _ZN42QTBUG32933_relatedObjectsDontIncludeItself2NS3ObjE
 QTBUG32933_relatedObjectsDontIncludeItself::NS::Obj

Pick-to: 6.7 6.5
Change-Id: I40b756c1ac0f6a986d79fffd14b2e245ac195afb
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
(cherry picked from commit b020bff6e9a2e45760bab61bdb84efc078c45f7f)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Thiago Macieira 2024-09-02 08:03:57 -07:00 committed by Qt Cherry-pick Bot
parent ee65704341
commit 30c490da13

View File

@ -202,17 +202,14 @@ static bool qualifiedNameEquals(const QByteArray &qualifiedName, const QByteArra
static QByteArray generateQualifiedClassNameIdentifier(const QByteArray &identifier)
{
QByteArray qualifiedClassNameIdentifier = identifier;
// Remove ':'s in the name, but be sure not to create any illegal
// identifiers in the process. (Don't replace with '_', because
// that will create problems with things like NS_::_class.)
qualifiedClassNameIdentifier.replace("::", "SCOPE");
// Also, avoid any leading/trailing underscores (we'll concatenate
// the generated name with other prefixes/suffixes, and these latter
// may already include an underscore, leading to two underscores)
qualifiedClassNameIdentifier = "CLASS" + qualifiedClassNameIdentifier + "ENDCLASS";
// This is similar to the IA-64 C++ ABI mangling scheme.
QByteArray qualifiedClassNameIdentifier = "ZN";
for (const auto scope : qTokenize(QLatin1StringView(identifier), QLatin1Char(':'),
Qt::SkipEmptyParts)) {
qualifiedClassNameIdentifier += QByteArray::number(scope.size());
qualifiedClassNameIdentifier += scope;
}
qualifiedClassNameIdentifier += 'E';
return qualifiedClassNameIdentifier;
}