Commit Graph

315 Commits

Author SHA1 Message Date
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 cebb3a7320 QmlCompiler: Optimize trivial as-casts out
If you as-cast to a base type, we don't have to do any actual check.
Furthermore, retain the content variant through as-casts and print a
nicer error message if we cannot generate efficient code for an internal
conversion.

Task-number: QTBUG-117800
Change-Id: Iedaf4ca411be429eec6c9f23b9bd7f20794592ce
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-11-04 01:29:18 +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 fa2b22a7a1 Add proper license header to tst_qmlcppcodegen.cpp
Fixes: QTBUG-105839
Change-Id: Icbb4c6e462c08be019ca203b11aaff840297ccd6
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-09-29 18:04:22 +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
Ulf Hermann f6735dba95 QmlCompiler: Fix console logging
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>
2023-08-15 17:48:43 +02:00
Ulf Hermann 759b8383d7 tst_qmlcppcodegen.cpp: Restore ordering of functions
We want them alphabetically sorted so that we minimize merge conflicts.

Change-Id: If6509fb1d196a10898fd6d9a5f51a9da678ad3c9
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-08-15 14:13:32 +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
Fabian Kosmale e9c87ad1b2 tst_qmlcppcodegen: Split enum test
That makes it more clear which ignoreMessage belongs to which part.

Change-Id: I4c2bcc16b80204c6bb55c18459b7e8b0b1b298be
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2023-07-27 09:36:50 +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
Alexandru Croitor 5818f97e70 CMake: Make qml tests standalone projects
Add the boilerplate standalone test prelude to each test, so that they
can be opened with an IDE without the qt-cmake-standalone-test script,
but directly with qt-cmake or cmake.

Boilerplate was added using the follow script:
https://git.qt.io/alcroito/cmake_refactor

Manual adjustments were made where the code was inserted in the wrong
location.

Task-number: QTBUG-93020
Change-Id: Ia68c9d263e7454f0c4a26c29b10f1c535d08e2f6
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Reviewed-by: Amir Masoud Abdol <amir.abdol@qt.io>
2023-07-05 12:34:11 +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 b48bb41681 QML: Use QQmlType as container for composite types (inline or not)
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>
2023-06-22 20:49:20 +02: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 ba64b7a70e Undeprecate AOTCompiledFunction
We're going to call the JavaScript-typed functions a different name.

Change-Id: If92c3fb1b16b1b0bd7d009e7dd712ae6405e1232
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-05-23 13:53:22 +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
Ulf Hermann 4634b6bf54 QmlCompiler: Disallow reading from values affected by side effects
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>
2023-05-04 16:44:44 +02:00
Ulf Hermann 6c0b98f61a tst_qmlcppcodegen: Sort methods alphabetically
This way we won't get so many merge conflicts.

Change-Id: I2630838d4d310141a6a427a6494c87cb73f79063
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-05-04 11:48:09 +02:00
Ulf Hermann 44ca1085d6 QML: Fix call frame conversion for QVariant return types
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>
2023-05-04 11:48:09 +02:00
Ulf Hermann b8814dfb36 QmlCompiler: Do not crash when converting number literals to enums
Amends commit 2a21efb5f7.

Change-Id: Id7d739b58c723eed9f165951b51ee2e5e55d7fe2
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
2023-05-04 11:48:09 +02:00
Ulf Hermann 1abfb04fae QmlCompiler: Do not stop parsing on top-level Component elements
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>
2023-05-03 14:38:52 +02:00
Ulf Hermann 25b259270d tst_qmlcppcodegen: Sort QML files again
Keeping them sorted reduces the chance of collisions and makes it easier
to find related ones.

Change-Id: Ie05cbfefa5805cd27ec91e566dd922107c70d8e2
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-05-02 19:29:25 +02:00
Ulf Hermann 46cc70e2aa QmlCompiler: Relax shadowing check
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>
2023-05-02 19:29:25 +02:00
Ulf Hermann e846864151 QmlCompiler: Inline some array methods
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>
2023-04-28 21:24:17 +02:00
Ulf Hermann f10630aa03 QmlCompiler: Use actual type of enums, rather than int
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>
2023-04-26 10:57:27 +02:00
Ulf Hermann 365b781599 QmlCompiler: Implement ConvertThisToObject and basic DTZ
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>
2023-04-25 16:53:00 +02:00
Ulf Hermann 653a6ff82a QmlCompiler: Recognize QStringList and QVariantList as special lists
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>
2023-04-24 22:22:14 +02:00
Ulf Hermann fa259ed4ff QmlCompiler: Allow conversion from QQmlListProperty to QList
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>
2023-04-24 22:22:14 +02:00
Ulf Hermann 7c2e31c34f QmlCompiler: Don't crash on bad list type in signature
Pick-to: 6.5
Change-Id: I2c4a4ffa810258134a29b87aff46e8eb544b6a55
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-04-19 20:01:09 +02:00
Ulf Hermann 1ceaeab982 QmlCompiler: Don't crash when checking for enum problems
When checking for CallProperty we want the call base, not the
accumulator.

