From 844e4f7b982f2622dbdce0c4b70775d5bd17f043 Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Wed, 24 Jun 2020 08:25:17 +0200 Subject: [PATCH] moc: Fix QProperty code generation This addresses two issues: 1. The generated code for QNotifiedProperty was broken when T is a pointer. Notably, const S* & is not a constant reference to S*. This is addressed by consistently using T const& instead of const T&. 2. The Q_PRIVATE_QPROPERTY approach assumed that the property name and the getter are equal. This does break when they are not, and we are unable to change either of them due to API compatibility concerns. An example of this would be QQuickItem's parent property with a parentItem getter. Therefore, we now allow the usage of NAME to override the name of the property. Change-Id: Idf2e85576c74371b5b0f6db15dbe6f2d17c5e33d Reviewed-by: Ulf Hermann --- src/corelib/kernel/qtmetamacros.h | 6 +++--- src/tools/moc/generator.cpp | 8 ++++---- src/tools/moc/moc.cpp | 7 +++++++ src/tools/moc/moc.h | 2 +- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/corelib/kernel/qtmetamacros.h b/src/corelib/kernel/qtmetamacros.h index 4214522e98e..68f74cafc3b 100644 --- a/src/corelib/kernel/qtmetamacros.h +++ b/src/corelib/kernel/qtmetamacros.h @@ -96,8 +96,8 @@ QT_BEGIN_NAMESPACE type value() const; \ type operator()() const { return value(); } \ void setValue(type &&); \ - void setValue(const type &); \ - void operator=(const type &v) { setValue(v); } \ + void setValue(type const &); \ + void operator=(type const &v) { setValue(v); } \ void operator=(type &&v) { setValue(std::move(v)); } \ QPropertyBinding setBinding(const QPropertyBinding &); \ QPropertyBinding setBinding(QPropertyBinding &&); \ @@ -114,7 +114,7 @@ QT_BEGIN_NAMESPACE QPropertyBinding binding() const; \ QPropertyBinding takeBinding(); \ }; \ - void setter(const type &value); + void setter(type const& value); #if __has_cpp_attribute(no_unique_address) #define Q_PRIVATE_QPROPERTIES_BEGIN #define QT_PRIVATE_QPROPERTY_PREFIX [[no_unique_address]] diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index 0d3a763a484..fcf6b37876c 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -1419,7 +1419,7 @@ void Generator::generateStaticMetacall() prefix += p.inPrivateClass + "->"; } fprintf(out, " case %d: observer->setSource(%s%s); break;\n", - propindex, prefix.constData(), p.name.constData()); + propindex, prefix.constData(), p.qpropertyname.isEmpty() ? p.name.constData() : p.qpropertyname.constData()); } fprintf(out, " default: break;\n"); fprintf(out, " }\n"); @@ -1447,7 +1447,7 @@ void Generator::generateStaticMetacall() else objectAccessor.clear(); fprintf(out, " case %d: %s%s.setBinding(%s*reinterpret_cast *>(_a[0])); break;\n", - propindex, prefix.constData(), p.name.constData(), objectAccessor.constData(), p.type.constData()); + propindex, prefix.constData(), p.qpropertyname.isEmpty() ? p.name.constData() : p.qpropertyname.constData(), objectAccessor.constData(), p.type.constData()); } fprintf(out, " default: break;\n"); fprintf(out, " }\n"); @@ -1557,7 +1557,7 @@ void Generator::generateQPropertyApi() fprintf(out, "}\n"); // property value setter - fprintf(out, "\nvoid %s::_qt_property_api_%s::setValue(const %s &value)\n{\n", + fprintf(out, "\nvoid %s::_qt_property_api_%s::setValue(%s const &value)\n{\n", cdef->qualified.constData(), property.name.constData(), property.type.name.constData()); @@ -1629,7 +1629,7 @@ void Generator::generateQPropertyApi() fprintf(out, "}\n"); // property setter function - fprintf(out, "\nvoid %s::%s(const %s &value)\n{\n", + fprintf(out, "\nvoid %s::%s(%s const& value)\n{\n", cdef->qualified.constData(), property.setter.constData(), property.type.name.constData()); diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 5a1f0afab67..e31bdfbb154 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -1317,6 +1317,12 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef) } else if(l[0] == 'F' && l == "FINAL") { propDef.final = true; continue; + } else if (l[0] == 'N' && l == "NAME") { + if (!propDef.isQProperty) + error(1); + next(IDENTIFIER); + propDef.name = lexem(); + continue; } else if (l[0] == 'R' && l == "REQUIRED") { propDef.required = true; continue; @@ -1525,6 +1531,7 @@ void Moc::parsePrivateQProperty(ClassDef *def) PropertyDef propDef; propDef.name = name; + propDef.qpropertyname = name; propDef.type = type.name; propDef.read = name + ".value"; propDef.write = name + ".setValue"; diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h index 0f056853278..549b3cdd39c 100644 --- a/src/tools/moc/moc.h +++ b/src/tools/moc/moc.h @@ -132,7 +132,7 @@ struct PropertyDef return (s == write); } - QByteArray name, type, member, read, write, reset, designable, scriptable, stored, user, notify, inPrivateClass; + QByteArray name, type, member, read, write, reset, designable, scriptable, stored, user, notify, inPrivateClass, qpropertyname; int notifyId = -1; // -1 means no notifyId, >= 0 means signal defined in this class, < -1 means signal not defined in this class enum Specification { ValueSpec, ReferenceSpec, PointerSpec }; Specification gspec = ValueSpec;