QMetaMethod: Store method constness in metaobject system

[ChangeLog][QtCore][QMetaMethod] It is now possible to query the
constness of a method with QMetaMethod::isConst.

Change-Id: I8a94480b8074ef5b30555aeccd64937c4c6d97d4
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
Fabian Kosmale 2021-05-07 09:21:23 +02:00
parent d5c3e1336b
commit 300dec66ce
7 changed files with 76 additions and 4 deletions

View File

@ -2139,6 +2139,23 @@ int QMetaMethod::revision() const
return 0;
}
/*!
\since 6.2
Returns whether the method is const qualified.
\note This method might errorneously return \false for a const method
if it belongs to a library compiled against an older version of Qt.
*/
bool QMetaMethod::isConst() const
{
if (!mobj)
return false;
if (QMetaObjectPrivate::get(mobj)->revision < 10)
return false;
return data.flags() & MethodIsConst;
}
/*!
Returns the access specification of this method (private,
protected, or public).

View File

@ -77,6 +77,7 @@ public:
int methodIndex() const;
int relativeMethodIndex() const;
int revision() const;
bool isConst() const;
inline const QMetaObject *enclosingMetaObject() const { return mobj; }

View File

@ -98,7 +98,9 @@ enum MethodFlags {
MethodCompatibility = 0x10,
MethodCloned = 0x20,
MethodScriptable = 0x40,
MethodRevisioned = 0x80
MethodRevisioned = 0x80,
MethodIsConst = 0x100, // no use case for volatile so far
};
enum MetaObjectFlag {
@ -173,6 +175,7 @@ struct QMetaObjectPrivate
// revision 8 is Qt 5.12: It adds the enum name to QMetaEnum
// revision 9 is Qt 6.0: It adds the metatype of properties and methods
// revision 10 is Qt 6.2: The metatype of the metaobject is stored in the metatypes array
// and metamethods store a flag stating whether they are const
enum { OutputRevision = 10 }; // Used by moc, qmetaobjectbuilder and qdbus
enum { IntsPerMethod = QMetaMethod::Data::Size };
enum { IntsPerEnum = QMetaEnum::Data::Size };

View File

@ -1742,6 +1742,28 @@ void QMetaMethodBuilder::setAttributes(int value)
d->attributes = ((d->attributes & 0x0f) | (value << 4));
}
/*!
Returns true if the method is const qualified.
*/
int QMetaMethodBuilder::isConst() const
{
QMetaMethodBuilderPrivate *d = d_func();
if (!d)
return false;
return (d->attributes & MethodIsConst);
}
void QMetaMethodBuilder::setConst(bool methodIsConst)
{
QMetaMethodBuilderPrivate *d = d_func();
if (!d)
return;
if (methodIsConst)
d->attributes |= MethodIsConst;
else
d->attributes &= ~MethodIsConst;
}
/*!
Returns the revision of this method.

View File

@ -204,6 +204,9 @@ public:
int attributes() const;
void setAttributes(int value);
int isConst() const;
void setConst(bool methodIsConst=true);
int revision() const;
void setRevision(int revision);

View File

@ -747,7 +747,7 @@ void Generator::generateFunctions(const QList<FunctionDef> &list, const char *fu
const FunctionDef &f = list.at(i);
QByteArray comment;
unsigned char flags = type;
uint flags = type;
if (f.access == FunctionDef::Private) {
flags |= AccessPrivate;
comment.append("Private");
@ -775,6 +775,11 @@ void Generator::generateFunctions(const QList<FunctionDef> &list, const char *fu
comment.append(" | MethodRevisioned");
}
if (f.isConst) {
flags |= MethodIsConst;
comment.append(" | MethodIsConst ");
}
int argc = f.arguments.count();
fprintf(out, " %4d, %4d, %4d, %4d, 0x%02x, %4d /* %s */,\n",
stridx(f.name), argc, paramsIndex, stridx(f.tag), flags, initialMetatypeOffset, comment.constData());

View File

@ -55,6 +55,8 @@ private slots:
void parameterMetaType();
void parameterTypeName();
void isConst();
};
struct CustomType { };
@ -82,7 +84,7 @@ public:
uchar ucharArg, float floatArg);
Q_INVOKABLE MethodTestObject(bool, int);
Q_INVOKABLE void voidInvokable();
Q_INVOKABLE void voidInvokable() const;
Q_INVOKABLE void voidInvokableInt(int voidInvokableIntArg);
Q_INVOKABLE void voidInvokableQReal(qreal voidInvokableQRealArg);
Q_INVOKABLE void voidInvokableQString(const QString &voidInvokableQStringArg);
@ -143,7 +145,7 @@ MethodTestObject::MethodTestObject(bool, int, uint, qlonglong, qulonglong,
uchar, float) {}
MethodTestObject::MethodTestObject(bool, int) {}
void MethodTestObject::voidInvokable() {}
void MethodTestObject::voidInvokable() const {}
void MethodTestObject::voidInvokableInt(int) {}
void MethodTestObject::voidInvokableQReal(qreal) {}
void MethodTestObject::voidInvokableQString(const QString &) {}
@ -866,6 +868,25 @@ void tst_QMetaMethod::parameterTypeName()
}
}
void tst_QMetaMethod::isConst()
{
auto mo = MethodTestObject::staticMetaObject;
{
const auto normalized = QMetaObject::normalizedSignature("qrealInvokable()");
const int idx = mo.indexOfSlot(normalized);
QMetaMethod mm = mo.method(idx);
QVERIFY(mm.isValid());
QCOMPARE(mm.isConst(), false);
}
{
const auto normalized = QMetaObject::normalizedSignature("voidInvokable()");
const int idx = mo.indexOfSlot(normalized);
QMetaMethod mm = mo.method(idx);
QVERIFY(mm.isValid());
QCOMPARE(mm.isConst(), true);
}
}
QTEST_MAIN(tst_QMetaMethod)
#include "tst_qmetamethod.moc"