Pick-to: 6.5
Change-Id: I24ac066dd440bde459e20b3cf962af04ca531629
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-04-19 20:01:09 +02:00
Ulf Hermann b3281f123e Fix content pointer check for QObject*
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>
2023-04-19 09:30:58 +02:00
Ulf Hermann f27cb5e3c1 QmlCompiler: Merge bool and any pointer type into the pointer type
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>
2023-04-15 20:14:42 +02:00
Ulf Hermann 03ff348b49 QmlCompiler: Support more integer types
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>
2023-03-30 15:46:55 +02:00
Ulf Hermann 55cb484934 QmlCompiler: Do not generate invalid code on generate_As
Pick-to: 6.5 6.5.0 6.2
Task-number: QTBUG-111986
Change-Id: Ib6e7179c20e6c7a4d6fc3a1a17eac550d2bbfa56
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-03-17 20:57:14 +01:00
Ulf Hermann ec410555ad QmlCompiler: Allow coercing anything to bool
JavaScript can coerce anything to bool, so should we.

Change-Id: Id560e4c1dc10b5432c0cedf3110ad3377bbc5f59
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-03-10 23:42:49 +01:00
Ulf Hermann 2a21efb5f7 QmlCompiler: Use value type ctors
This allows us to do the relevant conversions in a more civilized way,
dropping the outputVariantConversion() method. The latter is brittle
because you have to manually add it to each instruction, and it uses
QMetaType::convert() which is actually not guaranteed to give the same
results as a QML type coercion.

Task-number: QTBUG-94807
Change-Id: I4d6d05a60beb3b4dfc3da6f0142de25667510904
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-03-09 21:36:30 +01:00
Ulf Hermann 05f56d7c78 QML: Allow as-casting to value types
If the "Addressable" option to ValueTypeBehavior is set, you can use the
"as" operator to cast a previously unknown type into either undefined
or the given type. We can use this in qmlcachegen to generate efficient
code for further operations on the same type.

In the generated C++ it in fact only works for GetLookup because:
a, We generally don't do SetLookup on value types, yet.
b, We generally don't call methods on value types, yet.
c, We cannot store a union of undefined and a sequence type, yet.

However, getting properties of value types is the most important
application of the new casts so this is well worth it.

As a side effect we can also look up things in potentially undefined
results of other operations now. For example list lookups.

Task-number: QTBUG-94807
Change-Id: Ifdf34f1f3f67b7a0a8953b9ed0e947b74638a28c
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-03-03 12:02:00 +01:00
Ulf Hermann 35152b432e QML: Add an "Addressable" value to ValueTypeBehavior
Task-number: QTBUG-94807
Change-Id: I8c78faa99fc4c4b2ffd8c89f1037fc7569212c73
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
2023-03-02 17:54:30 +01:00
Ulf Hermann fc1d258069 QmlCompiler: Improve method overload selection
If we have an exact match we should definitely use that.

Change-Id: I2846ecf6f9963a978b84b70fbe18acdfe6eb45e6
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-03-02 13:17:47 +01:00
Ulf Hermann 8cbb30a650 QtQml: Always throw when requesting an enum from an invalid singleton
The interpreter does this and so should the enum lookup adapter for
generated C++ code.

Pick-to: 6.5 6.4 6.2
Fixes: QTBUG-109816
Change-Id: I576480c3ca808743ddc0ceaf2f0bd8a1de776a41
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-03-01 11:56:19 +01:00
Olivier De Cannière 98849309a2 QmlCompiler: Implement multi-argument Math.{min,max}()
This patch extends the logic for the 2-argument Math.min() and
Math.max() functions by reutilizing the same logic to compare two
elements and evaluate all arguments with the current max or min.

Fixes: QTBUG-108741
Change-Id: I993a26a1d44d66226c751272dfc2dc63330d115d
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2023-02-23 09:51:22 +01:00
Olivier De Cannière a142873d1c QmlCompiler: Implement get lookup of variantMap properties
This patch adds support for get lookups of QVariantMap properties.
Setting or modifying is not supported and will reject.

Also, QQmlJSRegisterContent::JavaScriptObjectProperty was
renamed to QQmlJSRegisterContent::GenericObjectProperty

Tests were added to TestQmllint::cleanQmlCode() and
tst_QmlCppCodegen::variantMapLookup().

Pick-to: 6.5
Fixes: QTBUG-105545
Change-Id: I653ee4e7de1fb1514e1e563a92cfc28633268a7e
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2023-02-22 16:21:09 +01:00
Amir Masoud Abdol 8f7080fd09 Replace AUTO_RESOURCE_PREFIX with Qt CMake Policy in examples, tests
Every instance of AUTO_RESOURCE_PREFIX has been replaced by either
qt_standard_project_setup(REQUIRES 6.5) or with
qt_policy(SET QTP0001 NEW), mainly in tests.

In addition, I added a warning message for the case where
AUTO_RESOURCE_PREFIX is used.

Pick-to: 6.5
Task-number: QTBUG-96233
Change-Id: I323a15e9d0bb5fe6ba649365314af9fc2ad67bda
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Oliver Eftevaag <oliver.eftevaag@qt.io>
2023-02-21 19:45:44 +01:00
Ulf Hermann b9834e0ee9 QmlCompiler: Fix coercion of undefined to float and double
It should result in NaN, not in 0. The typedArray() test exposes that
ExecutionEngine::toVariant() also gets this wrong. Fix that, too.

