Commit Graph

289 Commits

Author SHA1 Message Date
Ulf Hermann 5b867e3548 QmlCompiler: Allow conversion of object literals to QJSValue
Task-number: QTBUG-124634
Change-Id: Ifb09c0f5e4a732518e44a8d3b73c5a836ad66508
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
2024-11-01 12:52:03 +01:00
Ulf Hermann 35630eef3d QtQml: Unify detaching behavior for all reference objects
All reference objects should be detached when written to a property of
a QML-defined type. This is in line with what happens if you write the
same object to a property of a C++-defined type and doing anything else
makes very little sense.

In particular, before this change, the behavior differed between
ahead-of-time compiled code and interpreted code, between writing to
"var" properties and writing to typed properties, and between different
kinds of lists. Now everything we recognize as reference object always
gets detached when writing to a property.

[ChangeLog][QtQml][Important Behavior Changes] Writing a list or value
type to a QML-declared property now always detaches this same list or
value from any locals or other properties you may have read it from.
Therefore, subsequent changes to its "source" will not affect it
anymore. This is in line with what we do to C++-declared properties.

Fixes: QTBUG-127957
Change-Id: Icdf188ef29d28e5d3aaa8219cc003e07e8813f38
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
2024-10-24 18:27:03 +00:00
Olivier De Cannière 349a180967 tst_qmlcppcodegen: Compile test with QT_NO_CAST_FROM_ASCII
This should help find raw string literals in generated code

Task-number: QTBUG-129797
Change-Id: I66e5d6302319678b494030e8cb3459eb06f0f134
Reviewed-by: Semih Yavuz <semih.yavuz@qt.io>
2024-10-09 16:23:14 +02:00
Ulf Hermann a5a814d26a QmlCompiler: Fix handling of anonymous composite types
So far we produced invalid QMetaTypes for them in various places and
that "worked" for the most part because with QObject pointers we can
introspect the actual type at run time.

Realize that we never actually want the concrete anoymous type of the
object when we pass it around. Rather, all methods and properties need
to handle named types. What we really want to resolve is therefore not
the type of the original value we've produced in the type propagator,
but rather the replacement we've produced when analyzing the lookup.

Pick-to: 6.8
Task-number: QTBUG-129202
Change-Id: I0b93495d6603f120375048c80a747170f147f8af
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
(cherry picked from commit 14ff6822a0)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
2024-10-02 08:46:46 +00:00
Ulf Hermann 76ce5e4799 QmlCompiler: Do not cache composite metatypes in static members
The metatypes from any old engines may have been deleted.

Retrieve the types from the ResolveTypeReferenceMap instead. That is
much cheaper than doing a full type search and the CU should know the
types it's dealing with.

Sometimes, however, the CU does not pre-resolve the types. In
particular, types only used in function signatures do not end up in the
ResolvedTypeReferenceMap. In those cases, still do the full type search.

Amends commit 8bf5aae19b.

Pick-to: 6.8.0 6.8
Task-number: QTBUG-129388
Change-Id: I27f25e1c68de3c752d00345c6d94016fb315e16c
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2024-09-30 20:26:35 +02:00
Ulf Hermann dea8e38d95 QmlCompiler: Do not miscompile ID lookups in invalid types
If we cannot resolve a type, we need to assume that all its properties
are components and assign separate contexts to all inner objects.
Otherwise, if one of them actually is, the attempt to resolve it at run
time will crash.

Pick-to: 6.8
Fixes: QTBUG-129281
Change-Id: Ic34b5308accdd93f6797ee39fcd56040cf86b1ce
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2024-09-25 21:24:12 +02:00
Ulf Hermann bfd80e8dac QmlCompiler: Don't crash on broken type assertions
If we cannot properly resolve the types we should still set the
accumulator to something so that the type propagator can continue.

Amends commit 6a2308e500

Change-Id: Idf3d093ca877bcf11f6a9a82a9d01ccead19e2cc
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2024-09-25 10:42:01 +02:00
Ulf Hermann 815965f8fc QtQml: Allow initialization of value types with object types
If the value type has a suitable ctor, we can pass it a pointer to the
object just created.

Change-Id: I146c7dfc4f879ceb26201511d1c3b4127ad90dbe
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Sami Varanka <sami.varanka@qt.io>
2024-09-24 13:58:33 +02:00
Ulf Hermann 9ea281b3b5 Tests: Fix various CMake warnings
Add NO_GENERATE_EXTRA_QMLDIRS where applicable, make output directories
and module URIs match, and avoid setting QTP0004 to OLD since that just
generates a different warning. Also, explicitly include some .js files
in the qmldir, even if that means re-evaluation on each import.

Pick-to: 6.8
Change-Id: Ia03445ed7df85aa4d2032ba51675bab7501ad55b
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2024-09-10 15:51:06 +02:00
Ulf Hermann 9f554ef8cf QmlCompiler: Do not choose unstorable stored types
In order to pass the argument to a value type ctor we need to store it
in something we can rely on.

Amends commmit dd731b880b

Change-Id: I5d1ef6b4611aad9b595235f4f874ef4a063f04c6
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2024-08-12 16:19:40 +02:00
Olivier De Cannière 179581e16f Compiler: Properly read value type arguments when enforcing signatures
The patch that introduces the enforcing of signature types did so by
passing the contained rather than the stored metatypes for the
arguments.

These types are used to populate the registers of the function with the
arguments using the proper types by static_cast'ing the void* arguments
to the actual types.

However, for value types, the arguments were assumed to be QVariants and
were thus casted to one even though they were actually passed as the
actual argument type. This seems to have been mostly fine by accident
because of the inline storage of QVariant that lays at offset 0 in its
layout. Therefore, if the flag signalling that the value is actually
elsewhere was not set to 1 by the casting and the value fit in the
inline storage everything would still work. This is not always the case
however and can lead to crashes.

Therefore, treat value type arguments as plain non-wrapped values when
populating function arguments.

Amends 8bf5aae19b

