From 27fcf66319605ed29d35de4034a41f05e8ba0a3b Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Wed, 22 Jul 2020 11:21:42 +0200 Subject: [PATCH] QMetaType: force properties to have a complete type again When the compile time metatype support for methods was introduced, we needed to allow incomplete types to avoid breaking a large amount of code. However, this mistakenly enabled using incomplete types for properties, too. In contrast to methods, properties lack the fallback code to retrieve the metatype at runtime. Thus, this commit restores the completeness requirement for properties again. This is done by always calling QMetaTypeForType for properties in qTryMetaTypeForType. Amends fa987d44417528856d5e80ed7b48ba99e19fa307 Change-Id: I5f66ff289631c056eecebe40926bf321d283eea7 Reviewed-by: Thiago Macieira --- src/corelib/kernel/qmetatype.h | 13 +++++++++++-- src/tools/moc/generator.cpp | 20 ++++++++++++++++---- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index e5a71dd5a88..f89ece7d23f 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -2828,12 +2828,21 @@ template using qRemovePointerLike_t = typename qRemovePointerLike::type; #undef Q_REMOVE_POINTER_LIKE_IMPL -template +template +struct TypeAndForceComplete +{ + using type = T; + using ForceComplete = ForceComplete_; +}; + +template constexpr QMetaTypeInterface *qTryMetaTypeInterfaceForType() { + using T = typename TypeCompletePair::type; + using ForceComplete = typename TypeCompletePair::ForceComplete; using Ty = std::remove_cv_t>; using Tz = qRemovePointerLike_t; - if constexpr (!is_complete::value) { + if constexpr (!is_complete::value && !ForceComplete::value) { return nullptr; } else { return &QMetaTypeForType::metaType; diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index 9fd61a34c3c..da3f22aa96c 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -580,17 +580,26 @@ void Generator::generateCode() } for (int i = 0; i < cdef->propertyList.count(); ++i) { const PropertyDef &p = cdef->propertyList.at(i); - fprintf(out, "%s%s", needsComma ? ", " : "", p.type.data()); + if (requireCompleteTypes) + fprintf(out, "%s%s", needsComma ? ", " : "", p.type.data()); + else + fprintf(out, "%sQtPrivate::TypeAndForceComplete<%s, std::true_type>", needsComma ? ", " : "", p.type.data()); needsComma = true; } for (const QList &methodContainer : { cdef->signalList, cdef->slotList, cdef->methodList }) { for (int i = 0; i< methodContainer.count(); ++i) { const FunctionDef& fdef = methodContainer.at(i); - fprintf(out, "%s%s", needsComma ? ", " : "", fdef.type.name.data()); + if (requireCompleteTypes) + fprintf(out, "%s%s", needsComma ? ", " : "", fdef.type.name.data()); + else + fprintf(out, "%sQtPrivate::TypeAndForceComplete<%s, std::false_type>", needsComma ? ", " : "", fdef.type.name.data()); needsComma = true; for (const auto &argument: fdef.arguments) { - fprintf(out, ", %s", argument.type.name.data()); + if (requireCompleteTypes) + fprintf(out, ", %s", argument.type.name.data()); + else + fprintf(out, ", QtPrivate::TypeAndForceComplete<%s, std::false_type>", argument.type.name.data()); } } fprintf(out, "\n"); @@ -598,7 +607,10 @@ void Generator::generateCode() for (int i = 0; i< cdef->constructorList.count(); ++i) { const FunctionDef& fdef = cdef->constructorList.at(i); for (const auto &argument: fdef.arguments) { - fprintf(out, "%s%s", needsComma ? ", " : "", argument.type.name.data()); + if (requireCompleteTypes) + fprintf(out, "%s%s", needsComma ? ", " : "", argument.type.name.data()); + else + fprintf(out, "%sQtPrivate::TypeAndForceComplete<%s, std::false_type>", needsComma ? ", " : "", argument.type.name.data()); needsComma = true; } }