[ChangeLog][QtQml][Important Behavior Changes] Converting a JavaScript
value to a double or float, for example by inserting it into a typed
array, now assumes JavaScript type coercion semantics. In particular,
converting a value that is not actually a number now results in NaN
where it previously sometimes resulted in 0.

Pick-to: 6.5 6.4 6.2
Fixes: QTBUG-111179
Change-Id: If24444ae9014c8972761c565a6920f06699e485c
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-02-21 12:13:59 +01:00
Semih Yavuz 95228f0e66 qmlsc: Support equality operations for QUrl
Task-number: QTBUG-110983
Pick-to: 6.5
Change-Id: I9a664178c91bfa2962e2a5a3bf4bfa174a74a9d0
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-02-16 11:17:28 +01:00
Ulf Hermann 82cda71298 Controls: Use PlatformDialogHelper for enums in DialogButtonBox
Since we're already using 3 of the 4 enums in PlatformDialogHelper, we
can just as well declare PlatformDialogHelper as extended namespace and
avoid all the fiddling with Q_ENUMS and QFLAGS.

As an additional upside, we get code using those enums to compile to
C++ this way.

Pick-to: 6.5
Fixes: QTBUG-110933
Change-Id: I60bfc15c94133be368fa98ee1b3a0ab7a2bc53ef
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
2023-02-15 14:04:44 +01:00
Semih Yavuz 66bc001968 qmlcachegen: fix nonstrict equality code generation
We should generate type checking code for only strict comparison
of var against null/undefined types or vice versa cases. The non-
strict comparison should be handled elsewhere. Removed pragma Strict to
allow to add warning emitting tests of non-strict comparison.

This amends 6a816a9e0d

Pick-to: 6.5
Fixes: QTBUG-110769
Change-Id: I7f9a457e71a621a005f377216e841bec01667454
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2023-01-31 19:12:30 +01:00
Semih Yavuz db71a35b1e qmlcachegen: Improve QObject comparison code generation test
The code generated for QObject comparisons holds for both weak and
strong comparisons. Improve tst_qmlcppcodegen by adding missing weak
comparison tests.

Amends afc7928d1a.

Pick-to: 6.5
Change-Id: Ib6176a39b329e792b81b3d8e8a288dcea074320b
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2023-01-31 19:12:21 +01:00
Ulf Hermann ddba87612d QML: Turn singleton/type mismatch into a run time type error
There are many ways to "hide" the qmldir from the engine at run time,
which turns singletons into regular types. While all of this is invalid,
we should not assert on it, but rather produce a legible warning.

Furthermore, sharpen the importing of extra modules from qrc as implicit
imports. We should really only import modules the file in question can
ever be part of. Otherwise we needlessly produce the above situation and
hide legitimate warning messages.

Amends commit 7517c1b3ae.

Now we need to teach our tools about the default import paths in the
resorurce file system. They cannot guess any type they may find in any
resource file anymore.

Pick-to: 6.5
Task-number: QTBUG-106929
Change-Id: Ic8c02396d10830a7f461e8a81649bb8c9a1add1f
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
2023-01-27 10:42:06 +01:00
Ulf Hermann 5f3b8bd08c QML: Allow more conversions between different lists
You should be able to assign any list of QObjects to any other list of
QObjects.

Pick-to: 6.5
Fixes: QTBUG-108155
Change-Id: I6ddf0b49f7248ad56cc9560d217f3ea316c648a8
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
2023-01-26 11:42:33 +01:00
Ulf Hermann 6d181fc043 QML: Allow converting any object list to QQmlListProperty
We can use QSequentialIterable for this.

Pick-to: 6.5
Fixes: QTBUG-110438
Change-Id: I7e82d0f089c9bb9eab46be46dedc2db3726e64b0
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
2023-01-25 17:08:37 +00:00
Ulf Hermann 518509297f qmltyperegistrar: Strip '*' from list value types
We do this for function return types, property types, and function
argument types already. Formally, we would have to store some
"isPointer" somewhere, but considering that we never read it anyway,
let's not go there.

This allows the compilers to recognize lists of QObject-derived types as
proper lists. This way we can generate better code for moving them
around or getting their length.

Pick-to: 6.5
Task-number: QTBUG-110438
Change-Id: I35e0fc21d574afc18799e9c3cef402f05b60a3ed
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
2023-01-25 18:08:36 +01:00
Fabian Kosmale aa551eebb5 tst_qmlcppcodegen: Add QML dependency for Android
qmlimportscanner is rather limited in how it works,
and does not pick up the Qt.labs.folderlistmodel
dependency for Dialogs.

Pick-to: 6.5
Fixes: QTBUG-103044
Change-Id: I778f5c8981f1a2603bc3a5d2fd249a83de6c9bd8
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2023-01-25 17:08:36 +00:00
Ulf Hermann c9b8b06117 QmlCompiler: Wrap sequences with unknown elemnts in QVariantList
Otherwise we later try to perform value type lookups on them. That won't
work.

