aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
diff options
context:
space:
mode:
authorOlivier De Cannière <olivier.decanniere@qt.io>2023-07-11 15:01:10 +0200
committerOlivier De Cannière <olivier.decanniere@qt.io>2023-08-04 09:34:09 +0200
commit2cf9aeccddbd06a66df94bd27916714c4a5c7e24 (patch)
treef147cabe8e7f8d3dfcf1b02cf8d730e851fcc0a6 /tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
parent0667e68e7715f60916ee91189925855e1dcf5f0e (diff)
Compiler: Separate function prolog block and add validation of blocks
The function prolog logic is now separated in its own basic block. The first "real" block with user code starts at offset 0. Having the function prolog as a hidden part of the first block caused some inconsistencies in block generation and would create empty blocks. This happened for example when a back edge of a loop would target offset 0 in code where a loop condition is the very first set of instructions that are run. This is because the target block offset didn't exist due to it being part of the hidden prolog block. Validation for the basic blocks was also added. This checks for three things at the moment: 1. That return and throw blocks don't have jump targets. 2. That the basic blocks graph is connected. 3. That jump targets are the first offset of a block. Test tst_QmlCppCodegen::basicBlocksWithBackJump_infinite() is expected to fail because it contains an infinite loop and the basic blocks that are generated for it are inconsistent due to dead-code elimination happening earlier in compilation. Debug outputs for dumping basic blocks were also adapted to reflect these changes. Change-Id: I513f73856412d488d443c2b47a052b0023d45496 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp')
-rw-r--r--tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp39
1 files changed, 39 insertions, 0 deletions
diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
index 0c9648a19d..db1ae4f08b 100644
--- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
+++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
@@ -30,6 +30,7 @@ class tst_QmlCppCodegen : public QObject
Q_OBJECT
private slots:
void initTestCase();
+ void cleanupTestCase();
void accessModelMethodFromOutSide();
void aliasLookup();
void ambiguousAs();
@@ -43,6 +44,7 @@ private slots:
void attachedType();
void badSequence();
void basicBlocksWithBackJump();
+ void basicBlocksWithBackJump_infinite();
void basicDTZ();
void bindToValueType();
void bindingExpression();
@@ -458,6 +460,34 @@ void tst_QmlCppCodegen::initTestCase()
#endif
}
+void tst_QmlCppCodegen::cleanupTestCase()
+{
+ // This code checks for basic blocks validation failures in the tests
+ QStringList expectedFailures = {
+ "codegen_test_module_basicBlocksWithBackJump_infinite_qml.cpp",
+ "codegen_test_module_verify_basicBlocksWithBackJump_infinite_qml.cpp",
+ };
+
+ QString generatedCppFolder = GENERATED_CPP_FOLDER;
+ QDirIterator dirIterator(generatedCppFolder, { "*.cpp" }, QDir::Files);
+ while (dirIterator.hasNext()) {
+ QFile file(dirIterator.next());
+ if (!file.open(QIODeviceBase::ReadOnly | QIODeviceBase::Text)) {
+ qDebug() << "Couldn't open generated file";
+ continue;
+ }
+
+ const auto content = file.readAll();
+ if (bool validationFailed = content.contains("// QV4_BASIC_BLOCK_VALIDATION_FAILED:"_L1)) {
+ if (expectedFailures.contains(dirIterator.fileInfo().fileName())) {
+ QEXPECT_FAIL("", "Expected failure", Continue);
+ }
+ const auto message = file.fileName() + ": Basic blocks validation failed.";
+ QVERIFY2(!validationFailed, message.toStdString().c_str());
+ }
+ }
+}
+
void tst_QmlCppCodegen::accessModelMethodFromOutSide()
{
QQmlEngine engine;
@@ -744,6 +774,15 @@ void tst_QmlCppCodegen::basicBlocksWithBackJump()
QVERIFY(!expectingMessage);
}
+void tst_QmlCppCodegen::basicBlocksWithBackJump_infinite()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/basicBlocksWithBackJump_infinite.qml"_s));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
+}
+
void tst_QmlCppCodegen::basicDTZ()
{
QQmlEngine engine;