The type of the register may not be the one to be passed to the method.
We cannot rely on the run time internals to coerce the value anymore
since we've moved the type determination out of the generated code.
To make this happen, we need to adjust the storage types of read
registers in the storage generalizer.
Pick-to: 6.9
Fixes: QTBUG-132329
Change-Id: I642027f349f7c05f714ec36ef4e23f9d59b4a8df
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
qmlcachegen will never generate code that calls these with mismatched
types. Checking the type at run time is wasteful. With QML_USING, you
can make qmlcachegen generate code with types we cannot recognize as
compatible. However, those need to be layout-compatible so that they
can be reinterpret_cast'ed into each other. If they aren't that's a user
error in C++. We can crash on such a thing.
However, in StoreNameSloppy and in the variant lookup cases, we do need
to convert types. Since the QML_USING type conversions are unknown to
the QML engine, we have to provide a fallback via QMetaType::convert()
here. So, despite the layout compatibility requirement, the QML_USING
types also need to register metatype converters before any QML code
accesses them.
As a result QML_USING has quite a few complicated requirements now and
is _really_ dangerous.
Pick-to: 6.8
Task-number: QTBUG-127174
Change-Id: I1b8e1595e3088415ce711e910586a5dd456cb2c5
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>