Pick-to: 6.5
Task-number: QTBUG-110438
Change-Id: I1690a3375841ba5a1ff1a471a7f88bd2023ab4c4
Reviewed-by: Semih Yavuz <semih.yavuz@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-01-23 22:27:38 +01:00
Ulf Hermann ec58c0ddb7 QML: Add a pragma for value type behavior
Unfortunately value types behave differently when compiled to C++.
Document the difference and introduce a pragma to make them behave one
way or the other.

Pick-to: 6.5
Fixes: QTBUG-109221
Change-Id: Ib2685153c0b4ae209bafbea7a01229377fdb47dd
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-01-20 20:39:11 +01:00
Ulf Hermann bda7b2a444 QmlCompiler: Handle various date and time conversions correctly
We can coerce QDateTime, QDate and QTime into each other because they
would all be represented by a Date object in JavaScript. Furthermore we
can coerce them all to QString. Technically, we could also coerce
strings to all of them, but we don't want to because that is terrible.

Fixes: QTBUG-109380
Change-Id: I176bfb5b715a6a6750cb5918c44261fa23fb8832
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
2023-01-17 21:58:32 +01:00
Ulf Hermann e070b5aa39 Allow extraction of V4 values from QJSPrimitiveValue
Since we can produce QJSPrimitiveValue in metaTypeFromJS, we should also
handle the other direction.

Fixes: QTBUG-109867
Pick-to: 6.5
Change-Id: I2c7598d19eba3e78d071ca3eceb32deda4d0ead8
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2023-01-16 23:03:57 +00:00
Semih Yavuz afc7928d1a QmlCachegen: Equality comparison ability to QObject *
We should be able to compare QObject * with QObject * or a
nullptr.

Pick-to: 6.5
Fixes: QTBUG-109377
Change-Id: I0e9d6fdc89cbb471774d6382316dfb4813310e1d
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2023-01-10 15:09:23 +03:00
Semih Yavuz 6a816a9e0d QmlCachegen: Equality comparison ability to var and void/null types
The code generator currently rejects any comparisons other than
primitive types. Add comparison capability for var types against
null or undefined types and vice versa. To achieve this, we generate
code that fetches the contained object within the variant and
comparison is done depending on the stored type.

Ideally, we also need to add comparison capability for QObject *, that will be handled with QTBUG-109377.

Pick-to: 6.5
Fixes: QTBUG-108632
Change-Id: Ib15450d7922f6025c78def5cc548c74827ad740f
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2023-01-06 17:28:31 +00:00
Ulf Hermann 35e2bb0906 QmlCompiler: Test that infinities cleanly cast to int
Task-number: QTBUG-108820
Change-Id: I984f6f35ffd32ca9adae31e56010d10c683e5615
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
2022-12-23 09:02:24 +01:00
Ulf Hermann c4fc116718 QmlCompiler: Fix recognition of builtin list types
Previously all list types used as arguments or return types for methods
had to be looked up via the imports. However, builtin types are not part
of the imports at run time. Therefore, recognize list types already
early on, when generating the IR. This is the same way we do it for
property types and it allows us to easily identify lists of builtins.

Pick-to: 6.5
Fixes: QTBUG-109147
Change-Id: I91fa9c8fc99c1e0155cc5db5faddd928ca7fabbc
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2022-12-15 17:47:58 +01:00
Ulf Hermann b13e22f274 QmlCompiler: Fix wrapping of numbers in QJSPrimitiveValue
We need to explicitly cast to double if we are wrapping a number type
that's not natively accepted by the ctors.

As a side effect, correctly run conversions from generic QVariant to
QJSPrimitiveValue through the engine now. For that we need another
clause in metaTypeFromJS().

Since we are calling methods that return list types in the test, we need
to add another clause that converts JS arrays to list types. Otherwise
we cannot run that test in interpreted mode.

Pick-to: 6.5 6.2 6.4 6.4.2
Task-number: QTBUG-109111
Change-Id: I87f7aafd24371d2c1ffe85569e1f2cd3a1979742
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-12-15 17:47:11 +01:00
Ulf Hermann 07d2a80d01 QmlCompiler: Mark StoreElement on JS values has having side effects
A StoreElement on a JS value can do pretty much anything you can
imagine, after all.

Pick-to: 6.5 6.4 6.4.2
Fixes: QTBUG-109196
Change-Id: Ic638d94b55e6340eb9fe56abc663a6f0f2277f5e
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-12-15 14:03:55 +01:00
Fabian Kosmale aa4a1e96b8 QQmlJSCodeGenerator: fix nullptr dereference
If we try to lookup the length of a generic QVariant, we fail, and so
far crashed. We should ideally detect that we are dealing with an array
(and thus length is a known, available property), but for now simply
reject compilation to C++.

Pick-to: 6.4
Fixes: QTBUG-109164
Change-Id: I9d4149ac09a351754d012dbc829774413d6b32eb
Reviewed-by: Semih Yavuz <semih.yavuz@qt.io>
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
2022-12-12 15:33:18 +01:00
Ulf Hermann ce005eae58 QML: Unify postprocessing of imports
We want to always import dependencies, always import qualified scripts,
and always try to load C++-based types from the binary. Furthermore,
directory imports should be imported with their qmldir URI where
possible, so that we can find them when loading local C++-based types.

