From 388f9b151245ae194a0a9175da7cc70ce534e6e6 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Sat, 13 Jan 2018 19:32:22 +0100 Subject: QQuickItem::stackBefore/After: print more useful warnings Before this patch, you'd get the following warning: QQuickItem::stackAfter: Cannot stack after 0x7f9e668368c0, which must be a sibling After this patch, you get this warning: QQuickItem::stackAfter: Cannot stack QQuickItem_QML_131(0x7ff548f44d70, name="hoverPathDelegate", parent=0x7ff54a871c90, geometry=0,0 0x0) after QQuickItem_QML_131(0x7ff548f3c8f0, name = "hoverPathDelegate"), which must be a sibling This tells you which type caused the warning, and, if you've set it, its objectName. Change-Id: I7b20f1ac089f42d73f02bcca0382022905d0cb57 Reviewed-by: Shawn Rutledge --- src/quick/items/qquickitem.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index af60ab879b..8499c37010 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -2805,7 +2805,8 @@ void QQuickItem::stackBefore(const QQuickItem *sibling) { Q_D(QQuickItem); if (!sibling || sibling == this || !d->parentItem || d->parentItem != QQuickItemPrivate::get(sibling)->parentItem) { - qWarning("QQuickItem::stackBefore: Cannot stack before %p, which must be a sibling", sibling); + qWarning().nospace() << "QQuickItem::stackBefore: Cannot stack " + << this << " before " << sibling << ", which must be a sibling"; return; } @@ -2849,7 +2850,8 @@ void QQuickItem::stackAfter(const QQuickItem *sibling) { Q_D(QQuickItem); if (!sibling || sibling == this || !d->parentItem || d->parentItem != QQuickItemPrivate::get(sibling)->parentItem) { - qWarning("QQuickItem::stackAfter: Cannot stack after %p, which must be a sibling", sibling); + qWarning().nospace() << "QQuickItem::stackAfter: Cannot stack " + << this << " after " << sibling << ", which must be a sibling"; return; } -- cgit v1.2.3 From 99f338f27c48530468277fb5817ac9e185368154 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Wed, 17 Jan 2018 16:46:39 +0100 Subject: Add README for tests/auto/bic Task-number: QTBUG-65827 Change-Id: I0c0b960066377acea5de2e45ac21675aab223c64 Reviewed-by: Liang Qi Reviewed-by: Frederik Gladhorn --- tests/auto/bic/README | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 tests/auto/bic/README diff --git a/tests/auto/bic/README b/tests/auto/bic/README new file mode 100644 index 0000000000..2bde3dd9b9 --- /dev/null +++ b/tests/auto/bic/README @@ -0,0 +1,13 @@ +This directory contains test data to be used by tst_bic to check that we don't +introduce binary incompatible changes between releases. The bic test is run +after every successful integration on Linux only. This data is generated after +each minor release. The generated BC files contain virtual tables, and the bic +test checks new content against the old data. + +See the following README for an explanation of how to generate this data: + +http://code.qt.io/cgit/qt/qtqa.git/tree/tests/postbuild/bic/README + +The test itself can be found here: + +http://code.qt.io/cgit/qt/qtqa.git/tree/tests/postbuild/bic -- cgit v1.2.3 From eec58534ab9c3fae74a1b4cb0861d4b40253cd2d Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Wed, 10 Jan 2018 13:51:23 +0100 Subject: Fix segfault when alias target refers to lowercase-named type Create an error via QQmlCompileError and return it instead of asserting. Task-number: QTBUG-43567 Change-Id: I0c0741943d30516379eff5f44ed8618a0f0116a4 Reviewed-by: Simon Hausmann --- src/qml/compiler/qqmlpropertycachecreator_p.h | 27 ++++++++++++++-------- src/qml/compiler/qqmltypecompiler.cpp | 6 ++++- .../qqmllanguage/data/invalidAlias.13.errors.txt | 1 + .../auto/qml/qqmllanguage/data/invalidAlias.13.qml | 10 ++++++++ .../qqmllanguage/data/invalidAliasComponent.qml | 5 ++++ tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp | 1 + 6 files changed, 40 insertions(+), 10 deletions(-) create mode 100644 tests/auto/qml/qqmllanguage/data/invalidAlias.13.errors.txt create mode 100644 tests/auto/qml/qqmllanguage/data/invalidAlias.13.qml create mode 100644 tests/auto/qml/qqmllanguage/data/invalidAliasComponent.qml diff --git a/src/qml/compiler/qqmlpropertycachecreator_p.h b/src/qml/compiler/qqmlpropertycachecreator_p.h index 22e83de9ae..8743a57d7a 100644 --- a/src/qml/compiler/qqmlpropertycachecreator_p.h +++ b/src/qml/compiler/qqmlpropertycachecreator_p.h @@ -536,11 +536,11 @@ public: void appendAliasPropertiesToMetaObjects(); - void appendAliasesToPropertyCache(const CompiledObject &component, int objectIndex); + QQmlCompileError appendAliasesToPropertyCache(const CompiledObject &component, int objectIndex); private: void appendAliasPropertiesInMetaObjectsWithinComponent(const CompiledObject &component, int firstObjectIndex); - void propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, QQmlPropertyRawData::Flags *propertyFlags); + QQmlCompileError propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, QQmlPropertyRawData::Flags *propertyFlags); void collectObjectsWithAliasesRecursively(int objectIndex, QVector *objectsWithAliases) const; @@ -651,7 +651,7 @@ inline void QQmlPropertyCacheAliasCreator::collectObjectsWithAl } template -inline void QQmlPropertyCacheAliasCreator::propertyDataForAlias( +inline QQmlCompileError QQmlPropertyCacheAliasCreator::propertyDataForAlias( const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, QQmlPropertyData::Flags *propertyFlags) { @@ -670,12 +670,16 @@ inline void QQmlPropertyCacheAliasCreator::propertyDataForAlias auto targetAlias = targetObject.aliasesBegin(); for (uint i = 0; i < alias.localAliasIndex; ++i) ++targetAlias; - propertyDataForAlias(component, *targetAlias, type, propertyFlags); - return; + return propertyDataForAlias(component, *targetAlias, type, propertyFlags); } else if (alias.encodedMetaPropertyIndex == -1) { Q_ASSERT(alias.flags & QV4::CompiledData::Alias::AliasPointsToPointerObject); auto *typeRef = objectContainer->resolvedTypes.value(targetObject.inheritedTypeNameIndex); - Q_ASSERT(typeRef); + if (!typeRef) { + // Can be caused by the alias target not being a valid id or property. E.g.: + // property alias dataValue: dataVal + // invalidAliasComponent { id: dataVal } + return QQmlCompileError(targetObject.location, QQmlPropertyCacheCreatorBase::tr("Invalid alias target")); + } if (typeRef->type.isValid()) *type = typeRef->type.typeId(); @@ -718,15 +722,16 @@ inline void QQmlPropertyCacheAliasCreator::propertyDataForAlias propertyFlags->isWritable = !(alias.flags & QV4::CompiledData::Property::IsReadOnly) && writable; propertyFlags->isResettable = resettable; + return QQmlCompileError(); } template -inline void QQmlPropertyCacheAliasCreator::appendAliasesToPropertyCache( +inline QQmlCompileError QQmlPropertyCacheAliasCreator::appendAliasesToPropertyCache( const CompiledObject &component, int objectIndex) { const CompiledObject &object = *objectContainer->objectAt(objectIndex); if (!object.aliasCount()) - return; + return QQmlCompileError(); QQmlPropertyCache *propertyCache = propertyCaches->at(objectIndex); Q_ASSERT(propertyCache); @@ -742,7 +747,9 @@ inline void QQmlPropertyCacheAliasCreator::appendAliasesToPrope int type = 0; QQmlPropertyData::Flags propertyFlags; - propertyDataForAlias(component, *alias, &type, &propertyFlags); + QQmlCompileError error = propertyDataForAlias(component, *alias, &type, &propertyFlags); + if (error.isSet()) + return error; const QString propertyName = objectContainer->stringAt(alias->nameIndex); @@ -752,6 +759,8 @@ inline void QQmlPropertyCacheAliasCreator::appendAliasesToPrope propertyCache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++, type, effectiveSignalIndex++); } + + return QQmlCompileError(); } template diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index d152d26968..0eae909cf7 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -1010,7 +1010,11 @@ bool QQmlComponentAndAliasResolver::resolveAliases(int componentIndex) } if (result == AllAliasesResolved) { - aliasCacheCreator.appendAliasesToPropertyCache(*qmlObjects->at(componentIndex), objectIndex); + QQmlCompileError error = aliasCacheCreator.appendAliasesToPropertyCache(*qmlObjects->at(componentIndex), objectIndex); + if (error.isSet()) { + recordError(error); + return false; + } atLeastOneAliasResolved = true; } else if (result == SomeAliasesResolved) { atLeastOneAliasResolved = true; diff --git a/tests/auto/qml/qqmllanguage/data/invalidAlias.13.errors.txt b/tests/auto/qml/qqmllanguage/data/invalidAlias.13.errors.txt new file mode 100644 index 0000000000..234753ad59 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/invalidAlias.13.errors.txt @@ -0,0 +1 @@ +6:5:Invalid alias target diff --git a/tests/auto/qml/qqmllanguage/data/invalidAlias.13.qml b/tests/auto/qml/qqmllanguage/data/invalidAlias.13.qml new file mode 100644 index 0000000000..4050c0a7ad --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/invalidAlias.13.qml @@ -0,0 +1,10 @@ +import QtQml 2.0 + +QtObject { + property alias dataValue: dataVal + + invalidAliasComponent { + id: dataVal + strValue: "value2" + } +} diff --git a/tests/auto/qml/qqmllanguage/data/invalidAliasComponent.qml b/tests/auto/qml/qqmllanguage/data/invalidAliasComponent.qml new file mode 100644 index 0000000000..a45b1806a3 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/invalidAliasComponent.qml @@ -0,0 +1,5 @@ +import QtQml 2.0 + +QtObject { + property string strValue: "value1" +} diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 1af57f9247..803bf0c468 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -513,6 +513,7 @@ void tst_qqmllanguage::errors_data() QTest::newRow("invalidAlias.10") << "invalidAlias.10.qml" << "invalidAlias.10.errors.txt" << false; QTest::newRow("invalidAlias.11") << "invalidAlias.11.qml" << "invalidAlias.11.errors.txt" << false; QTest::newRow("invalidAlias.12") << "invalidAlias.12.qml" << "invalidAlias.12.errors.txt" << false; + QTest::newRow("invalidAlias.13") << "invalidAlias.13.qml" << "invalidAlias.13.errors.txt" << false; QTest::newRow("invalidAttachedProperty.1") << "invalidAttachedProperty.1.qml" << "invalidAttachedProperty.1.errors.txt" << false; QTest::newRow("invalidAttachedProperty.2") << "invalidAttachedProperty.2.qml" << "invalidAttachedProperty.2.errors.txt" << false; -- cgit v1.2.3 From 406ef45aaa3e84eb402a451eb4900afa17d20ea9 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 30 Jan 2018 09:47:06 +0100 Subject: Fix exposure of -1 as enum value in QML exposed C++ singletons When a C++ singleton has an enum with the value -1, we would expose that value correctly when taking the accelerated property access code path in the optimizer, but when going through the slower QQmlTypeWrapper we would return undefined. This turned out to be a silly logic error that assumed that -1 is not a valid value for an enum and instead indicates an enum value not present. [ChangeLog][Qml] Fix -1 as enum value in QML exposed C++ singletons showing up as undefined. Task-number: QTBUG-66067 Change-Id: Ib66dad7a4b59822b2c40ad6bd9af4b72469582e9 Reviewed-by: Lars Knoll Reviewed-by: Michael Brasser --- src/qml/qml/qqmltypewrapper.cpp | 22 ++++++++++++---------- tests/auto/qml/qqmlecmascript/testtypes.h | 3 ++- .../auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 9 +++++++++ 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp index d4e1910a72..0fae76066d 100644 --- a/src/qml/qml/qqmltypewrapper.cpp +++ b/src/qml/qml/qqmltypewrapper.cpp @@ -133,11 +133,11 @@ ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, Q } static int enumForSingleton(QV4::ExecutionEngine *v4, String *name, QObject *qobjectSingleton, - const QQmlType &type) + const QQmlType &type, bool *ok) { - bool ok; - int value = type.enumValue(QQmlEnginePrivate::get(v4->qmlEngine()), name, &ok); - if (ok) + Q_ASSERT(ok != nullptr); + int value = type.enumValue(QQmlEnginePrivate::get(v4->qmlEngine()), name, ok); + if (*ok) return value; // ### Optimize @@ -145,10 +145,11 @@ static int enumForSingleton(QV4::ExecutionEngine *v4, String *name, QObject *qob const QMetaObject *metaObject = qobjectSingleton->metaObject(); for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) { QMetaEnum e = metaObject->enumerator(ii); - value = e.keyToValue(enumName.constData(), &ok); - if (ok) + value = e.keyToValue(enumName.constData(), ok); + if (*ok) return value; } + *ok = false; return -1; } @@ -191,8 +192,9 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope // check for enum value const bool includeEnums = w->d()->mode == Heap::QmlTypeWrapper::IncludeEnums; if (includeEnums && name->startsWithUpper()) { - const int value = enumForSingleton(v4, name, qobjectSingleton, type); - if (value != -1) + bool ok = false; + const int value = enumForSingleton(v4, name, qobjectSingleton, type, &ok); + if (ok) return QV4::Primitive::fromInt32(value).asReturnedValue(); } @@ -204,8 +206,8 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope // Warn when attempting to access a lowercased enum value, singleton case if (!ok && includeEnums && !name->startsWithUpper()) { - const int value = enumForSingleton(v4, name, qobjectSingleton, type); - if (value != -1) + enumForSingleton(v4, name, qobjectSingleton, type, &ok); + if (ok) return throwLowercaseEnumError(v4, name, type); } diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h index e15a05a00c..ec20714c51 100644 --- a/tests/auto/qml/qqmlecmascript/testtypes.h +++ b/tests/auto/qml/qqmlecmascript/testtypes.h @@ -1670,7 +1670,8 @@ class SingletonWithEnum : public QObject Q_ENUMS(TestEnum) public: enum TestEnum { - TestValue = 42 + TestValue = 42, + TestValue_MinusOne = -1 }; }; diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 14c2aa18bf..db7ec87c02 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -7914,6 +7914,15 @@ void tst_qqmlecmascript::singletonWithEnum() QVariant prop = obj->property("testValue"); QCOMPARE(prop.type(), QVariant::Int); QCOMPARE(prop.toInt(), int(SingletonWithEnum::TestValue)); + + { + QQmlExpression expr(qmlContext(obj.data()), obj.data(), "SingletonWithEnum.TestValue_MinusOne"); + bool valueUndefined = false; + QVariant result = expr.evaluate(&valueUndefined); + QVERIFY2(!expr.hasError(), qPrintable(expr.error().toString())); + QVERIFY(!valueUndefined); + QCOMPARE(result.toInt(), -1); + } } void tst_qqmlecmascript::lazyBindingEvaluation() -- cgit v1.2.3