Fixes: QTBUG-127009
Pick-to: 6.8
Change-Id: I495bcff7631399f207d87fea698d7e921e8e4721
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2024-07-17 12:14:46 +02:00
Ulf Hermann f2431370ad QML: Allow conversion between different list types
We universally allow this pretty much everywhere else. We should also
allow it when evaluating bindings. To facilitate this, generalize the
SequencePrototype::toVariant() method so that it works with any
array-like and faithfully coerces the elements by the type coercion
rules.

Pick-to: 6.8
Fixes: QTBUG-126398
Change-Id: I520cd40e5f74bee5ac4b418aa86dc043774efcbe
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2024-07-03 16:36:49 +02:00
Ulf Hermann ae76c8f428 QmlCompiler: Fix side effect detection for array methods
Array methods that manipulate the array they are called on always have
side effects, on that array. In order to optimize them out we'd have to
do some more involved tracking of affected values.

Amends commit e846864151

Fixes: QTBUG-126834
Pick-to: 6.8 6.7
Change-Id: Ia4395ea21e89590e6ffe95e236f70b5e64402f5e
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2024-07-02 21:16:21 +02:00
Ulf Hermann 3d3ff946e3 QmlCompiler: Don't generate invalid code for unstorable lists
When printing a sequence type through one of the console methods, we
have to consider the adjusted type, not only the one we intended to
read.

Amends commit 7894f271ab.

Pick-to: 6.8
Task-number: QTBUG-126398
Change-Id: I4606ed2006a547bdf93ec136ebbfab10b706b917
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2024-06-28 18:16:48 +02:00
Ulf Hermann ed61e7c6d2 QmlCompiler: Explicitly cast operations that result in QString
We may be using QStringBuilder, and that can be stored in QVariant (and
possibly other places).

Fixes: QTBUG-125576
Change-Id: Ib31e31591a3333e51f1d5594ee05fdb8f0744714
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2024-05-25 08:11:24 +02:00
Ulf Hermann 8bf5aae19b QtQml: Properly enforce signatures of AOT-compiled functions
Pass the metatypes of the contained types rather than the stored types.

[ChangeLog][QtQml][Important Behavior Changes] The AOT compiled code for
type-annotated JavaScript functions does not let you pass or return
values of the wrong type anymore.

Fixes: QTBUG-119885
Change-Id: I685d398c0745d32a999a3abd76c622a2c0d6651f
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2024-04-26 12:18:15 +00:00
Ulf Hermann 2bc9c47608 qmltyperegistrar: Check properties, methods, enums for missing types
If you have a property of an unknown type, that will create problems
later on. The same holds for method arguments, return types and
underlying types of enums. qmltyperegistrar now warns about those.

When scanning the types, we consider a type potentially primitive if it
is not the root type, but one of:

a, a self-extending value type
b, a type with a JavaScript extension
c, a sequence type

If those types are found to be "missing" later, we ignore them.
All other missing types trigger warnings now. Since we use types from
QPA headers in a few places, we now need to recognize QPA headers when
looking for private Qt includes.

Task-number: QTBUG-101143
Change-Id: Ic4350e8ed46212c0f4af6f10e86323514f710e1e
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2024-04-25 18:55:23 +02:00
Luca Di Sera bd6df61c81 qmlsc: Support Math static properties
The javascript Math object presents some static properties that allow
access to some general mathematical constants.

Currently, `qmlsc` will refuse to generate optimized code for those
properties when used in a binding, for example given:

```
import QtQuick

Window {
    width: 200 * Math.PI
}

```

`qmlsc` will report a warning and will not generate code for the "width"
binding.

To allow `qmlsc` to generate optimized code for such cases, the handling
of `Math` related properties lookups is now specialized.

`QQmlJSTypePropagator::propagatePropertyLookup`, which is called when
dealing with an access such as `Math.PI`, was modified to consider the
result type a "double" when dealing with properties on the `Math`
object.

`QQmlJSCodeGenerator::generate_GetLookupHelper`, which generates the
code that provides a value for the property access, was modified to
special case lookups on the `Math` object.

If a property is being looked up on the `Math` object, `qmlsc` will now
generate a direct assignment for the output variable to a constant value
that is suitable for the accessed property.

A test was added to ensure that the snippet from the bug-report now
compiles without warnings.

A test was added to ensure that the properties from the Math global
object have an approximately correct value.

Fixes: QTBUG-113150
Change-Id: I8903794fc8ce2b55532a4706e1bda07a7b73f311
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2024-04-18 22:30:24 +02:00
Ulf Hermann 99c7fe45be QtQml: Add a wrapper builtin for QQmlV4Function*
This way qmltyperegistrar can recognize it and refrain from warning
about it.

Task-number: QTBUG-101143
Change-Id: I598140e7e90dbd3e27a78c26eff3d46f0fd3e989
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2024-04-12 20:32:59 +02:00
Ulf Hermann 7894f271ab QmlCompiler: Allow coercion of lists to strings
We have to allow two different forms of coercion. When printing directly
through console.log etc, we add a pair of square brackets around the
string.

Fixes: QTBUG-119482
Change-Id: I03177e5905b41f5f0b5aaa867b18379eb9c7a243
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2024-04-11 13:47:46 +00:00
Ulf Hermann 1087977a9a QmlCompiler: Correctly mark side effects for list operations
The contents of a QQmlListProperty are mutable even if the property is
not. This is because QQmlListProperty is only a view on a different
container.

Pick-to: 6.7
Fixes: QTBUG-123196
Change-Id: Id6309b1e1ddc219bf35e8d9888b8415dcc0f9d43
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2024-04-11 15:47:39 +02:00
Ulf Hermann 0d1462b3ae QmlCompiler: Handle scripts as type lookups on GetLookup
This can happen if you lookup a script from a type namespace. The type
lookup already has facilities for handling (or rather rejecting) it.