Fixes: QTBUG-109109
Change-Id: I58f08f479623a886c802035b41f5f604338468b5
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-12-07 16:48:35 +01:00
Ulf Hermann a354d91b88 QmlCompiler: Ignore cloned signals when analyzing signal handlers
We obviously want to see the defaulted parameters when generating the
handlers.

Fixes: QTBUG-108762
Change-Id: I33a52bac305238467d45650bf8a2ad59d40e366f
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-12-07 13:50:01 +01:00
Semih Yavuz 9793c663cc Fix comparison AOT-lookup and intended type in value types
We currently force the lookup metatype to be exactly the same data type
with the caller's. As a result, the conversion from enum to integral
data type is not recognized. Relax this comparison by using
isTypeCompatible helper.

Pick-to: 6.4
Fixes: QTBUG-109007
Change-Id: I188dc3e6c1fd7100e9ed5c4ba5d0c90d85d79be4
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2022-12-05 17:39:24 +01:00
Ulf Hermann 8bc748e7e5 QmlCompiler: Fix various kinds of enum lookup
* If we got an object type exposed as namespace, we still need to add
  the "*" to get its augmentedInternalName(). Otherwise we cannot get
  its metaobject, needed to look up enums.
* Enums cannot be shadowed. The shadow check will produce garbage if we
  try to check because an enum lookup also does not use the accumulator,
  which then contains some artifact from a previous operation.
* If we find a property lookup on a plain QMetaObject* we have to
  immediately return in order to not confuse it with attached
  properties.

Pick-to: 6.4 6.2
Fixes: QTBUG-109048
Change-Id: If9e3b4806e4d773de9cf48f1b3750b684a8c8f69
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-12-02 13:35:42 +01:00
Ulf Hermann 43ef237f99 qmltyperegistrar: Generate accessSemantics="none" for foreign namespaces
If the local type is a namespace, the resulting type can only be a
namespace, too, no matter what kind of tag the foreign one has.

Furthermore, we can re-use types with other QML_* tags this way.

Task-number: QTBUG-108883
Change-Id: Ib2ae08d5b081b8faa35124314f97d406d7b4f76f
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-11-29 12:32:27 +01:00
Ulf Hermann 6e640a0218 QmlCompiler: Store imported types in a QList
The same type can be exported multiple times with different attributes,
even in the same module.

