diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2023-11-01 14:11:37 +0100 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2023-11-04 03:52:18 +0000 |
commit | 590a47bc0cf557c36503df8ec493d826ae6c878d (patch) | |
tree | d5dba44419deae976c6493844d3cf167a300dda1 | |
parent | 97f627eabebbacff910fa22ceb266a6ea06b2df6 (diff) |
QmlCompiler: Extend shadow-checking
Method return values as well as whatever we hide behind "unknown" can
contain shadowable properties. We need to check it.
Pick-to: 6.5 6.2
Task-number: QTBUG-117800
Change-Id: I518bc11fd0c9c69340bf621198eeaf4c95d17dae
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
(cherry picked from commit 048c8f226ae09b79264e5dfc51f5d8fe7a8332a9)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
6 files changed, 81 insertions, 2 deletions
diff --git a/src/qmlcompiler/qqmljsshadowcheck.cpp b/src/qmlcompiler/qqmljsshadowcheck.cpp index 5b07140490..167396f614 100644 --- a/src/qmlcompiler/qqmljsshadowcheck.cpp +++ b/src/qmlcompiler/qqmljsshadowcheck.cpp @@ -114,10 +114,12 @@ void QQmlJSShadowCheck::checkShadowing( return; switch (baseType.variant()) { - case QQmlJSRegisterContent::ObjectProperty: case QQmlJSRegisterContent::ExtensionObjectProperty: + case QQmlJSRegisterContent::ExtensionScopeProperty: + case QQmlJSRegisterContent::MethodReturnValue: + case QQmlJSRegisterContent::ObjectProperty: case QQmlJSRegisterContent::ScopeProperty: - case QQmlJSRegisterContent::ExtensionScopeProperty: { + case QQmlJSRegisterContent::Unknown: { const QQmlJSRegisterContent member = m_typeResolver->memberType(baseType, memberName); // You can have something like parent.QtQuick.Screen.pixelDensity diff --git a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt index 37d953ec8e..539fb39068 100644 --- a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt +++ b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt @@ -53,6 +53,8 @@ set(qml_files ProgressBar/TimelineAnimation.qml RootWithoutId.qml SelectionRectangle.qml + ShadowedObjectName.qml + ShadowedObjectNameDerived.qml Test.qml TestCase.qml WindowDerived.qml @@ -199,6 +201,7 @@ set(qml_files script.mjs sequenceToIterable.qml setLookupConversion.qml + shadowedAsCasts.qml shadowedMethod.qml shared/Slider.qml shifts.qml diff --git a/tests/auto/qml/qmlcppcodegen/data/ShadowedObjectName.qml b/tests/auto/qml/qmlcppcodegen/data/ShadowedObjectName.qml new file mode 100644 index 0000000000..f079f4a94e --- /dev/null +++ b/tests/auto/qml/qmlcppcodegen/data/ShadowedObjectName.qml @@ -0,0 +1,6 @@ +pragma Strict +import QtQml + +QtObject { + property int objectName: 12 +} diff --git a/tests/auto/qml/qmlcppcodegen/data/ShadowedObjectNameDerived.qml b/tests/auto/qml/qmlcppcodegen/data/ShadowedObjectNameDerived.qml new file mode 100644 index 0000000000..f988cd6bc9 --- /dev/null +++ b/tests/auto/qml/qmlcppcodegen/data/ShadowedObjectNameDerived.qml @@ -0,0 +1,6 @@ +pragma Strict +import QtQml + +ShadowedObjectName { + property double objectName: 17.4 +} diff --git a/tests/auto/qml/qmlcppcodegen/data/shadowedAsCasts.qml b/tests/auto/qml/qmlcppcodegen/data/shadowedAsCasts.qml new file mode 100644 index 0000000000..ccb50f4934 --- /dev/null +++ b/tests/auto/qml/qmlcppcodegen/data/shadowedAsCasts.qml @@ -0,0 +1,31 @@ +pragma Strict +import QtQml + +QtObject { + property ShadowedObjectName shadowed1: ShadowedObjectName {} + property ShadowedObjectName shadowed2: ShadowedObjectName {} + property QtObject shadowed3: ShadowedObjectNameDerived {} + + function returnShadowed2() : QtObject { return shadowed2 } + + function a(mark: int) { + // as-cast can be optimized out if we're clever. + (shadowed1 as QtObject).objectName = mark; + } + + function b(mark: int) { + // method return values can contain shadowed properties! + returnShadowed2().objectName = mark; + } + + function c(mark: int) { + // Has to do an actual as-cast, but results in ShadowedObjectNameDerived! + (shadowed3 as ShadowedObjectName).objectName = mark; + } + + Component.onCompleted: { + a(43); + b(42); + c(41); + } +} diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp index b1e97b2560..a6a8f5db14 100644 --- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp +++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp @@ -166,6 +166,7 @@ private slots: void scopeVsObject(); void sequenceToIterable(); void setLookupConversion(); + void shadowedAsCasts(); void shadowedMethod(); void shifts(); void signalHandler(); @@ -3478,6 +3479,36 @@ void tst_QmlCppCodegen::setLookupConversion() QCOMPARE(o->objectName(), u"a"_s); } +void tst_QmlCppCodegen::shadowedAsCasts() +{ + QQmlEngine e; + QQmlComponent c(&e, QUrl(u"qrc:/qt/qml/TestTypes/shadowedAsCasts.qml"_s)); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer<QObject> obj(c.create()); + QVERIFY(!obj.isNull()); + + QObject *shadowed1 = obj->property("shadowed1").value<QObject *>(); + QVERIFY(shadowed1); + QVERIFY(shadowed1->objectName().isEmpty()); + const QVariant name1 = shadowed1->property("objectName"); + QCOMPARE(name1.metaType(), QMetaType::fromType<int>()); + QCOMPARE(name1.toInt(), 43); + + QObject *shadowed2 = obj->property("shadowed2").value<QObject *>(); + QVERIFY(shadowed2); + QVERIFY(shadowed2->objectName().isEmpty()); + const QVariant name2 = shadowed2->property("objectName"); + QCOMPARE(name2.metaType(), QMetaType::fromType<int>()); + QCOMPARE(name2.toInt(), 42); + + QObject *shadowed3 = obj->property("shadowed3").value<QObject *>(); + QVERIFY(shadowed3); + QVERIFY(shadowed3->objectName().isEmpty()); + const QVariant name3 = shadowed3->property("objectName"); + QCOMPARE(name3.metaType(), QMetaType::fromType<double>()); + QCOMPARE(name3.toDouble(), 41.0); +} + void tst_QmlCppCodegen::shadowedMethod() { QQmlEngine e; |