Pick-to: 6.7 6.5
Fixes: QTBUG-123050
Change-Id: I092b1d2f47edc152b4f3967b4eaf4620a81ce5ef
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
2024-04-05 20:38:07 +02:00
Ulf Hermann 06b3a0e6d2 QtQml: Add option to disambiguate resources for qmldir files
If you have multiple modules with the same target path in the same
directory, they will otherwise overwrite each others' .qrc files. This
is not a very sane thing to do in general, but it happens in our tests.

Task-number: QTBUG-124145
Change-Id: Ice5368d8b61907f610ad7e6e7370b43c2056c2fb
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
2024-04-05 20:38:07 +02:00
Ulf Hermann 6314d305ee Generate qmldir files for extra directories with QML files
Those qmldir files contain only a prefer directive for the canonical
resource location of the module. This way, any time another component
from the implicit import is requested, it will not be located in the
extra directory (where it probably doesn't exist), but instead in the
canonical location.

Since people may have manually written qmldir files with different
content in those places, or worse, relied on the other components to be
inaccessible, we need a new policy to opt into this.

Fixes: QTBUG-111763
Change-Id: If236feb7dd7c8d704b813ea56482ff758799d0a7
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2024-04-03 20:37:18 +02:00
Ulf Hermann f47df45b49 QmlCompiler: Fix code for object literal generation
We have to use the arguments as base for the run time calculated
members, not the argument count.

Amends commit f839171eef.

Pick-to: 6.7
Fixes: QTBUG-123613
Change-Id: I3ddc8bc459618bd9a9436d3616c444bf218463a3
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2024-03-26 12:31:58 +01:00
Ulf Hermann eb79815fbf QmlCompiler: Do not use QQmlEngine from current QML context
We cannot be sure the current context is still alive when a function is
called. We may be left with a skeleton context that doesn't have an
engine anymore.

However, we can always query the QJSEngine given in the AOT context.
That one cannot disappear and is generally the right one for capturing
properties.

Pick-to: 6.7 6.5 6.2
Fixes: QTBUG-123395
Change-Id: I2a6c38baa159fa790f3ba2aba225fdc9cc37001e
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2024-03-21 10:41:29 +01:00
Ulf Hermann 69ca18785c QQmlPropertyCache: Correctly set flags when loading methods
We commonly load multiple methods in sequence into the same
QQmlPropertyData. We need to set all the relevant flags for each one.
Otherwise the wrong flags are transferred to subsequent methods.

Pick-to: 6.7 6.6 6.5
Task-number: QTBUG-112366
Change-Id: I7432500b9149fdd8dd2dd98eb923ada70232fb6d
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
2024-02-29 12:08:08 +01:00
Ulf Hermann 7da544e862 QmlCompiler: Respect scoped enums
Correctly propagate the isClass and RegisterEnumClassesUnscoped
information from metatypes to qmltypes, then read it correctly, and
don't try to resolve unscoped values of scoped enums when resolving
types. Neither try to resolve the names of unscoped enums.

For historical reasons, enums are unscoped by default, even if they are
declared as "enum class".

Furthermore, QML enums can be accessed in both scoped and unscoped way.
Scoped C++ enums can only be accessed by explicitly stating the scope,
and unscoped C++ enums can only be accessed without scope. Since qmllint
now correctly analyzes this, we need to adapt the tests accordingly.

Finally, also fix the logic around populating the error message for
qmllint. We want to warn about the enum itself, not one of its values.
And we always want to setError() if something is wrong so that the
compilers don't try to continue from there.

Pick-to: 6.7 6.6 6.5 6.2
Fixes: QTBUG-107143
Change-Id: If1ee9a10479cffb46067ccb5e683906905c24160
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2024-02-29 12:08:08 +01:00
Lucie Gérard 9c5fc88388 Correct license for test files
According to QUIP-18 [1], all test files should be
LicenseRef-Qt-Commercial OR GPL-3.0-only

[1]: https://contribute.qt-project.org/quips/18

Pick-to: 6.7
Task-number: QTBUG-121787
Change-Id: I26d72e8de04d4c7c57b3b7838af5d033265de5ba
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Reviewed-by: Kai Köhne <kai.koehne@qt.io>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2024-02-27 10:32:21 +01:00
Ulf Hermann e2611e8ee9 QmlCompiler: Fix conditions around as casts
We can only generate an as-cast from an optional value type if we know
that the optional type is actually the requested one. Otherwise we have
to reject for now. We might add more logic here in a further iteration,
and process more complicated type assertions. However, we should pick
such logic back to 6.6.

Amends commit 05f56d7c78.

Pick-to: 6.7 6.6
Change-Id: I37fc1b6018bfb0663e5ce4fd80084c7d13c6d3e3
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
2024-02-21 14:27:54 +01:00
Ulf Hermann 49dc279bdc QmlCompiler: Use original scope type for SetLookup
This is in line with what we do for GetLookup. The concrete type can be
rewritten by the basic blocks pass, depending on other places where it's
used. We want to generate the lookup we've found at type propagation
time. The lookup is still valid here. If it wasn't we would have noticed
in a later iteration of the type propagation pass.

Pick-to: 6.7
Fixes: QTBUG-117798
Change-Id: I0ddb9866e4deec7c5b6a53a5c0f9785b51d47480
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
2024-02-21 14:27:53 +01:00
Ulf Hermann 655087e05d QmlCompiler: Escape question marks in string literals
This prevents the generation of trigraphs and suppresses the warnings
about those.

Pick-to: 6.7
Fixes: QTBUG-110772
Change-Id: If30ad39737eae097fdcb18b0d33b6bbfa05be656
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
2024-02-21 14:27:53 +01:00
Olivier De Cannière 2b336217b0 Compiler: Add tests for the nullish coalescing operator ??
Now that initial support for optional chaining was added, it would be
good to add tests ensuring the nullish coalescing works as expected. Add
some tests to enshrine the behavior.

The compiler is currently not smart enough to detect that
"(Anything as int) ?? 1" will always return an int. It returns an
optional int instead. Created QTBUG-119437.

Task-number: QTBUG-119437
Change-Id: If2d72b0c29e5844cd962dbf92406bfa9181a1bc7
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2024-02-16 20:31:30 +01:00
Olivier De Cannière e303d12827 Compiler: Handle method list return types from qmltypes file
When parsing methods details from qmltypes files, the `isList` value
was ignored. It indicates that the return type of the method is a list
of the type specified in the `type` value.

This patch adds QQmlJSMetaReturnType (typedef of QQmlJSMetaParameter) to
hold information about the method's return type. With this, we can now
mark a method's return type as being a list when reading qmltypes files
and we can act accordingly when resolving the method later on.

As a drive-by, only expose the getter and setter of the metaReturnType
in QQmlJSMetaMethod and not their internals directly.

Pick-to: 6.7 6.6 6.5
Fixes: QTBUG-122106
Change-Id: I6ea07c02fbeb6cb07d9fe9184205ff7f3274fd73
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2024-02-14 11:44:39 +01:00
Ulf Hermann 28340bdeb0 QmlCompiler: In debug mode, set instruction pointer before each lookup
This produces some overhead, but helps with debugging. Without the
instruction pointer we cannot determine the line numbers for
console.trace().

Pick-to: 6.7 6.6 6.5
Fixes: QTBUG-119459
Change-Id: I75a6bb1fcedd8514e2ba46d02dd2904ce222f0e4
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2024-02-08 14:37:02 +00:00
Olivier De Cannière 15b1aaadd2 Compiler: Also check for shadowing on optional lookups
Amends: fc4ee77116

Pick-to: 6.7
Change-Id: I3f5f2b74e4b89b82e7fb54072091143010bab8aa
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2024-02-08 10:17:33 +01:00
Olivier De Cannière 72308ce207 Compiler: Convert from stored to original type when generating equality
Pick-to: 6.7
Fixes: QTBUG-121909
Change-Id: I913f59324364052d7893d4c4072f92fcf418a388
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2024-02-07 17:23:01 +01:00
Ulf Hermann 452929cea1 QmlCompiler: Reject lookups on shadowable base types
If the base type of a lookup is shadowable we cannot give any guarantees
at all about what is going to happen. Only if the right hand side of the
lookup is shadowable we can use our QVariant trick.

Fixes: QTBUG-121734
Pick-to: 6.7 6.6
Change-Id: I969a842a6bc6d6a4446bfbfb50f1a7021b84049e
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
2024-02-01 09:33:09 +01:00
Olivier De Cannière 3672a173df Compiler: Don't crash on optional lookups on QJSValue base type
Handle the case where the base type of the lookup is QJSValue so that we
don't hit the assert.

However, it should not be possible to get a QJSValue there at all. This
should be investigated further. Created QTBUG-121662.

Pick-to: 6.7
Fixes: QTBUG-121393
Change-Id: I8bea87cbff74119bb977635ec391601f47269ff0
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2024-01-29 17:02:28 +01:00
Ulf Hermann afbf7b6990 QmlCompiler: Handle non-resettable undefined assignment
We need to generate an exception if undefined is assigned to a property
that can't be reset. We don't want to reject everything that can
potentially be undefined. Therefore, we use the QVariant fallback and
examine the value for undefined at run time.

Pick-to: 6.7 6.6 6.5 6.2
Change-Id: I0a034032f4522f017b452690d93319eb4bfedb1c
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2024-01-25 18:35:05 +01:00
Ulf Hermann da6680cb2e QmlCompiler: Implement resetting of properties
We piggy-back on the mechanism used to handle shadowable properties and
pass the value as QVariant. QVariant can hold undefined and the lookup
functions know how to handle it.

Pick-to: 6.7 6.6 6.5 6.2
Fixes: QTBUG-120512
Change-Id: I9bca4940256c82bdcf5540b956600eb420be363e
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2024-01-25 18:35:05 +01:00
Ulf Hermann be481412cc QmlCompiler: Allow primitive conversion if output is stored in var
We can always convertStored() if the contained type has been fixed.

Pick-to: 6.7
Fixes: QTBUG-120322
Change-Id: I7d834fa32a12503341c863c095d578ca6e838531
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2024-01-11 00:42:17 +01:00
Olivier De Cannière 6f74f50fe4 Compiler: Handle all integer signs and sizes when converting primitives
Fixes: QTBUG-120473
Pick-to: 6.7
Change-Id: I4941cd1567d94823551e4cc94df8bc5b413e951c
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2024-01-09 10:40:49 +01:00
Olivier De Cannière 22d4a1b795 Compiler: Guard against null dereference when ignoring function return
When a function is called, two arrays with the necessary information are
passed to the engine:
  argv:  [return address, prameter 1 address, parameter 2 address, ...]
  types: [return type, parameter 1 type, parameter 2 type, ...]

When the result of the call is ignored, the return type is set to void
and the return address to null.

A check for this null value was missing leading to a null derefence.

Amends: 4f1b9156a4

Fixes: QTBUG-120336
Pick-to: 6.7
Change-Id: I4a21779f3276b0143087b41b0d16c0cd3ba0e7db
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2024-01-09 10:40:49 +01:00
Ulf Hermann 49ea766c8f QmlCompiler: Return early after reject()
Otherwise we can run into an infinite loop.

Pick-to: 6.7
Fixes: QTBUG-120322
Change-Id: I81f9402beb48faf09b4fe148271d4347b84ddc5e
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
2023-12-22 09:50:35 +01:00
Ulf Hermann 87d27d0654 QML: Don't crash when calling coerceAndCall() with null thisObject
Pick-to: 6.6 6.5
Fixes: QTBUG-119395
Change-Id: I5877beef9a53d358a6f58f9ce5029688bd9dcedb
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-12-08 20:11:28 +01:00
Ulf Hermann c89c14423b QmlCompiler: Preferably wrap types in QJSPrimitiveValue for SetLookup
If we store one primitive type inside another, we cannot get its content
pointer.

Change-Id: I7088685fdd2633085de732aab87b4b5f93300b90
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-12-08 20:11:27 +01:00
Ulf Hermann 78b58582ba QmlCompiler: Add generic QVariant-to-typed comparison
Since we have a lot more shadowable values now, we need to add this.

Change-Id: Ie9f389730bb6f330b1cd28f9229c5dd143727e4f
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-12-07 13:29:41 +01:00
Ulf Hermann 9f8193b65b QmlCompiler: Do not adjust renames
A rename always produces a register with exactly one tracked type, but
we do not want to use it as base for the type adjustments. We want to
adjust based on the original location and its readers (which includes
any renames).

Pick-to: 6.6 6.5
Change-Id: Iaefdf56992c7c101a35a056fb93c49ade5ccf393
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
2023-12-07 12:54:37 +01:00
Ulf Hermann 6b39eb9be2 QML: Use actual type for aliases of enum values
The metatype system and the compiler may disagree about the underlying
type. It's generally better to pass the full type information. We can
deal with it everywhere by now.

Amends commit 3ea55bf398

Pick-to: 6.6
Fixes: QTBUG-119531
Change-Id: I4744f5fb81fb5430ac040ec5877f7d0845a2ab12
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-12-05 12:50:59 +01:00
Ulf Hermann 84d950bc32 QML: Let IDs in outer context override bound components' properties
This is necessary to make the usage of such IDs actually safe. If we let
local properties override outer IDs, then adding local properties in
later versions invalidates the ID lookups.

[ChangeLog][QtQml][Important Behavior Changes] In QML documents with
bound components, IDs defined in outer contexts override properties
defined in inner contexts now. This is how qmlcachegen has always
interpreted bound components when generating C++ code, and it is
required to make access to outer IDs actually safe. The interpreter and
JIT have previously preferred inner properties over outer IDs.

Pick-to: 6.6 6.5
Fixes: QTBUG-119162
Change-Id: Ic5d3cc3342b4518d3fde1b800efe1b95d8e8b210
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-12-04 15:19:09 +01:00
Olivier De Cannière fc4ee77116 Compiler: Add initial support for optional chaining
This patch implements the GetOptionalLookup instruction in the compiler.
This enables the use of optional chains.

Fixes: QTBUG-111283
Change-Id: I265f611415a946468b828b9d41f549acfcc76233
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-11-24 18:34:03 +01:00
Ulf Hermann 1a8911a13d QmlCompiler: Don't generate invalid code for argument conversion
We need an additional pair of parentheses here.

Pick-to: 6.6 6.5 6.2
Fixes: QTBUG-119165
Change-Id: I0d8e810ebb5baad35e2cc1bc5c6581d1ba180dc8
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-11-23 18:58:37 +01:00
Ulf Hermann 73f66c8f94 QmlCompiler: Do not generate lookups for bare meta enums
Such code is necessarily dead or uncompilable.

Pick-to: 6.6 6.5 6.2
Fixes: QTBUG-119090
Change-Id: I7319f7ceeb0b4994d5e974bbe8a9c3ba3bf72fc5
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-11-18 08:36:01 +01:00
Ulf Hermann 8190f5bd68 QmlCompiler: When rejecting empty constants, don't crash afterwards
Pick-to: 6.6 6.5
Fixes: QTBUG-119091
Change-Id: I1e24583aa998976c96bf3ddd6865f33cc4d5e94c
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-11-18 08:35:49 +01:00
Ulf Hermann 096f3c3097 QmlCompiler: Don't access unavailable input accumulator on 'as'
We only read it if the target type is composite. Therefore, check for
composite first, before looking for the accumulator.

Pick-to: 6.6 6.5 6.2
Fixes: QTBUG-119122
Change-Id: I2a50214f76ee4ffe2f877dc690704e7475b8bd77
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-11-17 15:28:57 +01:00
Ulf Hermann 7df34d498d QmlCompiler: Retrieve original types for comparison
If an original type is merely wrapped into a more generic type by the
basic blocks pass, we know the original data is still there and can be
used for comparison.

Fixes: QTBUG-117795
Change-Id: Ia7582cd8ed48e47a3a1b3bd8e2595e9cb42828de
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-11-13 10:13:18 +01:00
Ulf Hermann ae39055313 QmlCompiler: Allow comparison of optional types
The only extra case we have to consider is the construction of an
optional type from a QObject-derived since that is stored in a QVariant
rather than a QObject*. Everything else we can compare is already
covered by the generic QJSPrimitiveValue comparison since
QJSPrimitiveValue can store undefined.

Fixes: QTBUG-117799
Change-Id: Iac89f28497c34d217af156d363b8beeda76174ef
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
2023-11-09 19:12:37 +01:00
Ulf Hermann 674dc3f73d QmlCompiler: Always record original types for equality comparison
The shadow check may adjust the types later on and cause a different
comparison to happen than what we've expected when propagating. We can
only see this at code generation time.

Pick-to: 6.6 6.5 6.2
Task-number: QTBUG-117795
Change-Id: I04f1dd9902385f87114e48b0994e0f243f0c2c84
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
2023-11-09 19:12:37 +01:00
Ulf Hermann d0484963f4 QmlCompiler: Allow internal conversions from wrapped original types
If an original type is merely wrapped into a more generic type by the
basic blocks pass, we know the original data is still there and can be
used for conversion.

This happens if we assign the same value once via a shadowable lookup
and once via an exactly typed one. The basic blocks pass then has to
produce a QVariant for the shadowable lookup. However, we know that it
can only contain the original type.

Fixes: QTBUG-117800
Change-Id: I42335c3404dbcf8c1e7ad6427d22643ad490a345
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-11-04 01:29:26 +01:00
Ulf Hermann 048c8f226a 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.6 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>
2023-11-04 01:29:09 +01:00
Ulf Hermann c662ae7cbf QmlCompiler: Generate jump code also when skipping an instruction
The next instruction may still need the type conversions even if we
don't need to generate any code for the current instruction.

Also, generate trace info for generate_DeadTemporalZoneCheck so that we
can recognize it in the generated code.

Amends commit 2c410317b6.

Pick-to: 6.6 6.5
Fixes: QTBUG-118514
Change-Id: I70ad3691486176de2177e9d5f538f7c99d121bfa
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
2023-10-31 12:54:10 +02:00
Dmitrii Akshintsev c1320e7a35 Throw an exception in loadScopeObjectPropertyLookup when qmlScopeObject is null
When object is being destroyed, qmlScopeObject pointer is becoming null (I assume as part of the lookup invalidation?), causing nullptr dereferencing in the subsequent Init lookup stage.
This commit prevents it by introducing an "early exit" on the load stage.

Fixes: QTBUG-117866
Change-Id: Ifef1a0dd48a952f00f2c0d4d5015ec2f40b7f62a
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2023-10-24 18:44:55 +02:00
Ulf Hermann 22eaa614ea QmlCompiler: Reject calls to one of multiple fuzzy overloads
If we cannot statically determine the right overload better don't call
any of them for now. Also, allow attempts to pass arguments as derived
types during type propagation.

The test shows that we don't properly pass the thisObject when calling
with metatypes. Fix that, too.

Pick-to: 6.6 6.5 6.2
Fixes: QTBUG-117922
Change-Id: I02e70ffb9a05f3cfedccafde6e16170b0efbcd29
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-10-23 14:44:19 +02:00
Ulf Hermann 1ba14d58eb QmlCompiler: Disallow reading enums from instances
Pick-to: 6.6 6.5 6.2
Fixes: QTBUG-118089
Change-Id: Ib98bb84159847439614341a3cbd4d34d6eabfc8a
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
2023-10-23 14:23:38 +02:00
Ulf Hermann 53b9c17749 QmlCompiler: Prohibit writing to readonly properties
The extra check for hasOwnProperty() was wrong. It was originally meant
for qmllint to find initial assignments to the same property but qmllint
has a different way of identifying those these days.

Amends commit d2507f2383.

Pick-to: 6.6 6.5
Fixes: QTBUG-118100
Change-Id: I6151b8088315b6a99e331b0830b9fdd8188a30cb
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
2023-10-18 09:22:29 +02:00
Olivier De Cannière d4bab56356 codegenerator: Convert to the original type of registers for unary ops
When generating the code for unary operations, we converted from the
received type to the expected type in readAccumulator. Except, if the
latter was replaced by a different type such as with a generalization to
QVariant for example, then we would not retrieve the original type the
operations should be performed on but keep the replacement type.

Convert the received type to the original type instead of to the
replacement.

Fixes: QTBUG-117789
Pick-to: 6.6
Change-Id: Ia0109918443b1e1be2bc57b9d46a3a628799806b
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2023-10-06 18:06:47 +02:00
Ulf Hermann d0c7f46b40 QmlCompiler: Error out when writing to property of unknown type
Otherwise we get a conversion to unknown and that is bad.

Pick-to: 6.6 6.5
Fixes: QTBUG-117361
Change-Id: Iead1ddd21b692ed9fb9923dccdfa5bd01dc9d467
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Nicolas Fella <nicolas.fella@kdab.com>
2023-09-28 16:22:29 +02:00
Ulf Hermann 8a22282f6a QmlCompiler: Do not crash when trying to iterate non-iterables
Amends commit a173d50a9e.

Change-Id: I2774cd483e073c69f2ceff345436fbdd2a9ac692
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Semih Yavuz <semih.yavuz@qt.io>
2023-09-28 16:22:25 +02:00
Ulf Hermann a173d50a9e QmlCompiler: Implement GetIterator and IteratorNext
Each GetIterator generates

* A unique iterator variable that keeps track of the current index
* In the case of for...of a copy of reference to the list being iterated

The result register holds a pointer to the unique iterator so that it
can be loaded and stored without resetting it.

In order to do anything meaningful with iterators (in the tests) we also
need to allow LoadElement with our "optional" types. That is a
conversion of undefined and some other type to QVariant or
QJSPrimitiveValue. This follows the same pattern as the other
"optional"s we already have.

For...of is currently not testable because it requires exception
handlers. The tests will be added once we get exception handlers.

Task-number: QTBUG-116725
Change-Id: I167fe16b983dc34bf86e1840dfcbf2bf682eecc1
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-09-21 10:11:05 +02:00
Ulf Hermann 36478e252f QtQml: Cache correct properties for signal handlers
This exposes some invalid QML code in our tests: We shouldn't override
signals in QML and we now notice. Since banning it outright would be a
pretty drastic change in behavior, we only print a warning for now.

Coverity-Id: 416620
Change-Id: I28c6b818c4abccb830b0e6998fe840bf229bf081
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
2023-09-05 11:41:25 +02:00
Ulf Hermann 3ca5a7b3b6 QmlCompiler: Clean up equality operators
The special cases added for the number and null operations are generally
useful also for other kinds of equalities and vice versa. Furthermore,
there is no point in std::move'ing registers into equality operators.

Task-number: QTBUG-115110
Change-Id: I6de634ee45e13aefd069677c4bf75020875e09fa
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-08-25 23:58:12 +02:00
Ulf Hermann f839171eef QmlCompiler: Allow creation of actual QVariantMaps from object literals
There are places where we need this:

a, If the method in question actually takes a QVariantMap as argument.
b, If the resulting value can be shadowed. In that case we expect a
   QVariant. The engine has to internally convert to the expected type
   then.

Change-Id: Ic5b3faab4578d64ca757de644fe69660fd70e52a
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
2023-08-25 20:36:46 +02:00
Ulf Hermann 555125416e QmlCompiler: Allow coercing date values to numbers
This is the equivalent of JavaScript's valueOf().

Change-Id: If850519d6dbc7354b447acb6aad8ac04211d059d
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
2023-08-25 20:36:37 +02:00
Ulf Hermann ede3389a3e QmlCompiler: Allow setting values in sequences
Since we have write-back available now, this is not difficult anymore.
This does not yet cover setting properties of value type objects stored
in sequences such as "a[i].b = c". You can only set the whole element.

Task-number: QTBUG-116011
Change-Id: Id5f7a19125897602880e573d5f25b025f9b91f34
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
2023-08-25 20:36:33 +02:00
Ulf Hermann 72e9f47526 QmlCompiler: Allow write-back to members of objects
This covers recursive write-back, but not write-back to members of
singletons or attached types, write-back of lists.

Task-number: QTBUG-116011
Change-Id: I6d33fae3bf9fdaed8d696a708124e0a707ecb07e
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-08-24 12:39:43 +02:00
Ulf Hermann 8d9dfd3347 QmlCompiler: Fix conversion from/to void
We can convert everything to void, but we can only convert from void if
the result is either void or the invalid type.

Pick-to: 6.6
Fixes: QTBUG-116088
Change-Id: I532055405865c5b1581f79cc5d76c253bce6138d
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
2023-08-23 15:30:11 +02:00
Ulf Hermann 2eac7350c0 QmlCompiler: Stabilize test
Loading the implicit import might add extra types that use up indices.
So, make sure the implicit import has already been loaded at that point.

Use a file that only has one type reference so that the ordering of type
references cannot mess up the selection of indices for types.

Change-Id: Ia33979e660e114ef608e1f5e22252c822c7f3d61
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
2023-08-22 20:11:34 +02:00
Ulf Hermann d908d5e57c QmlCompiler: Allow construction of Array objects
Currently, only the constructor form of the Array function is compiled.
We only compile construction of Array objects if we can determine that
they are immediately assigned to a typed list. Consequently, we don't
have to deal with sparse arrays.

Change-Id: I2abd15139eb9a0d530ad49df7313b8dba415ae77
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-08-22 17:16:53 +02:00
Ulf Hermann 0f23346d2a QmlCompiler: Allow construction of Date objects
We map Date to QDateTime and special-case its constructors.

Task-number: QTBUG-111624
Change-Id: I0496f853613da3ccee9b6f6c4cf0adffa064f9f8
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
2023-08-18 14:26:04 +02:00
Sami Shalayel a1ce0596e5 Replace signal name manipulations with QQmlSignalNames
Remove custom implementations found in qqmljs* and use the
static helper methods from qqmlsignalnames_p.h instead. This sometimes
requires to move some code around to avoid bugs with property that do
not have letters in their name.
Add a warning in the JS implementation of the SignalSpy.qml that the
used heuristic might fail on certain signal names.
Add tests in in tst_qqmllanguage to see if the property change handlers
work correctly for weird names.

Change-Id: I4dc73c34df7f77f529511fa04ab5fcc5385b59fc
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-08-15 12:13:31 +00:00
Ulf Hermann d07744ef5d QmlCompiler: Fix SetLookup on shadowable properties
If we are procedurally setting a shadowable property, the read register
for the value will be converted to var. We can therefore not just
retrieve the property type again in the code generator to determine what
we have to do.

What we actually need is the information on the original scope type of
the lookup. We need to know what exactly the base type was supposed to
be. To that effect, store the scope of the target for each conversion in
QQmlJSRegisterContent.

We need to circumvent the questionable optimization of "deduplicating"
functions that certain compilers exhibit, like we do for the getters.

Pick-to: 6.6
Fixes: QTBUG-115526
Change-Id: I361f2e46e39ece7892df72ae13ec756f9aec4adf
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-08-08 15:12:46 +02:00
Olivier De Cannière 2cf9aeccdd 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>
2023-08-04 09:34:09 +02:00
Ulf Hermann fa6aedf7ac QmlCompiler: Allow calling methods on potentially undefined QObjects
We can use the same technique as for GetLookup there. Just check the
variant for validity to see if we can call it.

Change-Id: I1bcf4a5a84f47e0236762827488bc5d03e015efb
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-07-28 16:42:45 +02:00
Ulf Hermann 81bab13560 QmlCompiler: Force QObject* for LoadElement on list properties
In the presence of incomplete type information we may otherwise conclude
that the value type is QJSValue and generate broken code.

Pick-to: 6.6 6.5 6.2
Change-Id: I533f704a422d0efe8b7b5bb0a170966e9f290b1f
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-07-26 16:54:52 +00:00
Ulf Hermann 747c860354 QmlCompiler: Correctly handle lookups in results of method calls
Method calls often return just QVariant because we cannot be sure that
the method hasn't been shadowed. In order to figure out the right lookup
we should look at the type the type propagator assumed as the base of
the lookup. If the type propagator was assuming a list-length lookup we
need to try and generate a list-length lookup. If the base turns out to
be a QVariant after shadow-checking, the code generation will cleanly
fail (and refrain from generating bad code).

Amends commit 46cc70e2aa.

Pick-to: 6.6
Fixes: QTBUG-115278
Change-Id: I24dcd06161eb1af44450fb663d68a16d89efd6ac
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-07-25 16:33:29 +02:00
Ulf Hermann fb4cc245e0 QmlCompiler: Optimize storage for register variables
We don't need nested hashes there. A single hash is enough, and we also
don't need to key it by pointers. Keying it by internalName instead
makes the ordering deterministic. We also don't need to duplicate-track
the variable names when outputting the declarations anymore.

Verify that qmlcachegen's output is actually stable by compiling the
entire test data for tst_qmlcppcodegen twice, packaging the generated
code into the resource file system, and comparing it in a separate test.

Pick-to: 6.5 6.6
Fixes: QTBUG-115159
Change-Id: I659661e58a52ed9ff308c83d6c821cf016f2e94e
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-07-24 21:26:57 +02:00
Ulf Hermann ca27c051ab QmlCompiler: Allow creation of structured value types
With this change, qmlcachegen can populate structured value types from
object literals.

Also fix the construction of value types via Q_INVOKABLE ctors. We don't
need to wrap the ctor argument in QVariant if we can store the original
type, and we should always look at the base type for the creatable flag,
not the extension.

Task-number: QTBUG-107469
Task-number: QTBUG-112485
Change-Id: I9f3db13f00466dc9d87237bdf0b380d6eeb58a10
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-07-06 21:29:39 +02:00
Fabian Kosmale f7930126a6 qml compiler: Detect if user confuses flags and enums
If you pass the enumeration type to the Q_FLAG macro, you'll get an
qmltypes entry where the type is marked as a flag, but where aliasName
is empty. For backwards compatibility reasons, we cannot static_assert
that the type passed into QFlags is actually a flag type.
When using the interpreter, this does not cause any issues, because the
code there does not need to distinguish flags and enums.
When compilation is enabled, we do however generate bogus code, which
either leads to a wrong result, or to a crash if ASAN is enabled.

Avoid the issue by detecting that the enum is missing, and by rejecting
that case.

Pick-to: 6.6 6.5
Fixes: QTBUG-114326
Change-Id: If5cb801b3cf2c3bd7986ef0c8fc3664e6ed564b8
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2023-06-29 09:28:52 +02:00
Ulf Hermann c6d599bf60 QmlCompiler: Use int for flag-type enums
The isFlag flag overrides the underlying type as the resulting type is
then a QFlags.

Pick-to: 6.6
Fixes: QTBUG-114815
Change-Id: I9cc3b260a280b784fc8af38fafbc9ffbd7ca3453
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-06-23 21:22:34 +02:00
Ulf Hermann 779f6cf08c QmlCompiler: Add further tests for DTZ
Apparently we had some intermediate state where these ones were broken.
Let's make sure this doesn't happen again.

Pick-to: 6.6
Fixes: QTBUG-113403
Change-Id: If1da8200afe5c7cee417cd755a15251979fb18c5
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-06-23 18:49:37 +00:00
Ulf Hermann dae48cf190 QmlCompiler: Properly reset before re-running basic blocks pass
If we were within dead code at the end of the previous run we need to
reset the "skip until next label" flag. Otherwise we still assume we're
in dead code at the beginning of the function, with interesting effects.

Pick-to: 6.5 6.6
Fixes: QTBUG-114476
Change-Id: Ib6e3d6c81aad4c8aaac12accdb3936e4136235fc
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-06-21 14:14:39 +02:00
Olivier De Cannière 583e8c8216 QmlCompiler: Add missing conversion for equality with null or undefined
The result of the equality check is a bool. However, the expression
using that value may expect another type. It therefore needs to be
converted to that type. This was done implicitly until now because of
the missing explicit conversions. This is a problem because introducing
more conversion options causes an ambiguity in the choice of the
conversion to use. Leading to a compilation error.

For this reason the test is run in a Window because this includes
enough other code to make the implicit conversion ambiguous.

Fixes: QTBUG-114418
Pick-to: 6.5 6.6
Change-Id: I1c3f9ee21f9719cdfbce748a4fd0a687def9d1bf
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2023-06-12 13:32:15 +02:00
Ulf Hermann e6dd62ff19 QmlCompiler: Do check specificType on SetLookup
We may have implicitly invalidated it when shadow-checking.

Amends commit b3281f123e.

Change-Id: Ia5c54a3a0fa97c61e947ecb0a5b21d410e1bf19a
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-05-15 10:46:27 +02:00
Ulf Hermann 60a34c3393 QmlCompiler: Optimize list manipulations
We should never store a list in a wrapper type that is itself a
different list. Wrapping and unwrapping requires rebuilding the list in
such cases. We can, however, store lists of builtins as-is. There is no
need to transform them. Other lists can still be stored in QVariant.

As a result, we now need to discern between the access semantics of the
stored type and the access semantics of the contained type. They are not
guaranteed to be the same anymore. Furthermore, we need to reject
"internal" manipulation of QVariant-wrapped lists for now. We might
implement them using QMetaSequence, though.

Task-number: QTBUG-113465
Change-Id: If09ea345b2fac39bf2abd62a2fce2d354df85b6b
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-05-10 09:28:59 +02:00
Ulf Hermann 71b4a5e6df QmlCompiler: Re-allow conversion from QObject to QString
It only worked for the console functions in 6.5. There it was suppressed
by the enforcement of type conversions in the basic blocks pass in dev.

We have, however, a good enough way to coerce QObject to QString these
days.

Task-number: QTBUG-112291
Change-Id: I025976cc7fbe430c5cdc607cae3ca48838b24f88
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-05-09 21:28:07 +02:00
Ulf Hermann 9cead49c0e Properly support lists as method arguments
a, Teach QV4::QObjectWrapper how to convert QQmlListProperty to
   QObjectList.
b, Parse the isList attribute from qmltypes.
c, Resolve lists when resolving QQmlJSScope.

Change-Id: I70c6d40507de990b45a87eb7d8c7bba279d550e8
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-05-09 21:28:06 +02:00
Ulf Hermann 406a9e1301 QML: Encode "missing" line number as negated address of stack frame
This way we can identify which entry in a stack frame to amend when
processing an exception in generated code. However, negative line
numbers are also used to signal the position of "Ret" instructions.
Since you cannot throw an exception from a "Ret" instruction, those
cannot collide, but we cannot qAbs() the line number anymore when saving
it in the stack trace. We have to qAbs() it in all the places where it's
read.

Pick-to: 6.5
Fixes: QTBUG-112946
Change-Id: I24dc4008fb7eab38e4d24e70211c22e46f1b72a7
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-05-09 21:28:06 +02:00
Ulf Hermann 1b89c1edca QML: Allow conversion from QV4::Sequence to different iterable
Pick-to: 6.5
Fixes: QTBUG-112291
Change-Id: Idd47ea8daf9c54759af6c1feba68bd52d1163615
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-05-09 21:28:06 +02:00
Ulf Hermann 96ac9c2599 QmlCompiler: Convert thisObject to correct type
Amends commit 365b781599.

Change-Id: I5775d634ef4e5204cdec2f440b1992b7272866d2
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-05-04 18:59:34 +02:00