This requires us to fix directory imports as qmllint otherwise complains
about SegFault.bad.qml and SegFault.qml being the same type (which they
obviously aren't).

Task-number: QTCREATORBUG-27590
Change-Id: I295d927b9a07acbb715055a6883ac44b50129c2d
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
2022-11-25 00:04:02 +01:00
Ulf Hermann ed47bff411 QmlCompiler: Implement console logging methods
We provide semi-private functions in the AOT context for this. Since we
cannot know the complete run time type of the potential logging category
at compile time, we have to check any first argument that might be one
separately.

Fixes: QTBUG-107175
Change-Id: I46a8922b1c5c16d2b450b8728d650d31dfd867e3
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-11-23 10:27:55 +01:00
Ulf Hermann bce216d5c0 QmlCompiler: Fix comparison of null and undefined
Those are not stored. If we compare null to null or undefined to
undefined, we do not have to generate a comparison at all. the result is
statically known.

Pick-to: 6.4
Fixes: QTBUG-108634
Change-Id: I6a5323c2e0c023838609aec90d7ecc15b885dc08
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-11-23 10:27:48 +01:00
Ulf Hermann df01095a66 QmlCompiler: Don't crash on CallWithSpread
When preparing for such a call, the byte code loads an "empty" constant.
This has to be represented in the type system so that we don't hit the
assert at the end of the instruction.

Pick-to: 6.4 6.2
Task-number: QTBUG-108441
Change-Id: I66220bfae3d3a4b8e9600d84d4cfc43ac858b77e
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-11-22 12:32:23 +01:00
Sami Shalayel d9d2477464 Remove signal index mismatch in aot-compiled code
There are multiple types of signal indexes, one of them
belongs to QMetaMethod::signalIndex and another one to
QObjectPrivate::signalIndex.

Stop mixing them up in aot-compiled code when capturing
properties as this leads to weird and hard to debug bugs.

Add a smaller version of the drag and drop example as test
to make sure that the bug does not appear again, without any
visual elements.

Fixes: QTBUG-104047
Fixes: QTBUG-104716
Pick-to: 6.4 6.2
Change-Id: I4f64ba237e824ff0ba1624c29ddcf5371d03d69e
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-11-15 11:52:45 +01:00
Ulf Hermann 1d3d7437ba QML: Fix the most blatant TDZ violations
When reading a let or const register before its declaration we can be
sure this is invalid.

Task-number: QTBUG-108362
Fixes: QTBUG-77428
Change-Id: I7e8f8b46079860f00c051c1a91f773dc8cdd5595
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-11-14 10:19:08 +01:00
Ulf Hermann 259aec7cb4 QmlCompiler: Ignore InitializeDeadTemporalZone instruction
We don't discern between empty and undefined values in the compiler.

Fixes: QTBUG-104192
Change-Id: Ida06386433ef9e8f9a7cba4bec99ba8e77edc324
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-11-11 12:07:42 +01:00
Ulf Hermann 91c6d45559 QmlCompiler: Allow lists as arguments to methods
Since lists are allowed as property types, you should be able to pass
them as arguments to methods, too. For now we only handle QML-defined
methods, implemented by adding JavaScript functions to your QML
elements. The usual type coercion rules apply if you pass JavaScript
arrays to such methods. That is, it usually works.

We now resolve properties with the "list" flag to their actual types
(QQmlListProperty or QList) already when populating the QQmlJSScope, and
store the list types as members of QQmlJSScope rather than as a special
map in QQmlJSTypeResolver. This allows us to do the same to lists passed
as arguments and simplifies some of the type analysis.

Fixes: QTBUG-107171
Change-Id: Idf71ccdc1d59f472c17084a36b5d7879c4d959c0
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-11-10 15:00:11 +01:00
Marc Mutz 534241f723 Port to new Q_UNREACHABLE_RETURN()
This is a semantic patch using ClangTidyTransformator to convert
sequences of Q_UNREACHABLE() + return into Q_UNREACHABLE_RETURN(),
newly added to qtbase.

    const std::string unr = "unr", val = "val", ret = "ret";
    auto makeUnreachableReturn = cat("Q_UNREACHABLE_RETURN(",
                                    ifBound(val, cat(node(val)), cat("")),
                                    ")");
    auto ignoringSwitchCases = [](auto stmt) {
        return anyOf(stmt, switchCase(subStmt(stmt)));
    };

    makeRule(stmt(ignoringSwitchCases(stmt(isExpandedFromMacro("Q_UNREACHABLE")).bind(unr)),
                  nextStmt(returnStmt(optionally(hasReturnValue(expr().bind(val)))).bind(ret))),
             {changeTo(node(unr), cat(makeUnreachableReturn,
                                      ";")), // TODO: why is the ; lost w/o this?
              changeTo(node(ret), cat(""))},
             cat("use ", makeUnreachableReturn));

a.k.a qt-use-unreachable-return.

subStmt() and nextStmt() are non-standard matchers.

There was one false positive, suppressed it with NOLINTNEXTLINE.

It's not really a false positiive, it's just that Clang sees the world
in one way and if conditonal compilation (#if) differs for other
compilers, Clang doesn't know better. This is an artifact of matching
two consecutive statements.

Change-Id: I3855b2dc8523db1ea860f72ad9818738162495c6
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-10-20 23:59:33 +02:00
Ulf Hermann de2d7cba76 Add option to enforce function signatures
By default, the QML engine does not enforce signatures given as type
annotations to functions. By passing different types than the function
declares, you can get different behavior between the interpreter/JIT and
the AOT-compiled code. In addition, in interpreted or JIT'ed mode, we
pass all non-primitive value types as references. This means, if you
modify them within the called function, the modifications are propagated
back to the place where the value was loaded from.

Enforcing the signature prevents all of this, at a run time cost. Since
we have to coerce all arguments to the desired types, the function call
overhead grows. This change introduces a pragma
"FunctionSignatureBehavior" which you can set to "Ignored" or "Enforced"
to choose one way or the other as universal way of handling type
annotations.

Fixes: QTBUG-106819
Change-Id: I50e9b2bd6702907da44974cd9e05b48a96bb609e
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-10-14 16:36:36 +02:00
Marc Mutz 5eb52b7255 Port from container::count() and length() to size() - V5
This is a semantic patch using ClangTidyTransformator as in
qtbase/df9d882d41b741fef7c5beeddb0abe9d904443d8, but extended to
handle typedefs and accesses through pointers, too:

    const std::string o = "object";

    auto hasTypeIgnoringPointer = [](auto type) { return anyOf(hasType(type), hasType(pointsTo(type))); };

    auto derivedFromAnyOfClasses = [&](ArrayRef<StringRef> classes) {
        auto exprOfDeclaredType = [&](auto decl) {
            return expr(hasTypeIgnoringPointer(hasUnqualifiedDesugaredType(recordType(hasDeclaration(decl))))).bind(o);
        };
        return exprOfDeclaredType(cxxRecordDecl(isSameOrDerivedFrom(hasAnyName(classes))));
    };

    auto renameMethod = [&] (ArrayRef<StringRef> classes,
                            StringRef from, StringRef to) {
        return makeRule(cxxMemberCallExpr(on(derivedFromAnyOfClasses(classes)),
                            callee(cxxMethodDecl(hasName(from), parameterCountIs(0)))),
                        changeTo(cat(access(o, cat(to)), "()")),
                        cat("use '", to, "' instead of '", from, "'"));
    };

    renameMethod(<classes>, "count", "size");
    renameMethod(<classes>, "length", "size");

except that on() was replaced with a matcher that doesn't ignoreParens().

a.k.a qt-port-to-std-compatible-api V5 with config Scope: 'Container'.

Change-Id: I58e1b41b91c34d2e860dbb5847b3752edbfc6fc9
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2022-10-13 00:18:35 +02:00
Ulf Hermann 1a0c4094e0 QmlCompiler: Properly check contained type for enums
In case of an enum the actual contained type is the one the enum
dictates. This brings registerContains() in line with containedType()
and makes it possible to match previously discovered types on subsequent
passes of the type propagator. Therefore, it avoids infinite loops where
the same types would be tracked over and over.

Pick-to: 6.4
Fixes: QTBUG-107176
Fixes: QTBUG-107542
Change-Id: I4b8d66b157d0ec0ece4ca345cb99a630b8898a1b
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
2022-10-12 20:43:34 +02:00
Marc Mutz 958cd3ee10 Port from container::count() and length() to size()
This is a semantic patch using ClangTidyTransformator as in
qtbase/df9d882d41b741fef7c5beeddb0abe9d904443d8:

  auto QtContainerClass = anyOf(
      expr(hasType(cxxRecordDecl(isSameOrDerivedFrom(hasAnyName(classes))))).bind(o),
      expr(hasType(namedDecl(hasAnyName(<classes>)))).bind(o));
  makeRule(cxxMemberCallExpr(on(QtContainerClass),
                             callee(cxxMethodDecl(hasAnyName({"count", "length"),
                                                  parameterCountIs(0))))),
           changeTo(cat(access(o, cat("size"), "()"))),
           cat("use 'size()' instead of 'count()/length()'"))

a.k.a qt-port-to-std-compatible-api with config Scope: 'Container',
with the extended set of container classes recognized.

Change-Id: Idb1f75dfe2323bd1d9e8b4d58d54f1b4b80c7ed7
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-10-07 23:38:48 +02:00
Ulf Hermann 1e712c95ce QmlCompiler: Do not crash on version-mismatched property access
If we cannot access a property due to a version mismatch, that's not an
unqualified access.

Pick-to: 6.4
Fixes: QTBUG-107080
Change-Id: I1780b171928df437a2121601f1aac829dbe1e994
Reviewed-by: Semih Yavuz <semih.yavuz@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-10-06 20:37:53 +02:00
Ulf Hermann 4bc3f64b0e V4: Use an enum to categorize functions and rename aotFunction
We want to use the aotFunction member also for typed JavaScript
functions.

Change-Id: Iad6d12ebed3ad3069832484137ed8e4d9e7a7cf4
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-09-29 18:19:06 +02:00
Ulf Hermann 8f1edbf2ec Extend hack to pass QML types through QMetaObject::invokeMethod()
We now actually need a valid metatype.

Task-number: QTBUG-106194
Change-Id: Idfc41cae4216e30058f797b08863c350f473ba55
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-09-13 22:25:09 +02:00
Lucie Gérard 1b9808737a Change the license of all CMakeLists.txt and *.cmake files to BSD
Task-number: QTBUG-105718
Change-Id: Id89ed14990804a5024183e75382cc539d4293da1
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Jörg Bornemann <joerg.bornemann@qt.io>
2022-09-07 17:01:30 +02:00
Ulf Hermann 0a8fe228f6 QmlCompiler: Prevent lookup of value type where we need an object type
With a particular nefarious combination of Q_GADGET and inheritance from
QObject you can make QmlCompiler believe a type is a value type even
though it is actually an object type. We never want to touch such a
thing.

There was a safe guard against this when looking up the type from the
scope, but by putting it in a type namespace you could circumvent it.
Refactor the code to apply to both cases the same way.

Pick-to: 6.2 6.3 6.4
Fixes: QTBUG-104556
Fixes: QTBUG-105608
Change-Id: I8a690e2b6f78fcaba0911a93504cde0d2c7dde0d
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-08-30 18:53:01 +02:00
Ulf Hermann f4577447a1 QmlCompiler: Implement remaining operators
Some of the math operators were still missing. Add them and test them
all.

Since the "runInterpreted()" test function takes too long now, split the
qmlcppcodegen test in two: One that runs in compiled mode and one that
runs in interpreted mode.

Fixes: QTBUG-105188
Change-Id: I4b641d5e51b5a7e2a9254be40f257d7b249deb13
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-08-29 13:21:06 +02:00
Thiago Macieira 1b1d0e0c15 tst_QmlCppCodegen: don't use QGenericArgument directly
Just create a dummy type that has the actual name. To make that
possible, export the property cache creator's class counter to the
autotests – otherwise, we cannot know the name of the actual type, as it
would depend on the order in which the tests run.

Change-Id: I36b24183fbd041179f2ffffd17026b224c9737fa
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2022-08-04 19:10:09 +02:00
Ulf Hermann b184d02648 QmlCompiler: Allow any conversion possible via QJSPrimitiveValue
All of those are legal in ECMAScript, and so we need to support them in
script bindings. As we have stricter rules for literal bindings, add an
extra method there to check for what QQmlPropertyValidator does.

Pick-to: 6.4
Fixes: QTBUG-105252
Task-number: QTBUG-105188
Change-Id: I0621b2c3aa196414f669873e93670557284a8bca
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-08-03 08:32:50 +02:00
Ulf Hermann 6ea2a1cdb7 QQmlListAccessor: Accept QQmlListProperty
So far we have only accepted QQmlListReference. However, we can also
pass a QQmlListProperty around as value.

Pick-to: 6.2 6.3 6.4
Fixes: QTBUG-105137
Change-Id: I7d4cd3048b62594298f91013c4cda5ec864a28df
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
2022-07-26 21:17:28 +02:00
Ulf Hermann 1969a10821 QmlCompiler: Support conversions between QString and QByteArray
Pick-to: 6.4
Fixes: QTBUG-104702
Change-Id: I80d3a28e17751d440ec4bea4c7be0d09c935fa19
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-07-22 21:30:12 +02:00
Ulf Hermann e97f8cabc8 QmlCompiler: Implement Math.pow()
Also, add missing positive infinity to test data.

Pick-to: 6.4
Fixes: QTBUG-104745
Change-Id: I958aca672cca8cc83c540ed3ea75b08e70eb90fd
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-07-21 13:19:04 +02:00
Ulf Hermann e19328fb0f QmlCompiler: Allow storeNameSloppy to reset a property
We should not convert from undefined on storeNameSloppy. The reset is
intentional.

Task-number: QTBUG-104508
Change-Id: Iede88fe6331dd173c9e8ea0ec4200df2b8bd30eb
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-07-11 13:37:26 +02:00
Lucie Gérard 5a7b716474 Add license headers to cmake files
CMakeLists.txt and .cmake files of significant size
(more than 2 lines according to our check in tst_license.pl)
now have the copyright and license header.

Existing copyright statements remain intact

Task-number: QTBUG-88621
Change-Id: I72c89a98c42bbc9234d8495e9e503bec81d11037
Reviewed-by: Jörg Bornemann <joerg.bornemann@qt.io>
2022-07-08 10:41:06 +02:00
Ulf Hermann 38fdf2717d QmlCompiler: Handle trivial signal handler constructions
If the signal handler does nothing but return a closure, we have to
compile the closure using the same signature as the outer signal
handler.

In order for this to work, we also have to detect unresolved argument
types for signal handlers. Those are just as bad as unresolved argument
types for other functions.

Fixes: QTBUG-101531
Change-Id: Idb5b3994809d91a4b4ce936282685435eb75e670
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-07-07 19:33:39 +02:00
Ulf Hermann 3f3e961a5a QmlCompiler: Allow wrapping enums into int
This is what we do internally in the QML engine.

Pick-to: 6.4
Fixes: QTBUG-104683
Change-Id: I2f8712cb2cdc56b6c483500627fd8a218edbad81
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-07-07 19:33:27 +02:00
Ulf Hermann 8dc33d3672 QmlCompiler: Don't crash on unknown list value types
Pick-to: 6.4
Fixes: QTBUG-104743
Change-Id: I551b21498bb746acf05be525dbcb72a74f816c04
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-07-06 21:28:05 +02:00
Ulf Hermann 8056df3284 QML: Re-add the Qt namespace enums to the Qt object
They were replaced with an extension to the Qt singleton in Qt6.
However, the singleton is only available when QtQml is imported.
We can easily provide the enums using the metaobject of the Qt
namespace.

Pick-to: 6.4
Change-Id: I5f58d30c749c0cb9e531df180a5cbe75c92e1aa6
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
2022-07-05 23:29:37 +02:00
Ulf Hermann af335a89bd QmlCompiler: Initialize registers with undefined where necessary
If we read the initial state of a register, we need to make sure it
actually exists at that point. Uninitialized variables are implicitly
undefined in JavaScript.

Pick-to: 6.4
Task-number: QTBUG-104687
Change-Id: Ide4fe429b10ec28dcf267e7d34c6316355b16baa
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-07-05 19:50:28 +02:00
Ulf Hermann 7d36ec0bd9 QmlCompiler: Don't push type conversions back into the engine
In many cases we can generate better code for type conversions.
Furthermore, the engine only does QMetaType::convert(). This misses a
lot of conversions we do in other places.

Pick-to: 6.4
Change-Id: I1526ec327d189420885f6a7385f6cc1c2c94b19e
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-07-05 19:50:24 +02:00
Ulf Hermann 4639607036 QmlCompiler: Really fix writing into argument values
Arguments are now treated as registers "written" at the beginning of
the first basic block. By modeling them this way, we can avoid all the
complicated logic on whether to use a local or the arguments array when
accessing any particular one of them. Furthermore, we can detect whether
they are overwritten or not. If they are not overwritten, we can
initialize them as a const reference into the arguments array. This way
we save a copy.

Treating the arguments as generic registers causes the basic blocks pass
to aggressively adjust their types, pushing some conversions back into
the QML engine. This is good. Unused arguments become void, for example,
and don't have to be passed at all. However, we also need a special case
for QJSPrimitiveValue arguments now.

Pick-to: 6.4
Fixes: QTBUG-104462
Change-Id: I994bea0929bd508aa41db58dee4a7f12cd20f053
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
2022-07-05 19:50:19 +02:00
Ulf Hermann 5e4a1738b0 QmlCompiler: Fix register propagation in basic blocks pass
a, We were recording too many jump origins and targets. That messed up
   the basic blocks ordering logic.
b, In the presence of backward jumps, we need to revisit earlier basic
   blocks if additional writes are discovered. Otherwise the type
   adjustment will optimize "dead" type conversions out.

Pick-to: 6.4
Fixes: QTBUG-104665
Change-Id: I7219f85625761817ae4f63582d80d247a85df73b
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2022-07-05 19:50:15 +02:00