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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
Store a copy of the UTF-8 data for file and function so that we don't
run into heap-use-after-free.
Set the instruction pointer before calling the log function so that we
get a correct line number.
Pick-to: 6.6 6.5
Fixes: QTBUG-114655
Change-Id: I38249fe52719ddad620033716ff22b2087ab8382
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
We want them alphabetically sorted so that we minimize merge conflicts.
Change-Id: If6509fb1d196a10898fd6d9a5f51a9da678ad3c9
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
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>
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>
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>
That makes it more clear which ignoreMessage belongs to which part.
Change-Id: I4c2bcc16b80204c6bb55c18459b7e8b0b1b298be
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
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>
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>
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>
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>
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>
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>
This gives us a unified interface to all kinds of QML types at run time
and reduces the effort of finding corresponding type attributes.
QQmlType is much larger than CompositeMetaTypeIds. Most composite types,
however, are initially referenced by URL, and we call typeForUrl anyway.
typeForUrl already creates a mostly functional QQmlType; we only need to
add the dynamic metatypes. The same type can be retrieved later and
associated with the actual CU using the compositeTypes hash. That way,
we don't need any extra type. We do, however, incur the cost of creating
the QMetaTypePrivate instances when first referencing a type. This could
be optimized, like many things in this area, by using thread safe lazy
initialization.
Now some QQmlTypes implicitly depend on the CUs they were created for.
This creates problems if the CUs are removed but the types still
persist. Such a situation can arise if you create and delete engines. In
order to avoid it, we:
1. Make the compositeTypes hold a strong reference to the CUs
2. When unlinking, avoid dropping the property caches (as those are used
to hold the metaobjects)
Now, however we got a cyclic reference between the CU and its
QQmlType(s). To resolve this, we clear the QQmlTypes on unlinking.
Finally, to avoid deletion recursion when clearing the last CUs on
destruction of the QQmlMetaTypeData, we move the compilation units out
of the way first.
All of this still doesn't work if multiple CUs hold the same QQmlType,
since compositeTypes can only hold one CU per type and that may be the
one that gets removed first. Therefore, we cannot allow such a situation
to happen and have to create a new QQmlType if it arises. It can only
arise if you have multiple engines loading the same QML components,
which should be fairly rare.
For inline components, we apply a similar trick: You can either find an
inline component by Url, and receive any type that matches, no matter
what CU it belongs to. Or you can request an inline component type that
belongs to a specific CU. It turns out we don't have to store the
containing type of an IC at all. Also, we slightly change the naming of
internal components' "class names" since we want to use the inline
components' element names for them.
Change-Id: I0ef89bd4b0a02cc927aed2525e72f6bff56df626
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
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>
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>
We're going to call the JavaScript-typed functions a different name.
Change-Id: If92c3fb1b16b1b0bd7d009e7dd712ae6405e1232
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
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>
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>
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>
Instead of accepting the inconsistency between interpreter and compiled
code here, we can just detect whether a value can be affected by side
effects and refrain from reading it then. Since you can always
explicitly reload a value that may have been changed, the resulting
compile warnings are easily worked around in user code. Refactoring user
code this way also makes it much clearer what is actually going on.
Pick-to: 6.5
Task-number: QTBUG-109221
Change-Id: Ica832e39838ef732b0d181364630737fd7709b74
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
The function may return a QVariant in place of the actual type because
it cannot express the actual type as-is. This case needs special care
because QMetaType::convert() doesn't know what to do with it.
Pick-to: 6.5
Fixes: QTBUG-112837
Change-Id: Ibf93a28aa6a60d49c5ab63fa7eed5f5a8e58e163
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This just creates an inconsistent state where some of the document has
been parsed and some hasn't. The only thing we actually need is the log
message. Also, fix the warning message.
Amends commit 169f0f7166.
Pick-to: 6.5
Fixes: QTBUG-112897
Change-Id: Ie8486909f9bea9ee1b87f2857f7b77fb7cc561e8
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
If we detect a property or method as potentially shadowed, we don't have
to abandon all hope. We can still retrieve it as untyped var. Since
there are a number of things we can do with untyped var, this may still
be useful.
In the same sense, we need to treat function calls as untyped when the
function in question can be shadowed. Calling functions with var
arguments and return types leads to some more interesting situations in
the call frame setup, so we fix that, too.
Task-number: QTBUG-112480
Change-Id: I238d1cf04951f390c73e14ed9e299f2aa72b68cb
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
So far we can only deal with methods that don't change the source array
and don't use iterators or functions as parameters. We also omit
concat() for now. However, indexOf(), lastIndexOf(), includes(),
join(), slice() and toString() are possible already now.
Task-number: QTBUG-112722
Change-Id: Id19c74e8ad25af876bc954c040c767823b7e3259
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Now that the type is available from qmltypes we can just use it.
Task-number: QTBUG-112180
Change-Id: I315372da0925f19c209f676226f450863b0d3ea5
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>
We know that 'this' is a QObject* since the metatypes stack frame
mandates it. Whenever you pass 'this' to anything it's loaded from the
special 'This' stack slot which then triggers a DTZ check. A DTZ check
is a noop if we can prove that the type is statically known, though.
In QmlCompiler, if we have a valid register content, then the register
has been set in all code paths that lead to the instruction in question.
Fixes: QTBUG-111439
Change-Id: I81d1cd140eea63f85628c3bef3a8f6db0a12096d
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
They are equal to QList<QString> and QList<QVariant>, respectively. We
cannot express this fact in qmltypes, but since those are builtin, we
can just hardcode it.
Task-number: QTBUG-112227
Change-Id: Iebeb5f6a5350d1c7184b1d9e6a38647e048c3806
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
In the happy case this just retrieves the internal QList from the list
property. In the sad case it produces a deep copy. That's not worse than
what the interpreter does, though.
Fixes: QTBUG-112227
Change-Id: I8b2b0ac74c90b6dcee876e83a64502756733c1c5
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
It can actually be null rather than undefined. We need to generate a
separate check for that and output the correct error messages.
Amends commit 05f56d7c78
Change-Id: Ia795e31805181640cd5be19359af51067d3fc8d6
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
A pointer type can hold bool as either nullptr or some value. We don't
need to produce a QVariant for that.
Change-Id: I368c3fa703d08ff396a5b4702ba7d1f2614b1467
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This adds support for 8- and 16-bit signed and unsigned integer types.
The test exposes that the engine fails to correctly convert out of range
values when assigning to a 32-bit int property. Fix that as drive-by.
Fixes: QTBUG-101634
Change-Id: I0a4177f49ffc062a1f444e30424e94c1f293e70c
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>